00001
00020 #include "mfcpch.h"
00021 #ifdef __UNIX__
00022 #include <assert.h>
00023 #endif
00024 #include "underlin.h"
00025
00027 #define PROJECTION_MARGIN 10
00028 #define EXTERN
00029
00032 EXTERN double_VAR (textord_underline_offset, 0.1, "Fraction of x to ignore");
00033 EXTERN BOOL_VAR (textord_restore_underlines, TRUE,
00034 "Chop underlines & put back");
00042 void restore_underlined_blobs(
00043 TO_BLOCK *block
00044 ) {
00045 INT16 chop_coord;
00046 BOX blob_box;
00047 BLOBNBOX *u_line;
00048 TO_ROW *row;
00049 ICOORDELT_LIST chop_cells;
00050
00051 BLOBNBOX_LIST residual_underlines;
00052 OUTLINE_LIST left_outlines;
00053 OUTLINE_LIST right_outlines;
00054 C_OUTLINE_LIST left_coutlines;
00055 C_OUTLINE_LIST right_coutlines;
00056 ICOORDELT_IT cell_it = &chop_cells;
00057
00058 BLOBNBOX_IT under_it = &block->underlines;
00059 BLOBNBOX_IT ru_it = &residual_underlines;
00060
00061 if (block->get_rows()->empty())
00062 return;
00063 for (under_it.mark_cycle_pt (); !under_it.cycled_list ();
00064 under_it.forward ()) {
00065 u_line = under_it.extract ();
00066 blob_box = u_line->bounding_box ();
00067 row = most_overlapping_row (block->get_rows (), u_line);
00068 find_underlined_blobs (u_line, &row->baseline, row->xheight,
00069 row->xheight * textord_underline_offset,
00070 &chop_cells);
00071 cell_it.set_to_list (&chop_cells);
00072 for (cell_it.mark_cycle_pt (); !cell_it.cycled_list ();
00073 cell_it.forward ()) {
00074 chop_coord = cell_it.data ()->x ();
00075 if (cell_it.data ()->y () - chop_coord > textord_fp_chop_error + 1) {
00076 split_to_blob (u_line, chop_coord,
00077 textord_fp_chop_error + 0.5,
00078 &left_outlines, &left_coutlines,
00079 &right_outlines, &right_coutlines);
00080 if (!left_outlines.empty ())
00081 ru_it.
00082 add_after_then_move (new
00083 BLOBNBOX (new PBLOB (&left_outlines)));
00084 else if (!left_coutlines.empty ())
00085 ru_it.
00086 add_after_then_move (new
00087 BLOBNBOX (new
00088 C_BLOB (&left_coutlines)));
00089
00090 chop_coord = cell_it.data ()->y ();
00091 split_to_blob (NULL, chop_coord,
00092 textord_fp_chop_error + 0.5,
00093 &left_outlines, &left_coutlines,
00094 &right_outlines, &right_coutlines);
00095 if (!left_outlines.empty ())
00096 row->insert_blob (new BLOBNBOX (new PBLOB (&left_outlines)));
00097 else if (!left_coutlines.empty ())
00098 row->
00099 insert_blob (new BLOBNBOX (new C_BLOB (&left_coutlines)));
00100 else {
00101 ASSERT_HOST(FALSE);
00102 fprintf (stderr,
00103 "Error:no outlines after chopping from %d to %d from (%d,%d)->(%d,%d)\n",
00104 cell_it.data ()->x (), cell_it.data ()->y (),
00105 blob_box.left (), blob_box.bottom (),
00106 blob_box.right (), blob_box.top ());
00107 }
00108 u_line = NULL;
00109 }
00110 delete cell_it.extract ();
00111 }
00112 if (!right_outlines.empty () || !right_coutlines.empty ()) {
00113 split_to_blob (NULL, blob_box.right (),
00114 textord_fp_chop_error + 0.5,
00115 &left_outlines, &left_coutlines,
00116 &right_outlines, &right_coutlines);
00117 if (!left_outlines.empty ())
00118 ru_it.
00119 add_after_then_move (new BLOBNBOX (new PBLOB (&left_outlines)));
00120 else if (!left_coutlines.empty ())
00121 ru_it.
00122 add_after_then_move (new
00123 BLOBNBOX (new C_BLOB (&left_coutlines)));
00124 }
00125 if (u_line != NULL) {
00126 if (u_line->blob() != NULL)
00127 delete u_line->blob();
00128 if (u_line->cblob() != NULL)
00129 delete u_line->cblob();
00130 delete u_line;
00131 }
00132 }
00133 if (!ru_it.empty ()) {
00134 ru_it.move_to_first ();
00135 for (ru_it.mark_cycle_pt (); !ru_it.cycled_list (); ru_it.forward ()) {
00136 under_it.add_after_then_move (ru_it.extract ());
00137 }
00138 }
00139 }
00140
00141
00147 TO_ROW *most_overlapping_row(
00148 TO_ROW_LIST *rows,
00149 BLOBNBOX *blob
00150 ) {
00151 INT16 x = (blob->bounding_box ().left ()
00152 + blob->bounding_box ().right ()) / 2;
00153 TO_ROW_IT row_it = rows;
00154 TO_ROW *row;
00155 TO_ROW *best_row;
00156 float overlap;
00157 float bestover;
00158
00159 best_row = NULL;
00160 bestover = (float) -MAX_INT32;
00161 if (row_it.empty ())
00162 return NULL;
00163 row = row_it.data ();
00164 row_it.mark_cycle_pt ();
00165 while (row->baseline.y (x) + row->descdrop > blob->bounding_box ().top ()
00166 && !row_it.cycled_list ()) {
00167 best_row = row;
00168 bestover =
00169 blob->bounding_box ().top () - row->baseline.y (x) + row->descdrop;
00170 row_it.forward ();
00171 row = row_it.data ();
00172 }
00173 while (row->baseline.y (x) + row->xheight + row->ascrise
00174 >= blob->bounding_box ().bottom () && !row_it.cycled_list ()) {
00175 overlap = row->baseline.y (x) + row->xheight + row->ascrise;
00176 if (blob->bounding_box ().top () < overlap)
00177 overlap = blob->bounding_box ().top ();
00178 if (blob->bounding_box ().bottom () >
00179 row->baseline.y (x) + row->descdrop)
00180 overlap -= blob->bounding_box ().bottom ();
00181 else
00182 overlap -= row->baseline.y (x) + row->descdrop;
00183 if (overlap > bestover) {
00184 bestover = overlap;
00185 best_row = row;
00186 }
00187 row_it.forward ();
00188 row = row_it.data ();
00189 }
00190 if (bestover < 0
00191 && row->baseline.y (x) + row->xheight + row->ascrise
00192 - blob->bounding_box ().bottom () > bestover)
00193 best_row = row;
00194 return best_row;
00195 }
00196
00197
00203 void find_underlined_blobs(
00204 BLOBNBOX *u_line,
00205 QSPLINE *baseline,
00206 float xheight,
00207 float baseline_offset,
00208 ICOORDELT_LIST *chop_cells
00209 ) {
00210 INT16 x, y;
00211 ICOORD blob_chop;
00212 BOX blob_box = u_line->bounding_box ();
00213
00214 ICOORDELT_IT cell_it = chop_cells;
00215 STATS upper_proj (blob_box.left (), blob_box.right () + 1);
00216 STATS middle_proj (blob_box.left (), blob_box.right () + 1);
00217 STATS lower_proj (blob_box.left (), blob_box.right () + 1);
00218 C_OUTLINE_IT out_it;
00219
00220 ASSERT_HOST (u_line->cblob () != NULL);
00221
00222 out_it.set_to_list (u_line->cblob ()->out_list ());
00223 for (out_it.mark_cycle_pt (); !out_it.cycled_list (); out_it.forward ()) {
00224 vertical_cunderline_projection (out_it.data (),
00225 baseline, xheight, baseline_offset,
00226 &lower_proj, &middle_proj, &upper_proj);
00227 }
00228
00229 for (x = blob_box.left (); x < blob_box.right (); x++) {
00230 if (middle_proj.pile_count (x) > 0) {
00231 for (y = x + 1;
00232 y < blob_box.right () && middle_proj.pile_count (y) > 0; y++);
00233 blob_chop = ICOORD (x, y);
00234 cell_it.add_after_then_move (new ICOORDELT (blob_chop));
00235 x = y;
00236 }
00237 }
00238 }
00239
00240
00247 void vertical_cunderline_projection(
00248 C_OUTLINE *outline,
00249 QSPLINE *baseline,
00250 float xheight,
00251 float baseline_offset,
00252 STATS *lower_proj,
00253 STATS *middle_proj,
00254 STATS *upper_proj
00255 ) {
00256 ICOORD pos;
00257 ICOORD step;
00258 INT16 lower_y, upper_y;
00259 INT32 length;
00260 INT16 stepindex;
00261 C_OUTLINE_IT out_it = outline->child ();
00262
00263 pos = outline->start_pos ();
00264 length = outline->pathlength ();
00265 for (stepindex = 0; stepindex < length; stepindex++) {
00266 step = outline->step (stepindex);
00267 if (step.x () > 0) {
00268 lower_y =
00269 (INT16) floor (baseline->y (pos.x ()) + baseline_offset + 0.5);
00270 upper_y =
00271 (INT16) floor (baseline->y (pos.x ()) + baseline_offset +
00272 xheight + 0.5);
00273 if (pos.y () >= lower_y) {
00274 lower_proj->add (pos.x (), -lower_y);
00275 if (pos.y () >= upper_y) {
00276 middle_proj->add (pos.x (), lower_y - upper_y);
00277 upper_proj->add (pos.x (), upper_y - pos.y ());
00278 }
00279 else
00280 middle_proj->add (pos.x (), lower_y - pos.y ());
00281 }
00282 else
00283 lower_proj->add (pos.x (), -pos.y ());
00284 }
00285 else if (step.x () < 0) {
00286 lower_y =
00287 (INT16) floor (baseline->y (pos.x () - 1) + baseline_offset +
00288 0.5);
00289 upper_y =
00290 (INT16) floor (baseline->y (pos.x () - 1) + baseline_offset +
00291 xheight + 0.5);
00292 if (pos.y () >= lower_y) {
00293 lower_proj->add (pos.x () - 1, lower_y);
00294 if (pos.y () >= upper_y) {
00295 middle_proj->add (pos.x () - 1, upper_y - lower_y);
00296 upper_proj->add (pos.x () - 1, pos.y () - upper_y);
00297 }
00298 else
00299 middle_proj->add (pos.x () - 1, pos.y () - lower_y);
00300 }
00301 else
00302 lower_proj->add (pos.x () - 1, pos.y ());
00303 }
00304 pos += step;
00305 }
00306
00307 for (out_it.mark_cycle_pt (); !out_it.cycled_list (); out_it.forward ()) {
00308 vertical_cunderline_projection (out_it.data (),
00309 baseline, xheight, baseline_offset,
00310 lower_proj, middle_proj, upper_proj);
00311 }
00312 }