00001
00023 #include "mfcpch.h"
00024 #include "ocrshell.h"
00025 #include "tprintf.h"
00026 #include <stdlib.h>
00027
00028 #define EXTERN
00029
00030 #ifdef __UNIX__
00031 EXTERN ESHM_INFO shm;
00032 #define TICKS 1
00033 #endif
00034
00035 #ifdef __MSW32__
00036 EXTERN ESHM_INFO shm;
00037 #define TICKS 1000
00038 #endif
00039
00040 #ifdef __MAC__
00041
00042 #if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
00043 #pragma import on
00044 #endif
00045
00046 extern volatile ESHM_INFO shm;
00047 extern unsigned short WaitForSingleObject(
00048 volatile Boolean &semaphore,
00049 unsigned long timeout);
00050 extern unsigned short ReleaseSemaphore(
00051 volatile Boolean &semaphore);
00052 #if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
00053 #pragma import reset
00054 #endif
00055 #define WAIT_OBJECT_0 1
00056 #define TICKS 60
00057 #endif
00058
00063 typedef enum {
00064 OCS_UNINIT,
00065 OCS_SETUP_SHM,
00066 OCS_SETUP_INFO,
00067 OCS_READING_STRIPS,
00068 OCS_READ_STRIPS,
00069 OCS_RECOGNIZING,
00070 OCS_SENDING_TEXT,
00071 OCS_DEAD
00072 } OCR_STATE;
00073
00074
00075 INT16 ocr_internal_shutdown();
00076 INT16 wait_for_mutex();
00077 INT16 wait_for_hp(
00078 INT32 timeout
00079 );
00080 INT16 release_mutex();
00081 INT16 release_ocr();
00082
00083 static INT32 font_count = 0;
00084 static INT16 lines_read = 0;
00085
00086 static OCR_STATE ocr_state = OCS_UNINIT;
00087
00088 #ifdef __MAC__
00089 pascal short TerminateOCR(AppleEvent *theEvent,
00090 AppleEvent *theReply,
00091 long refCon) {
00092 ocr_internal_shutdown();
00093 ExitToShell();
00094
00095 }
00096 #endif
00097
00098
00115 #ifdef __MAC__
00116 INT16
00117 ocr_open_shm (UINT16 * lang)
00118 #else
00119 INT16
00120 ocr_open_shm (
00121 const char *shm_h,
00122 const char *shm_size,
00123 const char *mutex_h,
00124 const char *ocr_h,
00125 const char *hp_h,
00126 const char *lang_str,
00127 UINT16 * lang
00128 )
00129 #endif
00130 {
00131 font_count = 0;
00132 #ifdef __MAC__
00133 if (shm.OCRProcess.lowLongOfPSN && shm.OCRProcess.highLongOfPSN)
00134 return HPERR;
00135 *lang = shm.language;
00136 GetCurrentProcess (&shm.OCRProcess);
00137 if (WakeUpProcess (&shm.IPEProcess))
00138 ExitToShell();
00139 AEInstallEventHandler (kCoreEventClass, kAEQuitApplication,
00140 (AEEventHandlerUPP) TerminateOCR, 0, FALSE);
00141 #else
00142 if (lang != NULL)
00143
00144 *lang = (UINT16) strtol (lang_str, NULL, 10);
00145 #endif // __MAC__
00146 if (ocr_state != OCS_UNINIT) {
00147 ocr_error(OCR_ERR_BAD_STATE);
00148 return OCR_API_BAD_STATE;
00149 }
00150 #ifdef __MSW32__
00151 shm.shm_size = strtol (shm_size, NULL, 10);
00152
00153 shm.shm_hand = (HANDLE) strtol (shm_h, NULL, 10);
00154 shm.shm_mem = MapViewOfFile (shm.shm_hand, FILE_MAP_WRITE, 0, 0, 0);
00155 if (shm.shm_mem == NULL)
00156 return HPERR;
00157
00158 shm.mutex = (HANDLE) strtol (mutex_h, NULL, 10);
00159
00160 shm.ocr_sem = (HANDLE) strtol (ocr_h, NULL, 10);
00161
00162 shm.hp_sem = (HANDLE) strtol (hp_h, NULL, 10);
00163 #endif //__MSW32__
00164
00165 ocr_state = OCS_SETUP_SHM;
00166 return OKAY;
00167
00168 }
00169
00170
00171
00179 void ocr_error(
00180 OCR_ERR_CODE code
00181 ) {
00182 ESTRIP_DESC *strip = (ESTRIP_DESC *) shm.shm_mem;
00183
00184 ETEXT_DESC *monitor = (ETEXT_DESC *) shm.shm_mem;
00185
00186
00187 switch (ocr_state) {
00188 case OCS_UNINIT:
00189 case OCS_DEAD:
00190 return;
00191 case OCS_SETUP_SHM:
00192 if (font_count < 1)
00193 font_count = 1;
00194 ocr_setup_startinfo_ansi (-code, LANGE_NONE, "", "");
00195
00196 break;
00197 case OCS_SETUP_INFO:
00198 if (ocr_get_first_image_strip () == NULL)
00199 break;
00200 case OCS_READING_STRIPS:
00201 strip->x_size = -code;
00202 release_ocr();
00203 release_mutex();
00204 break;
00205 case OCS_READ_STRIPS:
00206 monitor->count = 0;
00207 monitor->progress = 0;
00208
00209 monitor->more_to_come = FALSE;
00210 monitor->ocr_alive = TRUE;
00211 monitor->err_code = -code;
00212 monitor->cancel = FALSE;
00213 release_ocr();
00214 break;
00215 case OCS_RECOGNIZING:
00216 case OCS_SENDING_TEXT:
00217 monitor->err_code = -code;
00218 release_ocr();
00219 }
00220 ocr_internal_shutdown();
00221 }
00222
00223
00224
00230 INT16 ocr_append_fontinfo(
00231 UINT16 language,
00232 UINT8 font_family,
00233 UINT8 char_set,
00234 UINT8 pitch,
00235 const char *name
00236 ) {
00237 EOCR_DESC *desc;
00238 int index;
00239 INT32 font_index;
00240
00241 if (ocr_state != OCS_SETUP_SHM) {
00242 ocr_error(OCR_ERR_BAD_STATE);
00243 return OCR_API_BAD_STATE;
00244 }
00245
00246
00247 desc = (EOCR_DESC *) shm.shm_mem;
00248 if (font_count >
00249 (INT32) ((shm.shm_size - sizeof (EOCR_DESC)) / sizeof (EFONT_DESC)))
00250 return OCR_API_NO_MEM;
00251 font_index = font_count++;
00252
00253 desc->fonts[font_index].language = language;
00254
00255 desc->fonts[font_index].font_family = font_family;
00256
00257 desc->fonts[font_index].char_set = char_set;
00258
00259 desc->fonts[font_index].pitch = pitch;
00260 if (name != NULL) {
00261 for (index = 0; index < MAX_FONT_NAME && name[index] != 0; index++)
00262 desc->fonts[font_index].name[index] = name[index];
00263 }
00264 else
00265 index = 0;
00266 desc->fonts[font_index].name[index] = 0;
00267 return OKAY;
00268 }
00269
00270
00271
00278 INT16 ocr_setup_startinfo(
00279 INT32 protocol,
00280 UINT16 language,
00281 const UINT16 *name,
00282 const UINT16 *version
00283 ) {
00284 EOCR_DESC *desc;
00285 int index;
00286 INT16 result;
00287
00288 if (ocr_state != OCS_SETUP_SHM || font_count < 1) {
00289 ocr_error(OCR_ERR_BAD_STATE);
00290 return OCR_API_BAD_STATE;
00291 }
00292
00293
00294 desc = (EOCR_DESC *) shm.shm_mem;
00295 desc->protocol = protocol;
00296 desc->font_count = font_count;
00297 desc->language = language;
00298 for (index = 0; index < MAX_OCR_NAME && name[index] != 0; index++)
00299 desc->name[index] = name[index];
00300 desc->name[index] = 0;
00301 for (index = 0; index < MAX_OCR_VERSION && version[index] != 0; index++)
00302 desc->version[index] = version[index];
00303 desc->version[index] = 0;
00304
00305 result = release_ocr ();
00306 if (result != OKAY)
00307 return result;
00308 ocr_state = OCS_SETUP_INFO;
00309 return OKAY;
00310 }
00311
00312
00313
00319 INT16 ocr_setup_startinfo_ansi(
00320 UINT32 protocol,
00321 UINT16 language,
00322 const char *name,
00323 const char *version
00324 ) {
00325 EOCR_DESC *desc;
00326 int index;
00327 INT16 result;
00328
00329 if (ocr_state != OCS_SETUP_SHM || font_count < 1) {
00330 ocr_error(OCR_ERR_BAD_STATE);
00331 return OCR_API_BAD_STATE;
00332 }
00333
00334
00335 desc = (EOCR_DESC *) shm.shm_mem;
00336 desc->protocol = protocol;
00337 desc->font_count = font_count;
00338 desc->language = language;
00339 for (index = 0; index < MAX_OCR_NAME && name[index] != 0; index++)
00340 desc->name[index] = name[index];
00341 desc->name[index] = 0;
00342 for (index = 0; index < MAX_OCR_VERSION && version[index] != 0; index++)
00343 desc->version[index] = version[index];
00344 desc->version[index] = 0;
00345
00346 result = release_ocr ();
00347 if (result != OKAY)
00348 return result;
00349 ocr_state = OCS_SETUP_INFO;
00350 return OKAY;
00351 }
00352
00353
00354
00361 ESTRIP_DESC *ocr_get_first_image_strip() {
00362 ESTRIP_DESC *strip;
00363 INT16 result;
00364
00365 if (ocr_state != OCS_SETUP_INFO) {
00366 tprintf ("Bad state reading strip");
00367 ocr_error(OCR_ERR_BAD_STATE);
00368 return NULL;
00369 }
00370
00371
00372 strip = (ESTRIP_DESC *) shm.shm_mem;
00373 lines_read = 0;
00374
00375 result = wait_for_mutex ();
00376 if (result != OKAY) {
00377 tprintf ("Mutax wait failed reading strip");
00378 return NULL;
00379 }
00380 result = release_mutex ();
00381 if (result != OKAY) {
00382 tprintf ("Mutax release failed reading strip");
00383 return NULL;
00384 }
00385 result = wait_for_hp (READIM_TIMEOUT);
00386 if (result != OKAY) {
00387 tprintf ("Wait for HP failed reading strip");
00388 return NULL;
00389 }
00390 lines_read = strip->strip_size;
00391 if (lines_read < strip->y_size)
00392
00393 ocr_state = OCS_READING_STRIPS;
00394 else
00395 ocr_state = OCS_READ_STRIPS;
00396 if (strip->x_size == 0 || strip->y_size == 0)
00397 return NULL;
00398
00399 return strip;
00400 }
00401
00402
00403
00410 ESTRIP_DESC *ocr_get_next_image_strip() {
00411 ESTRIP_DESC *strip;
00412 INT16 result;
00413
00414 if (ocr_state != OCS_READING_STRIPS) {
00415 ocr_error(OCR_ERR_BAD_STATE);
00416 return NULL;
00417 }
00418
00419
00420 strip = (ESTRIP_DESC *) shm.shm_mem;
00421 result = release_ocr ();
00422 if (result != OKAY)
00423 return NULL;
00424 result = wait_for_hp (READIM_TIMEOUT);
00425 if (result != OKAY)
00426 return NULL;
00427
00428 lines_read += strip->strip_size;
00429 if (lines_read < strip->y_size)
00430
00431 ocr_state = OCS_READING_STRIPS;
00432 else
00433 ocr_state = OCS_READ_STRIPS;
00434
00435 return strip;
00436 }
00437
00438
00439
00445 ETEXT_DESC *ocr_setup_monitor() {
00446 ETEXT_DESC *monitor;
00447
00448
00449 monitor = (ETEXT_DESC *) shm.shm_mem;
00450 monitor->count = 0;
00451 monitor->progress = 0;
00452 monitor->more_to_come = TRUE;
00453 monitor->ocr_alive = TRUE;
00454 monitor->err_code = 0;
00455 monitor->cancel = FALSE;
00456
00457 if (release_ocr () != OKAY)
00458 return NULL;
00459
00460 ocr_state = OCS_RECOGNIZING;
00461 return monitor;
00462 }
00463
00464
00465
00471 INT32 ocr_char_space() {
00472 ETEXT_DESC *buf;
00473 int result;
00474
00475
00476 buf = (ETEXT_DESC *) shm.shm_mem;
00477 result =
00478 (shm.shm_size - sizeof (ETEXT_DESC)) / sizeof (EANYCODE_CHAR) -
00479 buf->count + 1;
00480
00481
00482
00483
00484 return result;
00485 }
00486
00487
00488
00510 INT16 ocr_append_char(
00511 UINT16 char_code,
00512 INT16 left,
00513 INT16 right,
00514 INT16 top,
00515 INT16 bottom,
00516 INT16 font_index,
00517 UINT8 confidence,
00518 UINT8 point_size,
00519 INT8 blanks,
00520 UINT8 enhancement,
00521 OCR_CHAR_DIRECTION text_dir,
00522 OCR_LINE_DIRECTION line_dir,
00523 OCR_NEWLINE_TYPE nl_type
00524 ) {
00525 ETEXT_DESC *buf;
00526 int index;
00527 INT16 result;
00528
00529 if (ocr_state != OCS_RECOGNIZING && ocr_state != OCS_SENDING_TEXT) {
00530 ocr_error(OCR_ERR_BAD_STATE);
00531 return OCR_API_BAD_STATE;
00532 }
00533
00534 if (char_code == ' ' || char_code == '\n' || char_code == '\r'
00535 || char_code == '\t')
00536 return OCR_API_BAD_CHAR;
00537
00538
00539 buf = (ETEXT_DESC *) shm.shm_mem;
00540
00541 result =
00542 (shm.shm_size - sizeof (ETEXT_DESC)) / sizeof (EANYCODE_CHAR) -
00543 buf->count;
00544 if (result < 1)
00545 return OCR_API_NO_MEM;
00546
00547 index = buf->count++;
00548
00549 buf->text[index].char_code = char_code;
00550 buf->text[index].left = left;
00551 buf->text[index].right = right;
00552 buf->text[index].top = top;
00553
00554 buf->text[index].bottom = bottom;
00555
00556 buf->text[index].font_index = font_index;
00557
00558 buf->text[index].confidence = confidence;
00559
00560 buf->text[index].point_size = point_size;
00561
00562 buf->text[index].blanks = blanks;
00563 if (nl_type == OCR_NL_NONE) {
00564 if (text_dir == OCR_CDIR_TOP_BOTTOM || text_dir == OCR_CDIR_BOTTOM_TOP)
00565 buf->text[index].formatting = (text_dir << 5) | 128;
00566
00567 else
00568
00569 buf->text[index].formatting = text_dir << 5;
00570 }
00571 else {
00572 buf->text[index].formatting = (nl_type << 6) | (line_dir << 5);
00573
00574 }
00575 buf->text[index].formatting |= enhancement & (~EUC_FORMAT_MASK);
00576 return OKAY;
00577 }
00578
00579
00580
00590 INT16 ocr_send_text(
00591 BOOL8 more_to_come
00592 ) {
00593 ETEXT_DESC *buf;
00594
00595 if (ocr_state != OCS_RECOGNIZING && ocr_state != OCS_SENDING_TEXT) {
00596 ocr_error(OCR_ERR_BAD_STATE);
00597 return OCR_API_BAD_STATE;
00598 }
00599
00600
00601 buf = (ETEXT_DESC *) shm.shm_mem;
00602
00603
00604 buf->more_to_come = more_to_come;
00605 if (more_to_come) {
00606 if ((buf->text[buf->count - 1].formatting >> 6) != OCR_NL_NEWLINE
00607 && (buf->text[buf->count - 1].formatting >> 6) != OCR_NL_NEWPARA) {
00608
00609 buf->text[buf->count - 1].formatting &= 63;
00610 buf->text[buf->count - 1].formatting |= OCR_NL_NEWLINE << 6;
00611 }
00612 }
00613 else {
00614 if (buf->count < 1)
00615 ocr_append_char ('~', -1, -1, -1, -1, 0, 100, 10, 0,
00616 0, OCR_CDIR_RIGHT_LEFT, OCR_LDIR_DOWN_RIGHT,
00617 OCR_NL_NEWPARA);
00618
00619 else if ((buf->text[buf->count - 1].formatting >> 6) != OCR_NL_NEWPARA) {
00620
00621 buf->text[buf->count - 1].formatting &= 63;
00622 buf->text[buf->count - 1].formatting |= OCR_NL_NEWPARA << 6;
00623 }
00624 }
00625
00626 if (release_ocr () != OKAY)
00627 return HPERR;
00628 if (wait_for_hp (READTEXT_TIMEOUT) != OKAY)
00629 return HPERR;
00630 if (more_to_come) {
00631 buf->count = 0;
00632 ocr_state = OCS_SENDING_TEXT;
00633 }
00634 else
00635 ocr_state = OCS_SETUP_INFO;
00636 return OKAY;
00637 }
00638
00639
00640
00647 INT16 ocr_shutdown() {
00648 #ifdef __MAC__
00649 shm.OCRProcess.lowLongOfPSN = kNoProcess;
00650 shm.OCRProcess.highLongOfPSN = 0;
00651 #endif
00652 ocr_error(OCR_ERR_CLEAN_EXIT);
00653
00654 return OKAY;
00655 }
00656
00657
00658
00665 INT16 ocr_internal_shutdown() {
00666 ocr_state = OCS_DEAD;
00667 #ifdef __MSW32__
00668 if (shm.shm_mem != NULL) {
00669 UnmapViewOfFile (shm.shm_mem);
00670 CloseHandle (shm.shm_hand);
00671 CloseHandle (shm.mutex);
00672 CloseHandle (shm.ocr_sem);
00673 CloseHandle (shm.hp_sem);
00674 shm.shm_mem = NULL;
00675 }
00676 #elif defined (__MAC__)
00677 shm.OCRProcess.lowLongOfPSN = kNoProcess;
00678 shm.OCRProcess.highLongOfPSN = 0;
00679 #endif
00680 return OKAY;
00681 }
00682
00683
00684
00691 INT16 wait_for_mutex() {
00692 INT16 result = HPERR;
00693 #if defined (__MSW32__) || defined (__MAC__)
00694 result = WaitForSingleObject (shm.mutex, (unsigned long) -1)
00695
00696
00697 == WAIT_OBJECT_0 ? OKAY : HPERR;
00698 #endif
00699 if (result != OKAY)
00700 ocr_internal_shutdown();
00701 return result;
00702 }
00703
00704
00705
00712 INT16 wait_for_hp(
00713 INT32 timeout
00714 ) {
00715 INT16 result = HPERR;
00716 #if defined (__MSW32__) || defined (__MAC__)
00717
00718 result = WaitForSingleObject (shm.hp_sem, timeout * TICKS)
00719
00720 == WAIT_OBJECT_0 ? OKAY : HPERR;
00721 #endif
00722 if (result != OKAY)
00723 ocr_internal_shutdown();
00724 return result;
00725 }
00726
00727
00728
00734 INT16 release_mutex() {
00735 INT16 result = HPERR;
00736 #ifdef __MSW32__
00737
00738 result = ReleaseMutex (shm.mutex) ? OKAY : HPERR;
00739 #elif defined (__MAC__)
00740
00741 result = ReleaseSemaphore (shm.mutex) ? OKAY : HPERR;
00742 #endif
00743 if (result != OKAY)
00744 ocr_internal_shutdown();
00745 return result;
00746 }
00747
00748
00749
00755 INT16 release_ocr() {
00756 INT32 timeout;
00757
00758 timeout = RELEASE_TIMEOUT * TICKS;
00759 #ifdef __MSW32__
00760 BOOL result = 0;
00761 do {
00762
00763 result = ReleaseSemaphore (shm.ocr_sem, 1, NULL);
00764 if (result == FALSE) {
00765 timeout -= 50;
00766 Sleep (50);
00767 }
00768 }
00769 while (result == FALSE && timeout > 0);
00770 if (!result)
00771 ocr_internal_shutdown();
00772 return OKAY;
00773 #elif defined (__MAC__)
00774 INT16 result = HPERR;
00775
00776 result = ReleaseSemaphore (shm.ocr_sem) ? OKAY : HPERR;
00777
00778 if (result != OKAY)
00779 ocr_internal_shutdown();
00780 return result;
00781 #elif defined (__UNIX__)
00782 return 0;
00783 #endif
00784 }