pgedit.cpp
来自「一个google的OCR源码」· C++ 代码 · 共 1,866 行 · 第 1/4 页
CPP
1,866 行
/********************************************************************** * File: pgedit.cpp (Formerly pgeditor.c) * Description: Page structure file editor * Author: Phil Cheatle * Created: Thu Oct 10 16:25:24 BST 1991 * *(C) Copyright 1991, Hewlett-Packard Ltd. ** Licensed under the Apache License, Version 2.0(the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** http:// www.apache.org/licenses/LICENSE-2.0 ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. * **********************************************************************/#include "pgedit.h"#include <ctype.h>#include <math.h>#include "genblob.h"#include "tessio.h"#include "tessout.h"#include "tordmain.h"#include "statistc.h"#include "debugwin.h"#include "svshowim.h"#include "mainblk.h"#include "varabled.h"#include "string.h"#include "scrollview.h"#include "svmnode.h"#include "control.h"#define ASC_HEIGHT (2 * bln_baseline_offset + bln_x_height)#define X_HEIGHT (bln_baseline_offset + bln_x_height)#define BL_HEIGHT bln_baseline_offset#define DESC_HEIGHT 0#define MAXSPACING 128 /*max expected spacing in pix */const ERRCODE EMPTYBLOCKLIST = "No blocks to edit";extern IMAGE page_image;enum CMD_EVENTS{ NULL_CMD_EVENT, DELETE_CMD_EVENT, COPY_CMD_EVENT, CHANGE_DISP_CMD_EVENT, CHANGE_TEXT_CMD_EVENT, TOGGLE_SEG_CMD_EVENT, DUMP_WERD_CMD_EVENT, SHOW_POINT_CMD_EVENT, ROW_SPACE_STAT_CMD_EVENT, BLOCK_SPACE_STAT_CMD_EVENT, SHOW_BLN_WERD_CMD_EVENT, SEGMENT_WERD_CMD_EVENT, BOUNDING_BOX_CMD_EVENT, CORRECT_TEXT_CMD_EVENT, POLYGONAL_CMD_EVENT, BL_NORM_CMD_EVENT, BITMAP_CMD_EVENT, TIDY_CMD_EVENT, VIEW_CMD_EVENT, IMAGE_CMD_EVENT, BLOCKS_CMD_EVENT, BASELINES_CMD_EVENT, WRITE_CMD_EVENT, NEW_SOURCE_CMD_EVENT, UNIFORM_DISP_CMD_EVENT, REFRESH_CMD_EVENT, QUIT_CMD_EVENT, RECOG_WERDS, RECOG_PSEUDO};/********************************************************************** * * Some global data * **********************************************************************/ScrollView* image_win;#ifndef GRAPHICS_DISABLEDVariablesEditor* ve;#endifbool stillRunning = false;#ifdef __UNIX__FILE *debug_window = NULL; // opened on demand#endif // baseline norm wordsScrollView* bln_word_window = NULL;CMD_EVENTS mode = CHANGE_DISP_CMD_EVENT; // Selected words opBITS16 word_display_mode;BOOL8 display_image = FALSE;BOOL8 display_blocks = FALSE;BOOL8 display_baselines = FALSE;BOOL8 viewing_source = TRUE;BLOCK_LIST *source_block_list = NULL; // image blocksBLOCK_LIST target_block_list; // target blocksBLOCK_LIST *other_block_list = &target_block_list;BOOL8 source_changed = FALSE; // Changes not savedBOOL8 target_changed = FALSE; // Changes not savedBOOL8 *other_image_changed = &target_changed;/* Public globals */#define EXTERNEXTERN BLOCK_LIST *current_block_list = NULL;EXTERN BOOL8 *current_image_changed = &source_changed;/* Variables */EXTERN STRING_VAR(editor_image_win_name, "EditorImage","Editor image window name");EXTERN INT_VAR(editor_image_xpos, 590, "Editor image X Pos");EXTERN INT_VAR(editor_image_ypos, 10, "Editor image Y Pos");EXTERN INT_VAR(editor_image_menuheight, 50, "Add to image height for menu bar");EXTERN INT_VAR(editor_image_word_bb_color, ScrollView::BLUE,"Word bounding box colour");EXTERN INT_VAR(editor_image_blob_bb_color, ScrollView::YELLOW,"Blob bounding box colour");EXTERN INT_VAR(editor_image_text_color, ScrollView::WHITE,"Correct text colour");EXTERN STRING_VAR(editor_dbwin_name, "EditorDBWin","Editor debug window name");EXTERN INT_VAR(editor_dbwin_xpos, 50, "Editor debug window X Pos");EXTERN INT_VAR(editor_dbwin_ypos, 500, "Editor debug window Y Pos");EXTERN INT_VAR(editor_dbwin_height, 24, "Editor debug window height");EXTERN INT_VAR(editor_dbwin_width, 80, "Editor debug window width");EXTERN STRING_VAR(editor_word_name, "BlnWords", "BL normalised word window");EXTERN INT_VAR(editor_word_xpos, 60, "Word window X Pos");EXTERN INT_VAR(editor_word_ypos, 510, "Word window Y Pos");EXTERN INT_VAR(editor_word_height, 240, "Word window height");EXTERN INT_VAR(editor_word_width, 655, "Word window width");EXTERN double_VAR(editor_smd_scale_factor, 1.0, "Scaling for smd image");/********************************************************************** * add_word() * * Inserts the a word into a specified block list. The list is searched for a * block and row of the same file as those of the word to be added, which * contain the bounding box of the word. If such a row is found, the new * word is inserted into the row in the correct X order. If the * block is found, but not the row, a copy of the word's old row is added to * the block in the correct Y order, and the word is put in that row. * If neither the row nor the block are found, then the word's old block is * copied with only the word's row. It is added to the block list in the * correct Y order. **********************************************************************/void add_word( // to block list WERD *word, // word to be added ROW *src_row, // source row BLOCK *src_block, // source block BLOCK_LIST *dest_block_list // add to this ) { BLOCK_IT block_it(dest_block_list); BLOCK *block; // current block BLOCK *dest_block = NULL; // destination block ROW_IT row_it; ROW *row; // destination row ROW *dest_row = NULL; // destination row WERD_IT word_it; TBOX word_box = word->bounding_box(); TBOX insert_point_word_box; BOOL8 seen_blocks_for_current_file = FALSE; block_it.mark_cycle_pt(); while(!block_it.cycled_list() &&(dest_block == NULL)) { block = block_it.data(); if ((block->bounding_box().contains(word_box)) && (strcmp(block->name(), src_block->name()) == 0)) { dest_block = block; // found dest block row_it.set_to_list(block->row_list()); row_it.mark_cycle_pt(); while((!row_it.cycled_list()) &&(dest_row == NULL)) { row = row_it.data(); if (row->bounding_box().contains(word_box)) dest_row = row; // found dest row else row_it.forward(); } } else block_it.forward(); } if (dest_block == NULL) { // make a new one dest_block = new BLOCK; *dest_block = *src_block; block_it.set_to_list(dest_block_list); for (block_it.mark_cycle_pt(); !block_it.cycled_list(); block_it.forward()) { block = block_it.data(); if (!seen_blocks_for_current_file && (strcmp(block->name(), dest_block->name()) == 0)) seen_blocks_for_current_file = TRUE; if (seen_blocks_for_current_file && ((strcmp(block->name(), dest_block->name()) != 0) || (block->bounding_box().top() < dest_block->bounding_box().top()))) break; } if (block_it.cycled_list()) // didn't find insrt pt block_it.add_to_end(dest_block); else // did find insert pt block_it.add_before_stay_put(dest_block); } if (dest_row == NULL) { // make a new one dest_row = new ROW; *dest_row = *src_row; row_it.set_to_list(dest_block->row_list()); for (row_it.mark_cycle_pt(); !row_it.cycled_list(); row_it.forward()) { if (row_it.data()->bounding_box().top() < dest_row->bounding_box().top()) break; } if (row_it.cycled_list()) // didn't find insrt pt row_it.add_to_end(dest_row); else // did find insert pt row_it.add_before_stay_put(dest_row); } /* dest_block and dest_row are now found or built and inserted as necessesary so add the word to dest row */ word_it.set_to_list(dest_row->word_list()); for (word_it.mark_cycle_pt(); !word_it.cycled_list(); word_it.forward()) { if (word_it.data()->bounding_box().right() >= word_box.left()) break; } if (word_it.cycled_list()) word_it.add_to_end(word); // didn't find insrt pt else { // did find insert pt insert_point_word_box = word_it.data()->bounding_box(); if (insert_point_word_box.contains(word_box) || word_box.contains(insert_point_word_box)) image_win->AddMessage("Refusing to add words which obliterate," " or are obliterated by, others"); else { if (word_it.data()->bounding_box().left() > word->bounding_box().left()) // infront of insert pt word_it.add_before_stay_put(word); else // behind insert pt word_it.add_after_stay_put(word); } }}/********************************************************************** * bln_word_window_handle() * * Return a WINDOW for the word window, creating it if necessary **********************************************************************/class BlnEventHandler : public SVEventHandler { public: void Notify(const SVEvent* sv_event) { if (sv_event->type == SVET_DESTROY) bln_word_window = NULL; else if (sv_event->type == SVET_CLICK) show_point(current_block_list, sv_event->x, sv_event->y); }};ScrollView* bln_word_window_handle() { // return handle // not opened yet if (bln_word_window == NULL) { pgeditor_msg("Creating BLN word window..."); bln_word_window = new ScrollView(editor_word_name.string(), editor_word_xpos, editor_word_ypos, editor_word_width, editor_word_height, 4000, 4000, true); BlnEventHandler* a = new BlnEventHandler(); bln_word_window->AddEventHandler(a); pgeditor_msg("Creating BLN word window...Done"); } return bln_word_window;}/********************************************************************** * build_image_window() * * Destroy the existing image window if there is one. Work out how big the * new window needs to be. Create it and re-display. **********************************************************************/void build_image_window(TBOX page_bounding_box) { if (image_win != NULL) { delete image_win; } image_win = new ScrollView(editor_image_win_name.string(), editor_image_xpos, editor_image_ypos, page_bounding_box.right() + 1, page_bounding_box.top() + editor_image_menuheight + 1, page_bounding_box.right() + 1, page_bounding_box.top() + 1, true);}/********************************************************************** * build_menu() * * Construct the menu tree used by the command window **********************************************************************/SVMenuNode *build_menu_new() { SVMenuNode* parent_menu; SVMenuNode* root_menu_item = new SVMenuNode(); SVMenuNode* modes_menu_item = root_menu_item->AddChild("MODES"); modes_menu_item->AddChild("Change Display", CHANGE_DISP_CMD_EVENT); modes_menu_item->AddChild("Delete", DELETE_CMD_EVENT); modes_menu_item->AddChild("Copy to TARGET", COPY_CMD_EVENT); modes_menu_item->AddChild("Change Text", CHANGE_TEXT_CMD_EVENT); modes_menu_item->AddChild("Toggle Correct Seg Flg", TOGGLE_SEG_CMD_EVENT); modes_menu_item->AddChild("Dump Word", DUMP_WERD_CMD_EVENT); modes_menu_item->AddChild("Show Point", SHOW_POINT_CMD_EVENT); modes_menu_item->AddChild("Row gaps hist", ROW_SPACE_STAT_CMD_EVENT); modes_menu_item->AddChild("Block gaps hist", BLOCK_SPACE_STAT_CMD_EVENT); modes_menu_item->AddChild("Show BL Norm Word", SHOW_BLN_WERD_CMD_EVENT); modes_menu_item->AddChild("Re-Segment Word", SEGMENT_WERD_CMD_EVENT); modes_menu_item->AddChild("Recog Words", RECOG_WERDS); modes_menu_item->AddChild("Recog Blobs", RECOG_PSEUDO); parent_menu = root_menu_item->AddChild("DISPLAY"); parent_menu->AddChild("Bounding Boxes", BOUNDING_BOX_CMD_EVENT, TRUE); parent_menu->AddChild("Correct Text", CORRECT_TEXT_CMD_EVENT, FALSE); parent_menu->AddChild("Polygonal Approx", POLYGONAL_CMD_EVENT, FALSE); parent_menu->AddChild("Baseline Normalised", BL_NORM_CMD_EVENT, FALSE); parent_menu->AddChild("Edge Steps", BITMAP_CMD_EVENT, FALSE); parent_menu = root_menu_item->AddChild("OTHER"); parent_menu->AddChild("Quit", QUIT_CMD_EVENT); parent_menu->AddChild("Tidy Target", TIDY_CMD_EVENT); parent_menu->AddChild("View TARGET", VIEW_CMD_EVENT, FALSE); parent_menu->AddChild("Show Image", IMAGE_CMD_EVENT, FALSE); parent_menu->AddChild("ShowBlock Outlines", BLOCKS_CMD_EVENT, FALSE); parent_menu->AddChild("Show Baselines", BASELINES_CMD_EVENT, FALSE); parent_menu->AddChild("Write File", WRITE_CMD_EVENT, imagebasename.string()); parent_menu->AddChild("New Source File", NEW_SOURCE_CMD_EVENT, imagebasename.string()); parent_menu->AddChild("Uniform Display", UNIFORM_DISP_CMD_EVENT); parent_menu->AddChild("Refresh Display", REFRESH_CMD_EVENT); return root_menu_item;}/********************************************************************** * display_bln_lines() * * Display normalised baseline, x-height, ascender limit and descender limit **********************************************************************/void display_bln_lines(ScrollView* window, ScrollView::Color colour, float scale_factor, float y_offset, float minx, float maxx) { window->Pen(colour); window->Line(minx, y_offset + scale_factor * DESC_HEIGHT, maxx, y_offset + scale_factor * DESC_HEIGHT); window->Line(minx, y_offset + scale_factor * BL_HEIGHT, maxx, y_offset + scale_factor * BL_HEIGHT); window->Line(minx, y_offset + scale_factor * X_HEIGHT, maxx, y_offset + scale_factor * X_HEIGHT); window->Line(minx, y_offset + scale_factor * ASC_HEIGHT, maxx, y_offset + scale_factor * ASC_HEIGHT);}/********************************************************************** * do_new_source() * * Change to another source file. Automatically tidy page first * **********************************************************************/void do_new_source( // serialise ) { FILE *infp; // input file char* name = image_win->ShowInputDialog("New Source File name"); STRING name_str(name); delete[] name; if (source_changed) { int a = image_win->ShowYesNoDialog( "Source changes will be LOST. Continue?(Y/N)"); if (a != 'y') { image_win->AddMessage("Write cancelled"); return; } } // if not file exists if (!(infp = fopen(name_str.string(), "r"))) { image_win->AddMessage("Cant open file " "%s" "", name_str.string()); return; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?