• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**********************************************************************
2  * File:        polyblob.cpp  (Formerly blob.c)
3  * Description: Code for PBLOB class.
4  * Author:		Ray Smith
5  * Created:		Wed Oct 23 15:17:41 BST 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          "varable.h"
22 #include          "ocrrow.h"
23 #include          "polyblob.h"
24 //#include                                                      "lapoly.h"
25 #include          "polyaprx.h"
26 
27 #define EXTERN
28 
29 EXTERN BOOL_VAR (polygon_tess_approximation, TRUE,
30 "Do tess poly instead of greyscale");
31 
ELISTIZE_S(PBLOB)32 ELISTIZE_S (PBLOB)
33 /**********************************************************************
34  * position_outline
35  *
36  * Position the outline in the given list at the relevant place
37  * according to its nesting.
38  **********************************************************************/
39 static void position_outline(                        //put in place
40                              OUTLINE *outline,       //thing to place
41                              OUTLINE_LIST *destlist  //desstination list
42                             ) {
43   OUTLINE *dest_outline;         //outline from dest list
44   OUTLINE_IT it = destlist;      //iterator
45                                  //iterator on children
46   OUTLINE_IT child_it = outline->child ();
47 
48   if (!it.empty ()) {
49     do {
50       dest_outline = it.data (); //get destination
51                                  //encloses dest
52       if (*dest_outline < *outline) {
53                                  //take off list
54         dest_outline = it.extract ();
55                                  //put this in place
56         it.add_after_then_move (outline);
57                                  //make it a child
58         child_it.add_to_end (dest_outline);
59         while (!it.at_last ()) {
60           it.forward ();         //do rest of list
61                                  //check for other children
62           dest_outline = it.data ();
63           if (*dest_outline < *outline) {
64                                  //take off list
65             dest_outline = it.extract ();
66             child_it.add_to_end (dest_outline);
67             //make it a child
68             if (it.empty ())
69               break;
70           }
71         }
72         return;                  //finished
73       }
74                                  //enclosed by dest
75       else if (*outline < *dest_outline) {
76         position_outline (outline, dest_outline->child ());
77         //place in child list
78         return;                  //finished
79       }
80       it.forward ();
81     }
82     while (!it.at_first ());
83   }
84   it.add_to_end (outline);       //at outer level
85 }
86 
87 
88 /**********************************************************************
89  * plot_outline_list
90  *
91  * Draw a list of outlines in the given colour and their children
92  * in the child colour.
93  **********************************************************************/
94 
95 #ifndef GRAPHICS_DISABLED
plot_outline_list(OUTLINE_LIST * list,ScrollView * window,ScrollView::Color colour,ScrollView::Color child_colour)96 static void plot_outline_list(                     //draw outlines
97                               OUTLINE_LIST *list,  //outline to draw
98                               ScrollView* window,       //window to draw in
99                               ScrollView::Color colour,       //colour to use
100                               ScrollView::Color child_colour  //colour of children
101                              ) {
102   OUTLINE *outline;              //current outline
103   OUTLINE_IT it = list;          //iterator
104 
105   for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
106     outline = it.data ();
107                                  //draw it
108     outline->plot (window, colour);
109     if (!outline->child ()->empty ())
110       plot_outline_list (outline->child (), window,
111         child_colour, child_colour);
112   }
113 }
114 #endif
115 
116 
117 /**********************************************************************
118  * PBLOB::PBLOB
119  *
120  * Constructor to build a PBLOB from a list of OUTLINEs.
121  * The OUTLINEs are not copied so the source list is emptied.
122  * The OUTLINEs are nested correctly in the blob.
123  **********************************************************************/
124 
PBLOB(OUTLINE_LIST * outline_list)125 PBLOB::PBLOB(                            //constructor
126              OUTLINE_LIST *outline_list  //in random order
127             ) {
128   OUTLINE *outline;              //current outline
129   OUTLINE_IT it = outline_list;  //iterator
130 
131   while (!it.empty ()) {         //grab the list
132     outline = it.extract ();     //get off the list
133                                  //put it in place
134     position_outline(outline, &outlines);
135     if (!it.empty ())
136       it.forward ();
137   }
138 }
139 
140 
141 /**********************************************************************
142  * approximate_outline_list
143  *
144  * Convert a list of outlines to polygonal form.
145  **********************************************************************/
146 
approximate_outline_list(C_OUTLINE_LIST * srclist,OUTLINE_LIST * destlist,float xheight)147 static void approximate_outline_list(                          //do list of outlines
148                                      C_OUTLINE_LIST *srclist,  //list to convert
149                                      OUTLINE_LIST *destlist,   //desstination list
150                                      float xheight             //height of line
151                                     ) {
152   C_OUTLINE *src_outline;        //outline from src list
153   OUTLINE *dest_outline;         //result
154   C_OUTLINE_IT src_it = srclist; //source iterator
155   OUTLINE_IT dest_it = destlist; //iterator
156 
157   do {
158     src_outline = src_it.data ();
159     //              if (polygon_tess_approximation)
160     dest_outline = tesspoly_outline (src_outline, xheight);
161     //              else
162     //                      dest_outline=greypoly_outline(src_outline,xheight);
163     if (dest_outline != NULL) {
164       dest_it.add_after_then_move (dest_outline);
165       if (!src_outline->child ()->empty ())
166                                  //do child list
167         approximate_outline_list (src_outline->child (), dest_outline->child (), xheight);
168     }
169     src_it.forward ();
170   }
171   while (!src_it.at_first ());
172 }
173 
174 
175 /**********************************************************************
176  * PBLOB::PBLOB
177  *
178  * Constructor to build a PBLOB from a C_BLOB by polygonal approximation.
179  **********************************************************************/
180 
PBLOB(C_BLOB * cblob,float xheight)181 PBLOB::PBLOB(                //constructor
182              C_BLOB *cblob,  //compact blob
183              float xheight   //height of line
184             ) {
185   TBOX bbox;                      //bounding box
186 
187   if (!cblob->out_list ()->empty ()) {
188                                  //get bounding box
189     bbox = cblob->bounding_box ();
190     if (bbox.height () > xheight)
191       xheight = bbox.height ();  //max of line and blob
192                                  //copy it
193     approximate_outline_list (cblob->out_list (), &outlines, xheight);
194   }
195 }
196 
197 
198 /**********************************************************************
199  * PBLOB::bounding_box
200  *
201  * Return the bounding box of the blob.
202  **********************************************************************/
203 
bounding_box()204 TBOX PBLOB::bounding_box() {  //bounding box
205   OUTLINE *outline;              //current outline
206   OUTLINE_IT it = &outlines;     //outlines of blob
207   TBOX box;                       //bounding box
208 
209   for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
210     outline = it.data ();
211     box += outline->bounding_box ();
212   }
213   return box;
214 }
215 
216 
217 /**********************************************************************
218  * PBLOB::area
219  *
220  * Return the area of the blob.
221  **********************************************************************/
222 
area()223 float PBLOB::area() {  //area
224   OUTLINE *outline;              //current outline
225   OUTLINE_IT it = &outlines;     //outlines of blob
226   float total;                   //total area
227 
228   total = 0.0f;
229   for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
230     outline = it.data ();
231     total += outline->area ();
232   }
233   return total;
234 }
235 
236 
237 /**********************************************************************
238  * PBLOB::baseline_normalise
239  *
240  * Baseline normalize a blob
241  **********************************************************************/
242 
baseline_normalise(ROW * row,DENORM * denorm)243 PBLOB *PBLOB::baseline_normalise(                //normalize blob
244                                  ROW *row,       //row it came from
245                                  DENORM *denorm  //inverse mapping
246                                 ) {
247   TBOX blob_box = bounding_box ();
248   float x_centre = (blob_box.left () + blob_box.right ()) / 2.0;
249   PBLOB *bn_blob;                //copied blob
250 
251   *denorm = DENORM (x_centre, bln_x_height / row->x_height (), row);
252   bn_blob = new PBLOB;           //get one
253   *bn_blob = *this;              //deep copy
254   bn_blob->move (FCOORD (-denorm->origin (), -row->base_line (x_centre)));
255   bn_blob->scale (denorm->scale ());
256   bn_blob->move (FCOORD (0.0, bln_baseline_offset));
257   return bn_blob;
258 }
259 
260 
261 /**********************************************************************
262  * PBLOB::baseline_denormalise
263  *
264  * DeBaseline Normalise the blob properly with the given denorm.
265  **********************************************************************/
266 
baseline_denormalise(const DENORM * denorm)267 void PBLOB::baseline_denormalise(                      // Tess style BL Norm
268                                  const DENORM *denorm  //antidote
269                                 ) {
270   float blob_x_left;           // Left edge of blob.
271   TBOX blob_box;                  //blob bounding box
272 
273   move(FCOORD (0.0f, 0.0f - bln_baseline_offset));
274   blob_box = bounding_box ();
275   blob_x_left = blob_box.left ();
276   scale (1.0 / denorm->scale_at_x (blob_x_left));
277   move (FCOORD (denorm->origin (),
278     denorm->yshift_at_x (blob_x_left)));
279 }
280 
281 
282 /**********************************************************************
283  * PBLOB::move
284  *
285  * Move PBLOB by vector
286  **********************************************************************/
287 
move(const FCOORD vec)288 void PBLOB::move(                  // reposition blob
289                  const FCOORD vec  // by vector
290                 ) {
291   OUTLINE_IT it(&outlines);  // iterator
292 
293   for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
294     it.data ()->move (vec);      // move each outline
295 }
296 
297 
298 /**********************************************************************
299  * PBLOB::scale
300  *
301  * Scale PBLOB by float multiplier
302  **********************************************************************/
303 
scale(const float f)304 void PBLOB::scale(               // scale blob
305                   const float f  // by multiplier
306                  ) {
307   OUTLINE_IT it(&outlines);  // iterator
308 
309   for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
310     it.data ()->scale (f);       // scale each outline
311 }
312 
313 
314 /**********************************************************************
315  * PBLOB::scale
316  *
317  * Scale PBLOB by float multiplier
318  **********************************************************************/
319 
scale(const FCOORD vec)320 void PBLOB::scale(                  // scale blob
321                   const FCOORD vec  // by multiplier
322                  ) {
323   OUTLINE_IT it(&outlines);  // iterator
324 
325   for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
326     it.data ()->scale (vec);     // scale each outline
327 }
328 
329 /**********************************************************************
330  * PBLOB::rotate
331  *
332  * Rotate PBLOB 90 deg anticlockwise about the origin.
333  **********************************************************************/
334 
rotate()335 void PBLOB::rotate() {  // Rotate 90 deg anti
336   rotate(FCOORD(0.0f, 1.0f));
337 }
338 
339 /**********************************************************************
340  * PBLOB::rotate
341  *
342  * Rotate PBLOB by the given rotation about the origin.
343  * The rotation is defined to be (cos a, sin a) where a is the anticlockwise
344  * rotation angle (in units appropriate for cos, sin).
345  * Alternatively think of multiplication by the complex number
346  * rotation = z = (x + iy), with |z| = 1.
347  **********************************************************************/
rotate(const FCOORD & rotation)348 void PBLOB::rotate(const FCOORD& rotation) {  // Rotate by given rotation.
349   OUTLINE_IT it(&outlines);
350 
351   for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
352     it.data()->rotate(rotation);     // Rotate each outline.
353   }
354 }
355 
356 /**********************************************************************
357  * PBLOB::plot
358  *
359  * Draw the PBLOB in the given colour.
360  **********************************************************************/
361 
362 #ifndef GRAPHICS_DISABLED
plot(ScrollView * window,ScrollView::Color blob_colour,ScrollView::Color child_colour)363 void PBLOB::plot(                     //draw it
364                  ScrollView* window,       //window to draw in
365                  ScrollView::Color blob_colour,  //main colour
366                  ScrollView::Color child_colour  //for holes
367                 ) {
368   plot_outline_list(&outlines, window, blob_colour, child_colour);
369 }
370 #endif
371