39 #include "config_auto.h"
46 "Debug on fixed pitch test");
48 "Turn off dp fixed pitch algorithm");
50 "Do even faster pitch algorithm");
52 "Write full metric stuff");
56 "Use correct answer for fixed/prop");
58 "Attempt whole doc/block fixed pitch");
61 "Ding rate for unbalanced char cells");
63 #define FIXED_WIDTH_MULTIPLE 5
64 #define BLOCK_STATS_CLUSTERS 10
65 #define MAX_ALLOWED_PITCH 100 //max pixel pitch.
76 TO_BLOCK_LIST *port_blocks,
87 #ifndef GRAPHICS_DISABLED
94 block_it.set_to_list (port_blocks);
96 for (block_it.mark_cycle_pt (); !block_it.cycled_list ();
97 block_it.forward ()) {
98 block = block_it.data ();
105 for (block_it.mark_cycle_pt (); !block_it.cycled_list ();
106 block_it.forward ()) {
107 block = block_it.data ();
115 for (block_it.mark_cycle_pt(); !block_it.cycled_list();
116 block_it.forward()) {
117 block = block_it.data ();
120 row_it.set_to_list (block->
get_rows ());
122 for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) {
123 row = row_it.data ();
124 fix_row_pitch(row, block, port_blocks, row_index, block_index);
129 #ifndef GRAPHICS_DISABLED
146 TO_BLOCK_LIST *blocks,
148 inT32 block_target) {
156 TO_BLOCK_IT block_it = blocks;
164 block_votes = like_votes = other_votes = 0;
171 for (block_it.mark_cycle_pt(); !block_it.cycled_list();
172 block_it.forward()) {
173 block = block_it.data();
177 row_it.set_to_list (block->
get_rows ());
178 for (row_it.mark_cycle_pt (); !row_it.cycled_list ();
180 row = row_it.data ();
194 if (block_index == block_target) {
249 else if (block_votes <= textord_words_veto_power && like_votes > 0) {
256 if (block_votes == 0 && like_votes == 0 && other_votes > 0
259 (
"Warning:row %d of block %d set prop with no like rows against trend\n",
260 row_target, block_target);
265 tprintf(
":b_votes=%d:l_votes=%d:o_votes=%d",
266 block_votes, like_votes, other_votes);
273 else if (block_votes == 0 && like_votes > 0)
277 (
"Warning:guessing pitch as xheight on row %d, block %d\n",
278 row_target, block_target);
319 tprintf (
"Block %d at (%d,%d)->(%d,%d)\n",
322 block_box.
right (), block_box.
top ());
333 if (!block->
get_rows ()->empty ()) {
336 #ifndef GRAPHICS_DISABLED
363 TO_ROW_IT row_it = block->
get_rows ();
366 for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) {
367 row = row_it.data ();
374 row_index, testing_on)) {
400 TO_BLOCK_LIST *port_blocks,
410 TO_BLOCK_IT block_it = port_blocks;
414 inT16 projection_left;
415 inT16 projection_right;
418 ICOORDELT_LIST *master_cells;
431 if (block_it.empty ()
435 shift_factor = gradient / (gradient * gradient + 1);
436 row_it.set_to_list (block_it.data ()->get_rows ());
437 master_x = row_it.data ()->projection_left;
438 master_y = row_it.data ()->baseline.y (master_x);
445 for (block_it.mark_cycle_pt (); !block_it.cycled_list ();
446 block_it.forward ()) {
447 block = block_it.data ();
448 row_it.set_to_list (block->
get_rows ());
449 for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) {
450 row = row_it.data ();
458 shift_factor * (master_y - row_y));
461 shift_factor * (master_y - row_y));
462 if (row_left < projection_left)
463 projection_left = row_left;
464 if (row_right > projection_right)
465 projection_right = row_right;
470 projection.
set_range (projection_left, projection_right);
472 for (block_it.mark_cycle_pt (); !block_it.cycled_list ();
473 block_it.forward ()) {
474 block = block_it.data ();
475 row_it.set_to_list (block->
get_rows ());
476 for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) {
477 row = row_it.data ();
481 shift_factor * (master_y - row_y));
489 row_it.set_to_list (block_it.data ()->get_rows ());
490 row = row_it.data ();
491 #ifndef GRAPHICS_DISABLED
496 final_pitch = pitches.
ile (0.5);
497 pitch = (
inT16) final_pitch;
499 tune_row_pitch (row, &projection, projection_left, projection_right,
500 pitch * 0.75, final_pitch, sp_sd, mid_cuts,
505 (
"try_doc:props=%d:fixed=%d:pitch=%d:final_pitch=%g:pitch_sd=%g:sp_sd=%g:sd/trc=%g:sd/p=%g:sd/trc/p=%g\n",
506 prop_blocks, fixed_blocks, pitch, final_pitch, pitch_sd, sp_sd,
507 pitch_sd / total_row_count, pitch_sd / pitch,
508 pitch_sd / total_row_count / pitch);
510 #ifndef GRAPHICS_DISABLED
513 for (block_it.mark_cycle_pt (); !block_it.cycled_list ();
514 block_it.forward ()) {
515 block = block_it.data ();
516 row_it.set_to_list (block->
get_rows ());
517 for (row_it.mark_cycle_pt (); !row_it.cycled_list ();
519 row = row_it.data ();
521 row_shift = shift_factor * (master_y - row_y);
562 inT32 maybe_fixed = 0;
563 inT32 maybe_prop = 0;
565 inT32 corr_fixed = 0;
568 TO_ROW_IT row_it = block->
get_rows ();
571 for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) {
572 row = row_it.data ();
602 else if (def_prop > def_fixed * textord_words_veto_power)
604 else if (def_fixed > 0 || def_prop > 0)
606 else if (maybe_fixed > maybe_prop * textord_words_veto_power)
608 else if (maybe_prop > maybe_fixed * textord_words_veto_power)
628 inT32 maybe_fixed = 0;
629 inT32 maybe_prop = 0;
631 inT32 corr_fixed = 0;
642 tprintf (
"Block %d has (%d,%d,%d)",
643 block_index, def_fixed, maybe_fixed, corr_fixed);
646 tprintf (
" fixed, (%d,%d,%d)", def_prop, maybe_prop, corr_prop);
649 tprintf (
" prop, %d dunno\n", dunno);
669 TO_ROW_IT row_it = block->
get_rows ();
671 for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) {
672 row = row_it.data ();
723 STATS gap_stats (0, maxwidth);
729 if (!blob_it.empty ()) {
730 prev_x = blob_it.data ()->bounding_box ().right ();
732 while (!blob_it.at_first ()) {
733 blob = blob_it.data ();
736 if (blob_box.
left () - prev_x < maxwidth)
737 gap_stats.
add (blob_box.
left () - prev_x, 1);
738 prev_x = blob_box.
right ();
749 gap_stats.
smooth (smooth_factor);
751 prev_count = cluster_count;
752 cluster_count = gap_stats.
cluster (lower, upper,
757 if (cluster_count < 1) {
760 for (gap_index = 0; gap_index < cluster_count; gap_index++)
761 gaps[gap_index] = cluster_stats[gap_index + 1].ile (0.5);
764 tprintf (
"cluster_count=%d:", cluster_count);
765 for (gap_index = 0; gap_index < cluster_count; gap_index++)
766 tprintf (
" %g(%d)", gaps[gap_index],
767 cluster_stats[gap_index + 1].get_total ());
770 qsort (gaps, cluster_count,
sizeof (
float),
sort_floats);
775 for (gap_index = 0; gap_index < cluster_count
776 && gaps[gap_index] < lower; gap_index++);
777 if (gap_index == 0) {
779 tprintf (
"No clusters below nonspace threshold!!\n");
780 if (cluster_count > 1) {
790 row->
pr_nonsp = gaps[gap_index - 1];
791 while (gap_index < cluster_count && gaps[gap_index] < upper)
793 if (gap_index == cluster_count) {
795 tprintf (
"No clusters above nonspace threshold!!\n");
804 for (gap_index = 0; gap_index < cluster_count
805 && gaps[gap_index] < upper; gap_index++);
806 if (gap_index == 0) {
808 tprintf (
"No clusters below space threshold!!\n");
813 row->
fp_nonsp = gaps[gap_index - 1];
814 if (gap_index == cluster_count) {
816 tprintf (
"No clusters above space threshold!!\n");
824 (
"Initial estimates:pr_nonsp=%g, pr_space=%g, fp_nonsp=%g, fp_space=%g\n",
858 STATS gap_stats (0, maxwidth);
860 STATS pitch_stats (0, maxwidth);
867 if (non_space > initial_pitch)
868 non_space = initial_pitch;
869 min_space = (initial_pitch + non_space) / 2;
872 initial_pitch, min_space,
TRUE,
FALSE, dm_gap)) {
874 dm_pitch_iqr = maxwidth * 2.0f;
875 dm_pitch = initial_pitch;
878 dm_gap_iqr = gap_stats.
ile (0.75) - gap_stats.
ile (0.25);
879 dm_pitch_iqr = pitch_stats.
ile (0.75) - pitch_stats.
ile (0.25);
880 dm_pitch = pitch_stats.
ile (0.5);
883 pitch_stats.
clear ();
885 initial_pitch, min_space,
TRUE,
FALSE, 0)) {
887 pitch_iqr = maxwidth * 3.0f;
890 gap_iqr = gap_stats.
ile (0.75) - gap_stats.
ile (0.25);
891 pitch_iqr = pitch_stats.
ile (0.75) - pitch_stats.
ile (0.25);
894 (
"First fp iteration:initial_pitch=%g, gap_iqr=%g, pitch_iqr=%g, pitch=%g\n",
895 initial_pitch, gap_iqr, pitch_iqr, pitch_stats.
ile (0.5));
896 initial_pitch = pitch_stats.
ile (0.5);
897 if (min_space > initial_pitch
899 initial_pitch, initial_pitch,
TRUE,
FALSE, 0)) {
900 min_space = initial_pitch;
901 gap_iqr = gap_stats.
ile (0.75) - gap_stats.
ile (0.25);
902 pitch_iqr = pitch_stats.
ile (0.75) - pitch_stats.
ile (0.25);
905 (
"Revised fp iteration:initial_pitch=%g, gap_iqr=%g, pitch_iqr=%g, pitch=%g\n",
906 initial_pitch, gap_iqr, pitch_iqr, pitch_stats.
ile (0.5));
907 initial_pitch = pitch_stats.
ile (0.5);
911 tprintf(
"Blk=%d:Row=%d:%c:p_iqr=%g:g_iqr=%g:dm_p_iqr=%g:dm_g_iqr=%g:%c:",
912 block_index, row_index,
'X',
913 pitch_iqr, gap_iqr, dm_pitch_iqr, dm_gap_iqr,
914 pitch_iqr > maxwidth && dm_pitch_iqr > maxwidth ?
'D' :
915 (pitch_iqr * dm_gap_iqr <= dm_pitch_iqr * gap_iqr ?
'S' :
'M'));
916 if (pitch_iqr > maxwidth && dm_pitch_iqr > maxwidth) {
922 if (pitch_iqr * dm_gap_iqr <= dm_pitch_iqr * gap_iqr) {
925 (
"Choosing non dm version:pitch_iqr=%g, gap_iqr=%g, dm_pitch_iqr=%g, dm_gap_iqr=%g\n",
926 pitch_iqr, gap_iqr, dm_pitch_iqr, dm_gap_iqr);
927 gap_iqr = gap_stats.
ile (0.75) - gap_stats.
ile (0.25);
928 pitch_iqr = pitch_stats.
ile (0.75) - pitch_stats.
ile (0.25);
929 pitch = pitch_stats.
ile (0.5);
930 used_dm_model =
FALSE;
935 (
"Choosing dm version:pitch_iqr=%g, gap_iqr=%g, dm_pitch_iqr=%g, dm_gap_iqr=%g\n",
936 pitch_iqr, gap_iqr, dm_pitch_iqr, dm_gap_iqr);
937 gap_iqr = dm_gap_iqr;
938 pitch_iqr = dm_pitch_iqr;
940 used_dm_model =
TRUE;
943 tprintf (
"rev_p_iqr=%g:rev_g_iqr=%g:pitch=%g:",
944 pitch_iqr, gap_iqr, pitch);
945 tprintf (
"p_iqr/g=%g:p_iqr/x=%g:iqr_res=%c:",
946 pitch_iqr / gap_iqr, pitch_iqr / block->
xheight,
983 const char *res_string;
1004 if (pitch_sd < textord_words_pitchsd_threshold * row->fixed_pitch
1005 && ((pitsync_linear_version & 3) < 3
1006 || ((pitsync_linear_version & 3) >= 3 && (row->
used_dm_model
1008 || (pitch_sd == 0 && sp_sd > 10))))) {
1009 if (pitch_sd < textord_words_def_fixed * row->fixed_pitch
1011 && ((pitsync_linear_version & 3) < 3 || sp_sd > 20))
1016 else if ((pitsync_linear_version & 3) < 3
1020 if (pitch_sd < textord_words_def_prop * row->fixed_pitch)
1046 tprintf (
":sd/p=%g:occ=%g:init_res=%s\n",
1066 float initial_pitch,
1068 BOOL8 ignore_outsize,
1069 BOOL8 split_outsize,
1075 BLOBNBOX_IT blob_it = row->
blob_list ();
1085 gap_stats->
clear ();
1086 pitch_stats->
clear ();
1087 if (blob_it.empty ())
1092 joined_box = blob_it.data ()->bounding_box ();
1095 blob = blob_it.data ();
1098 if ((blob_box.
left () - joined_box.
right () < dm_gap
1099 && !blob_it.at_first ())
1101 joined_box += blob_box;
1103 blob_width = joined_box.
width ();
1104 if (split_outsize) {
1106 (
inT32) floor ((
float) blob_width / initial_pitch + 0.5);
1107 if (width_units < 1)
1111 else if (ignore_outsize) {
1112 width = (float) blob_width / initial_pitch;
1120 width_units * initial_pitch) / 2);
1121 if (prev_valid && width_units >= 0) {
1127 gap_stats->
add (joined_box.
left () - prev_right, 1);
1128 pitch_stats->
add (x_centre - prev_centre, 1);
1130 prev_centre = (
inT32) (x_centre + width_units * initial_pitch);
1131 prev_right = joined_box.
right ();
1132 prev_valid = blob_box.
left () - joined_box.
right () < min_space;
1133 prev_valid = prev_valid && width_units >= 0;
1134 joined_box = blob_box;
1138 while (!blob_it.at_first ());
1153 inT16 projection_left,
1154 inT16 projection_right,
1156 float &initial_pitch,
1158 inT16 &best_mid_cuts,
1159 ICOORDELT_LIST *best_cells,
1169 ICOORDELT_LIST test_cells;
1170 ICOORDELT_IT best_it;
1174 projection_right, space_size, initial_pitch,
1177 best_mid_cuts, best_cells, testing_on);
1179 best_sp_sd = initial_pitch;
1180 return initial_pitch;
1193 best_sd = initial_sd;
1194 best_pitch = initial_pitch;
1196 tprintf (
"tune_row_pitch:start pitch=%g, sd=%g\n", best_pitch, best_sd);
1200 space_size, initial_pitch + pitch_delta, sp_sd,
1201 mid_cuts, &test_cells, testing_on);
1203 tprintf (
"testing pitch at %g, sd=%g\n", initial_pitch + pitch_delta,
1205 if (pitch_sd < best_sd) {
1207 best_mid_cuts = mid_cuts;
1209 best_pitch = initial_pitch + pitch_delta;
1210 best_cells->clear ();
1211 best_it.set_to_list (best_cells);
1212 best_it.add_list_after (&test_cells);
1215 test_cells.clear ();
1216 if (pitch_sd > initial_sd)
1222 space_size, initial_pitch - pitch_delta, sp_sd,
1223 mid_cuts, &test_cells, testing_on);
1225 tprintf (
"testing pitch at %g, sd=%g\n", initial_pitch - pitch_delta,
1227 if (pitch_sd < best_sd) {
1229 best_mid_cuts = mid_cuts;
1231 best_pitch = initial_pitch - pitch_delta;
1232 best_cells->clear ();
1233 best_it.set_to_list (best_cells);
1234 best_it.add_list_after (&test_cells);
1237 test_cells.clear ();
1238 if (pitch_sd > initial_sd)
1241 initial_pitch = best_pitch;
1265 inT16 projection_left,
1266 inT16 projection_right,
1268 float &initial_pitch,
1270 inT16 &best_mid_cuts,
1271 ICOORDELT_LIST *best_cells,
1285 best_sp_sd = initial_pitch;
1288 return initial_pitch;
1291 if (sum_proj ==
NULL)
1292 return initial_pitch;
1293 best_pitch = (
inT32) initial_pitch;
1300 for (pixel = projection_left; pixel <= projection_right; pixel++) {
1304 pitch_delta].add ((pixel - projection_left) % (best_pitch +
1313 for (pixel = 0; pixel < best_pitch + pitch_delta; pixel++) {
1319 best_delta = pitch_delta;
1325 tprintf (
"tune_row_pitch:start pitch=%g, best_delta=%d, count=%d\n",
1326 initial_pitch, best_delta, best_count);
1327 best_pitch += best_delta;
1328 initial_pitch = best_pitch;
1330 best_count += best_count;
1331 for (start = best_pixel - 2; start > best_pixel - best_pitch
1333 best_delta].
pile_count (start % best_pitch) <= best_count;
1335 for (end = best_pixel + 2;
1336 end < best_pixel + best_pitch
1338 best_delta].
pile_count (end % best_pitch) <= best_count;
1355 tprintf (
"tune_row_pitch:output pitch=%g, sd=%g\n", initial_pitch,
1382 inT16 projection_left,
1383 inT16 projection_right,
1385 float initial_pitch,
1388 ICOORDELT_LIST *row_cells,
1395 BLOBNBOX_IT blob_it = row->
blob_list ();
1396 BLOBNBOX_IT start_it;
1397 BLOBNBOX_IT plot_it;
1404 FPSEGPT_LIST seg_list;
1409 ICOORDELT_IT cell_it = row_cells;
1417 if ((pitsync_linear_version & 3) > 1) {
1419 projection_right, initial_pitch,
1420 occupation, mid_cuts, row_cells,
1421 testing_on, start, end);
1432 if (blob_it.empty ())
1433 return space_size * 10;
1434 #ifndef GRAPHICS_DISABLED
1435 if (testing_on &&
to_win > 0) {
1436 blob_box = blob_it.data ()->bounding_box ();
1444 blob_it.mark_cycle_pt ();
1446 for (; blob_count > 0; blob_count--)
1449 prev_box = blob_box;
1453 while (!blob_it.cycled_list ()
1454 && blob_box.
left () - prev_box.
right () < space_size);
1456 if (pitsync_linear_version & 3)
1459 projection, projection_left, projection_right,
1461 occupation, &seg_list, start, end);
1465 projection, &seg_list);
1467 tprintf (
"Word ending at (%d,%d), len=%d, sync rating=%g, ",
1468 prev_box.
right (), prev_box.
top (),
1469 seg_list.length () - 1, word_sync);
1470 seg_it.set_to_list (&seg_list);
1471 for (seg_it.mark_cycle_pt (); !seg_it.cycled_list ();
1472 seg_it.forward ()) {
1473 if (seg_it.data ()->faked)
1475 tprintf (
"%d, ", seg_it.data ()->position ());
1483 #ifndef GRAPHICS_DISABLED
1487 seg_it.set_to_list (&seg_list);
1488 if (prev_right >= 0) {
1489 sp_var = seg_it.data ()->position () - prev_right;
1490 sp_var -= floor (sp_var / initial_pitch + 0.5) * initial_pitch;
1495 for (seg_it.mark_cycle_pt (); !seg_it.cycled_list (); seg_it.forward ()) {
1496 segpos = seg_it.data ()->position ();
1497 if (cell_it.empty () || segpos > cellpos + initial_pitch / 2) {
1499 while (!cell_it.empty () && segpos > cellpos + initial_pitch * 3 / 2) {
1501 cell_it.add_after_then_move (cell);
1502 cellpos += (
inT16) initial_pitch;
1506 cell_it.add_after_then_move (cell);
1509 else if (segpos > cellpos - initial_pitch / 2) {
1510 cell = cell_it.data ();
1512 cell->
set_x ((cellpos + segpos) / 2);
1513 cellpos = cell->
x ();
1516 seg_it.move_to_last ();
1517 prev_right = seg_it.data ()->position ();
1519 scale_factor = (seg_list.length () - 2) / 2;
1520 if (scale_factor < 1)
1525 sqsum += word_sync * scale_factor;
1526 total_count += (seg_list.length () - 1) * scale_factor;
1529 while (!blob_it.cycled_list ());
1530 sp_sd = sp_count > 0 ? sqrt (spsum / sp_count) : 0;
1531 return total_count > 0 ? sqrt (sqsum / total_count) : space_size * 10;
1545 inT16 projection_left,
1546 inT16 projection_right,
1547 float initial_pitch,
1550 ICOORDELT_LIST *row_cells,
1556 BLOBNBOX_IT blob_it = row->
blob_list ();
1557 BLOBNBOX_IT plot_it;
1560 FPSEGPT_LIST seg_list;
1564 ICOORDELT_IT cell_it = row_cells;
1569 if (blob_it.empty ()) {
1571 return initial_pitch * 10;
1573 #ifndef GRAPHICS_DISABLED
1574 if (testing_on &&
to_win > 0) {
1580 blob_it.mark_cycle_pt ();
1586 while (!blob_it.cycled_list ());
1589 2, projection, projection_left,
1592 occupation, &seg_list, start, end);
1594 tprintf (
"Row ending at (%d,%d), len=%d, sync rating=%g, ",
1595 blob_box.
right (), blob_box.
top (),
1596 seg_list.length () - 1, word_sync);
1597 seg_it.set_to_list (&seg_list);
1598 for (seg_it.mark_cycle_pt (); !seg_it.cycled_list (); seg_it.forward ()) {
1599 if (seg_it.data ()->faked)
1601 tprintf (
"%d, ", seg_it.data ()->position ());
1609 #ifndef GRAPHICS_DISABLED
1613 seg_it.set_to_list (&seg_list);
1614 for (seg_it.mark_cycle_pt (); !seg_it.cycled_list (); seg_it.forward ()) {
1615 segpos = seg_it.data ()->position ();
1618 cell_it.add_after_then_move (cell);
1619 if (seg_it.at_last ())
1620 mid_cuts = seg_it.data ()->cheap_cuts ();
1623 return occupation > 0 ? sqrt (word_sync / occupation) : initial_pitch * 10;
1637 inT16 projection_left,
1638 inT16 projection_right,
1646 BLOBNBOX_IT blob_it = row->
blob_list ();
1647 BLOBNBOX_IT start_it;
1648 BLOBNBOX_IT row_start;
1650 inT16 total_blob_count;
1656 FPSEGPT_LIST seg_list;
1664 if (blob_it.empty ())
1666 row_start = blob_it;
1667 total_blob_count = 0;
1674 blob_it = row_start;
1678 blob_it.mark_cycle_pt ();
1680 for (; blob_count > 0; blob_count--)
1683 prev_box = blob_box;
1687 while (!blob_it.cycled_list ()
1688 && blob_box.
left () - prev_box.
right () < space_size);
1691 projection, projection_left, projection_right,
1693 occupation, &seg_list, 0, 0);
1694 total_blob_count += blob_count;
1695 seg_it.set_to_list (&seg_list);
1696 if (prev_right >= 0) {
1697 sp_var = seg_it.data ()->position () - prev_right;
1698 sp_var -= floor (sp_var / initial_pitch + 0.5) * initial_pitch;
1703 seg_it.move_to_last ();
1704 prev_right = seg_it.data ()->position ();
1706 scale_factor = (seg_list.length () - 2) / 2;
1707 if (scale_factor < 1)
1712 sqsum += word_sync * scale_factor;
1713 total_count += (seg_list.length () - 1) * scale_factor;
1716 while (!blob_it.cycled_list ());
1717 sp_sd = sp_count > 0 ? sqrt (spsum / sp_count) : 0;
1718 word_sync = total_count > 0 ? sqrt (sqsum / total_count) : space_size * 10;
1719 tprintf (
"new_sd=%g:sd/p=%g:new_sp_sd=%g:res=%c:",
1720 word_sync, word_sync / initial_pitch, sp_sd,
1724 start_it = row_start;
1725 blob_it = row_start;
1728 projection, projection_left, projection_right,
1732 word_sync /= occupation;
1733 word_sync = sqrt (word_sync);
1735 #ifndef GRAPHICS_DISABLED
1750 (
"row_sd=%g:sd/p=%g:res=%c:N=%d:res2=%s,init pitch=%g, row_pitch=%g, all_caps=%d\n",
1751 word_sync, word_sync / initial_pitch,
1770 BLOBNBOX_IT search_it;
1774 int blobcount, repeated_set;
1776 TO_ROW_IT row_it = block->
get_rows();
1777 if (row_it.empty())
return;
1778 for (row_it.mark_cycle_pt(); !row_it.cycled_list(); row_it.forward()) {
1779 row = row_it.data();
1781 if (box_it.empty())
continue;
1788 if (box_it.data()->repeated_set() != 0 &&
1789 !box_it.data()->joined_to_prev()) {
1791 repeated_set = box_it.data()->repeated_set();
1793 search_it.forward();
1794 while (!search_it.at_first() &&
1795 search_it.data()->repeated_set() == repeated_set) {
1797 search_it.forward();
1803 if (!box_it.empty() && box_it.data()->joined_to_prev()) {
1804 tprintf(
"Bad box joined to prev at");
1805 box_it.data()->bounding_box().print();
1806 tprintf(
"After repeated word:");
1809 ASSERT_HOST(box_it.empty() || !box_it.data()->joined_to_prev());
1812 word_it.add_after_then_move(word);
1816 }
while (!box_it.at_first());
1827 #ifndef GRAPHICS_DISABLED
1834 TO_ROW_IT row_it = block->
get_rows ();
1836 for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) {
1837 row = row_it.data ();