00001
00033 #include "mfcpch.h"
00034 #include <ctype.h>
00035 #include <math.h>
00036 #include "cmndwin.h"
00037 #include "genblob.h"
00038 #include "pgedit.h"
00039 #include "pgeditx.h"
00040 #include "tessio.h"
00041 #include "tessout.h"
00042 #include "submen.h"
00043 #include "varblwin.h"
00044 #include "tordmain.h"
00045 #include "statistc.h"
00046 #include "debugwin.h"
00047 #include "showim.h"
00048 #include "mainblk.h"
00049 #include "evnts.h"
00050
00051 #define ASC_HEIGHT (2 * bln_baseline_offset + bln_x_height)
00052 #define X_HEIGHT (bln_baseline_offset + bln_x_height)
00053 #define BL_HEIGHT bln_baseline_offset
00054 #define DESC_HEIGHT 0
00055
00056 #define MAXSPACING 128
00057
00058 const ERRCODE EMPTYBLOCKLIST = "No blocks to edit";
00059 extern IMAGE page_image;
00060
00065 enum CMD_EVENTS
00066 {
00067 NULL_CMD_EVENT,
00068 DELETE_CMD_EVENT,
00069 COPY_CMD_EVENT,
00070 CHANGE_DISP_CMD_EVENT,
00071 CHANGE_TEXT_CMD_EVENT,
00072 TOGGLE_SEG_CMD_EVENT,
00073 DUMP_WERD_CMD_EVENT,
00074 SHOW_POINT_CMD_EVENT,
00075 ROW_SPACE_STAT_CMD_EVENT,
00076 BLOCK_SPACE_STAT_CMD_EVENT,
00077 SHOW_BLN_WERD_CMD_EVENT,
00078 SEGMENT_WERD_CMD_EVENT,
00079 BOUNDING_BOX_CMD_EVENT,
00080 CORRECT_TEXT_CMD_EVENT,
00081 POLYGONAL_CMD_EVENT,
00082 BL_NORM_CMD_EVENT,
00083 BITMAP_CMD_EVENT,
00084 TIDY_CMD_EVENT,
00085 VIEW_CMD_EVENT,
00086 IMAGE_CMD_EVENT,
00087 BLOCKS_CMD_EVENT,
00088 BASELINES_CMD_EVENT,
00089 WRITE_CMD_EVENT,
00090 SMD_CMD_EVENT,
00091 NEW_SOURCE_CMD_EVENT,
00092 UNIFORM_DISP_CMD_EVENT,
00093 REFRESH_CMD_EVENT,
00094 QUIT_CMD_EVENT
00095 };
00096
00097 #define EXTENDED_MODES_BASE 1000 //for extended cmd ids
00098 #define EXTENDED_OTHER_BASE 2000
00099
00100
00101
00102
00103
00104 RADIO_MENU *modes_menu_item;
00105 RADIO_MENU_LEAF *change_display_menu_item;
00106 SIMPLE_MENU_LEAF *view_menu_item;
00107 RADIO_MENU_LEAF *copy_menu_item;
00108 VARIABLE_MENU_LEAF *write_menu_item;
00109
00110 #ifdef __UNIX__
00111 FILE *debug_window = NULL;
00112 #endif
00113
00114 WINDOW bln_word_window = NO_WINDOW;
00115
00116 CMD_EVENTS mode = CHANGE_DISP_CMD_EVENT;
00117
00118
00119 BITS16 word_display_mode;
00120 BOOL8 display_image = FALSE;
00121 BOOL8 display_blocks = FALSE;
00122 BOOL8 display_baselines = FALSE;
00123 BOOL8 viewing_source = TRUE;
00124
00125 BLOCK_LIST *source_block_list = NULL;
00126 BLOCK_LIST target_block_list;
00127 BLOCK_LIST *other_block_list = &target_block_list;
00128
00129 BOOL8 source_changed = FALSE;
00130 BOOL8 target_changed = FALSE;
00131 BOOL8 *other_image_changed = &target_changed;
00132
00133
00134
00135 #define EXTERN
00136
00137
00138 EXTERN WINDOW image_win = NO_WINDOW;
00139 EXTERN COMMAND_WINDOW *command_window;
00140
00141 EXTERN BLOCK_LIST *current_block_list = NULL;
00142 EXTERN BOOL8 *current_image_changed = &source_changed;
00143 EXTERN void (*show_pt_handler) (GRAPHICS_EVENT *) = NULL;
00144
00145
00146
00149 EXTERN STRING_VAR (editor_image_win_name, "EditorImage",
00150 "Editor image window name");
00151 EXTERN INT_VAR (editor_image_xpos, 590, "Editor image X Pos");
00152 EXTERN INT_VAR (editor_image_ypos, 10, "Editor image Y Pos");
00153 EXTERN INT_VAR (editor_image_height, 680, "Editor image height");
00154 EXTERN INT_VAR (editor_image_width, 655, "Editor image width");
00155 EXTERN INT_VAR (editor_image_word_bb_color, BLUE, "Word bounding box colour");
00156 EXTERN INT_VAR (editor_image_blob_bb_color, YELLOW,
00157 "Blob bounding box colour");
00158 EXTERN INT_VAR (editor_image_text_color, WHITE, "Correct text colour");
00159
00160 EXTERN STRING_VAR (editor_dbwin_name, "EditorDBWin",
00161 "Editor debug window name");
00162 EXTERN INT_VAR (editor_dbwin_xpos, 50, "Editor debug window X Pos");
00163 EXTERN INT_VAR (editor_dbwin_ypos, 500, "Editor debug window Y Pos");
00164 EXTERN INT_VAR (editor_dbwin_height, 24, "Editor debug window height");
00165 EXTERN INT_VAR (editor_dbwin_width, 80, "Editor debug window width");
00166
00167 EXTERN STRING_VAR (editor_word_name, "BlnWords", "BL normalised word window");
00168 EXTERN INT_VAR (editor_word_xpos, 60, "Word window X Pos");
00169 EXTERN INT_VAR (editor_word_ypos, 510, "Word window Y Pos");
00170 EXTERN INT_VAR (editor_word_height, 240, "Word window height");
00171 EXTERN INT_VAR (editor_word_width, 655, "Word window width");
00172
00173 EXTERN double_VAR (editor_smd_scale_factor, 1.0, "Scaling for smd image");
00193 void add_word(
00194 WERD *word,
00195 ROW *src_row,
00196 BLOCK *src_block,
00197 BLOCK_LIST *dest_block_list
00198 ) {
00199 BLOCK_IT block_it(dest_block_list);
00200 BLOCK *block;
00201 BLOCK *dest_block = NULL;
00202 ROW_IT row_it;
00203 ROW *row;
00204 ROW *dest_row = NULL;
00205 WERD_IT word_it;
00206 BOX word_box = word->bounding_box ();
00207 BOX insert_point_word_box;
00208 BOOL8 seen_blocks_for_current_file = FALSE;
00209
00210 block_it.mark_cycle_pt ();
00211 while (!block_it.cycled_list () && (dest_block == NULL)) {
00212 block = block_it.data ();
00213 if ((block->bounding_box ().contains (word_box)) &&
00214 (strcmp (block->name (), src_block->name ()) == 0)) {
00215 dest_block = block;
00216 row_it.set_to_list (block->row_list ());
00217 row_it.mark_cycle_pt ();
00218 while ((!row_it.cycled_list ()) && (dest_row == NULL)) {
00219 row = row_it.data ();
00220 if (row->bounding_box ().contains (word_box))
00221 dest_row = row;
00222 else
00223 row_it.forward ();
00224 }
00225 }
00226 else
00227 block_it.forward ();
00228 }
00229
00230 if (dest_block == NULL) {
00231 dest_block = new BLOCK;
00232 *dest_block = *src_block;
00233
00234 block_it.set_to_list (dest_block_list);
00235 for (block_it.mark_cycle_pt ();
00236 !block_it.cycled_list (); block_it.forward ()) {
00237 block = block_it.data ();
00238
00239 if (!seen_blocks_for_current_file &&
00240 (strcmp (block->name (), dest_block->name ()) == 0))
00241 seen_blocks_for_current_file = TRUE;
00242
00243 if (seen_blocks_for_current_file &&
00244 ((strcmp (block->name (), dest_block->name ()) != 0) ||
00245 (block->bounding_box ().top () <
00246 dest_block->bounding_box ().top ())))
00247 break;
00248 }
00249
00250 if (block_it.cycled_list ())
00251
00252 block_it.add_to_end (dest_block);
00253 else
00254
00255 block_it.add_before_stay_put (dest_block);
00256 }
00257
00258 if (dest_row == NULL) {
00259 dest_row = new ROW;
00260 *dest_row = *src_row;
00261
00262 row_it.set_to_list (dest_block->row_list ());
00263 for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) {
00264 if (row_it.data ()->bounding_box ().top () <
00265 dest_row->bounding_box ().top ())
00266 break;
00267 }
00268
00269 if (row_it.cycled_list ())
00270
00271 row_it.add_to_end (dest_row);
00272 else
00273
00274 row_it.add_before_stay_put (dest_row);
00275 }
00276
00277
00278
00279
00280 word_it.set_to_list (dest_row->word_list ());
00281 for (word_it.mark_cycle_pt (); !word_it.cycled_list (); word_it.forward ()) {
00282 if (word_it.data ()->bounding_box ().right () >= word_box.left ())
00283 break;
00284 }
00285
00286 if (word_it.cycled_list ())
00287 word_it.add_to_end (word);
00288 else {
00289 insert_point_word_box = word_it.data ()->bounding_box ();
00290 if (insert_point_word_box.contains (word_box) ||
00291 word_box.contains (insert_point_word_box))
00292 command_window->
00293 msg
00294 ("Refusing to add words which obliterate, or are obliterated by, others");
00295 else {
00296 if (word_it.data ()->bounding_box ().left () >
00297 word->bounding_box ().left ())
00298
00299 word_it.add_before_stay_put (word);
00300 else
00301
00302 word_it.add_after_stay_put (word);
00303 }
00304 }
00305 }
00306
00307
00311 WINDOW bln_word_window_handle() {
00312
00313 if (bln_word_window == NO_WINDOW) {
00314 pgeditor_msg ("Creating BLN word window...");
00315
00316 bln_word_window = create_window (editor_word_name.string (),
00317 SCROLLINGWIN, editor_word_xpos, editor_word_ypos,
00318 editor_word_width, editor_word_height, -2000.0, 2000.0,
00319 DESC_HEIGHT - 30.0f,
00320 ASC_HEIGHT + 30.0f,
00321
00322 TRUE, FALSE, FALSE, FALSE);
00323
00324
00325 pgeditor_msg ("Creating BLN word window...Done");
00326 }
00327 return bln_word_window;
00328 }
00329
00330
00336 void build_image_window(BOX page_bounding_box) {
00337 if (image_win != NO_WINDOW)
00338 destroy_window(image_win);
00339
00340
00341 image_win = create_window (editor_image_win_name.string (),
00342 SCROLLINGWIN, editor_image_xpos, editor_image_ypos,
00343 editor_image_width, editor_image_height, 0.0,
00344 (float) page_bounding_box.right () + 1,
00345
00346 0.0,
00347 (float) page_bounding_box.top () + 1,
00348
00349 TRUE, FALSE, TRUE, FALSE);
00350 }
00351
00352
00356 MENU_ROOT *build_menu() {
00357 NON_RADIO_MENU *parent_menu;
00358 MENU_ROOT *root_menu_item;
00359
00360 root_menu_item = new MENU_ROOT ();
00361
00362 modes_menu_item = new RADIO_MENU ("MODES");
00363 root_menu_item->add_child (modes_menu_item);
00364
00365 change_display_menu_item = new RADIO_MENU_LEAF ("Change Display",
00366 CHANGE_DISP_CMD_EVENT);
00367 modes_menu_item->add_child (change_display_menu_item);
00368 modes_menu_item->add_child (new RADIO_MENU_LEAF ("Delete",
00369 DELETE_CMD_EVENT));
00370 copy_menu_item = new RADIO_MENU_LEAF ("Copy to TARGET", COPY_CMD_EVENT);
00371 modes_menu_item->add_child (copy_menu_item);
00372 modes_menu_item->add_child (new RADIO_MENU_LEAF ("Change Text",
00373 CHANGE_TEXT_CMD_EVENT));
00374 modes_menu_item->add_child (new RADIO_MENU_LEAF ("Toggle Correct Seg Flg",
00375 TOGGLE_SEG_CMD_EVENT));
00376 modes_menu_item->add_child (new RADIO_MENU_LEAF ("Dump Word",
00377 DUMP_WERD_CMD_EVENT));
00378 modes_menu_item->add_child (new RADIO_MENU_LEAF ("Show Point",
00379 SHOW_POINT_CMD_EVENT));
00380 modes_menu_item->add_child (new RADIO_MENU_LEAF ("Row gaps hist",
00381 ROW_SPACE_STAT_CMD_EVENT));
00382 modes_menu_item->add_child (new RADIO_MENU_LEAF ("Block gaps hist",
00383 BLOCK_SPACE_STAT_CMD_EVENT));
00384 modes_menu_item->add_child (new RADIO_MENU_LEAF ("Show BL Norm Word",
00385 SHOW_BLN_WERD_CMD_EVENT));
00386 modes_menu_item->add_child (new RADIO_MENU_LEAF ("Re-Segment Word",
00387 SEGMENT_WERD_CMD_EVENT));
00388
00389 parent_menu = new NON_RADIO_MENU ("DISPLAY");
00390 root_menu_item->add_child (parent_menu);
00391
00392 parent_menu->add_child (new TOGGLE_MENU_LEAF ("Bounding Boxes",
00393 BOUNDING_BOX_CMD_EVENT,
00394 TRUE));
00395 parent_menu->add_child (new TOGGLE_MENU_LEAF ("Correct Text",
00396 CORRECT_TEXT_CMD_EVENT,
00397 FALSE));
00398 parent_menu->add_child (new TOGGLE_MENU_LEAF ("Polygonal Approx",
00399 POLYGONAL_CMD_EVENT, FALSE));
00400 parent_menu->add_child (new TOGGLE_MENU_LEAF ("Baseline Normalised",
00401 BL_NORM_CMD_EVENT, FALSE));
00402 parent_menu->add_child (new TOGGLE_MENU_LEAF ("Edge Steps",
00403 BITMAP_CMD_EVENT, FALSE));
00404
00405 parent_menu = new NON_RADIO_MENU ("OTHER");
00406 root_menu_item->add_child (parent_menu);
00407
00408 parent_menu->add_child (new SIMPLE_MENU_LEAF ("Quit", QUIT_CMD_EVENT));
00409 parent_menu->add_child (new SIMPLE_MENU_LEAF ("Tidy Target",
00410 TIDY_CMD_EVENT));
00411 view_menu_item = new SIMPLE_MENU_LEAF ("View TARGET", VIEW_CMD_EVENT);
00412 parent_menu->add_child (view_menu_item);
00413 parent_menu->add_child (new TOGGLE_MENU_LEAF ("Show Image",
00414 IMAGE_CMD_EVENT, FALSE));
00415 parent_menu->add_child (new TOGGLE_MENU_LEAF ("ShowBlock Outlines",
00416 BLOCKS_CMD_EVENT, FALSE));
00417 parent_menu->add_child (new TOGGLE_MENU_LEAF ("Show Baselines",
00418 BASELINES_CMD_EVENT, FALSE));
00419 write_menu_item = new VARIABLE_MENU_LEAF ("Write File",
00420 WRITE_CMD_EVENT,
00421 imagebasename.string ());
00422 parent_menu->add_child (write_menu_item);
00423 parent_menu->add_child (new SIMPLE_MENU_LEAF ("Make SMD Image",
00424 SMD_CMD_EVENT));
00425 parent_menu->add_child (new VARIABLE_MENU_LEAF ("New Source File",
00426 NEW_SOURCE_CMD_EVENT,
00427 imagebasename.string ()));
00428 parent_menu->add_child (new SIMPLE_MENU_LEAF ("Uniform Display",
00429 UNIFORM_DISP_CMD_EVENT));
00430 parent_menu->add_child (new SIMPLE_MENU_LEAF ("Refresh Display",
00431 REFRESH_CMD_EVENT));
00432
00433
00434 extend_menu(modes_menu_item,
00435 EXTENDED_MODES_BASE,
00436 parent_menu,
00437 EXTENDED_OTHER_BASE);
00438 return root_menu_item;
00439 }
00440
00441
00445 void debug_window_handle() {
00446
00447
00448
00449
00450 pgeditor_msg ("Creating debug window...Done");
00451
00452 }
00453
00454
00458 void display_bln_lines(WINDOW window,
00459 COLOUR colour,
00460 float scale_factor,
00461 float y_offset,
00462 float minx,
00463 float maxx) {
00464 line_color_index(window, colour);
00465 line_type(window, SOLID);
00466 move2d (window, minx, y_offset + scale_factor * DESC_HEIGHT);
00467 draw2d (window, maxx, y_offset + scale_factor * DESC_HEIGHT);
00468 move2d (window, minx, y_offset + scale_factor * BL_HEIGHT);
00469 draw2d (window, maxx, y_offset + scale_factor * BL_HEIGHT);
00470 move2d (window, minx, y_offset + scale_factor * X_HEIGHT);
00471 draw2d (window, maxx, y_offset + scale_factor * X_HEIGHT);
00472 move2d (window, minx, y_offset + scale_factor * ASC_HEIGHT);
00473 draw2d (window, maxx, y_offset + scale_factor * ASC_HEIGHT);
00474 }
00475
00476
00480 void do_new_source(
00481 char *name
00482 ) {
00483 FILE *infp;
00484 char msg_str[MAX_CHARS + 1];
00485 STRING name_str(name);
00486 char response_str[MAX_CHARS + 1];
00487 char *token;
00488
00489 if (source_changed) {
00490 response_str[0] = '\0';
00491 command_window->prompt ("Source changes will be LOST. Continue? (Y/N)",
00492 response_str);
00493 token = strtok (response_str, " ");
00494 if (tolower (token[0]) != 'y')
00495 return;
00496 }
00497
00498
00499 if (!(infp = fopen (name, "r"))) {
00500 sprintf (msg_str, "Cant open file " "%s" "", name);
00501 command_window->msg (msg_str);
00502 return;
00503 }
00504
00505 fclose(infp);
00506 sprintf (msg_str, "Reading file " "%s" "...", name);
00507 command_window->msg (msg_str);
00508 source_block_list->clear ();
00509
00510 pgeditor_read_file(name_str, source_block_list);
00511 source_changed = FALSE;
00512 command_window->msg ("Doing automatic Tidy Target...");
00513 viewing_source = FALSE;
00514 do_tidy_cmd();
00515 command_window->msg ("Doing automatic Tidy Target...Done");
00516 }
00517
00518
00522 void do_re_display (
00523 BOOL8 word_painter (
00524 BLOCK *, ROW *, WERD *)
00525 ) {
00526 BLOCK_IT block_it(current_block_list);
00527 BLOCK *block;
00528 int block_count = 1;
00529
00530 ROW_IT row_it;
00531 ROW *row;
00532
00533 WERD_IT word_it;
00534 WERD *word;
00535
00536 clear_view_surface(image_win);
00537 if (display_image) {
00538 show_sub_image (&page_image, 0, 0,
00539 page_image.get_xsize (), page_image.get_ysize (),
00540 image_win, 0, 0);
00541 }
00542
00543 for (block_it.mark_cycle_pt ();
00544 !block_it.cycled_list (); block_it.forward ()) {
00545 block = block_it.data ();
00546 row_it.set_to_list (block->row_list ());
00547 for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) {
00548 row = row_it.data ();
00549 word_it.set_to_list (row->word_list ());
00550 for (word_it.mark_cycle_pt ();
00551 !word_it.cycled_list (); word_it.forward ()) {
00552 word = word_it.data ();
00553 word_painter(block, row, word);
00554 }
00555 if (display_baselines)
00556 row->plot_baseline (image_win, GREEN);
00557 }
00558 if (display_blocks)
00559 block->plot (image_win, block_count++, RED);
00560 }
00561 }
00562
00563
00567 const BOX do_tidy_cmd() {
00568 ICOORD shift_vector;
00569 BOX tidy_box;
00570 BOX source_box;
00571
00572 source_box = block_list_bounding_box (source_block_list);
00573
00574
00575 if (!target_block_list.empty ()) {
00576 tidy_box = block_list_compress (&target_block_list);
00577
00578
00579
00580 shift_vector = ICOORD (0, source_box.top () + BLOCK_SPACING)
00581 - tidy_box.botleft ();
00582 block_list_move(&target_block_list, shift_vector);
00583 tidy_box.move (shift_vector);
00584 }
00585 source_box += tidy_box;
00586
00587 build_image_window(source_box);
00588 do_view_cmd();
00589 return tidy_box;
00590 }
00591
00592
00596 void do_view_cmd() {
00597 viewing_source = !viewing_source;
00598 clear_view_surface(image_win);
00599 if (viewing_source) {
00600 current_block_list = source_block_list;
00601 current_image_changed = &source_changed;
00602 other_block_list = &target_block_list;
00603 other_image_changed = &target_changed;
00604 do_re_display(&word_display);
00605
00606 command_window->replace_menu_text (view_menu_item, "View TARGET");
00607 command_window->replace_menu_text (copy_menu_item, "Copy to TARGET");
00608 write_menu_item->replace_value (imagebasename.string ());
00609 }
00610 else {
00611 current_block_list = &target_block_list;
00612 current_image_changed = &target_changed;
00613 other_block_list = source_block_list;
00614 other_image_changed = &source_changed;
00615 do_re_display(&word_display);
00616
00617 command_window->replace_menu_text (view_menu_item, "View SOURCE");
00618 command_window->replace_menu_text (copy_menu_item, "");
00619 write_menu_item->replace_value ((imagebasename + ".bits.pg").string ());
00620 }
00621 }
00622
00623
00629 void do_write_file(
00630 char *name
00631 ) {
00632 FILE *infp;
00633 char msg_str[MAX_CHARS + 1];
00634 char response_str[MAX_CHARS + 1];
00635 char *token;
00636 BOX enclosing_box;
00637
00638
00639 if ((infp = fopen (name, "r")) != NULL) {
00640 fclose(infp);
00641 sprintf (msg_str, "Overwrite file " "%s" "? (Y/N)", name);
00642 response_str[0] = '\0';
00643 if (!command_window->prompt (msg_str, response_str))
00644 return;
00645 token = strtok (response_str, " ");
00646 if (tolower (token[0]) != 'y')
00647 return;
00648 }
00649
00650 infp = fopen (name, "w");
00651 if (infp == NULL) {
00652 sprintf (msg_str, "Cant write to file " "%s" "", name);
00653 command_window->msg (msg_str);
00654 return;
00655 }
00656 fclose(infp);
00657
00658 if (!viewing_source && !target_block_list.empty ()) {
00659
00660 command_window->msg ("Automatic tidy...");
00661 viewing_source = TRUE;
00662 enclosing_box = do_tidy_cmd ();
00663 block_list_move (&target_block_list, -enclosing_box.botleft ());
00664 command_window->msg ("Writing file...");
00665 pgeditor_write_file(name, &target_block_list);
00666
00667 block_list_move (&target_block_list,
00668 enclosing_box.botleft ());
00669 }
00670 else {
00671 command_window->msg ("Writing file...");
00672 pgeditor_write_file(name, current_block_list);
00673 }
00674 command_window->msg ("Writing file...Done");
00675 *current_image_changed = FALSE;
00676 }
00677
00678
00682 void smd_cmd() {
00683 char response_str[MAX_CHARS + 1];
00684 WINDOW display_window;
00685 ICOORD tr, bl;
00686 BOX page_box = block_list_bounding_box (current_block_list);
00687
00688 bl = ICOORD (0, 0);
00689 tr = ICOORD (page_image.get_xsize () + 1, page_image.get_ysize () + 1);
00690 page_box += BOX (bl, tr);
00691
00692 strcpy (response_str, imagebasename.string ());
00693 strcpy (response_str + imagebasename.length (), ".smd.tif");
00694 command_window->prompt ("SMD File Name?", response_str);
00695
00696 display_window = image_win;
00697
00698 image_win = create_window (response_str, SMDWINDOW, 0, 0,
00699 (INT16) (page_box.width () * editor_smd_scale_factor),
00700 (INT16) (page_box.height () * editor_smd_scale_factor), 0.0,
00701 page_box.width (),
00702 0.0,
00703 page_box.height (),
00704 FALSE, FALSE, FALSE, FALSE);
00705 do_re_display(&word_display);
00706 destroy_window(image_win);
00707 image_win = display_window;
00708 }
00709
00710
00715 void pgeditor_main(BLOCK_LIST *blocks) {
00716 GRAPHICS_EVENT event;
00717 INT32 cmd_event = 0;
00718 char new_value[MAX_CHARS + 1];
00719 BOOL8 exit = FALSE;
00720
00721 source_block_list = blocks;
00722 current_block_list = blocks;
00723 if (current_block_list->empty ())
00724 return;
00725
00726 command_window = new COMMAND_WINDOW ("WordEditorCmd", build_menu ());
00727 build_image_window (block_list_bounding_box (source_block_list));
00728 do_re_display(&word_display);
00729 word_display_mode.turn_on_bit (DF_BOX);
00730
00731 while (!exit) {
00732 overlap_picture_ops(TRUE);
00733 await_event (0,
00734 TRUE,
00735 ANY_EVENT, &event);
00736
00737 if (event.fd == command_window->window ()) {
00738 command_window->msg ("");
00739 command_window->event (event, &cmd_event, new_value);
00740 exit = process_cmd_win_event (cmd_event, new_value);
00741 }
00742 else {
00743 if (event.fd == image_win)
00744 process_image_event(event);
00745 else
00746 pgeditor_show_point(&event);
00747 }
00748 current_word_quit.set_value (FALSE);
00749 selection_quit.set_value (FALSE);
00750
00751 VARIABLES_WINDOW::plot_all();
00752 }
00753 }
00754
00755
00759 void pgeditor_msg(
00760 const char *msg) {
00761 if (command_window == NO_WINDOW) {
00762 tprintf(msg);
00763 tprintf ("\n");
00764 }
00765 else
00766 command_window->msg (msg);
00767 }
00768
00769
00773 void pgeditor_read_file(
00774 STRING &name,
00775 BLOCK_LIST *blocks
00776 ) {
00777 int c;
00778 FILE *infp;
00779 BLOCK_IT block_it(blocks);
00780 BLOCK *block;
00781
00782 ICOORD page_tr;
00783
00784 char *filename_extension;
00785
00786 block_it.move_to_last ();
00787
00788
00789 filename_extension = strrchr (name.string (), '.');
00790 #ifdef __UNIX__
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815 if (strcmp (filename_extension, ".pb") == 0) {
00816 tprintf ("Converting from .pb file format.\n");
00817
00818 read_and_textord (name.string (), blocks);
00819 }
00820 else
00821 #endif
00822 if ((strcmp (filename_extension, ".pg") == 0) ||
00823
00824
00825 (strcmp (filename_extension, ".sp") == 0)) {
00826 tprintf ("Reading %s file format.\n", filename_extension);
00827 infp = fopen (name.string (), "r");
00828 if (infp == NULL)
00829 CANTOPENFILE.error ("pgeditor_read_file", EXIT, name.string ());
00830
00831
00832 while (((c = fgetc (infp)) != EOF) && (ungetc (c, infp) != EOF)) {
00833
00834 block = BLOCK::de_serialise (infp);
00835
00836 block_it.add_after_then_move (block);
00837 }
00838 fclose(infp);
00839 } else {
00840 edges_and_textord (name.string (), blocks);
00841 }
00842 }
00843
00844
00848 void pgeditor_show_point(
00849 GRAPHICS_EVENT *event) {
00850 char msg[160];
00851
00852 sprintf (msg, "Pointing at (%f, %f)", event->x, event->y);
00853 command_window->msg (msg);
00854 }
00855
00856
00860 void pgeditor_write_file(
00861 char *name,
00862 BLOCK_LIST *blocks
00863 ) {
00864 FILE *infp;
00865 BLOCK_IT block_it(blocks);
00866 BLOCK *block;
00867 ROW_IT row_it;
00868
00869 infp = fopen (name, "w");
00870 if (infp == NULL)
00871 CANTCREATEFILE.error ("pgeditor_write_file", EXIT, name);
00872
00873 for (block_it.mark_cycle_pt ();
00874 !block_it.cycled_list (); block_it.forward ()) {
00875 block = block_it.extract ();
00876
00877 row_it.set_to_list (block->row_list ());
00878 for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ())
00879
00880 row_it.data ()->recalc_bounding_box ();
00881
00882 block->serialise (infp);
00883 block_it.add_after_then_move (block);
00884 }
00885 fclose(infp);
00886 }
00887
00888
00893 BOOL8 process_cmd_win_event(
00894 INT32 cmd_event,
00895 char *new_value
00896 ) {
00897 char msg[160];
00898 BOOL8 exit = FALSE;
00899 char response_str[MAX_CHARS + 1];
00900 char *token;
00901
00902 switch (cmd_event) {
00903 case NULL_CMD_EVENT:
00904 break;
00905
00906 case VIEW_CMD_EVENT:
00907 do_view_cmd();
00908 break;
00909 case CHANGE_DISP_CMD_EVENT:
00910 case DELETE_CMD_EVENT:
00911 case CHANGE_TEXT_CMD_EVENT:
00912 case TOGGLE_SEG_CMD_EVENT:
00913 case DUMP_WERD_CMD_EVENT:
00914 case SHOW_POINT_CMD_EVENT:
00915 case ROW_SPACE_STAT_CMD_EVENT:
00916 case BLOCK_SPACE_STAT_CMD_EVENT:
00917 case SHOW_BLN_WERD_CMD_EVENT:
00918 case SEGMENT_WERD_CMD_EVENT:
00919 mode = (CMD_EVENTS) cmd_event;
00920 break;
00921 case COPY_CMD_EVENT:
00922 mode = (CMD_EVENTS) cmd_event;
00923 if (!viewing_source)
00924 command_window->msg ("Can't COPY while viewing target!");
00925 break;
00926 case BOUNDING_BOX_CMD_EVENT:
00927 if (new_value[0] == 'T')
00928 word_display_mode.turn_on_bit (DF_BOX);
00929 else
00930 word_display_mode.turn_off_bit (DF_BOX);
00931 command_window->press_radio_button (modes_menu_item,
00932 change_display_menu_item);
00933 mode = CHANGE_DISP_CMD_EVENT;
00934 break;
00935 case CORRECT_TEXT_CMD_EVENT:
00936 if (new_value[0] == 'T')
00937 word_display_mode.turn_on_bit (DF_TEXT);
00938 else
00939 word_display_mode.turn_off_bit (DF_TEXT);
00940 command_window->press_radio_button (modes_menu_item,
00941 change_display_menu_item);
00942 mode = CHANGE_DISP_CMD_EVENT;
00943 break;
00944 case POLYGONAL_CMD_EVENT:
00945 if (new_value[0] == 'T')
00946 word_display_mode.turn_on_bit (DF_POLYGONAL);
00947 else
00948 word_display_mode.turn_off_bit (DF_POLYGONAL);
00949 command_window->press_radio_button (modes_menu_item,
00950 change_display_menu_item);
00951 mode = CHANGE_DISP_CMD_EVENT;
00952 break;
00953 case BL_NORM_CMD_EVENT:
00954 if (new_value[0] == 'T')
00955 word_display_mode.turn_on_bit (DF_BN_POLYGONAL);
00956 else
00957 word_display_mode.turn_off_bit (DF_BN_POLYGONAL);
00958 command_window->press_radio_button (modes_menu_item,
00959 change_display_menu_item);
00960 mode = CHANGE_DISP_CMD_EVENT;
00961 break;
00962 case BITMAP_CMD_EVENT:
00963 if (new_value[0] == 'T')
00964 word_display_mode.turn_on_bit (DF_EDGE_STEP);
00965 else
00966 word_display_mode.turn_off_bit (DF_EDGE_STEP);
00967 command_window->press_radio_button (modes_menu_item,
00968 change_display_menu_item);
00969 mode = CHANGE_DISP_CMD_EVENT;
00970 break;
00971 case UNIFORM_DISP_CMD_EVENT:
00972 do_re_display(&word_set_display);
00973 *current_image_changed = TRUE;
00974 break;
00975 case WRITE_CMD_EVENT:
00976 do_write_file(new_value);
00977 break;
00978 case SMD_CMD_EVENT:
00979 smd_cmd();
00980 break;
00981 case TIDY_CMD_EVENT:
00982 if (!target_block_list.empty ()) {
00983 viewing_source = TRUE;
00984 do_tidy_cmd();
00985 }
00986 break;
00987 case NEW_SOURCE_CMD_EVENT:
00988 do_new_source(new_value);
00989 break;
00990 case IMAGE_CMD_EVENT:
00991 display_image = (new_value[0] == 'T');
00992 do_re_display(&word_display);
00993 break;
00994 case BLOCKS_CMD_EVENT:
00995 display_blocks = (new_value[0] == 'T');
00996 do_re_display(&word_display);
00997 break;
00998 case BASELINES_CMD_EVENT:
00999 display_baselines = (new_value[0] == 'T');
01000 do_re_display(&word_display);
01001 break;
01002 case REFRESH_CMD_EVENT:
01003 do_re_display(&word_display);
01004 break;
01005 case QUIT_CMD_EVENT:
01006 if (source_changed || target_changed) {
01007 response_str[0] = '\0';
01008 command_window->prompt ("Changes not saved. Exit anyway? (Y/N)",
01009 response_str);
01010 token = strtok (response_str, " ");
01011 if (tolower (token[0]) == 'y')
01012 exit = TRUE;
01013 }
01014 else
01015 exit = TRUE;
01016 break;
01017 default:
01018 if ((cmd_event >= EXTENDED_MODES_BASE) &&
01019 (cmd_event < EXTENDED_OTHER_BASE))
01020 mode = (CMD_EVENTS) cmd_event;
01021 else {
01022 if (cmd_event >= EXTENDED_OTHER_BASE)
01023 extend_unmoded_commands (cmd_event - EXTENDED_OTHER_BASE,
01024 new_value);
01025 else {
01026 sprintf (msg, "Unrecognised event " INT32FORMAT " (%s)",
01027 cmd_event, new_value);
01028 command_window->msg (msg);
01029 }
01030 }
01031 break;
01032 }
01033 return exit;
01034 }
01035
01036
01045 void process_image_event(
01046 GRAPHICS_EVENT event) {
01047 static ICOORD down;
01048 ICOORD up;
01049 BOX selection_box;
01050 char msg[80];
01051
01052 switch (event.type) {
01053 case DOWN_EVENT:
01054 down.set_x ((INT16) floor (event.x + 0.5));
01055 down.set_y ((INT16) floor (event.y + 0.5));
01056 if (mode == SHOW_POINT_CMD_EVENT)
01057 show_point (current_block_list, event.x, event.y);
01058 break;
01059
01060 case UP_EVENT:
01061 case SELECT_EVENT:
01062 if (event.type == SELECT_EVENT) {
01063 down.set_x ((INT16) floor (event.xmax + 0.5));
01064 down.set_y ((INT16) floor (event.ymax + 0.5));
01065 if (mode == SHOW_POINT_CMD_EVENT)
01066 show_point (current_block_list, event.x, event.y);
01067 }
01068 if (mode != SHOW_POINT_CMD_EVENT)
01069 command_window->msg ("");
01070 up.set_x ((INT16) floor (event.x + 0.5));
01071 up.set_y ((INT16) floor (event.y + 0.5));
01072 selection_box = BOX (up, down);
01073
01074 switch (mode) {
01075 case CHANGE_DISP_CMD_EVENT:
01076 process_selected_words(current_block_list,
01077 selection_box,
01078 &word_blank_and_set_display);
01079 break;
01080 case COPY_CMD_EVENT:
01081 if (!viewing_source)
01082 command_window->msg ("Can't COPY while viewing target!");
01083 else
01084 process_selected_words(current_block_list,
01085 selection_box,
01086 &word_copy);
01087 break;
01088 case DELETE_CMD_EVENT:
01089 process_selected_words_it(current_block_list,
01090 selection_box,
01091 &word_delete);
01092 break;
01093 case CHANGE_TEXT_CMD_EVENT:
01094 process_selected_words(current_block_list,
01095 selection_box,
01096 &word_change_text);
01097 break;
01098 case TOGGLE_SEG_CMD_EVENT:
01099 process_selected_words(current_block_list,
01100 selection_box,
01101 &word_toggle_seg);
01102 break;
01103 case DUMP_WERD_CMD_EVENT:
01104 process_selected_words(current_block_list,
01105 selection_box,
01106 &word_dumper);
01107 break;
01108 case SHOW_BLN_WERD_CMD_EVENT:
01109 process_selected_words(current_block_list,
01110 selection_box,
01111 &word_bln_display);
01112 break;
01113 case SEGMENT_WERD_CMD_EVENT:
01114 re_segment_word(current_block_list, selection_box);
01115 break;
01116 case ROW_SPACE_STAT_CMD_EVENT:
01117 row_space_stat(current_block_list, selection_box);
01118 break;
01119 case BLOCK_SPACE_STAT_CMD_EVENT:
01120 block_space_stat(current_block_list, selection_box);
01121 break;
01122 case SHOW_POINT_CMD_EVENT:
01123 break;
01124 default:
01125 if ((mode >= EXTENDED_MODES_BASE) && (mode < EXTENDED_OTHER_BASE))
01126 extend_moded_commands (mode - EXTENDED_MODES_BASE, selection_box);
01127 else {
01128 sprintf (msg, "Mode %d not yet implemented", mode);
01129 command_window->msg (msg);
01130 }
01131 break;
01132 }
01133 default:
01134 break;
01135 }
01136 }
01137
01138
01144 float re_scale_and_move_bln_word(
01145 WERD *norm_word,
01146 const BOX &box
01147 ) {
01148 BOX norm_box = norm_word->bounding_box ();
01149 float width_scale_factor;
01150 float height_scale_factor;
01151 float selected_scale_factor;
01152
01153 width_scale_factor = box.width () / (float) norm_box.width ();
01154 height_scale_factor = box.height () / (float) ASC_HEIGHT;
01155
01156 if ((ASC_HEIGHT * width_scale_factor) <= box.height ())
01157 selected_scale_factor = width_scale_factor;
01158 else
01159 selected_scale_factor = height_scale_factor;
01160
01161 norm_word->scale (selected_scale_factor);
01162 norm_word->move (ICOORD ((box.left () + box.width () / 2), box.bottom ()));
01163 return selected_scale_factor;
01164 }
01165
01166
01173 void re_segment_word(
01174 BLOCK_LIST *block_list,
01175 BOX &selection_box) {
01176 BLOCK_IT block_it(block_list);
01177 BLOCK *block;
01178 BLOCK *block_to_process = NULL;
01179 ROW_IT row_it;
01180 ROW *row;
01181 ROW *row_to_process = NULL;
01182 WERD_IT word_it;
01183 WERD *word;
01184 WERD *new_word = NULL;
01185 BOOL8 polyg = false;
01186 PBLOB_IT blob_it;
01187 PBLOB_LIST dummy;
01188 PBLOB_IT new_blob_it = &dummy;
01189 PBLOB *blob;
01190
01191
01192
01193 for (block_it.mark_cycle_pt ();
01194 !block_it.cycled_list (); block_it.forward ()) {
01195 block = block_it.data ();
01196 if (block->bounding_box ().overlap (selection_box)) {
01197 row_it.set_to_list (block->row_list ());
01198 for (row_it.mark_cycle_pt ();
01199 !row_it.cycled_list (); row_it.forward ()) {
01200 row = row_it.data ();
01201 if (row->bounding_box ().overlap (selection_box)) {
01202 if (row_to_process == NULL) {
01203 block_to_process = block;
01204 row_to_process = row;
01205 }
01206 else {
01207 command_window->
01208 msg ("Cant resegment words in more than one row");
01209 return;
01210 }
01211 }
01212 }
01213 }
01214 }
01215
01216
01217 word_it.set_to_list (row_to_process->word_list ());
01218 for (word_it.mark_cycle_pt (); !word_it.cycled_list (); word_it.forward ()) {
01219 word = word_it.data ();
01220 polyg = word->flag (W_POLYGON);
01221 if (word->bounding_box ().overlap (selection_box)) {
01222 blob_it.set_to_list (word->gblob_list ());
01223 for (blob_it.mark_cycle_pt ();
01224 !blob_it.cycled_list (); blob_it.forward ()) {
01225 blob = blob_it.data ();
01226 if (gblob_bounding_box (blob, polyg).overlap (selection_box)) {
01227 if (new_word == NULL) {
01228 new_word = word->shallow_copy ();
01229 new_blob_it.set_to_list (new_word->gblob_list ());
01230 }
01231 new_blob_it.add_to_end (blob_it.extract ());
01232
01233 }
01234 }
01235 if (blob_it.empty ()) {
01236
01237 delete word_it.extract ();
01238 }
01239 }
01240 }
01241 if (new_word != NULL) {
01242 gblob_sort_list (new_word->gblob_list (), polyg);
01243 word_it.add_to_end (new_word);
01244 word_it.sort (word_comparator);
01245 row_to_process->bounding_box ().plot (image_win,
01246 INT_SOLID, FALSE, BLACK, BLACK);
01247 word_it.set_to_list (row_to_process->word_list ());
01248 for (word_it.mark_cycle_pt ();
01249 !word_it.cycled_list (); word_it.forward ())
01250 word_display (block_to_process, row_to_process, word_it.data ());
01251 *current_image_changed = TRUE;
01252 }
01253 }
01254
01255
01259 void block_space_stat(
01260 BLOCK_LIST *block_list,
01261 BOX &selection_box) {
01262 BLOCK_IT block_it(block_list);
01263 BLOCK *block;
01264 ROW_IT row_it;
01265 ROW *row;
01266 int block_idx = 0;
01267 STATS all_gap_stats (0, MAXSPACING);
01268 WERD_IT word_it;
01269 WERD *word;
01270 PBLOB_IT blob_it;
01271 PBLOB *blob;
01272 C_BLOB_IT cblob_it;
01273 C_BLOB *cblob;
01274 BOX box;
01275 INT16 prev_box_right;
01276 INT16 gap_width;
01277 INT16 min_inter_word_gap;
01278 INT16 max_inter_char_gap;
01279
01280
01281
01282 for (block_it.mark_cycle_pt ();
01283 !block_it.cycled_list (); block_it.forward ()) {
01284 block_idx++;
01285 block = block_it.data ();
01286 if (block->bounding_box ().overlap (selection_box)) {
01287
01288 tprintf ("\nBlock %d\n", block_idx);
01289 min_inter_word_gap = 3000;
01290 max_inter_char_gap = 0;
01291 all_gap_stats.clear ();
01292 row_it.set_to_list (block->row_list ());
01293 for (row_it.mark_cycle_pt ();
01294 !row_it.cycled_list (); row_it.forward ()) {
01295 row = row_it.data ();
01296 prev_box_right = -1;
01297 word_it.set_to_list (row->word_list ());
01298 for (word_it.mark_cycle_pt ();
01299 !word_it.cycled_list (); word_it.forward ()) {
01300 word = word_it.data ();
01301 if (word->flag (W_POLYGON)) {
01302 blob_it.set_to_list (word->blob_list ());
01303 for (blob_it.mark_cycle_pt ();
01304 !blob_it.cycled_list (); blob_it.forward ()) {
01305 blob = blob_it.data ();
01306 box = blob->bounding_box ();
01307 if (prev_box_right > -1) {
01308 gap_width = box.left () - prev_box_right;
01309 all_gap_stats.add (gap_width, 1);
01310 if (blob_it.at_first ()) {
01311 if (gap_width < min_inter_word_gap)
01312 min_inter_word_gap = gap_width;
01313 }
01314 else {
01315 if (gap_width > max_inter_char_gap)
01316 max_inter_char_gap = gap_width;
01317 }
01318 }
01319 prev_box_right = box.right ();
01320 }
01321 }
01322 else {
01323 cblob_it.set_to_list (word->cblob_list ());
01324 for (cblob_it.mark_cycle_pt ();
01325 !cblob_it.cycled_list (); cblob_it.forward ()) {
01326 cblob = cblob_it.data ();
01327 box = cblob->bounding_box ();
01328 if (prev_box_right > -1) {
01329 gap_width = box.left () - prev_box_right;
01330 all_gap_stats.add (gap_width, 1);
01331 if (cblob_it.at_first ()) {
01332 if (gap_width < min_inter_word_gap)
01333 min_inter_word_gap = gap_width;
01334 }
01335 else {
01336 if (gap_width > max_inter_char_gap)
01337 max_inter_char_gap = gap_width;
01338 }
01339 }
01340 prev_box_right = box.right ();
01341 }
01342 }
01343 }
01344 }
01345 tprintf ("Max inter char gap = %d.\nMin inter word gap = %d.\n",
01346 max_inter_char_gap, min_inter_word_gap);
01347 all_gap_stats.short_print (NULL, TRUE);
01348 all_gap_stats.smooth (2);
01349 tprintf ("SMOOTHED DATA...\n");
01350 all_gap_stats.short_print (NULL, TRUE);
01351 }
01352 }
01353 }
01354
01355
01359 void row_space_stat(
01360 BLOCK_LIST *block_list,
01361 BOX &selection_box) {
01362 BLOCK_IT block_it(block_list);
01363 BLOCK *block;
01364 ROW_IT row_it;
01365 ROW *row;
01366 int block_idx = 0;
01367 int row_idx;
01368 STATS all_gap_stats (0, MAXSPACING);
01369 WERD_IT word_it;
01370 WERD *word;
01371 PBLOB_IT blob_it;
01372 PBLOB *blob;
01373 C_BLOB_IT cblob_it;
01374 C_BLOB *cblob;
01375 BOX box;
01376 INT16 prev_box_right;
01377 INT16 gap_width;
01378 INT16 min_inter_word_gap;
01379 INT16 max_inter_char_gap;
01380
01381
01382
01383 for (block_it.mark_cycle_pt ();
01384 !block_it.cycled_list (); block_it.forward ()) {
01385 block_idx++;
01386 block = block_it.data ();
01387 if (block->bounding_box ().overlap (selection_box)) {
01388 row_it.set_to_list (block->row_list ());
01389 row_idx = 0;
01390 for (row_it.mark_cycle_pt ();
01391 !row_it.cycled_list (); row_it.forward ()) {
01392 row_idx++;
01393 row = row_it.data ();
01394 if (row->bounding_box ().overlap (selection_box)) {
01395
01396
01397 tprintf ("\nBlock %d Row %d\n", block_idx, row_idx);
01398 min_inter_word_gap = 3000;
01399 max_inter_char_gap = 0;
01400 prev_box_right = -1;
01401 all_gap_stats.clear ();
01402 word_it.set_to_list (row->word_list ());
01403 for (word_it.mark_cycle_pt ();
01404 !word_it.cycled_list (); word_it.forward ()) {
01405 word = word_it.data ();
01406 if (word->flag (W_POLYGON)) {
01407 blob_it.set_to_list (word->blob_list ());
01408 for (blob_it.mark_cycle_pt ();
01409 !blob_it.cycled_list (); blob_it.forward ()) {
01410 blob = blob_it.data ();
01411 box = blob->bounding_box ();
01412 if (prev_box_right > -1) {
01413 gap_width = box.left () - prev_box_right;
01414 all_gap_stats.add (gap_width, 1);
01415 if (blob_it.at_first ()) {
01416 if (gap_width < min_inter_word_gap)
01417 min_inter_word_gap = gap_width;
01418 }
01419 else {
01420 if (gap_width > max_inter_char_gap)
01421 max_inter_char_gap = gap_width;
01422 }
01423 }
01424 prev_box_right = box.right ();
01425 }
01426 }
01427 else {
01428 cblob_it.set_to_list (word->cblob_list ());
01429 for (cblob_it.mark_cycle_pt ();
01430 !cblob_it.cycled_list (); cblob_it.forward ()) {
01431 cblob = cblob_it.data ();
01432 box = cblob->bounding_box ();
01433 if (prev_box_right > -1) {
01434 gap_width = box.left () - prev_box_right;
01435 all_gap_stats.add (gap_width, 1);
01436 if (cblob_it.at_first ()) {
01437 if (gap_width < min_inter_word_gap)
01438 min_inter_word_gap = gap_width;
01439 }
01440 else {
01441 if (gap_width > max_inter_char_gap)
01442 max_inter_char_gap = gap_width;
01443 }
01444 }
01445 prev_box_right = box.right ();
01446 }
01447 }
01448 }
01449 tprintf
01450 ("Max inter char gap = %d.\nMin inter word gap = %d.\n",
01451 max_inter_char_gap, min_inter_word_gap);
01452 all_gap_stats.short_print (NULL, TRUE);
01453 all_gap_stats.smooth (2);
01454 tprintf ("SMOOTHED DATA...\n");
01455 all_gap_stats.short_print (NULL, TRUE);
01456 }
01457 }
01458 }
01459 }
01460 }
01461
01462
01467 void show_point(
01468 BLOCK_LIST *block_list,
01469 float x,
01470 float y) {
01471 FCOORD pt(x, y);
01472 BOX box;
01473 BLOCK_IT block_it(block_list);
01474 BLOCK *block;
01475 ROW_IT row_it;
01476 ROW *row;
01477 WERD_IT word_it;
01478 WERD *word;
01479 PBLOB_IT blob_it;
01480 PBLOB *blob;
01481 C_BLOB_IT cblob_it;
01482 C_BLOB *cblob;
01483
01484 char msg[160];
01485 char *msg_ptr = msg;
01486
01487 msg_ptr += sprintf (msg_ptr, "Pt:(%0.3f, %0.3f) ", x, y);
01488
01489 for (block_it.mark_cycle_pt ();
01490 !block_it.cycled_list (); block_it.forward ()) {
01491 block = block_it.data ();
01492 if (block->bounding_box ().contains (pt)) {
01493 row_it.set_to_list (block->row_list ());
01494 for (row_it.mark_cycle_pt ();
01495 !row_it.cycled_list (); row_it.forward ()) {
01496 row = row_it.data ();
01497 if (row->bounding_box ().contains (pt)) {
01498 msg_ptr += sprintf (msg_ptr, "BL(x)=%0.3f ",
01499 row->base_line (x));
01500
01501 word_it.set_to_list (row->word_list ());
01502 for (word_it.mark_cycle_pt ();
01503 !word_it.cycled_list (); word_it.forward ()) {
01504 word = word_it.data ();
01505 box = word->bounding_box ();
01506 if (box.contains (pt)) {
01507 msg_ptr += sprintf (msg_ptr,
01508 "Wd(%d, %d)/(%d, %d) ",
01509 box.left (), box.bottom (),
01510 box.right (), box.top ());
01511
01512 if (word->flag (W_POLYGON)) {
01513 blob_it.set_to_list (word->blob_list ());
01514 for (blob_it.mark_cycle_pt ();
01515 !blob_it.cycled_list ();
01516 blob_it.forward ()) {
01517 blob = blob_it.data ();
01518 box = blob->bounding_box ();
01519 if (box.contains (pt)) {
01520 msg_ptr += sprintf (msg_ptr,
01521 "Blb(%d, %d)/(%d, %d) ",
01522 box.left (),
01523 box.bottom (),
01524 box.right (),
01525 box.top ());
01526 }
01527 }
01528 }
01529 else {
01530 cblob_it.set_to_list (word->cblob_list ());
01531 for (cblob_it.mark_cycle_pt ();
01532 !cblob_it.cycled_list ();
01533 cblob_it.forward ()) {
01534 cblob = cblob_it.data ();
01535 box = cblob->bounding_box ();
01536 if (box.contains (pt)) {
01537 msg_ptr += sprintf (msg_ptr,
01538 "CBlb(%d, %d)/(%d, %d) ",
01539 box.left (),
01540 box.bottom (),
01541 box.right (),
01542 box.top ());
01543 }
01544 }
01545 }
01546 }
01547 }
01548 }
01549 }
01550 }
01551 }
01552 command_window->msg (msg);
01553 }
01554
01555
01560 BOOL8 word_blank_and_set_display(
01561 BLOCK *block,
01562 ROW *row,
01563 WERD *word
01564 ) {
01565 word->bounding_box ().plot (image_win, INT_SOLID, FALSE, BLACK, BLACK);
01566 return word_set_display (block, row, word);
01567 }
01568
01569
01573 BOOL8 word_bln_display(
01574 BLOCK *,
01575 ROW *row,
01576 WERD *word
01577 ) {
01578 WERD *bln_word;
01579
01580 bln_word = word->poly_copy (row->x_height ());
01581 bln_word->baseline_normalise (row);
01582 clear_view_surface (bln_word_window_handle ());
01583 display_bln_lines (bln_word_window_handle (), CYAN, 1.0, 0.0f, -1000.0f,
01584 1000.0f);
01585 bln_word->plot (bln_word_window_handle (), RED);
01586 delete bln_word;
01587 return TRUE;
01588 }
01589
01590
01594 BOOL8 word_change_text(
01595 BLOCK *block,
01596 ROW *row,
01597 WERD *word
01598 ) {
01599 char response_str[MAX_CHARS + 1];
01600
01601 strcpy (response_str, word->text ());
01602 if (!command_window->
01603 prompt ("Enter/edit the correct text and press <<RETURN>>",
01604 response_str))
01605 return FALSE;
01606 else
01607 word->set_text (response_str);
01608
01609 if (word_display_mode.bit (DF_TEXT) || word->display_flag (DF_TEXT)) {
01610 word_blank_and_set_display(block, row, word);
01611 overlap_picture_ops(TRUE);
01612 }
01613
01614 *current_image_changed = TRUE;
01615 return TRUE;
01616 }
01617
01618
01622 BOOL8 word_copy(
01623 BLOCK *block,
01624 ROW *row,
01625 WERD *word
01626 ) {
01627 WERD *copy_word = new WERD;
01628
01629 *copy_word = *word;
01630 add_word(copy_word, row, block, other_block_list);
01631 *other_image_changed = TRUE;
01632 return TRUE;
01633 }
01634
01635
01639 BOOL8 word_delete(
01640 BLOCK *block,
01641 ROW *row,
01642 WERD *word,
01643 BLOCK_IT &block_it,
01644 ROW_IT &row_it,
01645 WERD_IT &word_it
01646 ) {
01647 word_it.extract ();
01648 word->bounding_box ().plot (image_win, INT_SOLID, FALSE, BLACK, BLACK);
01649 delete(word);
01650
01651 if (word_it.empty ()) {
01652
01653 row_it.extract ();
01654 row->bounding_box ().plot (image_win, INT_SOLID, FALSE, BLACK, BLACK);
01655 delete(row);
01656
01657 if (row_it.empty ()) {
01658
01659 block_it.extract ();
01660 block->bounding_box ().plot (image_win, INT_SOLID, FALSE,
01661 BLACK, BLACK);
01662 delete(block);
01663 }
01664 }
01665 *current_image_changed = TRUE;
01666 return TRUE;
01667 }
01668
01669
01673 BOOL8 word_display(
01674 BLOCK *,
01675 ROW *row,
01676 WERD *word
01677 ) {
01678 BOX word_bb;
01679 int word_height;
01680 BOOL8 displayed_something = FALSE;
01681 BOOL8 displayed_rainbow = FALSE;
01682 float shift;
01683 PBLOB_IT it;
01684 C_BLOB_IT c_it;
01685 WERD *word_ptr;
01686 WERD temp_word;
01687 float scale_factor;
01688
01689
01690
01691
01692
01693
01694
01695 if (word->display_flag (DF_BOX)) {
01696 word->bounding_box ().plot (image_win, INT_HOLLOW, TRUE,
01697 (COLOUR) ((INT32)
01698 editor_image_word_bb_color),
01699 (COLOUR) ((INT32)
01700 editor_image_word_bb_color));
01701
01702 perimeter_color_index (image_win,
01703 (COLOUR) ((INT32) editor_image_blob_bb_color));
01704 if (word->flag (W_POLYGON)) {
01705 it.set_to_list (word->blob_list ());
01706 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
01707 it.data ()->bounding_box ().plot (image_win);
01708 }
01709 else {
01710 c_it.set_to_list (word->cblob_list ());
01711 for (c_it.mark_cycle_pt (); !c_it.cycled_list (); c_it.forward ())
01712 c_it.data ()->bounding_box ().plot (image_win);
01713 }
01714 displayed_something = TRUE;
01715 }
01716
01717
01718 if (word->display_flag (DF_EDGE_STEP) &&
01719 !word->flag (W_POLYGON)) {
01720 word->plot (image_win);
01721 displayed_something = TRUE;
01722 displayed_rainbow = TRUE;
01723 }
01724
01725
01726 if (word->display_flag (DF_POLYGONAL)) {
01727
01728 if (!word->flag (W_POLYGON)) {
01729 word_ptr = word->poly_copy (row->x_height ());
01730
01731
01732
01733 if (displayed_rainbow)
01734
01735 word_ptr->plot (image_win, WHITE);
01736 else
01737
01738 word_ptr->plot (image_win);
01739 delete word_ptr;
01740 }
01741 else {
01742 if (displayed_rainbow)
01743
01744 word->plot (image_win, WHITE);
01745 else
01746 word->plot (image_win);
01747 }
01748
01749 displayed_rainbow = TRUE;
01750 displayed_something = TRUE;
01751 }
01752
01753
01754 if (word->display_flag (DF_BN_POLYGONAL)) {
01755
01756 if (!word->flag (W_POLYGON)) {
01757 word_ptr = word->poly_copy (row->x_height ());
01758 temp_word = *word_ptr;
01759 delete word_ptr;
01760
01761
01762
01763 }
01764 else
01765 temp_word = *word;
01766 word_bb = word->bounding_box ();
01767 if (!temp_word.flag (W_NORMALIZED))
01768 temp_word.baseline_normalise (row);
01769
01770 scale_factor = re_scale_and_move_bln_word (&temp_word, word_bb);
01771 display_bln_lines (image_win, CYAN, scale_factor, word_bb.bottom (),
01772 word_bb.left (), word_bb.right ());
01773
01774 if (displayed_rainbow)
01775
01776 temp_word.plot (image_win, WHITE);
01777 else
01778 temp_word.plot (image_win);
01779
01780 displayed_rainbow = TRUE;
01781 displayed_something = TRUE;
01782 }
01783
01784
01785 if (word->display_flag (DF_TEXT)) {
01786 word_bb = word->bounding_box ();
01787 text_color_index (image_win,
01788 (COLOUR) ((INT32) editor_image_text_color));
01789 text_font_index (image_win, 1);
01790 word_height = word_bb.height ();
01791 character_height (image_win, 0.75 * word_height);
01792
01793 if (word_height < word_bb.width ())
01794 shift = 0.25 * word_height;
01795 else
01796 shift = 0.0f;
01797
01798 text2d (image_win,
01799 word_bb.left () + shift,
01800 word_bb.bottom () + 0.25 * word_height,
01801 word->text (), 0, FALSE);
01802 if (strlen (word->text ()) > 0)
01803 displayed_something = TRUE;
01804 }
01805
01806 if (!displayed_something)
01807 word->bounding_box ().plot (image_win, INT_HOLLOW, TRUE,
01808 (COLOUR) ((INT32) editor_image_word_bb_color),
01809 (COLOUR) ((INT32)
01810 editor_image_word_bb_color));
01811 return TRUE;
01812 }
01813
01814
01818 BOOL8 word_dumper(
01819 BLOCK *block,
01820 ROW *row,
01821 WERD *word
01822 ) {
01823
01824 tprintf ("\nBlock data...\n");
01825 block->print (NULL, FALSE);
01826 tprintf ("\nRow data...\n");
01827 row->print (NULL);
01828 tprintf ("\nWord data...\n");
01829 word->print (NULL);
01830 return TRUE;
01831 }
01832
01833
01837 BOOL8 word_set_display(
01838 BLOCK *block,
01839 ROW *row,
01840 WERD *word
01841 ) {
01842 BOX word_bb;
01843
01844 word->set_display_flag (DF_BOX, word_display_mode.bit (DF_BOX));
01845 word->set_display_flag (DF_TEXT, word_display_mode.bit (DF_TEXT));
01846 word->set_display_flag (DF_POLYGONAL, word_display_mode.bit (DF_POLYGONAL));
01847 word->set_display_flag (DF_EDGE_STEP, word_display_mode.bit (DF_EDGE_STEP));
01848 word->set_display_flag (DF_BN_POLYGONAL,
01849 word_display_mode.bit (DF_BN_POLYGONAL));
01850 *current_image_changed = TRUE;
01851 return word_display (block, row, word);
01852 }
01853
01854
01858 BOOL8 word_toggle_seg(
01859 BLOCK *,
01860 ROW *,
01861 WERD *word
01862 ) {
01863 word->set_flag (W_SEGMENTED, !word->flag (W_SEGMENTED));
01864 *current_image_changed = TRUE;
01865 return TRUE;
01866 }
01867
01871 void do_check_mem(
01872 INT32 level) {
01873 check_mem ("Doing it", level);
01874 }