/********************************************************************** * 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 #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 ( //rectangular 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) { //box(ICOORD(xmin,ymin),ICOORD(xmax,ymax)) //boundaries 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_block = NULL; 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)); } /********************************************************************** * BLOCK::set_sides * * Sets left and right vertex lists **********************************************************************/ //void BLOCK::set_sides( //set vertex lists //ICOORDELT_LIST *left, //left vertices //ICOORDELT_LIST *right //right vertices //) //{ // ICOORDELT_IT left_it= &leftside; //boundaries // ICOORDELT_IT right_it= &rightside; // leftside.clear(); // left_it.move_to_first(); // left_it.add_list_before(left); // rightside.clear(); // right_it.move_to_first(); // right_it.add_list_before(right); //} /********************************************************************** * BLOCK::contains * * Return TRUE if the given point is within the block. **********************************************************************/ //BOOL8 BLOCK::contains( //test containment //ICOORD pt //point to test //) //{ // BLOCK_RECT_IT it=this; //rectangle iterator // ICOORD bleft,tright; //corners of rectangle // for (it.start_block();!it.cycled_rects();it.forward()) // { // it.bounding_box(bleft,tright); //get rectangle // if (pt.x()>=bleft.x() && pt.x()<=tright.x() //inside rect // && pt.y()>=bleft.y() && pt.y()<=tright.y()) // return TRUE; //is inside // } // return FALSE; //not inside //} /********************************************************************** * BLOCK::move * * Reposition block **********************************************************************/ //void BLOCK::move( // reposition block //const ICOORD vec // by vector //) //{ // ROW_IT row_it( &rows ); // ICOORDELT_IT it( &leftside ); // for( row_it.mark_cycle_pt(); !row_it.cycled_list(); row_it.forward() ) // row_it.data()->move( vec ); // for( it.mark_cycle_pt(); !it.cycled_list(); it.forward() ) // *(it.data()) += vec; // it.set_to_list( &rightside ); // for( it.mark_cycle_pt(); !it.cycled_list(); it.forward() ) // *(it.data()) += vec; // box.move( vec ); //} /********************************************************************** * 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::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::plot * * Plot the outline of a block in the given colour. **********************************************************************/ //void BLOCK::plot( //draw outline //WINDOW window, //window to draw in //inT32 serial, //serial number //COLOUR colour //colour to draw in //) //{ // ICOORD startpt; //start of outline // ICOORD endpt; //end of outline // ICOORD prevpt; //previous point // ICOORDELT_IT it= &leftside; //iterator // char number[32]; //block id // line_color_index(window,colour); //set the colour // text_color_index(window,colour); // character_height(window,(float)BLOCK_LABEL_HEIGHT); // text_font_index(window,6); // if (!leftside.empty()) // { // startpt= *(it.data()); //bottom left corner //// fprintf(stderr,"Block %d bottom left is (%d,%d)\n", //// serial,startpt.x(),startpt.y()); // sprintf(number,"%d",serial); // text2d(window,startpt.x(),startpt.y(),number,0,FALSE); // move2d(window,startpt.x(),startpt.y()); // do // { // prevpt= *(it.data()); //previous point // it.forward(); //move to next point // draw2d(window,prevpt.x(),it.data()->y()); //draw round corner // draw2d(window,it.data()->x(),it.data()->y()); // } // while (!it.at_last()); //until end of list // endpt= *(it.data()); //end point // move2d(window,startpt.x(),startpt.y()); //other side of boundary // it.set_to_list(&rightside); // prevpt=startpt; // for (it.mark_cycle_pt();!it.cycled_list();it.forward()) // { // draw2d(window,prevpt.x(),it.data()->y()); //draw round corner // draw2d(window,it.data()->x(),it.data()->y()); // prevpt= *(it.data()); //previous point // } // draw2d(window,endpt.x(),endpt.y()); //close boundary // if (hand_block!=NULL) // hand_block->plot(window,colour,serial); // } //} /********************************************************************** * BLOCK::show * * Show the image corresponding to a block as its set of rectangles. **********************************************************************/ //void BLOCK::show( //show image block //IMAGE *image, //image to show //WINDOW window //window to show in //) //{ // BLOCK_RECT_IT it=this; //rectangle iterator // ICOORD bleft,tright; //corners of rectangle // for (it.start_block();!it.cycled_rects();it.forward()) // { // it.bounding_box(bleft,tright); //get rectangle //// fprintf(stderr,"Drawing a block with a bottom left of (%d,%d)\n", //// bleft.x(),bleft.y()); // show_sub_image(image,bleft.x(),bleft.y(), // tright.x()-bleft.x(),tright.y()-bleft.y(), // window,bleft.x(),bleft.y()); //show it // } //} /********************************************************************** * 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 (); // if ( !leftside.empty() ) // leftside.clear(); // if ( !rightside.empty() ) // rightside.clear(); // leftside.deep_copy( &source.leftside ); // rightside.deep_copy( &source.rightside ); // box=source.box; return *this; }