1 /**********************************************************************
2 * File: ocrblock.cpp (Formerly block.c)
3 * Description: BLOCK member functions and iterator functions.
4 * Author: Ray Smith
5 * Created: Fri Mar 15 09:41:28 GMT 1991
6 *
7 * (C) Copyright 1991, Hewlett-Packard Ltd.
8 ** Licensed under the Apache License, Version 2.0 (the "License");
9 ** you may not use this file except in compliance with the License.
10 ** You may obtain a copy of the License at
11 ** http://www.apache.org/licenses/LICENSE-2.0
12 ** Unless required by applicable law or agreed to in writing, software
13 ** distributed under the License is distributed on an "AS IS" BASIS,
14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ** See the License for the specific language governing permissions and
16 ** limitations under the License.
17 *
18 **********************************************************************/
19
20 #include "mfcpch.h"
21 #include <stdlib.h>
22 #include "blckerr.h"
23 #include "ocrblock.h"
24 #include "tprintf.h"
25
26 #define BLOCK_LABEL_HEIGHT 150 //char height of block id
27
ELISTIZE_S(BLOCK)28 ELISTIZE_S (BLOCK)
29 /**********************************************************************
30 * BLOCK::BLOCK
31 *
32 * Constructor for a simple rectangular block.
33 **********************************************************************/
34 BLOCK::BLOCK(const char *name, //filename
35 BOOL8 prop, //proportional
36 inT16 kern, //kerning
37 inT16 space, //spacing
38 inT16 xmin, //bottom left
39 inT16 ymin, inT16 xmax, //top right
40 inT16 ymax)
41 : PDBLK (xmin, ymin, xmax, ymax),
42 filename(name),
43 re_rotation_(1.0f, 0.0f),
44 classify_rotation_(1.0f, 0.0f),
45 skew_(1.0f, 0.0f) {
46 ICOORDELT_IT left_it = &leftside;
47 ICOORDELT_IT right_it = &rightside;
48
49 proportional = prop;
50 kerning = kern;
51 spacing = space;
52 font_class = -1; //not assigned
53 cell_over_xheight_ = 2.0f;
54 hand_poly = NULL;
55 left_it.set_to_list (&leftside);
56 right_it.set_to_list (&rightside);
57 //make default box
58 left_it.add_to_end (new ICOORDELT (xmin, ymin));
59 left_it.add_to_end (new ICOORDELT (xmin, ymax));
60 right_it.add_to_end (new ICOORDELT (xmax, ymin));
61 right_it.add_to_end (new ICOORDELT (xmax, ymax));
62 }
63
64 /**********************************************************************
65 * decreasing_top_order
66 *
67 * Sort Comparator: Return <0 if row1 top < row2 top
68 **********************************************************************/
69
decreasing_top_order(const void * row1,const void * row2)70 int decreasing_top_order( //
71 const void *row1,
72 const void *row2) {
73 return (*(ROW **) row2)->bounding_box ().top () -
74 (*(ROW **) row1)->bounding_box ().top ();
75 }
76
77
78 /**********************************************************************
79 * BLOCK::rotate
80 *
81 * Rotate the polygon by the given rotation and recompute the bounding_box.
82 **********************************************************************/
rotate(const FCOORD & rotation)83 void BLOCK::rotate(const FCOORD& rotation) {
84 poly_block()->rotate(rotation);
85 box = *poly_block()->bounding_box();
86 }
87
88 /**********************************************************************
89 * BLOCK::sort_rows
90 *
91 * Order rows so that they are in order of decreasing Y coordinate
92 **********************************************************************/
93
sort_rows()94 void BLOCK::sort_rows() { // order on "top"
95 ROW_IT row_it(&rows);
96
97 row_it.sort (decreasing_top_order);
98 }
99
100
101 /**********************************************************************
102 * BLOCK::compress
103 *
104 * Delete space between the rows. (And maybe one day, compress the rows)
105 * Fill space of block from top down, left aligning rows.
106 **********************************************************************/
107
compress()108 void BLOCK::compress() { // squash it up
109 #define ROW_SPACING 5
110
111 ROW_IT row_it(&rows);
112 ROW *row;
113 ICOORD row_spacing (0, ROW_SPACING);
114
115 ICOORDELT_IT icoordelt_it;
116
117 sort_rows();
118
119 box = TBOX (box.topleft (), box.topleft ());
120 box.move_bottom_edge (ROW_SPACING);
121 for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) {
122 row = row_it.data ();
123 row->move (box.botleft () - row_spacing -
124 row->bounding_box ().topleft ());
125 box += row->bounding_box ();
126 }
127
128 leftside.clear ();
129 icoordelt_it.set_to_list (&leftside);
130 icoordelt_it.add_to_end (new ICOORDELT (box.left (), box.bottom ()));
131 icoordelt_it.add_to_end (new ICOORDELT (box.left (), box.top ()));
132 rightside.clear ();
133 icoordelt_it.set_to_list (&rightside);
134 icoordelt_it.add_to_end (new ICOORDELT (box.right (), box.bottom ()));
135 icoordelt_it.add_to_end (new ICOORDELT (box.right (), box.top ()));
136 }
137
138
139 /**********************************************************************
140 * BLOCK::check_pitch
141 *
142 * Check whether the block is fixed or prop, set the flag, and set
143 * the pitch if it is fixed.
144 **********************************************************************/
145
check_pitch()146 void BLOCK::check_pitch() { // check prop
147 // tprintf("Missing FFT fixed pitch stuff!\n");
148 pitch = -1;
149 }
150
151
152 /**********************************************************************
153 * BLOCK::compress
154 *
155 * Compress and move in a single operation.
156 **********************************************************************/
157
compress(const ICOORD vec)158 void BLOCK::compress( // squash it up
159 const ICOORD vec // and move
160 ) {
161 box.move (vec);
162 compress();
163 }
164
165
166 /**********************************************************************
167 * BLOCK::print
168 *
169 * Print the info on a block
170 **********************************************************************/
171
print(FILE *,BOOL8 dump)172 void BLOCK::print( //print list of sides
173 FILE *, //file to print on
174 BOOL8 dump //print full detail
175 ) {
176 ICOORDELT_IT it = &leftside; //iterator
177
178 box.print ();
179 tprintf ("Proportional= %s\n", proportional ? "TRUE" : "FALSE");
180 tprintf ("Kerning= %d\n", kerning);
181 tprintf ("Spacing= %d\n", spacing);
182 tprintf ("Fixed_pitch=%d\n", pitch);
183 tprintf ("Filename= %s\n", filename.string ());
184
185 if (dump) {
186 tprintf ("Left side coords are:\n");
187 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
188 tprintf ("(%d,%d) ", it.data ()->x (), it.data ()->y ());
189 tprintf ("\n");
190 tprintf ("Right side coords are:\n");
191 it.set_to_list (&rightside);
192 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
193 tprintf ("(%d,%d) ", it.data ()->x (), it.data ()->y ());
194 tprintf ("\n");
195 }
196 }
197
198 /**********************************************************************
199 * BLOCK::operator=
200 *
201 * Assignment - duplicate the block structure, but with an EMPTY row list.
202 **********************************************************************/
203
operator =(const BLOCK & source)204 BLOCK & BLOCK::operator= ( //assignment
205 const BLOCK & source //from this
206 ) {
207 this->ELIST_LINK::operator= (source);
208 this->PDBLK::operator= (source);
209 proportional = source.proportional;
210 kerning = source.kerning;
211 spacing = source.spacing;
212 filename = source.filename; //STRINGs assign ok
213 if (!rows.empty ())
214 rows.clear ();
215 re_rotation_ = source.re_rotation_;
216 classify_rotation_ = source.classify_rotation_;
217 skew_ = source.skew_;
218 return *this;
219 }
220