/**********************************************************************
 * File:        ocrrow.cpp  (Formerly row.c)
 * Description: Code for the ROW class.
 * Author:					Ray Smith
 * Created:					Tue Oct 08 15:58:04 BST 1991
 *
 * (C) Copyright 1991, Hewlett-Packard Ltd.
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 ** http://www.apache.org/licenses/LICENSE-2.0
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 *
 **********************************************************************/

#include "mfcpch.h"
#include          "ocrrow.h"
#include          "blobbox.h"

ELISTIZE_S (ROW)
/**********************************************************************
 * ROW::ROW
 *
 * Constructor to build a ROW. Only the stats stuff are given here.
 * The words are added directly.
 **********************************************************************/
ROW::ROW (                       //constructor
INT32 spline_size,               //no of segments
INT32 * xstarts,                 //segment boundaries
double *coeffs,                  //coefficients
float x_height,                  //line height
float ascenders,                 //ascender size
float descenders,                //descender drop
INT16 kern,                      //char gap
INT16 space                      //word gap
):
baseline(spline_size, xstarts, coeffs) { 
  kerning = kern;                //just store stuff
  spacing = space;
  xheight = x_height;
  ascrise = ascenders;
  descdrop = descenders;
}


/**********************************************************************
 * ROW::ROW
 *
 * Constructor to build a ROW. Only the stats stuff are given here.
 * The words are added directly.
 **********************************************************************/

ROW::ROW(                 //constructor
         TO_ROW *to_row,  //source row
         INT16 kern,      //char gap
         INT16 space      //word gap
        ) {
  kerning = kern;                //just store stuff
  spacing = space;
  xheight = to_row->xheight;
  ascrise = to_row->ascrise;
  descdrop = to_row->descdrop;
  baseline = to_row->baseline;
}


/**********************************************************************
 * ROW::recalc_bounding_box
 *
 * Set the bounding box correctly
 **********************************************************************/

void ROW::recalc_bounding_box() {  //recalculate BB
  WERD *word;                    //current word
  WERD_IT it = &words;           //words of ROW
  INT16 left;                    //of word
  INT16 prev_left;               //old left

  if (!it.empty ()) {
    word = it.data ();
    prev_left = word->bounding_box ().left ();
    it.forward ();
    while (!it.at_first ()) {
      word = it.data ();
      left = word->bounding_box ().left ();
      if (left < prev_left) {
        it.move_to_first ();
                                 //words in BB order
        it.sort (word_comparator);
        break;
      }
      prev_left = left;
      it.forward ();
    }
  }
  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
    word = it.data ();
    if (it.at_first ())
      word->set_flag (W_BOL, TRUE);
    else
                                 //not start of line
      word->set_flag (W_BOL, FALSE);
    if (it.at_last ())
      word->set_flag (W_EOL, TRUE);
    else
                                 //not end of line
      word->set_flag (W_EOL, FALSE);
                                 //extend BB as reqd
    bound_box += word->bounding_box ();
  }
}


/**********************************************************************
 * ROW::move
 *
 * Reposition row by vector
 **********************************************************************/

void ROW::move(                  // reposition row
               const ICOORD vec  // by vector
              ) {
  WERD_IT it(&words);  // word iterator

  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
    it.data ()->move (vec);

  bound_box.move (vec);
  baseline.move (vec);
}


/**********************************************************************
 * ROW::print
 *
 * Display members
 **********************************************************************/

void ROW::print(          //print
                FILE *fp  //file to print on
               ) {
  tprintf ("Kerning= %d\n", kerning);
  tprintf ("Spacing= %d\n", spacing);
  bound_box.print ();
  tprintf ("Xheight= %f\n", xheight);
  tprintf ("Ascrise= %f\n", ascrise);
  tprintf ("Descdrop= %f\n", descdrop);
}


/**********************************************************************
 * ROW::plot
 *
 * Draw the ROW in the given colour.
 **********************************************************************/

#ifndef GRAPHICS_DISABLED
void ROW::plot(                //draw it
               WINDOW window,  //window to draw in
               COLOUR colour   //colour to draw in
              ) {
  WERD *word;                    //current word
  WERD_IT it = &words;           //words of ROW

  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
    word = it.data ();
    word->plot (window, colour); //all in one colour
  }
}
#endif

/**********************************************************************
 * ROW::plot
 *
 * Draw the ROW in rainbow colours.
 **********************************************************************/

#ifndef GRAPHICS_DISABLED
void ROW::plot(               //draw it
               WINDOW window  //window to draw in
              ) {
  WERD *word;                    //current word
  WERD_IT it = &words;           //words of ROW

  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
    word = it.data ();
    word->plot (window);         //in rainbow colours
  }
}
#endif

/**********************************************************************
 * ROW::operator=
 *
 * Assign rows by duplicating the row structure but NOT the WERDLIST
 **********************************************************************/

ROW & ROW::operator= (           //assignment
const ROW & source               //from this
) {
  this->ELIST_LINK::operator= (source);
  kerning = source.kerning;
  spacing = source.spacing;
  xheight = source.xheight;
  ascrise = source.ascrise;
  descdrop = source.descdrop;
  if (!words.empty ())
    words.clear ();
  baseline = source.baseline;    //QSPLINES must do =
  bound_box = source.bound_box;
  return *this;
}
