00001 
00020 #include "mfcpch.h"
00021 #include          "blckerr.h"
00022 #include          "linlsq.h"
00023 #include          "werd.h"
00024 
00025 #define FIRST_COLOUR    RED      //first rainbow colour
00026                                  
00027 #define LAST_COLOUR     AQUAMARINE
00028 #define CHILD_COLOUR    BROWN    //colour of children
00029 
00030 const ERRCODE CANT_SCALE_EDGESTEPS =
00031 "Attempted to scale an edgestep format word";
00032 
00033 #define EXTERN
00034 
00037 EXTERN BOOL_VAR (bln_numericmode, 0, "Optimize for numbers");
00038 EXTERN INT_VAR (bln_x_height, 128, "Baseline Normalisation X-height");
00039 EXTERN INT_VAR (bln_baseline_offset, 64, "Baseline Norm. offset of baseline");
00040 EXTERN double_VAR (bln_blshift_maxshift, -1.0,
00041 "Fraction of xh before shifting");
00042 EXTERN double_VAR (bln_blshift_xfraction, 0.75,
00043 "Size fraction of xh before shifting");
00046 ELISTIZE_S (WERD)
00047 
00048 
00074 WERD::WERD (                     
00075 C_BLOB_LIST * blob_list,         
00076 UINT8 blank_count,               
00077 const char *text                 
00078 ):
00079 flags (0),
00080 correct(text) { 
00081   C_BLOB_IT start_it = blob_list;
00082   C_BLOB_IT end_it = blob_list;  
00083                                  
00084   C_BLOB_IT rej_cblob_it = &rej_cblobs;
00085   C_OUTLINE_IT c_outline_it;     
00086   BOOL8 blob_inverted;
00087   BOOL8 reject_blob;
00088   INT16 inverted_vote = 0;
00089   INT16 non_inverted_vote = 0;
00090 
00091   while (!end_it.at_last ())
00092     end_it.forward ();           
00093                                  
00094   cblobs.assign_to_sublist (&start_it, &end_it);
00095   blanks = blank_count;
00096 
00097     
00098   start_it.set_to_list (&cblobs);
00099   if (start_it.empty ())
00100     return;
00101   for (start_it.mark_cycle_pt ();
00102   !start_it.cycled_list (); start_it.forward ()) {
00103     c_outline_it.set_to_list (start_it.data ()->out_list ());
00104     blob_inverted = c_outline_it.data ()->flag (COUT_INVERSE);
00105     reject_blob = FALSE;
00106     for (c_outline_it.mark_cycle_pt ();
00107       !c_outline_it.cycled_list () && !reject_blob;
00108     c_outline_it.forward ()) {
00109       reject_blob =
00110         c_outline_it.data ()->flag (COUT_INVERSE) != blob_inverted;
00111     }
00112     if (reject_blob)
00113       rej_cblob_it.add_after_then_move (start_it.extract ());
00114     else {
00115       if (blob_inverted)
00116         inverted_vote++;
00117       else
00118         non_inverted_vote++;
00119     }
00120   }
00121 
00122   flags.set_bit (W_INVERSE, (inverted_vote > non_inverted_vote));
00123 
00124   start_it.set_to_list (&cblobs);
00125   if (start_it.empty ())
00126     return;
00127   for (start_it.mark_cycle_pt ();
00128   !start_it.cycled_list (); start_it.forward ()) {
00129     c_outline_it.set_to_list (start_it.data ()->out_list ());
00130     if (c_outline_it.data ()->flag (COUT_INVERSE) != flags.bit (W_INVERSE))
00131       rej_cblob_it.add_after_then_move (start_it.extract ());
00132   }
00133 }
00134 
00135 
00141 WERD::WERD (                     
00142 PBLOB_LIST * blob_list,          
00143 UINT8 blank_count,               
00144 const char *text                 
00145 ):
00146 flags (0),
00147 correct(text) { 
00148   PBLOB_IT start_it = blob_list; 
00149   PBLOB_IT end_it = blob_list;   
00150 
00151   while (!end_it.at_last ())
00152     end_it.forward ();           
00153   ((PBLOB_LIST *) (&cblobs))->assign_to_sublist (&start_it, &end_it);
00154   
00155                                  
00156   flags.set_bit (W_POLYGON, TRUE);
00157   blanks = blank_count;
00158   
00159 }
00160 
00161 
00167 WERD::WERD (                     
00168 PBLOB_LIST * blob_list,          
00169 WERD * clone                     
00170 ):flags (clone->flags), correct (clone->correct) {
00171   PBLOB_IT start_it = blob_list; 
00172   PBLOB_IT end_it = blob_list;   
00173 
00174   while (!end_it.at_last ())
00175     end_it.forward ();           
00176   ((PBLOB_LIST *) (&cblobs))->assign_to_sublist (&start_it, &end_it);
00177   
00178   blanks = clone->blanks;
00179   
00180 }
00181 
00182 
00188 WERD::WERD (                     
00189 C_BLOB_LIST * blob_list,         
00190 WERD * clone                     
00191 ):flags (clone->flags), correct (clone->correct) {
00192   C_BLOB_IT start_it = blob_list;
00193   C_BLOB_IT end_it = blob_list;  
00194 
00195   while (!end_it.at_last ())
00196     end_it.forward ();           
00197   ((C_BLOB_LIST *) (&cblobs))->assign_to_sublist (&start_it, &end_it);
00198   
00199   blanks = clone->blanks;
00200   
00201 }
00202 
00203 
00209 WERD *WERD::poly_copy(               
00210                       float xheight  
00211                      ) {
00212   PBLOB *blob;                   
00213   WERD *result = new WERD;       
00214   C_BLOB_IT src_it = &cblobs;    
00215   
00216   PBLOB_IT dest_it = (PBLOB_LIST *) (&result->cblobs);
00217   
00218 
00219   if (flags.bit (W_POLYGON)) {
00220     *result = *this;             
00221   }
00222   else {
00223     result->flags = flags;
00224     result->correct = correct;   
00225     result->dummy = dummy;
00226     if (!src_it.empty ()) {
00227       
00228       
00229       
00230       
00231       
00232       
00233       
00234       
00235       
00236       
00237       
00238       
00239       
00240       
00241       do {
00242         blob = new PBLOB (src_it.data (), xheight);
00243         
00244                                  
00245         dest_it.add_after_then_move (blob);
00246         src_it.forward ();
00247       }
00248       while (!src_it.at_first ());
00249       
00250     }
00251     if (!rej_cblobs.empty ()) {
00252       
00253       src_it.set_to_list (&rej_cblobs);
00254       dest_it = (PBLOB_LIST *) (&result->rej_cblobs);
00255       do {
00256                                  
00257         blob = new PBLOB (src_it.data (), xheight);
00258                                  
00259         dest_it.add_after_then_move (blob);
00260         src_it.forward ();
00261       }
00262       while (!src_it.at_first ());
00263     }
00264                                  
00265     result->flags.set_bit (W_POLYGON, TRUE);
00266     result->blanks = blanks;
00267   }
00268   return result;
00269 }
00270 
00271 
00283 BOX WERD::bounding_box() {  
00284   BOX box;                       
00285                                  
00286   C_BLOB_IT rej_cblob_it = &rej_cblobs;
00287 
00288   for (rej_cblob_it.mark_cycle_pt ();
00289   !rej_cblob_it.cycled_list (); rej_cblob_it.forward ()) {
00290     box += rej_cblob_it.data ()->bounding_box ();
00291   }
00292 
00293   if (flags.bit (W_POLYGON)) {
00294                                  
00295     PBLOB_IT it = (PBLOB_LIST *) (&cblobs);
00296 
00297     for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
00298       box += it.data ()->bounding_box ();
00299     }
00300   }
00301   else {
00302     C_BLOB_IT it = &cblobs;      
00303 
00304     for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
00305       box += it.data ()->bounding_box ();
00306     }
00307   }
00308   return box;
00309 }
00310 
00311 
00317 void WERD::move(                  
00318                 const ICOORD vec  
00319                ) {
00320   PBLOB_IT blob_it ((PBLOB_LIST *) & cblobs);
00321   
00322   
00323   C_BLOB_IT cblob_it(&cblobs);  
00324 
00325   if (flags.bit (W_POLYGON))
00326     for (blob_it.mark_cycle_pt ();
00327     !blob_it.cycled_list (); blob_it.forward ())
00328   blob_it.data ()->move (vec);
00329   
00330   
00331   
00332   
00333   
00334   else
00335     for (cblob_it.mark_cycle_pt ();
00336     !cblob_it.cycled_list (); cblob_it.forward ())
00337   cblob_it.data ()->move (vec);
00338 }
00339 
00340 
00344 void WERD::scale(               
00345                  const float f  
00346                 ) {
00347   PBLOB_IT blob_it ((PBLOB_LIST *) & cblobs);
00348   
00349   
00350 
00351   if (flags.bit (W_POLYGON))
00352     for (blob_it.mark_cycle_pt ();
00353     !blob_it.cycled_list (); blob_it.forward ())
00354   blob_it.data ()->scale (f);
00355   
00356   
00357   
00358   
00359   
00360   else
00361     CANT_SCALE_EDGESTEPS.error ("WERD::scale", ABORT, NULL);
00362 }
00363 
00364 
00368 void WERD::join_on(              
00369                    WERD *&other  
00370                   ) {
00371   PBLOB_IT blob_it ((PBLOB_LIST *) & cblobs);
00372   
00373   PBLOB_IT src_it ((PBLOB_LIST *) & other->cblobs);
00374   C_BLOB_IT rej_cblob_it(&rej_cblobs); 
00375   C_BLOB_IT src_rej_it (&other->rej_cblobs);
00376 
00377   while (!src_it.empty ()) {
00378     blob_it.add_to_end (src_it.extract ());
00379     src_it.forward ();
00380   }
00381   while (!src_rej_it.empty ()) {
00382     rej_cblob_it.add_to_end (src_rej_it.extract ());
00383     src_rej_it.forward ();
00384   }
00385 }
00386 
00387 
00391 void WERD::copy_on(              
00392                    WERD *&other  
00393                   ) {
00394   if (flags.bit (W_POLYGON)) {
00395     PBLOB_IT blob_it ((PBLOB_LIST *) & cblobs);
00396     
00397     PBLOB_LIST blobs;
00398 
00399     blobs.deep_copy ((PBLOB_LIST *) (&other->cblobs));
00400     blob_it.move_to_last ();
00401     blob_it.add_list_after (&blobs);
00402   }
00403   
00404   
00405   
00406   
00407 
00408   
00409   
00410   
00411   
00412   else {
00413     C_BLOB_IT c_blob_it(&cblobs); 
00414     C_BLOB_LIST c_blobs;
00415 
00416     c_blobs.deep_copy (&other->cblobs);
00417     c_blob_it.move_to_last ();
00418     c_blob_it.add_list_after (&c_blobs);
00419   }
00420   if (!other->rej_cblobs.empty ()) {
00421     C_BLOB_IT rej_c_blob_it(&rej_cblobs); 
00422     C_BLOB_LIST new_rej_c_blobs;
00423 
00424     new_rej_c_blobs.deep_copy (&other->rej_cblobs);
00425     rej_c_blob_it.move_to_last ();
00426     rej_c_blob_it.add_list_after (&new_rej_c_blobs);
00427   }
00428 }
00429 
00430 
00441 void WERD::baseline_normalise( 
00442                               ROW *row,
00443                               DENORM *denorm  
00444                              ) {
00445   baseline_normalise_x (row, row->x_height (), denorm);
00446   
00447 }
00448 
00449 
00463 void WERD::baseline_normalise_x(                 
00464                                 ROW *row,
00465                                 float x_height,  
00466                                 DENORM *denorm   
00467                                ) {
00468   BOOL8 using_row;               
00469   float blob_x_centre;           
00470   float blob_offset;             
00471   float top_offset;              
00472   float blob_x_height;           
00473   INT16 segments;                
00474   INT16 segment;                 
00475   DENORM_SEG *segs;              
00476   float mean_x;                  
00477   INT32 x_count;                 
00478   BOX word_box = bounding_box ();
00479   BOX blob_box;                  
00480   PBLOB_IT blob_it ((PBLOB_LIST *) & cblobs);
00481   
00482   PBLOB *blob;
00483   LLSQ line;                     
00484   double line_m, line_c;         
00485                                  
00486   DENORM antidote (word_box.left () +
00487 
00488     (word_box.right () - word_box.left ()) / 2.0,
00489     bln_x_height / x_height, row);
00490 
00491   if (!flags.bit (W_POLYGON)) {
00492     WRONG_WORD.error ("WERD::baseline_normalise", ABORT,
00493       "Need to poly approx");
00494   }
00495 
00496   if (flags.bit (W_NORMALIZED)) {
00497     WRONG_WORD.error ("WERD::baseline_normalise", ABORT,
00498       "Baseline unnormalised");
00499   }
00500 
00501   if (bln_numericmode) {
00502     segs = new DENORM_SEG[blob_it.length ()];
00503     segments = 0;
00504     float factor;  
00505     for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();
00506     blob_it.forward ()) {
00507       blob = blob_it.data ();
00508       blob_box = blob->bounding_box ();
00509       blob->move (FCOORD (-antidote.origin (),
00510         -blob_box.bottom ()));
00511       factor = bln_x_height * 4.0f / (3 * blob_box.height ());
00512       
00513       
00514       if (factor < antidote.scale())
00515         factor = antidote.scale();
00516       else if (factor > antidote.scale() * 1.5f)
00517         factor = antidote.scale() * 1.5f;
00518       blob->scale (factor);
00519       blob->move (FCOORD (0.0, bln_baseline_offset));
00520       segs[segments].xstart = blob->bounding_box().left();
00521       segs[segments].ycoord = blob_box.bottom();
00522       segs[segments++].scale_factor = factor;
00523     }
00524     antidote = DENORM (antidote.origin (), antidote.scale (),
00525       0.0f, 0.0f, segments, segs, true, row);
00526     delete [] segs;
00527 
00528                                  
00529     blob_it.set_to_list ((PBLOB_LIST *) & rej_cblobs);
00530     for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();
00531     blob_it.forward ()) {
00532       blob = blob_it.data ();
00533       blob_box = blob->bounding_box ();
00534       blob->move (FCOORD (-antidote.origin (),
00535                           -blob_box.bottom ()));
00536       blob->scale (bln_x_height * 4.0f / (3 * blob_box.height ()));
00537       blob->move (FCOORD (0.0, bln_baseline_offset));
00538     }
00539   }
00540   else if (bln_blshift_maxshift < 0) {
00541     for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();
00542     blob_it.forward ()) {
00543       blob = blob_it.data ();
00544       blob_box = blob->bounding_box ();
00545       blob_x_centre = blob_box.left () +
00546         (blob_box.right () - blob_box.left ()) / 2.0;
00547       blob->move (FCOORD (-antidote.origin (),
00548         -(row->base_line (blob_x_centre))));
00549       blob->scale (antidote.scale ());
00550       blob->move (FCOORD (0.0, bln_baseline_offset));
00551     }
00552 
00553                                  
00554     blob_it.set_to_list ((PBLOB_LIST *) & rej_cblobs);
00555     for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();
00556     blob_it.forward ()) {
00557       blob = blob_it.data ();
00558       blob_box = blob->bounding_box ();
00559       blob_x_centre = blob_box.left () +
00560         (blob_box.right () - blob_box.left ()) / 2.0;
00561       blob->move (FCOORD (-antidote.origin (),
00562         -(row->base_line (blob_x_centre))));
00563       blob->scale (antidote.scale ());
00564       blob->move (FCOORD (0.0, bln_baseline_offset));
00565     }
00566 
00567   }
00568   else {
00569     mean_x = x_height;
00570     x_count = 1;
00571     segs = new DENORM_SEG[blob_it.length ()];
00572     segments = 0;
00573     for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();
00574     blob_it.forward ()) {
00575       blob = blob_it.data ();
00576       blob_box = blob->bounding_box ();
00577       if (blob_box.height () > bln_blshift_xfraction * x_height) {
00578         blob_x_centre = blob_box.left () +
00579           (blob_box.right () - blob_box.left ()) / 2.0;
00580         blob_offset =
00581           blob_box.bottom () - row->base_line (blob_x_centre);
00582         top_offset = blob_offset + blob_box.height () - x_height - 1;
00583         blob_x_height = top_offset + x_height;
00584         if (top_offset < 0)
00585           top_offset = -top_offset;
00586         if (blob_offset < 0)
00587           blob_offset = -blob_offset;
00588         if (blob_offset < bln_blshift_maxshift * x_height) {
00589           segs[segments].ycoord = blob_box.bottom ();
00590           line.add (blob_x_centre, blob_box.bottom ());
00591           if (top_offset < bln_blshift_maxshift * x_height) {
00592             segs[segments].scale_factor = blob_box.height () - 1.0f;
00593             x_count++;
00594           }
00595           else
00596             segs[segments].scale_factor = 0.0f;
00597           
00598         }
00599         else {
00600                                  
00601           segs[segments].ycoord = -MAX_INT32;
00602           if (top_offset < bln_blshift_maxshift * x_height) {
00603             segs[segments].scale_factor = blob_x_height;
00604             x_count++;
00605           }
00606           else
00607             segs[segments].scale_factor = 0.0f;
00608           
00609         }
00610       }
00611       else {
00612         segs[segments].scale_factor = 0.0f;
00613         segs[segments].ycoord = -MAX_INT32;
00614       }
00615       segs[segments].xstart = blob_box.left ();
00616       segments++;
00617     }
00618     using_row = line.count () <= 1;
00619     if (!using_row) {
00620       line_m = line.m ();
00621       line_c = line.c (line_m);
00622     }
00623     else
00624       line_m = line_c = 0;
00625     segments = 0;
00626     for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();
00627     blob_it.forward ()) {
00628       blob = blob_it.data ();
00629       blob_box = blob->bounding_box ();
00630       blob_x_centre = blob_box.left () +
00631         (blob_box.right () - blob_box.left ()) / 2.0;
00632       if (segs[segments].ycoord == -MAX_INT32
00633       && segs[segments].scale_factor != 0 && !using_row) {
00634         blob_offset = line_m * blob_x_centre + line_c;
00635         segs[segments].scale_factor = blob_box.top () - blob_offset;
00636       }
00637       if (segs[segments].scale_factor != 0)
00638         mean_x += segs[segments].scale_factor;
00639       segments++;
00640     }
00641     mean_x /= x_count;
00642     
00643     
00644     segments = 0;
00645     for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();
00646     blob_it.forward ()) {
00647       blob = blob_it.data ();
00648       blob_box = blob->bounding_box ();
00649       blob_x_centre = blob_box.left () +
00650         (blob_box.right () - blob_box.left ()) / 2.0;
00651       if (segs[segments].ycoord != -MAX_INT32)
00652         blob_offset = (float) segs[segments].ycoord;
00653       else if (using_row)
00654         blob_offset = row->base_line (blob_x_centre);
00655       else
00656         blob_offset = line_m * blob_x_centre + line_c;
00657       if (segs[segments].scale_factor == 0)
00658         segs[segments].scale_factor = mean_x;
00659       segs[segments].scale_factor =
00660         bln_x_height / segs[segments].scale_factor;
00661       
00662       
00663       
00664       blob->move (FCOORD (-antidote.origin (), -blob_offset));
00665       blob->
00666         scale (FCOORD (antidote.scale (), segs[segments].scale_factor));
00667       blob->move (FCOORD (0.0, bln_baseline_offset));
00668       segments++;
00669     }
00670 
00671                                  
00672     blob_it.set_to_list ((PBLOB_LIST *) & rej_cblobs);
00673     segment = 0;
00674     for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();
00675     blob_it.forward ()) {
00676       blob = blob_it.data ();
00677       blob_box = blob->bounding_box ();
00678       blob_x_centre = blob_box.left () +
00679         (blob_box.right () - blob_box.left ()) / 2.0;
00680       while (segment < segments - 1
00681         && segs[segment + 1].xstart <= blob_x_centre)
00682         segment++;
00683       if (segs[segment].ycoord != -MAX_INT32)
00684         blob_offset = (float) segs[segment].ycoord;
00685       else if (using_row)
00686         blob_offset = row->base_line (blob_x_centre);
00687       else
00688         blob_offset = line_m * blob_x_centre + line_c;
00689       blob->move (FCOORD (-antidote.origin (), -blob_offset));
00690       blob->
00691         scale (FCOORD (antidote.scale (), segs[segment].scale_factor));
00692       blob->move (FCOORD (0.0, bln_baseline_offset));
00693     }
00694     if (line.count () > 0 || x_count > 1)
00695       antidote = DENORM (antidote.origin (), antidote.scale (),
00696         line_m, line_c, segments, segs, using_row, row);
00697     delete[]segs;
00698   }
00699   if (denorm != NULL)
00700     *denorm = antidote;
00701                                  
00702   flags.set_bit (W_NORMALIZED, TRUE);
00703 }
00704 
00705 
00717 void WERD::baseline_denormalise(       
00718                                 const DENORM *denorm  
00719                                ) {
00720   PBLOB_IT blob_it ((PBLOB_LIST *) & cblobs);
00721   
00722   PBLOB *blob;
00723 
00724   if (!flags.bit (W_NORMALIZED)) {
00725     WRONG_WORD.error ("WERD::baseline_denormalise", ABORT,
00726       "Baseline normalised");
00727   }
00728 
00729   for (blob_it.mark_cycle_pt (); !blob_it.cycled_list (); blob_it.forward ()) {
00730     blob = blob_it.data ();
00731                                  
00732     blob->baseline_denormalise (denorm);
00733   }
00734 
00735                                  
00736   blob_it.set_to_list ((PBLOB_LIST *) & rej_cblobs);
00737   for (blob_it.mark_cycle_pt (); !blob_it.cycled_list (); blob_it.forward ()) {
00738     blob = blob_it.data ();
00739                                  
00740     blob->baseline_denormalise (denorm);
00741   }
00742 
00743                                  
00744   flags.set_bit (W_NORMALIZED, FALSE);
00745 }
00746 
00747 
00751 void WERD::print(        
00752                  FILE *  
00753                 ) {
00754   tprintf ("Blanks= %d\n", blanks);
00755   bounding_box ().print ();
00756   tprintf ("Flags = %d = 0%o\n", flags.val, flags.val);
00757   tprintf ("   W_SEGMENTED = %s\n",
00758     flags.bit (W_SEGMENTED) ? "TRUE" : "FALSE ");
00759   tprintf ("   W_ITALIC = %s\n", flags.bit (W_ITALIC) ? "TRUE" : "FALSE ");
00760   tprintf ("   W_BOL = %s\n", flags.bit (W_BOL) ? "TRUE" : "FALSE ");
00761   tprintf ("   W_EOL = %s\n", flags.bit (W_EOL) ? "TRUE" : "FALSE ");
00762   tprintf ("   W_NORMALIZED = %s\n",
00763     flags.bit (W_NORMALIZED) ? "TRUE" : "FALSE ");
00764   tprintf ("   W_POLYGON = %s\n", flags.bit (W_POLYGON) ? "TRUE" : "FALSE ");
00765   tprintf ("   W_LINEARC = %s\n", flags.bit (W_LINEARC) ? "TRUE" : "FALSE ");
00766   tprintf ("   W_DONT_CHOP = %s\n",
00767     flags.bit (W_DONT_CHOP) ? "TRUE" : "FALSE ");
00768   tprintf ("   W_REP_CHAR = %s\n",
00769     flags.bit (W_REP_CHAR) ? "TRUE" : "FALSE ");
00770   tprintf ("   W_FUZZY_SP = %s\n",
00771     flags.bit (W_FUZZY_SP) ? "TRUE" : "FALSE ");
00772   tprintf ("   W_FUZZY_NON = %s\n",
00773     flags.bit (W_FUZZY_NON) ? "TRUE" : "FALSE ");
00774   tprintf ("Correct= %s\n", correct.string ());
00775   tprintf ("Rejected cblob count = %d\n", rej_cblobs.length ());
00776 }
00777 
00778 
00782 #ifndef GRAPHICS_DISABLED
00783 void WERD::plot(                
00784                 WINDOW window,  
00785                 COLOUR colour,  
00786                 BOOL8 solid     
00787                ) {
00788   if (flags.bit (W_POLYGON)) {
00789                                  
00790     PBLOB_IT it = (PBLOB_LIST *) (&cblobs);
00791 
00792     for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
00793       it.data ()->plot (window, colour, colour);
00794     }
00795   }
00796   
00797   
00798   
00799 
00800   
00801   
00802   
00803   
00804   
00805   else {
00806     C_BLOB_IT it = &cblobs;      
00807 
00808     for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
00809       it.data ()->plot (window, colour, colour);
00810     }
00811   }
00812   plot_rej_blobs(window, solid); 
00813 }
00814 #endif
00815 
00816 
00820 #ifndef GRAPHICS_DISABLED
00821 void WERD::plot(                
00822                 WINDOW window,  
00823                 BOOL8 solid     
00824                ) {
00825   COLOUR colour = FIRST_COLOUR;  
00826   if (flags.bit (W_POLYGON)) {
00827                                  
00828     PBLOB_IT it = (PBLOB_LIST *) (&cblobs);
00829 
00830     for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
00831       it.data ()->plot (window, colour, CHILD_COLOUR);
00832       colour = (COLOUR) (colour + 1);
00833       if (colour == LAST_COLOUR)
00834         colour = FIRST_COLOUR;   
00835     }
00836   }
00837   
00838   
00839   
00840 
00841   
00842   
00843   
00844   
00845   
00846   
00847   
00848   else {
00849     C_BLOB_IT it = &cblobs;      
00850 
00851     for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
00852       it.data ()->plot (window, colour, CHILD_COLOUR);
00853       colour = (COLOUR) (colour + 1);
00854       if (colour == LAST_COLOUR)
00855         colour = FIRST_COLOUR;   
00856     }
00857   }
00858   plot_rej_blobs(window, solid); 
00859 }
00860 #endif
00861 
00862 
00867 #ifndef GRAPHICS_DISABLED
00868 void WERD::plot_rej_blobs(                
00869                           WINDOW window,  
00870                           BOOL8 solid     
00871                          ) {
00872   if (flags.bit (W_POLYGON)) {
00873     PBLOB_IT it = (PBLOB_LIST *) (&rej_cblobs);
00874     
00875 
00876     for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
00877       it.data ()->plot (window, GREY, GREY);
00878     }
00879   }
00880   
00881   
00882   
00883   
00884   
00885   
00886   
00887   else {
00888     C_BLOB_IT it = &rej_cblobs;  
00889 
00890     for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
00891       it.data ()->plot (window, GREY, GREY);
00892     }
00893   }
00894 }
00895 #endif
00896 
00897 
00901 WERD *WERD::shallow_copy() {  
00902   WERD *new_word = new WERD;
00903 
00904   new_word->blanks = blanks;
00905   new_word->flags = flags;
00906   new_word->dummy = dummy;
00907   new_word->correct = correct;
00908   return new_word;
00909 }
00910 
00911 
00915 WERD & WERD::operator= (         
00916 const WERD & source              
00917 ) {
00918   this->ELIST_LINK::operator= (source);
00919   blanks = source.blanks;
00920   flags = source.flags;
00921   dummy = source.dummy;
00922   correct = source.correct;
00923   if (flags.bit (W_POLYGON)) {
00924     if (!cblobs.empty ())
00925       ((PBLOB_LIST *) (&cblobs))->clear ();
00926     ((PBLOB_LIST *) (&cblobs))->deep_copy ((PBLOB_LIST *) (&source.cblobs));
00927 
00928     if (!rej_cblobs.empty ())
00929       ((PBLOB_LIST *) (&rej_cblobs))->clear ();
00930     ((PBLOB_LIST *) (&rej_cblobs))->deep_copy ((PBLOB_LIST *) (&source.
00931       rej_cblobs));
00932 
00933   }
00934   
00935   
00936   
00937   
00938   
00939   
00940 
00941   
00942   
00943   
00944   
00945   else {
00946     if (!cblobs.empty ())
00947       cblobs.clear ();
00948     cblobs.deep_copy (&source.cblobs);
00949 
00950     if (!rej_cblobs.empty ())
00951       rej_cblobs.clear ();
00952     rej_cblobs.deep_copy (&source.rej_cblobs);
00953   }
00954   return *this;
00955 }
00956 
00957 
00958 
00959 
00960 
00961 
00962 int word_comparator(                     
00963                     const void *word1p,  
00964                     const void *word2p   
00965                    ) {
00966   WERD *
00967     word1 = *(WERD **) word1p;
00968   WERD *
00969     word2 = *(WERD **) word2p;
00970 
00971   return word1->bounding_box ().left () - word2->bounding_box ().left ();
00972 }