blob: b48908800e2bbd198e0280824490c9782fc55edd [file] [log] [blame]
/**********************************************************************
* File: ocrblock.cpp (Formerly block.c)
* Description: BLOCK member functions and iterator functions.
* Author: Ray Smith
* Created: Fri Mar 15 09:41:28 GMT 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 <stdlib.h>
#include "blckerr.h"
#include "ocrblock.h"
#include "tprintf.h"
#define BLOCK_LABEL_HEIGHT 150 //char height of block id
ELISTIZE_S (BLOCK)
/**********************************************************************
* BLOCK::BLOCK
*
* Constructor for a simple rectangular block.
**********************************************************************/
BLOCK::BLOCK(const char *name, //filename
BOOL8 prop, //proportional
inT16 kern, //kerning
inT16 space, //spacing
inT16 xmin, //bottom left
inT16 ymin, inT16 xmax, //top right
inT16 ymax)
: PDBLK (xmin, ymin, xmax, ymax),
filename(name),
re_rotation_(1.0f, 0.0f),
classify_rotation_(1.0f, 0.0f),
skew_(1.0f, 0.0f) {
ICOORDELT_IT left_it = &leftside;
ICOORDELT_IT right_it = &rightside;
proportional = prop;
kerning = kern;
spacing = space;
font_class = -1; //not assigned
cell_over_xheight_ = 2.0f;
hand_poly = NULL;
left_it.set_to_list (&leftside);
right_it.set_to_list (&rightside);
//make default box
left_it.add_to_end (new ICOORDELT (xmin, ymin));
left_it.add_to_end (new ICOORDELT (xmin, ymax));
right_it.add_to_end (new ICOORDELT (xmax, ymin));
right_it.add_to_end (new ICOORDELT (xmax, ymax));
}
/**********************************************************************
* decreasing_top_order
*
* Sort Comparator: Return <0 if row1 top < row2 top
**********************************************************************/
int decreasing_top_order( //
const void *row1,
const void *row2) {
return (*(ROW **) row2)->bounding_box ().top () -
(*(ROW **) row1)->bounding_box ().top ();
}
/**********************************************************************
* BLOCK::rotate
*
* Rotate the polygon by the given rotation and recompute the bounding_box.
**********************************************************************/
void BLOCK::rotate(const FCOORD& rotation) {
poly_block()->rotate(rotation);
box = *poly_block()->bounding_box();
}
/**********************************************************************
* BLOCK::sort_rows
*
* Order rows so that they are in order of decreasing Y coordinate
**********************************************************************/
void BLOCK::sort_rows() { // order on "top"
ROW_IT row_it(&rows);
row_it.sort (decreasing_top_order);
}
/**********************************************************************
* BLOCK::compress
*
* Delete space between the rows. (And maybe one day, compress the rows)
* Fill space of block from top down, left aligning rows.
**********************************************************************/
void BLOCK::compress() { // squash it up
#define ROW_SPACING 5
ROW_IT row_it(&rows);
ROW *row;
ICOORD row_spacing (0, ROW_SPACING);
ICOORDELT_IT icoordelt_it;
sort_rows();
box = TBOX (box.topleft (), box.topleft ());
box.move_bottom_edge (ROW_SPACING);
for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) {
row = row_it.data ();
row->move (box.botleft () - row_spacing -
row->bounding_box ().topleft ());
box += row->bounding_box ();
}
leftside.clear ();
icoordelt_it.set_to_list (&leftside);
icoordelt_it.add_to_end (new ICOORDELT (box.left (), box.bottom ()));
icoordelt_it.add_to_end (new ICOORDELT (box.left (), box.top ()));
rightside.clear ();
icoordelt_it.set_to_list (&rightside);
icoordelt_it.add_to_end (new ICOORDELT (box.right (), box.bottom ()));
icoordelt_it.add_to_end (new ICOORDELT (box.right (), box.top ()));
}
/**********************************************************************
* BLOCK::check_pitch
*
* Check whether the block is fixed or prop, set the flag, and set
* the pitch if it is fixed.
**********************************************************************/
void BLOCK::check_pitch() { // check prop
// tprintf("Missing FFT fixed pitch stuff!\n");
pitch = -1;
}
/**********************************************************************
* BLOCK::compress
*
* Compress and move in a single operation.
**********************************************************************/
void BLOCK::compress( // squash it up
const ICOORD vec // and move
) {
box.move (vec);
compress();
}
/**********************************************************************
* BLOCK::print
*
* Print the info on a block
**********************************************************************/
void BLOCK::print( //print list of sides
FILE *, //file to print on
BOOL8 dump //print full detail
) {
ICOORDELT_IT it = &leftside; //iterator
box.print ();
tprintf ("Proportional= %s\n", proportional ? "TRUE" : "FALSE");
tprintf ("Kerning= %d\n", kerning);
tprintf ("Spacing= %d\n", spacing);
tprintf ("Fixed_pitch=%d\n", pitch);
tprintf ("Filename= %s\n", filename.string ());
if (dump) {
tprintf ("Left side coords are:\n");
for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
tprintf ("(%d,%d) ", it.data ()->x (), it.data ()->y ());
tprintf ("\n");
tprintf ("Right side coords are:\n");
it.set_to_list (&rightside);
for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
tprintf ("(%d,%d) ", it.data ()->x (), it.data ()->y ());
tprintf ("\n");
}
}
/**********************************************************************
* BLOCK::operator=
*
* Assignment - duplicate the block structure, but with an EMPTY row list.
**********************************************************************/
BLOCK & BLOCK::operator= ( //assignment
const BLOCK & source //from this
) {
this->ELIST_LINK::operator= (source);
this->PDBLK::operator= (source);
proportional = source.proportional;
kerning = source.kerning;
spacing = source.spacing;
filename = source.filename; //STRINGs assign ok
if (!rows.empty ())
rows.clear ();
re_rotation_ = source.re_rotation_;
classify_rotation_ = source.classify_rotation_;
skew_ = source.skew_;
return *this;
}