tesseract  3.04.00
intproto.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  ** Filename: intproto.c
3  ** Purpose: Definition of data structures for integer protos.
4  ** Author: Dan Johnson
5  ** History: Thu Feb 7 14:38:16 1991, DSJ, Created.
6  **
7  ** (c) Copyright Hewlett-Packard Company, 1988.
8  ** Licensed under the Apache License, Version 2.0 (the "License");
9  ** you may not use this file except in compliance with the License.
10  ** You may obtain a copy of the License at
11  ** http://www.apache.org/licenses/LICENSE-2.0
12  ** Unless required by applicable law or agreed to in writing, software
13  ** distributed under the License is distributed on an "AS IS" BASIS,
14  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  ** See the License for the specific language governing permissions and
16  ** limitations under the License.
17  ******************************************************************************/
18 /*-----------------------------------------------------------------------------
19  Include Files and Type Defines
20 -----------------------------------------------------------------------------*/
21 
22 #include <math.h>
23 #include <stdio.h>
24 #include <assert.h>
25 #ifdef __UNIX__
26 #include <unistd.h>
27 #endif
28 
29 #include "classify.h"
30 #include "const.h"
31 #include "emalloc.h"
32 #include "fontinfo.h"
33 #include "genericvector.h"
34 #include "globals.h"
35 #include "helpers.h"
36 #include "intproto.h"
37 #include "mfoutline.h"
38 #include "ndminx.h"
39 #include "picofeat.h"
40 #include "points.h"
41 #include "shapetable.h"
42 #include "svmnode.h"
43 
44 // Include automatically generated configuration file if running autoconf.
45 #ifdef HAVE_CONFIG_H
46 #include "config_auto.h"
47 #endif
48 
50 using tesseract::FontSet;
52 
53 /* match debug display constants*/
54 #define PROTO_PRUNER_SCALE (4.0)
55 
56 #define INT_DESCENDER (0.0 * INT_CHAR_NORM_RANGE)
57 #define INT_BASELINE (0.25 * INT_CHAR_NORM_RANGE)
58 #define INT_XHEIGHT (0.75 * INT_CHAR_NORM_RANGE)
59 #define INT_CAPHEIGHT (1.0 * INT_CHAR_NORM_RANGE)
60 
61 #define INT_XCENTER (0.5 * INT_CHAR_NORM_RANGE)
62 #define INT_YCENTER (0.5 * INT_CHAR_NORM_RANGE)
63 #define INT_XRADIUS (0.2 * INT_CHAR_NORM_RANGE)
64 #define INT_YRADIUS (0.2 * INT_CHAR_NORM_RANGE)
65 #define INT_MIN_X 0
66 #define INT_MIN_Y 0
67 #define INT_MAX_X INT_CHAR_NORM_RANGE
68 #define INT_MAX_Y INT_CHAR_NORM_RANGE
69 
71 #define HV_TOLERANCE (0.0025) /* approx 0.9 degrees */
72 
73 typedef enum
76 #define MAX_NUM_SWITCHES 3
77 
78 typedef struct
79 {
81  inT8 X, Y;
84 }
85 
86 
88 
89 typedef struct
90 {
92  uinT8 AngleStart, AngleEnd;
94  inT16 YStart, YEnd;
95  inT16 StartDelta, EndDelta;
97 }
98 
99 
101 
102 typedef struct
103 {
105  inT8 YStart, YEnd;
106  uinT8 AngleStart, AngleEnd;
107 }
108 
109 
110 FILL_SPEC;
111 
112 
113 /* constants for conversion from old inttemp format */
114 #define OLD_MAX_NUM_CONFIGS 32
115 #define OLD_WERDS_PER_CONFIG_VEC ((OLD_MAX_NUM_CONFIGS + BITS_PER_WERD - 1) /\
116  BITS_PER_WERD)
117 
118 /*-----------------------------------------------------------------------------
119  Macros
120 -----------------------------------------------------------------------------*/
122 #define CircularIncrement(i,r) (((i) < (r) - 1)?((i)++):((i) = 0))
123 
125 #define MapParam(P,O,N) (floor (((P) + (O)) * (N)))
126 
127 /*---------------------------------------------------------------------------
128  Private Function Prototypes
129 ----------------------------------------------------------------------------*/
130 FLOAT32 BucketStart(int Bucket, FLOAT32 Offset, int NumBuckets);
131 
132 FLOAT32 BucketEnd(int Bucket, FLOAT32 Offset, int NumBuckets);
133 
134 void DoFill(FILL_SPEC *FillSpec,
135  CLASS_PRUNER_STRUCT* Pruner,
136  register uinT32 ClassMask,
137  register uinT32 ClassCount,
138  register uinT32 WordIndex);
139 
140 BOOL8 FillerDone(TABLE_FILLER *Filler);
141 
143  ParamTable[NUM_PP_BUCKETS][WERDS_PER_PP_VECTOR],
144  int Bit, FLOAT32 Center, FLOAT32 Spread, bool debug);
145 
147  int Bit, FLOAT32 Center, FLOAT32 Spread, bool debug);
148 
149 void GetCPPadsForLevel(int Level,
150  FLOAT32 *EndPad,
151  FLOAT32 *SidePad,
152  FLOAT32 *AnglePad);
153 
155 
156 void GetNextFill(TABLE_FILLER *Filler, FILL_SPEC *Fill);
157 
158 void InitTableFiller(FLOAT32 EndPad,
159  FLOAT32 SidePad,
160  FLOAT32 AnglePad,
161  PROTO Proto,
162  TABLE_FILLER *Filler);
163 
164 #ifndef GRAPHICS_DISABLED
165 void RenderIntFeature(ScrollView *window, const INT_FEATURE_STRUCT* Feature,
166  ScrollView::Color color);
167 
168 void RenderIntProto(ScrollView *window,
169  INT_CLASS Class,
170  PROTO_ID ProtoId,
171  ScrollView::Color color);
172 #endif // GRAPHICS_DISABLED
173 
174 int TruncateParam(FLOAT32 Param, int Min, int Max, char *Id);
175 
176 /*-----------------------------------------------------------------------------
177  Global Data Definitions and Declarations
178 -----------------------------------------------------------------------------*/
179 
180 /* global display lists used to display proto and feature match information*/
184 
185 /*-----------------------------------------------------------------------------
186  Variables
187 -----------------------------------------------------------------------------*/
188 
189 /* control knobs */
190 INT_VAR(classify_num_cp_levels, 3, "Number of Class Pruner Levels");
192  "Class Pruner Angle Pad Loose");
194  "Class Pruner Angle Pad Medium");
196  "CLass Pruner Angle Pad Tight");
197 double_VAR(classify_cp_end_pad_loose, 0.5, "Class Pruner End Pad Loose");
198 double_VAR(classify_cp_end_pad_medium, 0.5, "Class Pruner End Pad Medium");
199 double_VAR(classify_cp_end_pad_tight, 0.5, "Class Pruner End Pad Tight");
200 double_VAR(classify_cp_side_pad_loose, 2.5, "Class Pruner Side Pad Loose");
201 double_VAR(classify_cp_side_pad_medium, 1.2, "Class Pruner Side Pad Medium");
202 double_VAR(classify_cp_side_pad_tight, 0.6, "Class Pruner Side Pad Tight");
203 double_VAR(classify_pp_angle_pad, 45.0, "Proto Pruner Angle Pad");
204 double_VAR(classify_pp_end_pad, 0.5, "Proto Prune End Pad");
205 double_VAR(classify_pp_side_pad, 2.5, "Proto Pruner Side Pad");
206 
207 /*-----------------------------------------------------------------------------
208  Public Code
209 -----------------------------------------------------------------------------*/
210 // Builds a feature from an FCOORD for position with all the necessary
211 // clipping and rounding.
213  : X(ClipToRange<inT16>(static_cast<inT16>(pos.x() + 0.5), 0, 255)),
214  Y(ClipToRange<inT16>(static_cast<inT16>(pos.y() + 0.5), 0, 255)),
215  Theta(theta),
216  CP_misses(0) {
217 }
218 // Builds a feature from ints with all the necessary clipping and casting.
220  : X(static_cast<uinT8>(ClipToRange(x, 0, MAX_UINT8))),
221  Y(static_cast<uinT8>(ClipToRange(y, 0, MAX_UINT8))),
222  Theta(static_cast<uinT8>(ClipToRange(theta, 0, MAX_UINT8))),
223  CP_misses(0) {
224 }
225 
226 /*---------------------------------------------------------------------------*/
241 void AddIntClass(INT_TEMPLATES Templates, CLASS_ID ClassId, INT_CLASS Class) {
242  int Pruner;
243 
244  assert (LegalClassId (ClassId));
245  if (ClassId != Templates->NumClasses) {
246  fprintf(stderr, "Please make sure that classes are added to templates");
247  fprintf(stderr, " in increasing order of ClassIds\n");
248  exit(1);
249  }
250  ClassForClassId (Templates, ClassId) = Class;
251  Templates->NumClasses++;
252 
253  if (Templates->NumClasses > MaxNumClassesIn (Templates)) {
254  Pruner = Templates->NumClassPruners++;
255  Templates->ClassPruners[Pruner] = new CLASS_PRUNER_STRUCT;
256  memset(Templates->ClassPruners[Pruner], 0, sizeof(CLASS_PRUNER_STRUCT));
257  }
258 } /* AddIntClass */
259 
260 
261 /*---------------------------------------------------------------------------*/
275  int Index;
276 
277  assert(Class->NumConfigs < MAX_NUM_CONFIGS);
278 
279  Index = Class->NumConfigs++;
280  Class->ConfigLengths[Index] = 0;
281  return Index;
282 } /* AddIntConfig */
283 
284 
285 /*---------------------------------------------------------------------------*/
298 int AddIntProto(INT_CLASS Class) {
299  int Index;
300  int ProtoSetId;
301  PROTO_SET ProtoSet;
302  INT_PROTO Proto;
303  register uinT32 *Word;
304 
305  if (Class->NumProtos >= MAX_NUM_PROTOS)
306  return (NO_PROTO);
307 
308  Index = Class->NumProtos++;
309 
310  if (Class->NumProtos > MaxNumIntProtosIn(Class)) {
311  ProtoSetId = Class->NumProtoSets++;
312 
313  ProtoSet = (PROTO_SET) Emalloc(sizeof(PROTO_SET_STRUCT));
314  Class->ProtoSets[ProtoSetId] = ProtoSet;
315  memset(ProtoSet, 0, sizeof(*ProtoSet));
316 
317  /* reallocate space for the proto lengths and install in class */
318  Class->ProtoLengths =
319  (uinT8 *)Erealloc(Class->ProtoLengths,
320  MaxNumIntProtosIn(Class) * sizeof(uinT8));
321  memset(&Class->ProtoLengths[Index], 0,
322  sizeof(*Class->ProtoLengths) * (MaxNumIntProtosIn(Class) - Index));
323  }
324 
325  /* initialize proto so its length is zero and it isn't in any configs */
326  Class->ProtoLengths[Index] = 0;
327  Proto = ProtoForProtoId (Class, Index);
328  for (Word = Proto->Configs;
329  Word < Proto->Configs + WERDS_PER_CONFIG_VEC; *Word++ = 0);
330 
331  return (Index);
332 
333 } /* AddIntProto */
334 
335 
336 /*---------------------------------------------------------------------------*/
337 void AddProtoToClassPruner (PROTO Proto, CLASS_ID ClassId,
338  INT_TEMPLATES Templates)
339 /*
340  ** Parameters:
341  ** Proto floating-pt proto to add to class pruner
342  ** ClassId class id corresponding to Proto
343  ** Templates set of templates containing class pruner
344  ** Globals:
345  ** classify_num_cp_levels number of levels used in the class pruner
346  ** Operation: This routine adds Proto to the class pruning tables
347  ** for the specified class in Templates.
348  ** Return: none
349  ** Exceptions: none
350  ** History: Wed Feb 13 08:49:54 1991, DSJ, Created.
351  */
352 #define MAX_LEVEL 2
353 {
354  CLASS_PRUNER_STRUCT* Pruner;
355  uinT32 ClassMask;
356  uinT32 ClassCount;
357  uinT32 WordIndex;
358  int Level;
359  FLOAT32 EndPad, SidePad, AnglePad;
360  TABLE_FILLER TableFiller;
361  FILL_SPEC FillSpec;
362 
363  Pruner = CPrunerFor (Templates, ClassId);
364  WordIndex = CPrunerWordIndexFor (ClassId);
365  ClassMask = CPrunerMaskFor (MAX_LEVEL, ClassId);
366 
367  for (Level = classify_num_cp_levels - 1; Level >= 0; Level--) {
368  GetCPPadsForLevel(Level, &EndPad, &SidePad, &AnglePad);
369  ClassCount = CPrunerMaskFor (Level, ClassId);
370  InitTableFiller(EndPad, SidePad, AnglePad, Proto, &TableFiller);
371 
372  while (!FillerDone (&TableFiller)) {
373  GetNextFill(&TableFiller, &FillSpec);
374  DoFill(&FillSpec, Pruner, ClassMask, ClassCount, WordIndex);
375  }
376  }
377 } /* AddProtoToClassPruner */
378 
379 
380 /*---------------------------------------------------------------------------*/
381 void AddProtoToProtoPruner(PROTO Proto, int ProtoId,
382  INT_CLASS Class, bool debug) {
383 /*
384  ** Parameters:
385  ** Proto floating-pt proto to be added to proto pruner
386  ** ProtoId id of proto
387  ** Class integer class that contains desired proto pruner
388  ** Globals: none
389  ** Operation: This routine updates the proto pruner lookup tables
390  ** for Class to include a new proto identified by ProtoId
391  ** and described by Proto.
392  ** Return: none
393  ** Exceptions: none
394  ** History: Fri Feb 8 13:07:19 1991, DSJ, Created.
395  */
396  FLOAT32 Angle, X, Y, Length;
397  FLOAT32 Pad;
398  int Index;
399  PROTO_SET ProtoSet;
400 
401  if (ProtoId >= Class->NumProtos)
402  cprintf("AddProtoToProtoPruner:assert failed: %d < %d",
403  ProtoId, Class->NumProtos);
404  assert(ProtoId < Class->NumProtos);
405 
406  Index = IndexForProto (ProtoId);
407  ProtoSet = Class->ProtoSets[SetForProto (ProtoId)];
408 
409  Angle = Proto->Angle;
410 #ifndef _WIN32
411  assert(!isnan(Angle));
412 #endif
413 
414  FillPPCircularBits (ProtoSet->ProtoPruner[PRUNER_ANGLE], Index,
415  Angle + ANGLE_SHIFT, classify_pp_angle_pad / 360.0,
416  debug);
417 
418  Angle *= 2.0 * PI;
419  Length = Proto->Length;
420 
421  X = Proto->X + X_SHIFT;
422  Pad = MAX (fabs (cos (Angle)) * (Length / 2.0 +
425  fabs (sin (Angle)) * (classify_pp_side_pad *
427 
428  FillPPLinearBits(ProtoSet->ProtoPruner[PRUNER_X], Index, X, Pad, debug);
429 
430  Y = Proto->Y + Y_SHIFT;
431  Pad = MAX (fabs (sin (Angle)) * (Length / 2.0 +
434  fabs (cos (Angle)) * (classify_pp_side_pad *
436 
437  FillPPLinearBits(ProtoSet->ProtoPruner[PRUNER_Y], Index, Y, Pad, debug);
438 } /* AddProtoToProtoPruner */
439 
440 
441 /*---------------------------------------------------------------------------*/
442 // Returns a quantized bucket for the given param shifted by offset,
443 // notionally (param + offset) * num_buckets, but clipped and casted to the
444 // appropriate type.
445 uinT8 Bucket8For(FLOAT32 param, FLOAT32 offset, int num_buckets) {
446  int bucket = IntCastRounded(MapParam(param, offset, num_buckets));
447  return static_cast<uinT8>(ClipToRange(bucket, 0, num_buckets - 1));
448 }
449 uinT16 Bucket16For(FLOAT32 param, FLOAT32 offset, int num_buckets) {
450  int bucket = IntCastRounded(MapParam(param, offset, num_buckets));
451  return static_cast<uinT16>(ClipToRange(bucket, 0, num_buckets - 1));
452 }
453 
454 /*---------------------------------------------------------------------------*/
455 // Returns a quantized bucket for the given circular param shifted by offset,
456 // notionally (param + offset) * num_buckets, but modded and casted to the
457 // appropriate type.
458 uinT8 CircBucketFor(FLOAT32 param, FLOAT32 offset, int num_buckets) {
459  int bucket = IntCastRounded(MapParam(param, offset, num_buckets));
460  return static_cast<uinT8>(Modulo(bucket, num_buckets));
461 } /* CircBucketFor */
462 
463 
464 /*---------------------------------------------------------------------------*/
465 #ifndef GRAPHICS_DISABLED
467 /*
468  ** Parameters: none
469  ** Globals:
470  ** FeatureShapes display list for features
471  ** ProtoShapes display list for protos
472  ** Operation: This routine clears the global feature and proto
473  ** display lists.
474  ** Return: none
475  ** Exceptions: none
476  ** History: Thu Mar 21 15:40:19 1991, DSJ, Created.
477  */
478  if (IntMatchWindow != NULL)
479  IntMatchWindow->Update();
480 } /* ClearMatchDisplay */
481 #endif
482 
483 /*---------------------------------------------------------------------------*/
484 void ConvertConfig(BIT_VECTOR Config, int ConfigId, INT_CLASS Class) {
485 /*
486  ** Parameters:
487  ** Config config to be added to class
488  ** ConfigId id to be used for new config
489  ** Class class to add new config to
490  ** Globals: none
491  ** Operation: This operation updates the config vectors of all protos
492  ** in Class to indicate that the protos with 1's in Config
493  ** belong to a new configuration identified by ConfigId.
494  ** It is assumed that the length of the Config bit vector is
495  ** equal to the number of protos in Class.
496  ** Return: none
497  ** Exceptions: none
498  ** History: Mon Feb 11 14:57:31 1991, DSJ, Created.
499  */
500  int ProtoId;
501  INT_PROTO Proto;
502  int TotalLength;
503 
504  for (ProtoId = 0, TotalLength = 0;
505  ProtoId < Class->NumProtos; ProtoId++) {
506  if (test_bit(Config, ProtoId)) {
507  Proto = ProtoForProtoId(Class, ProtoId);
508  SET_BIT(Proto->Configs, ConfigId);
509  TotalLength += Class->ProtoLengths[ProtoId];
510  }
511  }
512  Class->ConfigLengths[ConfigId] = TotalLength;
513 } /* ConvertConfig */
514 
515 
516 namespace tesseract {
517 /*---------------------------------------------------------------------------*/
518 void Classify::ConvertProto(PROTO Proto, int ProtoId, INT_CLASS Class) {
519 /*
520  ** Parameters:
521  ** Proto floating-pt proto to be converted to integer format
522  ** ProtoId id of proto
523  ** Class integer class to add converted proto to
524  ** Globals: none
525  ** Operation: This routine converts Proto to integer format and
526  ** installs it as ProtoId in Class.
527  ** Return: none
528  ** Exceptions: none
529  ** History: Fri Feb 8 11:22:43 1991, DSJ, Created.
530  */
531  INT_PROTO P;
532  FLOAT32 Param;
533 
534  assert(ProtoId < Class->NumProtos);
535 
536  P = ProtoForProtoId(Class, ProtoId);
537 
538  Param = Proto->A * 128;
539  P->A = TruncateParam(Param, -128, 127, NULL);
540 
541  Param = -Proto->B * 256;
542  P->B = TruncateParam(Param, 0, 255, NULL);
543 
544  Param = Proto->C * 128;
545  P->C = TruncateParam(Param, -128, 127, NULL);
546 
547  Param = Proto->Angle * 256;
548  if (Param < 0 || Param >= 256)
549  P->Angle = 0;
550  else
551  P->Angle = (uinT8) Param;
552 
553  /* round proto length to nearest integer number of pico-features */
554  Param = (Proto->Length / GetPicoFeatureLength()) + 0.5;
555  Class->ProtoLengths[ProtoId] = TruncateParam(Param, 1, 255, NULL);
556  if (classify_learning_debug_level >= 2)
557  cprintf("Converted ffeat to (A=%d,B=%d,C=%d,L=%d)",
558  P->A, P->B, P->C, Class->ProtoLengths[ProtoId]);
559 } /* ConvertProto */
560 
561 
562 /*---------------------------------------------------------------------------*/
563 INT_TEMPLATES Classify::CreateIntTemplates(CLASSES FloatProtos,
564  const UNICHARSET&
565  target_unicharset) {
566 /*
567  ** Parameters:
568  ** FloatProtos prototypes in old floating pt format
569  ** Globals: none
570  ** Operation: This routine converts from the old floating point format
571  ** to the new integer format.
572  ** Return: New set of training templates in integer format.
573  ** Exceptions: none
574  ** History: Thu Feb 7 14:40:42 1991, DSJ, Created.
575  */
576  INT_TEMPLATES IntTemplates;
577  CLASS_TYPE FClass;
578  INT_CLASS IClass;
579  int ClassId;
580  int ProtoId;
581  int ConfigId;
582 
583  IntTemplates = NewIntTemplates();
584 
585  for (ClassId = 0; ClassId < target_unicharset.size(); ClassId++) {
586  FClass = &(FloatProtos[ClassId]);
587  if (FClass->NumProtos == 0 && FClass->NumConfigs == 0 &&
588  strcmp(target_unicharset.id_to_unichar(ClassId), " ") != 0) {
589  cprintf("Warning: no protos/configs for %s in CreateIntTemplates()\n",
590  target_unicharset.id_to_unichar(ClassId));
591  }
592  assert(UnusedClassIdIn(IntTemplates, ClassId));
593  IClass = NewIntClass(FClass->NumProtos, FClass->NumConfigs);
594  FontSet fs;
595  fs.size = FClass->font_set.size();
596  fs.configs = new int[fs.size];
597  for (int i = 0; i < fs.size; ++i) {
598  fs.configs[i] = FClass->font_set.get(i);
599  }
600  if (this->fontset_table_.contains(fs)) {
601  IClass->font_set_id = this->fontset_table_.get_id(fs);
602  delete[] fs.configs;
603  } else {
604  IClass->font_set_id = this->fontset_table_.push_back(fs);
605  }
606  AddIntClass(IntTemplates, ClassId, IClass);
607 
608  for (ProtoId = 0; ProtoId < FClass->NumProtos; ProtoId++) {
609  AddIntProto(IClass);
610  ConvertProto(ProtoIn(FClass, ProtoId), ProtoId, IClass);
611  AddProtoToProtoPruner(ProtoIn(FClass, ProtoId), ProtoId, IClass,
612  classify_learning_debug_level >= 2);
613  AddProtoToClassPruner(ProtoIn(FClass, ProtoId), ClassId, IntTemplates);
614  }
615 
616  for (ConfigId = 0; ConfigId < FClass->NumConfigs; ConfigId++) {
617  AddIntConfig(IClass);
618  ConvertConfig(FClass->Configurations[ConfigId], ConfigId, IClass);
619  }
620  }
621  return (IntTemplates);
622 } /* CreateIntTemplates */
623 } // namespace tesseract
624 
625 
626 /*---------------------------------------------------------------------------*/
627 #ifndef GRAPHICS_DISABLED
628 void DisplayIntFeature(const INT_FEATURE_STRUCT* Feature, FLOAT32 Evidence) {
629 /*
630  ** Parameters:
631  ** Feature pico-feature to be displayed
632  ** Evidence best evidence for this feature (0-1)
633  ** Globals:
634  ** FeatureShapes global display list for features
635  ** Operation: This routine renders the specified feature into a
636  ** global display list.
637  ** Return: none
638  ** Exceptions: none
639  ** History: Thu Mar 21 14:45:04 1991, DSJ, Created.
640  */
641  ScrollView::Color color = GetMatchColorFor(Evidence);
642  RenderIntFeature(IntMatchWindow, Feature, color);
643  if (FeatureDisplayWindow) {
644  RenderIntFeature(FeatureDisplayWindow, Feature, color);
645  }
646 } /* DisplayIntFeature */
647 
648 
649 /*---------------------------------------------------------------------------*/
650 void DisplayIntProto(INT_CLASS Class, PROTO_ID ProtoId, FLOAT32 Evidence) {
651 /*
652  ** Parameters:
653  ** Class class to take proto from
654  ** ProtoId id of proto in Class to be displayed
655  ** Evidence total evidence for proto (0-1)
656  ** Globals:
657  ** ProtoShapes global display list for protos
658  ** Operation: This routine renders the specified proto into a
659  ** global display list.
660  ** Return: none
661  ** Exceptions: none
662  ** History: Thu Mar 21 14:45:04 1991, DSJ, Created.
663  */
664  ScrollView::Color color = GetMatchColorFor(Evidence);
665  RenderIntProto(IntMatchWindow, Class, ProtoId, color);
666  if (ProtoDisplayWindow) {
667  RenderIntProto(ProtoDisplayWindow, Class, ProtoId, color);
668  }
669 } /* DisplayIntProto */
670 #endif
671 
672 /*---------------------------------------------------------------------------*/
673 INT_CLASS NewIntClass(int MaxNumProtos, int MaxNumConfigs) {
674 /*
675  ** Parameters:
676  ** MaxNumProtos number of protos to allocate space for
677  ** MaxNumConfigs number of configs to allocate space for
678  ** Globals: none
679  ** Operation: This routine creates a new integer class data structure
680  ** and returns it. Sufficient space is allocated
681  ** to handle the specified number of protos and configs.
682  ** Return: New class created.
683  ** Exceptions: none
684  ** History: Fri Feb 8 10:51:23 1991, DSJ, Created.
685  */
686  INT_CLASS Class;
687  PROTO_SET ProtoSet;
688  int i;
689 
690  assert(MaxNumConfigs <= MAX_NUM_CONFIGS);
691 
692  Class = (INT_CLASS) Emalloc(sizeof(INT_CLASS_STRUCT));
693  Class->NumProtoSets = ((MaxNumProtos + PROTOS_PER_PROTO_SET - 1) /
695 
696  assert(Class->NumProtoSets <= MAX_NUM_PROTO_SETS);
697 
698  Class->NumProtos = 0;
699  Class->NumConfigs = 0;
700 
701  for (i = 0; i < Class->NumProtoSets; i++) {
702  /* allocate space for a proto set, install in class, and initialize */
703  ProtoSet = (PROTO_SET) Emalloc(sizeof(PROTO_SET_STRUCT));
704  memset(ProtoSet, 0, sizeof(*ProtoSet));
705  Class->ProtoSets[i] = ProtoSet;
706 
707  /* allocate space for the proto lengths and install in class */
708  }
709  if (MaxNumIntProtosIn (Class) > 0) {
710  Class->ProtoLengths =
711  (uinT8 *)Emalloc(MaxNumIntProtosIn (Class) * sizeof (uinT8));
712  memset(Class->ProtoLengths, 0,
713  MaxNumIntProtosIn(Class) * sizeof(*Class->ProtoLengths));
714  } else {
715  Class->ProtoLengths = NULL;
716  }
717  memset(Class->ConfigLengths, 0, sizeof(Class->ConfigLengths));
718 
719  return (Class);
720 
721 } /* NewIntClass */
722 
723 
724 /*-------------------------------------------------------------------------*/
725 void free_int_class(INT_CLASS int_class) {
726  int i;
727 
728  for (i = 0; i < int_class->NumProtoSets; i++) {
729  Efree (int_class->ProtoSets[i]);
730  }
731  if (int_class->ProtoLengths != NULL) {
732  Efree (int_class->ProtoLengths);
733  }
734  Efree(int_class);
735 }
736 
737 
738 /*---------------------------------------------------------------------------*/
740 /*
741  ** Parameters: none
742  ** Globals: none
743  ** Operation: This routine allocates a new set of integer templates
744  ** initialized to hold 0 classes.
745  ** Return: The integer templates created.
746  ** Exceptions: none
747  ** History: Fri Feb 8 08:38:51 1991, DSJ, Created.
748  */
749  INT_TEMPLATES T;
750  int i;
751 
752  T = (INT_TEMPLATES) Emalloc (sizeof (INT_TEMPLATES_STRUCT));
753  T->NumClasses = 0;
754  T->NumClassPruners = 0;
755 
756  for (i = 0; i < MAX_NUM_CLASSES; i++)
757  ClassForClassId (T, i) = NULL;
758 
759  return (T);
760 } /* NewIntTemplates */
761 
762 
763 /*---------------------------------------------------------------------------*/
765  int i;
766 
767  for (i = 0; i < templates->NumClasses; i++)
768  free_int_class(templates->Class[i]);
769  for (i = 0; i < templates->NumClassPruners; i++)
770  delete templates->ClassPruners[i];
771  Efree(templates);
772 }
773 
774 
775 namespace tesseract {
776 INT_TEMPLATES Classify::ReadIntTemplates(FILE *File) {
777 /*
778  ** Parameters:
779  ** File open file to read templates from
780  ** Globals: none
781  ** Operation: This routine reads a set of integer templates from
782  ** File. File must already be open and must be in the
783  ** correct binary format.
784  ** Return: Pointer to integer templates read from File.
785  ** Exceptions: none
786  ** History: Wed Feb 27 11:48:46 1991, DSJ, Created.
787  */
788  int i, j, w, x, y, z;
789  BOOL8 swap;
790  int nread;
791  int unicharset_size;
792  int version_id = 0;
793  INT_TEMPLATES Templates;
794  CLASS_PRUNER_STRUCT* Pruner;
795  INT_CLASS Class;
796  uinT8 *Lengths;
797  PROTO_SET ProtoSet;
798 
799  /* variables for conversion from older inttemp formats */
800  int b, bit_number, last_cp_bit_number, new_b, new_i, new_w;
801  CLASS_ID class_id, max_class_id;
802  inT16 *IndexFor = new inT16[MAX_NUM_CLASSES];
803  CLASS_ID *ClassIdFor = new CLASS_ID[MAX_NUM_CLASSES];
804  CLASS_PRUNER_STRUCT **TempClassPruner =
806  uinT32 SetBitsForMask = // word with NUM_BITS_PER_CLASS
807  (1 << NUM_BITS_PER_CLASS) - 1; // set starting at bit 0
808  uinT32 Mask, NewMask, ClassBits;
809  int MaxNumConfigs = MAX_NUM_CONFIGS;
810  int WerdsPerConfigVec = WERDS_PER_CONFIG_VEC;
811 
812  /* first read the high level template struct */
813  Templates = NewIntTemplates();
814  // Read Templates in parts for 64 bit compatibility.
815  if (fread(&unicharset_size, sizeof(int), 1, File) != 1)
816  cprintf("Bad read of inttemp!\n");
817  if (fread(&Templates->NumClasses,
818  sizeof(Templates->NumClasses), 1, File) != 1 ||
819  fread(&Templates->NumClassPruners,
820  sizeof(Templates->NumClassPruners), 1, File) != 1)
821  cprintf("Bad read of inttemp!\n");
822  // Swap status is determined automatically.
823  swap = Templates->NumClassPruners < 0 ||
825  if (swap) {
826  Reverse32(&Templates->NumClassPruners);
827  Reverse32(&Templates->NumClasses);
828  Reverse32(&unicharset_size);
829  }
830  if (Templates->NumClasses < 0) {
831  // This file has a version id!
832  version_id = -Templates->NumClasses;
833  if (fread(&Templates->NumClasses, sizeof(Templates->NumClasses),
834  1, File) != 1)
835  cprintf("Bad read of inttemp!\n");
836  if (swap)
837  Reverse32(&Templates->NumClasses);
838  }
839 
840  if (version_id < 3) {
841  MaxNumConfigs = OLD_MAX_NUM_CONFIGS;
842  WerdsPerConfigVec = OLD_WERDS_PER_CONFIG_VEC;
843  }
844 
845  if (version_id < 2) {
846  for (i = 0; i < unicharset_size; ++i) {
847  if (fread(&IndexFor[i], sizeof(inT16), 1, File) != 1)
848  cprintf("Bad read of inttemp!\n");
849  }
850  for (i = 0; i < Templates->NumClasses; ++i) {
851  if (fread(&ClassIdFor[i], sizeof(CLASS_ID), 1, File) != 1)
852  cprintf("Bad read of inttemp!\n");
853  }
854  if (swap) {
855  for (i = 0; i < Templates->NumClasses; i++)
856  Reverse16(&IndexFor[i]);
857  for (i = 0; i < Templates->NumClasses; i++)
858  Reverse32(&ClassIdFor[i]);
859  }
860  }
861 
862  /* then read in the class pruners */
863  for (i = 0; i < Templates->NumClassPruners; i++) {
864  Pruner = new CLASS_PRUNER_STRUCT;
865  if ((nread =
866  fread(Pruner, 1, sizeof(CLASS_PRUNER_STRUCT),
867  File)) != sizeof(CLASS_PRUNER_STRUCT))
868  cprintf("Bad read of inttemp!\n");
869  if (swap) {
870  for (x = 0; x < NUM_CP_BUCKETS; x++) {
871  for (y = 0; y < NUM_CP_BUCKETS; y++) {
872  for (z = 0; z < NUM_CP_BUCKETS; z++) {
873  for (w = 0; w < WERDS_PER_CP_VECTOR; w++) {
874  Reverse32(&Pruner->p[x][y][z][w]);
875  }
876  }
877  }
878  }
879  }
880  if (version_id < 2) {
881  TempClassPruner[i] = Pruner;
882  } else {
883  Templates->ClassPruners[i] = Pruner;
884  }
885  }
886 
887  /* fix class pruners if they came from an old version of inttemp */
888  if (version_id < 2) {
889  // Allocate enough class pruners to cover all the class ids.
890  max_class_id = 0;
891  for (i = 0; i < Templates->NumClasses; i++)
892  if (ClassIdFor[i] > max_class_id)
893  max_class_id = ClassIdFor[i];
894  for (i = 0; i <= CPrunerIdFor(max_class_id); i++) {
895  Templates->ClassPruners[i] = new CLASS_PRUNER_STRUCT;
896  memset(Templates->ClassPruners[i], 0, sizeof(CLASS_PRUNER_STRUCT));
897  }
898  // Convert class pruners from the old format (indexed by class index)
899  // to the new format (indexed by class id).
900  last_cp_bit_number = NUM_BITS_PER_CLASS * Templates->NumClasses - 1;
901  for (i = 0; i < Templates->NumClassPruners; i++) {
902  for (x = 0; x < NUM_CP_BUCKETS; x++)
903  for (y = 0; y < NUM_CP_BUCKETS; y++)
904  for (z = 0; z < NUM_CP_BUCKETS; z++)
905  for (w = 0; w < WERDS_PER_CP_VECTOR; w++) {
906  if (TempClassPruner[i]->p[x][y][z][w] == 0)
907  continue;
908  for (b = 0; b < BITS_PER_WERD; b += NUM_BITS_PER_CLASS) {
909  bit_number = i * BITS_PER_CP_VECTOR + w * BITS_PER_WERD + b;
910  if (bit_number > last_cp_bit_number)
911  break; // the rest of the bits in this word are not used
912  class_id = ClassIdFor[bit_number / NUM_BITS_PER_CLASS];
913  // Single out NUM_BITS_PER_CLASS bits relating to class_id.
914  Mask = SetBitsForMask << b;
915  ClassBits = TempClassPruner[i]->p[x][y][z][w] & Mask;
916  // Move these bits to the new position in which they should
917  // appear (indexed corresponding to the class_id).
918  new_i = CPrunerIdFor(class_id);
919  new_w = CPrunerWordIndexFor(class_id);
920  new_b = CPrunerBitIndexFor(class_id) * NUM_BITS_PER_CLASS;
921  if (new_b > b) {
922  ClassBits <<= (new_b - b);
923  } else {
924  ClassBits >>= (b - new_b);
925  }
926  // Copy bits relating to class_id to the correct position
927  // in Templates->ClassPruner.
928  NewMask = SetBitsForMask << new_b;
929  Templates->ClassPruners[new_i]->p[x][y][z][new_w] &= ~NewMask;
930  Templates->ClassPruners[new_i]->p[x][y][z][new_w] |= ClassBits;
931  }
932  }
933  }
934  for (i = 0; i < Templates->NumClassPruners; i++) {
935  delete TempClassPruner[i];
936  }
937  }
938 
939  /* then read in each class */
940  for (i = 0; i < Templates->NumClasses; i++) {
941  /* first read in the high level struct for the class */
942  Class = (INT_CLASS) Emalloc (sizeof (INT_CLASS_STRUCT));
943  if (fread(&Class->NumProtos, sizeof(Class->NumProtos), 1, File) != 1 ||
944  fread(&Class->NumProtoSets, sizeof(Class->NumProtoSets), 1, File) != 1 ||
945  fread(&Class->NumConfigs, sizeof(Class->NumConfigs), 1, File) != 1)
946  cprintf ("Bad read of inttemp!\n");
947  if (version_id == 0) {
948  // Only version 0 writes 5 pointless pointers to the file.
949  for (j = 0; j < 5; ++j) {
950  int junk;
951  if (fread(&junk, sizeof(junk), 1, File) != 1)
952  cprintf ("Bad read of inttemp!\n");
953  }
954  }
955  if (version_id < 4) {
956  for (j = 0; j < MaxNumConfigs; ++j) {
957  if (fread(&Class->ConfigLengths[j], sizeof(uinT16), 1, File) != 1)
958  cprintf ("Bad read of inttemp!\n");
959  }
960  if (swap) {
961  Reverse16(&Class->NumProtos);
962  for (j = 0; j < MaxNumConfigs; j++)
963  Reverse16(&Class->ConfigLengths[j]);
964  }
965  } else {
966  ASSERT_HOST(Class->NumConfigs < MaxNumConfigs);
967  for (j = 0; j < Class->NumConfigs; ++j) {
968  if (fread(&Class->ConfigLengths[j], sizeof(uinT16), 1, File) != 1)
969  cprintf ("Bad read of inttemp!\n");
970  }
971  if (swap) {
972  Reverse16(&Class->NumProtos);
973  for (j = 0; j < MaxNumConfigs; j++)
974  Reverse16(&Class->ConfigLengths[j]);
975  }
976  }
977  if (version_id < 2) {
978  ClassForClassId (Templates, ClassIdFor[i]) = Class;
979  } else {
980  ClassForClassId (Templates, i) = Class;
981  }
982 
983  /* then read in the proto lengths */
984  Lengths = NULL;
985  if (MaxNumIntProtosIn (Class) > 0) {
986  Lengths = (uinT8 *)Emalloc(sizeof(uinT8) * MaxNumIntProtosIn(Class));
987  if ((nread =
988  fread((char *)Lengths, sizeof(uinT8),
989  MaxNumIntProtosIn(Class), File)) != MaxNumIntProtosIn (Class))
990  cprintf ("Bad read of inttemp!\n");
991  }
992  Class->ProtoLengths = Lengths;
993 
994  /* then read in the proto sets */
995  for (j = 0; j < Class->NumProtoSets; j++) {
996  ProtoSet = (PROTO_SET)Emalloc(sizeof(PROTO_SET_STRUCT));
997  if (version_id < 3) {
998  if ((nread =
999  fread((char *) &ProtoSet->ProtoPruner, 1,
1000  sizeof(PROTO_PRUNER), File)) != sizeof(PROTO_PRUNER))
1001  cprintf("Bad read of inttemp!\n");
1002  for (x = 0; x < PROTOS_PER_PROTO_SET; x++) {
1003  if ((nread = fread((char *) &ProtoSet->Protos[x].A, 1,
1004  sizeof(inT8), File)) != sizeof(inT8) ||
1005  (nread = fread((char *) &ProtoSet->Protos[x].B, 1,
1006  sizeof(uinT8), File)) != sizeof(uinT8) ||
1007  (nread = fread((char *) &ProtoSet->Protos[x].C, 1,
1008  sizeof(inT8), File)) != sizeof(inT8) ||
1009  (nread = fread((char *) &ProtoSet->Protos[x].Angle, 1,
1010  sizeof(uinT8), File)) != sizeof(uinT8))
1011  cprintf("Bad read of inttemp!\n");
1012  for (y = 0; y < WerdsPerConfigVec; y++)
1013  if ((nread = fread((char *) &ProtoSet->Protos[x].Configs[y], 1,
1014  sizeof(uinT32), File)) != sizeof(uinT32))
1015  cprintf("Bad read of inttemp!\n");
1016  }
1017  } else {
1018  if ((nread =
1019  fread((char *) ProtoSet, 1, sizeof(PROTO_SET_STRUCT),
1020  File)) != sizeof(PROTO_SET_STRUCT))
1021  cprintf("Bad read of inttemp!\n");
1022  }
1023  if (swap) {
1024  for (x = 0; x < NUM_PP_PARAMS; x++)
1025  for (y = 0; y < NUM_PP_BUCKETS; y++)
1026  for (z = 0; z < WERDS_PER_PP_VECTOR; z++)
1027  Reverse32(&ProtoSet->ProtoPruner[x][y][z]);
1028  for (x = 0; x < PROTOS_PER_PROTO_SET; x++)
1029  for (y = 0; y < WerdsPerConfigVec; y++)
1030  Reverse32(&ProtoSet->Protos[x].Configs[y]);
1031  }
1032  Class->ProtoSets[j] = ProtoSet;
1033  }
1034  if (version_id < 4)
1035  Class->font_set_id = -1;
1036  else {
1037  fread(&Class->font_set_id, sizeof(int), 1, File);
1038  if (swap)
1039  Reverse32(&Class->font_set_id);
1040  }
1041  }
1042 
1043  if (version_id < 2) {
1044  /* add an empty NULL class with class id 0 */
1045  assert(UnusedClassIdIn (Templates, 0));
1046  ClassForClassId (Templates, 0) = NewIntClass (1, 1);
1047  ClassForClassId (Templates, 0)->font_set_id = -1;
1048  Templates->NumClasses++;
1049  /* make sure the classes are contiguous */
1050  for (i = 0; i < MAX_NUM_CLASSES; i++) {
1051  if (i < Templates->NumClasses) {
1052  if (ClassForClassId (Templates, i) == NULL) {
1053  fprintf(stderr, "Non-contiguous class ids in inttemp\n");
1054  exit(1);
1055  }
1056  } else {
1057  if (ClassForClassId (Templates, i) != NULL) {
1058  fprintf(stderr, "Class id %d exceeds NumClassesIn (Templates) %d\n",
1059  i, Templates->NumClasses);
1060  exit(1);
1061  }
1062  }
1063  }
1064  }
1065  if (version_id >= 4) {
1066  this->fontinfo_table_.read(File, NewPermanentTessCallback(read_info), swap);
1067  if (version_id >= 5) {
1068  this->fontinfo_table_.read(File,
1070  swap);
1071  }
1072  this->fontset_table_.read(File, NewPermanentTessCallback(read_set), swap);
1073  }
1074 
1075  // Clean up.
1076  delete[] IndexFor;
1077  delete[] ClassIdFor;
1078  delete[] TempClassPruner;
1079 
1080  return (Templates);
1081 } /* ReadIntTemplates */
1082 
1083 
1084 /*---------------------------------------------------------------------------*/
1085 #ifndef GRAPHICS_DISABLED
1087 /*
1088  ** Parameters: none
1089  ** Globals:
1090  ** FeatureShapes display list containing feature matches
1091  ** ProtoShapes display list containing proto matches
1092  ** Operation: This routine sends the shapes in the global display
1093  ** lists to the match debugger window.
1094  ** Return: none
1095  ** Exceptions: none
1096  ** History: Thu Mar 21 15:47:33 1991, DSJ, Created.
1097  */
1099  if (ProtoDisplayWindow) {
1100  ProtoDisplayWindow->Clear();
1101  }
1102  if (FeatureDisplayWindow) {
1103  FeatureDisplayWindow->Clear();
1104  }
1106  static_cast<NORM_METHOD>(static_cast<int>(classify_norm_method)),
1107  IntMatchWindow);
1108  IntMatchWindow->ZoomToRectangle(INT_MIN_X, INT_MIN_Y,
1109  INT_MAX_X, INT_MAX_Y);
1110  if (ProtoDisplayWindow) {
1111  ProtoDisplayWindow->ZoomToRectangle(INT_MIN_X, INT_MIN_Y,
1112  INT_MAX_X, INT_MAX_Y);
1113  }
1114  if (FeatureDisplayWindow) {
1115  FeatureDisplayWindow->ZoomToRectangle(INT_MIN_X, INT_MIN_Y,
1116  INT_MAX_X, INT_MAX_Y);
1117  }
1118 } /* ShowMatchDisplay */
1119 
1120 // Clears the given window and draws the featurespace guides for the
1121 // appropriate normalization method.
1122 void ClearFeatureSpaceWindow(NORM_METHOD norm_method, ScrollView* window) {
1123  window->Clear();
1124 
1125  window->Pen(ScrollView::GREY);
1126  // Draw the feature space limit rectangle.
1127  window->Rectangle(0, 0, INT_MAX_X, INT_MAX_Y);
1128  if (norm_method == baseline) {
1129  window->SetCursor(0, INT_DESCENDER);
1130  window->DrawTo(INT_MAX_X, INT_DESCENDER);
1131  window->SetCursor(0, INT_BASELINE);
1132  window->DrawTo(INT_MAX_X, INT_BASELINE);
1133  window->SetCursor(0, INT_XHEIGHT);
1134  window->DrawTo(INT_MAX_X, INT_XHEIGHT);
1135  window->SetCursor(0, INT_CAPHEIGHT);
1136  window->DrawTo(INT_MAX_X, INT_CAPHEIGHT);
1137  } else {
1140  }
1141 }
1142 #endif
1143 
1144 /*---------------------------------------------------------------------------*/
1145 void Classify::WriteIntTemplates(FILE *File, INT_TEMPLATES Templates,
1146  const UNICHARSET& target_unicharset) {
1147 /*
1148  ** Parameters:
1149  ** File open file to write templates to
1150  ** Templates templates to save into File
1151  ** Globals: none
1152  ** Operation: This routine writes Templates to File. The format
1153  ** is an efficient binary format. File must already be open
1154  ** for writing.
1155  ** Return: none
1156  ** Exceptions: none
1157  ** History: Wed Feb 27 11:48:46 1991, DSJ, Created.
1158  */
1159  int i, j;
1160  INT_CLASS Class;
1161  int unicharset_size = target_unicharset.size();
1162  int version_id = -5; // When negated by the reader -1 becomes +1 etc.
1163 
1164  if (Templates->NumClasses != unicharset_size) {
1165  cprintf("Warning: executing WriteIntTemplates() with %d classes in"
1166  " Templates, while target_unicharset size is %d\n",
1167  Templates->NumClasses, unicharset_size);
1168  }
1169 
1170  /* first write the high level template struct */
1171  fwrite(&unicharset_size, sizeof(unicharset_size), 1, File);
1172  fwrite(&version_id, sizeof(version_id), 1, File);
1173  fwrite(&Templates->NumClassPruners, sizeof(Templates->NumClassPruners),
1174  1, File);
1175  fwrite(&Templates->NumClasses, sizeof(Templates->NumClasses), 1, File);
1176 
1177  /* then write out the class pruners */
1178  for (i = 0; i < Templates->NumClassPruners; i++)
1179  fwrite(Templates->ClassPruners[i],
1180  sizeof(CLASS_PRUNER_STRUCT), 1, File);
1181 
1182  /* then write out each class */
1183  for (i = 0; i < Templates->NumClasses; i++) {
1184  Class = Templates->Class[i];
1185 
1186  /* first write out the high level struct for the class */
1187  fwrite(&Class->NumProtos, sizeof(Class->NumProtos), 1, File);
1188  fwrite(&Class->NumProtoSets, sizeof(Class->NumProtoSets), 1, File);
1189  ASSERT_HOST(Class->NumConfigs == this->fontset_table_.get(Class->font_set_id).size);
1190  fwrite(&Class->NumConfigs, sizeof(Class->NumConfigs), 1, File);
1191  for (j = 0; j < Class->NumConfigs; ++j) {
1192  fwrite(&Class->ConfigLengths[j], sizeof(uinT16), 1, File);
1193  }
1194 
1195  /* then write out the proto lengths */
1196  if (MaxNumIntProtosIn (Class) > 0) {
1197  fwrite ((char *) (Class->ProtoLengths), sizeof (uinT8),
1198  MaxNumIntProtosIn (Class), File);
1199  }
1200 
1201  /* then write out the proto sets */
1202  for (j = 0; j < Class->NumProtoSets; j++)
1203  fwrite ((char *) Class->ProtoSets[j],
1204  sizeof (PROTO_SET_STRUCT), 1, File);
1205 
1206  /* then write the fonts info */
1207  fwrite(&Class->font_set_id, sizeof(int), 1, File);
1208  }
1209 
1210  /* Write the fonts info tables */
1211  this->fontinfo_table_.write(File, NewPermanentTessCallback(write_info));
1212  this->fontinfo_table_.write(File,
1214  this->fontset_table_.write(File, NewPermanentTessCallback(write_set));
1215 } /* WriteIntTemplates */
1216 } // namespace tesseract
1217 
1218 
1219 /*-----------------------------------------------------------------------------
1220  Private Code
1221 -----------------------------------------------------------------------------*/
1222 /*---------------------------------------------------------------------------*/
1223 FLOAT32 BucketStart(int Bucket, FLOAT32 Offset, int NumBuckets) {
1224 /*
1225  ** Parameters:
1226  ** Bucket bucket whose start is to be computed
1227  ** Offset offset used to map params to buckets
1228  ** NumBuckets total number of buckets
1229  ** Globals: none
1230  ** Operation: This routine returns the parameter value which
1231  ** corresponds to the beginning of the specified bucket.
1232  ** The bucket number should have been generated using the
1233  ** BucketFor() function with parameters Offset and NumBuckets.
1234  ** Return: Param value corresponding to start position of Bucket.
1235  ** Exceptions: none
1236  ** History: Thu Feb 14 13:24:33 1991, DSJ, Created.
1237  */
1238  return (((FLOAT32) Bucket / NumBuckets) - Offset);
1239 
1240 } /* BucketStart */
1241 
1242 
1243 /*---------------------------------------------------------------------------*/
1244 FLOAT32 BucketEnd(int Bucket, FLOAT32 Offset, int NumBuckets) {
1245 /*
1246  ** Parameters:
1247  ** Bucket bucket whose end is to be computed
1248  ** Offset offset used to map params to buckets
1249  ** NumBuckets total number of buckets
1250  ** Globals: none
1251  ** Operation: This routine returns the parameter value which
1252  ** corresponds to the end of the specified bucket.
1253  ** The bucket number should have been generated using the
1254  ** BucketFor() function with parameters Offset and NumBuckets.
1255  ** Return: Param value corresponding to end position of Bucket.
1256  ** Exceptions: none
1257  ** History: Thu Feb 14 13:24:33 1991, DSJ, Created.
1258  */
1259  return (((FLOAT32) (Bucket + 1) / NumBuckets) - Offset);
1260 } /* BucketEnd */
1261 
1262 
1263 /*---------------------------------------------------------------------------*/
1264 void DoFill(FILL_SPEC *FillSpec,
1265  CLASS_PRUNER_STRUCT* Pruner,
1266  register uinT32 ClassMask,
1267  register uinT32 ClassCount,
1268  register uinT32 WordIndex) {
1269 /*
1270  ** Parameters:
1271  ** FillSpec specifies which bits to fill in pruner
1272  ** Pruner class pruner to be filled
1273  ** ClassMask indicates which bits to change in each word
1274  ** ClassCount indicates what to change bits to
1275  ** WordIndex indicates which word to change
1276  ** Globals: none
1277  ** Operation: This routine fills in the section of a class pruner
1278  ** corresponding to a single x value for a single proto of
1279  ** a class.
1280  ** Return: none
1281  ** Exceptions: none
1282  ** History: Tue Feb 19 11:11:29 1991, DSJ, Created.
1283  */
1284  register int X, Y, Angle;
1285  register uinT32 OldWord;
1286 
1287  X = FillSpec->X;
1288  if (X < 0)
1289  X = 0;
1290  if (X >= NUM_CP_BUCKETS)
1291  X = NUM_CP_BUCKETS - 1;
1292 
1293  if (FillSpec->YStart < 0)
1294  FillSpec->YStart = 0;
1295  if (FillSpec->YEnd >= NUM_CP_BUCKETS)
1296  FillSpec->YEnd = NUM_CP_BUCKETS - 1;
1297 
1298  for (Y = FillSpec->YStart; Y <= FillSpec->YEnd; Y++)
1299  for (Angle = FillSpec->AngleStart;
1301  OldWord = Pruner->p[X][Y][Angle][WordIndex];
1302  if (ClassCount > (OldWord & ClassMask)) {
1303  OldWord &= ~ClassMask;
1304  OldWord |= ClassCount;
1305  Pruner->p[X][Y][Angle][WordIndex] = OldWord;
1306  }
1307  if (Angle == FillSpec->AngleEnd)
1308  break;
1309  }
1310 } /* DoFill */
1311 
1312 
1313 /*---------------------------------------------------------------------------*/
1315 /*
1316  ** Parameters:
1317  ** Filler table filler to check if done
1318  ** Globals: none
1319  ** Operation: Return TRUE if the specified table filler is done, i.e.
1320  ** if it has no more lines to fill.
1321  ** Return: TRUE if no more lines to fill, FALSE otherwise.
1322  ** Exceptions: none
1323  ** History: Tue Feb 19 10:08:05 1991, DSJ, Created.
1324  */
1325  FILL_SWITCH *Next;
1326 
1327  Next = &(Filler->Switch[Filler->NextSwitch]);
1328 
1329  if (Filler->X > Next->X && Next->Type == LastSwitch)
1330  return (TRUE);
1331  else
1332  return (FALSE);
1333 
1334 } /* FillerDone */
1335 
1336 
1337 /*---------------------------------------------------------------------------*/
1339  int Bit, FLOAT32 Center, FLOAT32 Spread, bool debug) {
1340 /*
1341  ** Parameters:
1342  ** ParamTable table of bit vectors, one per param bucket
1343  ** Bit bit position in vectors to be filled
1344  ** Center center of filled area
1345  ** Spread spread of filled area
1346  ** Globals: none
1347  ** Operation: This routine sets Bit in each bit vector whose
1348  ** bucket lies within the range Center +- Spread. The fill
1349  ** is done for a circular dimension, i.e. bucket 0 is adjacent
1350  ** to the last bucket. It is assumed that Center and Spread
1351  ** are expressed in a circular coordinate system whose range
1352  ** is 0 to 1.
1353  ** Return: none
1354  ** Exceptions: none
1355  ** History: Tue Oct 16 09:26:54 1990, DSJ, Created.
1356  */
1357  int i, FirstBucket, LastBucket;
1358 
1359  if (Spread > 0.5)
1360  Spread = 0.5;
1361 
1362  FirstBucket = (int) floor ((Center - Spread) * NUM_PP_BUCKETS);
1363  if (FirstBucket < 0)
1364  FirstBucket += NUM_PP_BUCKETS;
1365 
1366  LastBucket = (int) floor ((Center + Spread) * NUM_PP_BUCKETS);
1367  if (LastBucket >= NUM_PP_BUCKETS)
1368  LastBucket -= NUM_PP_BUCKETS;
1369  if (debug) tprintf("Circular fill from %d to %d", FirstBucket, LastBucket);
1370  for (i = FirstBucket; TRUE; CircularIncrement (i, NUM_PP_BUCKETS)) {
1371  SET_BIT (ParamTable[i], Bit);
1372 
1373  /* exit loop after we have set the bit for the last bucket */
1374  if (i == LastBucket)
1375  break;
1376  }
1377 
1378 } /* FillPPCircularBits */
1379 
1380 
1381 /*---------------------------------------------------------------------------*/
1383  int Bit, FLOAT32 Center, FLOAT32 Spread, bool debug) {
1384 /*
1385  ** Parameters:
1386  ** ParamTable table of bit vectors, one per param bucket
1387  ** Bit bit number being filled
1388  ** Center center of filled area
1389  ** Spread spread of filled area
1390  ** Globals: none
1391  ** Operation: This routine sets Bit in each bit vector whose
1392  ** bucket lies within the range Center +- Spread. The fill
1393  ** is done for a linear dimension, i.e. there is no wrap-around
1394  ** for this dimension. It is assumed that Center and Spread
1395  ** are expressed in a linear coordinate system whose range
1396  ** is approximately 0 to 1. Values outside this range will
1397  ** be clipped.
1398  ** Return: none
1399  ** Exceptions: none
1400  ** History: Tue Oct 16 09:26:54 1990, DSJ, Created.
1401  */
1402  int i, FirstBucket, LastBucket;
1403 
1404  FirstBucket = (int) floor ((Center - Spread) * NUM_PP_BUCKETS);
1405  if (FirstBucket < 0)
1406  FirstBucket = 0;
1407 
1408  LastBucket = (int) floor ((Center + Spread) * NUM_PP_BUCKETS);
1409  if (LastBucket >= NUM_PP_BUCKETS)
1410  LastBucket = NUM_PP_BUCKETS - 1;
1411 
1412  if (debug) tprintf("Linear fill from %d to %d", FirstBucket, LastBucket);
1413  for (i = FirstBucket; i <= LastBucket; i++)
1414  SET_BIT (ParamTable[i], Bit);
1415 
1416 } /* FillPPLinearBits */
1417 
1418 
1419 /*---------------------------------------------------------------------------*/
1420 #ifndef GRAPHICS_DISABLED
1421 namespace tesseract {
1422 CLASS_ID Classify::GetClassToDebug(const char *Prompt, bool* adaptive_on,
1423  bool* pretrained_on, int* shape_id) {
1424 /*
1425  ** Parameters:
1426  ** Prompt prompt to print while waiting for input from window
1427  ** Globals: none
1428  ** Operation: This routine prompts the user with Prompt and waits
1429  ** for the user to enter something in the debug window.
1430  ** Return: Character entered in the debug window.
1431  ** Exceptions: none
1432  ** History: Thu Mar 21 16:55:13 1991, DSJ, Created.
1433  */
1434  tprintf("%s\n", Prompt);
1435  SVEvent* ev;
1436  SVEventType ev_type;
1437  int unichar_id = INVALID_UNICHAR_ID;
1438  // Wait until a click or popup event.
1439  do {
1440  ev = IntMatchWindow->AwaitEvent(SVET_ANY);
1441  ev_type = ev->type;
1442  if (ev_type == SVET_POPUP) {
1443  if (ev->command_id == IDA_SHAPE_INDEX) {
1444  if (shape_table_ != NULL) {
1445  *shape_id = atoi(ev->parameter);
1446  *adaptive_on = false;
1447  *pretrained_on = true;
1448  if (*shape_id >= 0 && *shape_id < shape_table_->NumShapes()) {
1449  int font_id;
1450  shape_table_->GetFirstUnicharAndFont(*shape_id, &unichar_id,
1451  &font_id);
1452  tprintf("Shape %d, first unichar=%d, font=%d\n",
1453  *shape_id, unichar_id, font_id);
1454  return unichar_id;
1455  }
1456  tprintf("Shape index '%s' not found in shape table\n", ev->parameter);
1457  } else {
1458  tprintf("No shape table loaded!\n");
1459  }
1460  } else {
1461  if (unicharset.contains_unichar(ev->parameter)) {
1462  unichar_id = unicharset.unichar_to_id(ev->parameter);
1463  if (ev->command_id == IDA_ADAPTIVE) {
1464  *adaptive_on = true;
1465  *pretrained_on = false;
1466  *shape_id = -1;
1467  } else if (ev->command_id == IDA_STATIC) {
1468  *adaptive_on = false;
1469  *pretrained_on = true;
1470  } else {
1471  *adaptive_on = true;
1472  *pretrained_on = true;
1473  }
1474  if (ev->command_id == IDA_ADAPTIVE || shape_table_ == NULL) {
1475  *shape_id = -1;
1476  return unichar_id;
1477  }
1478  for (int s = 0; s < shape_table_->NumShapes(); ++s) {
1479  if (shape_table_->GetShape(s).ContainsUnichar(unichar_id)) {
1480  tprintf("%s\n", shape_table_->DebugStr(s).string());
1481  }
1482  }
1483  } else {
1484  tprintf("Char class '%s' not found in unicharset",
1485  ev->parameter);
1486  }
1487  }
1488  }
1489  delete ev;
1490  } while (ev_type != SVET_CLICK);
1491  return 0;
1492 } /* GetClassToDebug */
1493 
1494 } // namespace tesseract
1495 #endif
1496 
1497 /*---------------------------------------------------------------------------*/
1498 void GetCPPadsForLevel(int Level,
1499  FLOAT32 *EndPad,
1500  FLOAT32 *SidePad,
1501  FLOAT32 *AnglePad) {
1502 /*
1503  ** Parameters:
1504  ** Level "tightness" level to return pads for
1505  ** EndPad place to put end pad for Level
1506  ** SidePad place to put side pad for Level
1507  ** AnglePad place to put angle pad for Level
1508  ** Globals: none
1509  ** Operation: This routine copies the appropriate global pad variables
1510  ** into EndPad, SidePad, and AnglePad. This is a kludge used
1511  ** to get around the fact that global control variables cannot
1512  ** be arrays. If the specified level is illegal, the tightest
1513  ** possible pads are returned.
1514  ** Return: none (results are returned in EndPad, SidePad, and AnglePad.
1515  ** Exceptions: none
1516  ** History: Thu Feb 14 08:26:49 1991, DSJ, Created.
1517  */
1518  switch (Level) {
1519  case 0:
1522  *AnglePad = classify_cp_angle_pad_loose / 360.0;
1523  break;
1524 
1525  case 1:
1528  *AnglePad = classify_cp_angle_pad_medium / 360.0;
1529  break;
1530 
1531  case 2:
1534  *AnglePad = classify_cp_angle_pad_tight / 360.0;
1535  break;
1536 
1537  default:
1540  *AnglePad = classify_cp_angle_pad_tight / 360.0;
1541  break;
1542  }
1543  if (*AnglePad > 0.5)
1544  *AnglePad = 0.5;
1545 
1546 } /* GetCPPadsForLevel */
1547 
1548 
1549 /*---------------------------------------------------------------------------*/
1551 /*
1552  ** Parameters:
1553  ** Evidence evidence value to return color for
1554  ** Globals: none
1555  ** Operation:
1556  ** Return: Color which corresponds to specified Evidence value.
1557  ** Exceptions: none
1558  ** History: Thu Mar 21 15:24:52 1991, DSJ, Created.
1559  */
1560 
1561  assert (Evidence >= 0.0);
1562  assert (Evidence <= 1.0);
1563 
1564  if (Evidence >= 0.90)
1565  return ScrollView::WHITE;
1566  else if (Evidence >= 0.75)
1567  return ScrollView::GREEN;
1568  else if (Evidence >= 0.50)
1569  return ScrollView::RED;
1570  else
1571  return ScrollView::BLUE;
1572 } /* GetMatchColorFor */
1573 
1574 
1575 /*---------------------------------------------------------------------------*/
1576 void GetNextFill(TABLE_FILLER *Filler, FILL_SPEC *Fill) {
1577 /*
1578  ** Parameters:
1579  ** Filler filler to get next fill spec from
1580  ** Fill place to put spec for next fill
1581  ** Globals: none
1582  ** Operation: This routine returns (in Fill) the specification of
1583  ** the next line to be filled from Filler. FillerDone() should
1584  ** always be called before GetNextFill() to ensure that we
1585  ** do not run past the end of the fill table.
1586  ** Return: none (results are returned in Fill)
1587  ** Exceptions: none
1588  ** History: Tue Feb 19 10:17:42 1991, DSJ, Created.
1589  */
1590  FILL_SWITCH *Next;
1591 
1592  /* compute the fill assuming no switches will be encountered */
1593  Fill->AngleStart = Filler->AngleStart;
1594  Fill->AngleEnd = Filler->AngleEnd;
1595  Fill->X = Filler->X;
1596  Fill->YStart = Filler->YStart >> 8;
1597  Fill->YEnd = Filler->YEnd >> 8;
1598 
1599  /* update the fill info and the filler for ALL switches at this X value */
1600  Next = &(Filler->Switch[Filler->NextSwitch]);
1601  while (Filler->X >= Next->X) {
1602  Fill->X = Filler->X = Next->X;
1603  if (Next->Type == StartSwitch) {
1604  Fill->YStart = Next->Y;
1605  Filler->StartDelta = Next->Delta;
1606  Filler->YStart = Next->YInit;
1607  }
1608  else if (Next->Type == EndSwitch) {
1609  Fill->YEnd = Next->Y;
1610  Filler->EndDelta = Next->Delta;
1611  Filler->YEnd = Next->YInit;
1612  }
1613  else { /* Type must be LastSwitch */
1614  break;
1615  }
1616  Filler->NextSwitch++;
1617  Next = &(Filler->Switch[Filler->NextSwitch]);
1618  }
1619 
1620  /* prepare the filler for the next call to this routine */
1621  Filler->X++;
1622  Filler->YStart += Filler->StartDelta;
1623  Filler->YEnd += Filler->EndDelta;
1624 
1625 } /* GetNextFill */
1626 
1627 
1628 /*---------------------------------------------------------------------------*/
1644 void InitTableFiller (FLOAT32 EndPad, FLOAT32 SidePad,
1645  FLOAT32 AnglePad, PROTO Proto, TABLE_FILLER * Filler)
1646 #define XS X_SHIFT
1647 #define YS Y_SHIFT
1648 #define AS ANGLE_SHIFT
1649 #define NB NUM_CP_BUCKETS
1650 {
1651  FLOAT32 Angle;
1652  FLOAT32 X, Y, HalfLength;
1653  FLOAT32 Cos, Sin;
1654  FLOAT32 XAdjust, YAdjust;
1655  FPOINT Start, Switch1, Switch2, End;
1656  int S1 = 0;
1657  int S2 = 1;
1658 
1659  Angle = Proto->Angle;
1660  X = Proto->X;
1661  Y = Proto->Y;
1662  HalfLength = Proto->Length / 2.0;
1663 
1664  Filler->AngleStart = CircBucketFor(Angle - AnglePad, AS, NB);
1665  Filler->AngleEnd = CircBucketFor(Angle + AnglePad, AS, NB);
1666  Filler->NextSwitch = 0;
1667 
1668  if (fabs (Angle - 0.0) < HV_TOLERANCE || fabs (Angle - 0.5) < HV_TOLERANCE) {
1669  /* horizontal proto - handle as special case */
1670  Filler->X = Bucket8For(X - HalfLength - EndPad, XS, NB);
1671  Filler->YStart = Bucket16For(Y - SidePad, YS, NB * 256);
1672  Filler->YEnd = Bucket16For(Y + SidePad, YS, NB * 256);
1673  Filler->StartDelta = 0;
1674  Filler->EndDelta = 0;
1675  Filler->Switch[0].Type = LastSwitch;
1676  Filler->Switch[0].X = Bucket8For(X + HalfLength + EndPad, XS, NB);
1677  } else if (fabs(Angle - 0.25) < HV_TOLERANCE ||
1678  fabs(Angle - 0.75) < HV_TOLERANCE) {
1679  /* vertical proto - handle as special case */
1680  Filler->X = Bucket8For(X - SidePad, XS, NB);
1681  Filler->YStart = Bucket16For(Y - HalfLength - EndPad, YS, NB * 256);
1682  Filler->YEnd = Bucket16For(Y + HalfLength + EndPad, YS, NB * 256);
1683  Filler->StartDelta = 0;
1684  Filler->EndDelta = 0;
1685  Filler->Switch[0].Type = LastSwitch;
1686  Filler->Switch[0].X = Bucket8For(X + SidePad, XS, NB);
1687  } else {
1688  /* diagonal proto */
1689 
1690  if ((Angle > 0.0 && Angle < 0.25) || (Angle > 0.5 && Angle < 0.75)) {
1691  /* rising diagonal proto */
1692  Angle *= 2.0 * PI;
1693  Cos = fabs(cos(Angle));
1694  Sin = fabs(sin(Angle));
1695 
1696  /* compute the positions of the corners of the acceptance region */
1697  Start.x = X - (HalfLength + EndPad) * Cos - SidePad * Sin;
1698  Start.y = Y - (HalfLength + EndPad) * Sin + SidePad * Cos;
1699  End.x = 2.0 * X - Start.x;
1700  End.y = 2.0 * Y - Start.y;
1701  Switch1.x = X - (HalfLength + EndPad) * Cos + SidePad * Sin;
1702  Switch1.y = Y - (HalfLength + EndPad) * Sin - SidePad * Cos;
1703  Switch2.x = 2.0 * X - Switch1.x;
1704  Switch2.y = 2.0 * Y - Switch1.y;
1705 
1706  if (Switch1.x > Switch2.x) {
1707  S1 = 1;
1708  S2 = 0;
1709  }
1710 
1711  /* translate into bucket positions and deltas */
1712  Filler->X = Bucket8For(Start.x, XS, NB);
1713  Filler->StartDelta = -(inT16) ((Cos / Sin) * 256);
1714  Filler->EndDelta = (inT16) ((Sin / Cos) * 256);
1715 
1716  XAdjust = BucketEnd(Filler->X, XS, NB) - Start.x;
1717  YAdjust = XAdjust * Cos / Sin;
1718  Filler->YStart = Bucket16For(Start.y - YAdjust, YS, NB * 256);
1719  YAdjust = XAdjust * Sin / Cos;
1720  Filler->YEnd = Bucket16For(Start.y + YAdjust, YS, NB * 256);
1721 
1722  Filler->Switch[S1].Type = StartSwitch;
1723  Filler->Switch[S1].X = Bucket8For(Switch1.x, XS, NB);
1724  Filler->Switch[S1].Y = Bucket8For(Switch1.y, YS, NB);
1725  XAdjust = Switch1.x - BucketStart(Filler->Switch[S1].X, XS, NB);
1726  YAdjust = XAdjust * Sin / Cos;
1727  Filler->Switch[S1].YInit = Bucket16For(Switch1.y - YAdjust, YS, NB * 256);
1728  Filler->Switch[S1].Delta = Filler->EndDelta;
1729 
1730  Filler->Switch[S2].Type = EndSwitch;
1731  Filler->Switch[S2].X = Bucket8For(Switch2.x, XS, NB);
1732  Filler->Switch[S2].Y = Bucket8For(Switch2.y, YS, NB);
1733  XAdjust = Switch2.x - BucketStart(Filler->Switch[S2].X, XS, NB);
1734  YAdjust = XAdjust * Cos / Sin;
1735  Filler->Switch[S2].YInit = Bucket16For(Switch2.y + YAdjust, YS, NB * 256);
1736  Filler->Switch[S2].Delta = Filler->StartDelta;
1737 
1738  Filler->Switch[2].Type = LastSwitch;
1739  Filler->Switch[2].X = Bucket8For(End.x, XS, NB);
1740  } else {
1741  /* falling diagonal proto */
1742  Angle *= 2.0 * PI;
1743  Cos = fabs(cos(Angle));
1744  Sin = fabs(sin(Angle));
1745 
1746  /* compute the positions of the corners of the acceptance region */
1747  Start.x = X - (HalfLength + EndPad) * Cos - SidePad * Sin;
1748  Start.y = Y + (HalfLength + EndPad) * Sin - SidePad * Cos;
1749  End.x = 2.0 * X - Start.x;
1750  End.y = 2.0 * Y - Start.y;
1751  Switch1.x = X - (HalfLength + EndPad) * Cos + SidePad * Sin;
1752  Switch1.y = Y + (HalfLength + EndPad) * Sin + SidePad * Cos;
1753  Switch2.x = 2.0 * X - Switch1.x;
1754  Switch2.y = 2.0 * Y - Switch1.y;
1755 
1756  if (Switch1.x > Switch2.x) {
1757  S1 = 1;
1758  S2 = 0;
1759  }
1760 
1761  /* translate into bucket positions and deltas */
1762  Filler->X = Bucket8For(Start.x, XS, NB);
1763  Filler->StartDelta = -(inT16) ((Sin / Cos) * 256);
1764  Filler->EndDelta = (inT16) ((Cos / Sin) * 256);
1765 
1766  XAdjust = BucketEnd(Filler->X, XS, NB) - Start.x;
1767  YAdjust = XAdjust * Sin / Cos;
1768  Filler->YStart = Bucket16For(Start.y - YAdjust, YS, NB * 256);
1769  YAdjust = XAdjust * Cos / Sin;
1770  Filler->YEnd = Bucket16For(Start.y + YAdjust, YS, NB * 256);
1771 
1772  Filler->Switch[S1].Type = EndSwitch;
1773  Filler->Switch[S1].X = Bucket8For(Switch1.x, XS, NB);
1774  Filler->Switch[S1].Y = Bucket8For(Switch1.y, YS, NB);
1775  XAdjust = Switch1.x - BucketStart(Filler->Switch[S1].X, XS, NB);
1776  YAdjust = XAdjust * Sin / Cos;
1777  Filler->Switch[S1].YInit = Bucket16For(Switch1.y + YAdjust, YS, NB * 256);
1778  Filler->Switch[S1].Delta = Filler->StartDelta;
1779 
1780  Filler->Switch[S2].Type = StartSwitch;
1781  Filler->Switch[S2].X = Bucket8For(Switch2.x, XS, NB);
1782  Filler->Switch[S2].Y = Bucket8For(Switch2.y, YS, NB);
1783  XAdjust = Switch2.x - BucketStart(Filler->Switch[S2].X, XS, NB);
1784  YAdjust = XAdjust * Cos / Sin;
1785  Filler->Switch[S2].YInit = Bucket16For(Switch2.y - YAdjust, YS, NB * 256);
1786  Filler->Switch[S2].Delta = Filler->EndDelta;
1787 
1788  Filler->Switch[2].Type = LastSwitch;
1789  Filler->Switch[2].X = Bucket8For(End.x, XS, NB);
1790  }
1791  }
1792 } /* InitTableFiller */
1793 
1794 
1795 /*---------------------------------------------------------------------------*/
1796 #ifndef GRAPHICS_DISABLED
1797 /*
1798  * Parameters:
1799  * ShapeList shape list to add feature rendering to
1800  * Feature feature to be rendered
1801  * Color color to use for feature rendering
1802  * Globals: none
1803  * Operation: This routine renders the specified feature into ShapeList.
1804  * Return: New shape list with rendering of Feature added.
1805  * @note Exceptions: none
1806  * @note History: Thu Mar 21 14:57:41 1991, DSJ, Created.
1807  */
1808 void RenderIntFeature(ScrollView *window, const INT_FEATURE_STRUCT* Feature,
1809  ScrollView::Color color) {
1810  FLOAT32 X, Y, Dx, Dy, Length;
1811 
1812  window->Pen(color);
1813  assert(Feature != NULL);
1814  assert(color != 0);
1815 
1816  X = Feature->X;
1817  Y = Feature->Y;
1818  Length = GetPicoFeatureLength() * 0.7 * INT_CHAR_NORM_RANGE;
1819  // The -PI has no significant effect here, but the value of Theta is computed
1820  // using BinaryAnglePlusPi in intfx.cpp.
1821  Dx = (Length / 2.0) * cos((Feature->Theta / 256.0) * 2.0 * PI - PI);
1822  Dy = (Length / 2.0) * sin((Feature->Theta / 256.0) * 2.0 * PI - PI);
1823 
1824  window->SetCursor(X, Y);
1825  window->DrawTo(X + Dx, Y + Dy);
1826 } /* RenderIntFeature */
1827 
1828 
1829 /*---------------------------------------------------------------------------*/
1830 /*
1831  * This routine extracts the parameters of the specified
1832  * proto from the class description and adds a rendering of
1833  * the proto onto the ShapeList.
1834  *
1835  * @param Class class that proto is contained in
1836  * @param ProtoId id of proto to be rendered
1837  * @param color color to render proto in
1838  *
1839  * Globals: none
1840  *
1841  * @return New shape list with a rendering of one proto added.
1842  * @note Exceptions: none
1843  * @note History: Thu Mar 21 10:21:09 1991, DSJ, Created.
1844  */
1846  INT_CLASS Class,
1847  PROTO_ID ProtoId,
1848  ScrollView::Color color) {
1849  PROTO_SET ProtoSet;
1850  INT_PROTO Proto;
1851  int ProtoSetIndex;
1852  int ProtoWordIndex;
1853  FLOAT32 Length;
1854  int Xmin, Xmax, Ymin, Ymax;
1855  FLOAT32 X, Y, Dx, Dy;
1856  uinT32 ProtoMask;
1857  int Bucket;
1858 
1859  assert(ProtoId >= 0);
1860  assert(Class != NULL);
1861  assert(ProtoId < Class->NumProtos);
1862  assert(color != 0);
1863  window->Pen(color);
1864 
1865  ProtoSet = Class->ProtoSets[SetForProto(ProtoId)];
1866  ProtoSetIndex = IndexForProto(ProtoId);
1867  Proto = &(ProtoSet->Protos[ProtoSetIndex]);
1868  Length = (Class->ProtoLengths[ProtoId] *
1870  ProtoMask = PPrunerMaskFor(ProtoId);
1871  ProtoWordIndex = PPrunerWordIndexFor(ProtoId);
1872 
1873  // find the x and y extent of the proto from the proto pruning table
1874  Xmin = Ymin = NUM_PP_BUCKETS;
1875  Xmax = Ymax = 0;
1876  for (Bucket = 0; Bucket < NUM_PP_BUCKETS; Bucket++) {
1877  if (ProtoMask & ProtoSet->ProtoPruner[PRUNER_X][Bucket][ProtoWordIndex]) {
1878  UpdateRange(Bucket, &Xmin, &Xmax);
1879  }
1880 
1881  if (ProtoMask & ProtoSet->ProtoPruner[PRUNER_Y][Bucket][ProtoWordIndex]) {
1882  UpdateRange(Bucket, &Ymin, &Ymax);
1883  }
1884  }
1885  X = (Xmin + Xmax + 1) / 2.0 * PROTO_PRUNER_SCALE;
1886  Y = (Ymin + Ymax + 1) / 2.0 * PROTO_PRUNER_SCALE;
1887  // The -PI has no significant effect here, but the value of Theta is computed
1888  // using BinaryAnglePlusPi in intfx.cpp.
1889  Dx = (Length / 2.0) * cos((Proto->Angle / 256.0) * 2.0 * PI - PI);
1890  Dy = (Length / 2.0) * sin((Proto->Angle / 256.0) * 2.0 * PI - PI);
1891 
1892  window->SetCursor(X - Dx, Y - Dy);
1893  window->DrawTo(X + Dx, Y + Dy);
1894 } /* RenderIntProto */
1895 #endif
1896 
1897 /*---------------------------------------------------------------------------*/
1913 int TruncateParam(FLOAT32 Param, int Min, int Max, char *Id) {
1914  if (Param < Min) {
1915  if (Id)
1916  cprintf("Warning: Param %s truncated from %f to %d!\n",
1917  Id, Param, Min);
1918  Param = Min;
1919  } else if (Param > Max) {
1920  if (Id)
1921  cprintf("Warning: Param %s truncated from %f to %d!\n",
1922  Id, Param, Max);
1923  Param = Max;
1924  }
1925  return static_cast<int>(floor(Param));
1926 } /* TruncateParam */
1927 
1928 
1929 /*---------------------------------------------------------------------------*/
1930 #ifndef GRAPHICS_DISABLED
1931 
1936  if (IntMatchWindow == NULL) {
1937  IntMatchWindow = CreateFeatureSpaceWindow("IntMatchWindow", 50, 200);
1938  SVMenuNode* popup_menu = new SVMenuNode();
1939 
1940  popup_menu->AddChild("Debug Adapted classes", IDA_ADAPTIVE,
1941  "x", "Class to debug");
1942  popup_menu->AddChild("Debug Static classes", IDA_STATIC,
1943  "x", "Class to debug");
1944  popup_menu->AddChild("Debug Both", IDA_BOTH,
1945  "x", "Class to debug");
1946  popup_menu->AddChild("Debug Shape Index", IDA_SHAPE_INDEX,
1947  "0", "Index to debug");
1948  popup_menu->BuildMenu(IntMatchWindow, false);
1949  }
1950 }
1951 
1957  if (ProtoDisplayWindow == NULL) {
1958  ProtoDisplayWindow = CreateFeatureSpaceWindow("ProtoDisplayWindow",
1959  550, 200);
1960  }
1961 }
1962 
1968  if (FeatureDisplayWindow == NULL) {
1969  FeatureDisplayWindow = CreateFeatureSpaceWindow("FeatureDisplayWindow",
1970  50, 700);
1971  }
1972 }
1973 
1974 // Creates a window of the appropriate size for displaying elements
1975 // in feature space.
1976 ScrollView* CreateFeatureSpaceWindow(const char* name, int xpos, int ypos) {
1977  return new ScrollView(name, xpos, ypos, 520, 520, 260, 260, true);
1978 }
1979 #endif // GRAPHICS_DISABLED
BOOL8 FillerDone(TABLE_FILLER *Filler)
Definition: intproto.cpp:1314
USHORT Offset
Definition: GlyphLessFont.h:26
#define X_SHIFT
Definition: intproto.h:40
#define Y_SHIFT
Definition: intproto.h:41
uinT32 Configs[WERDS_PER_CONFIG_VEC]
Definition: intproto.h:86
double classify_cp_end_pad_loose
Definition: intproto.cpp:197
#define INT_MAX_Y
Definition: intproto.cpp:68
#define BITS_PER_CP_VECTOR
Definition: intproto.h:58
#define INT_MAX_X
Definition: intproto.cpp:67
void GetCPPadsForLevel(int Level, FLOAT32 *EndPad, FLOAT32 *SidePad, FLOAT32 *AnglePad)
Definition: intproto.cpp:1498
inT8 YEnd
Definition: intproto.cpp:105
name_table name
void UpdateRange(const T1 &x, T2 *lower_bound, T2 *upper_bound)
Definition: helpers.h:125
bool write_set(FILE *f, const FontSet &fs)
Definition: fontinfo.cpp:253
inT16 StartDelta
Definition: intproto.cpp:95
#define SET_BIT(array, bit)
Definition: bitvec.h:57
INT_CLASS NewIntClass(int MaxNumProtos, int MaxNumConfigs)
Definition: intproto.cpp:673
Definition: fpoint.h:29
FLOAT32 y
Definition: fpoint.h:31
inT16 YEnd
Definition: intproto.cpp:94
#define PROTO_PRUNER_SCALE
Definition: intproto.cpp:54
#define PPrunerMaskFor(I)
Definition: intproto.h:176
int IntCastRounded(double x)
Definition: helpers.h:172
#define WERDS_PER_PP_VECTOR
Definition: intproto.h:62
INT_PROTO_STRUCT Protos[PROTOS_PER_PROTO_SET]
Definition: intproto.h:97
void SetCursor(int x, int y)
Definition: scrollview.cpp:525
double classify_pp_end_pad
Definition: intproto.cpp:204
int AddIntConfig(INT_CLASS Class)
Definition: intproto.cpp:274
double classify_pp_angle_pad
Definition: intproto.cpp:203
#define CPrunerIdFor(c)
Definition: intproto.h:183
#define INT_CHAR_NORM_RANGE
Definition: intproto.h:133
UNICHAR_ID CLASS_ID
Definition: matchdefs.h:35
#define tprintf(...)
Definition: tprintf.h:31
void AddIntClass(INT_TEMPLATES Templates, CLASS_ID ClassId, INT_CLASS Class)
Definition: intproto.cpp:241
uinT8 NumProtoSets
Definition: intproto.h:109
void free_int_templates(INT_TEMPLATES templates)
Definition: intproto.cpp:764
#define WERDS_PER_CONFIG_VEC
Definition: intproto.h:68
#define double_VAR(name, val, comment)
Definition: params.h:286
int size() const
Return the size used.
#define ProtoIn(Class, Pid)
Definition: protos.h:123
#define NB
SIGNED char inT8
Definition: host.h:98
double classify_cp_angle_pad_medium
Definition: intproto.cpp:194
#define AS
#define INT_XHEIGHT
Definition: intproto.cpp:58
SVEventType
Definition: scrollview.h:45
uinT8 NextSwitch
Definition: intproto.cpp:91
uinT32 PROTO_PRUNER[NUM_PP_PARAMS][NUM_PP_BUCKETS][WERDS_PER_PP_VECTOR]
Definition: intproto.h:92
#define BITS_PER_WERD
Definition: intproto.h:44
int AddIntProto(INT_CLASS Class)
Definition: intproto.cpp:298
#define LegalClassId(c)
Definition: intproto.h:179
void UpdateMatchDisplay()
Definition: intproto.cpp:466
void FillPPLinearBits(uinT32 ParamTable[NUM_PP_BUCKETS][WERDS_PER_PP_VECTOR], int Bit, FLOAT32 Center, FLOAT32 Spread, bool debug)
Definition: intproto.cpp:1382
FLOAT32 Y
Definition: protos.h:48
#define MAX(x, y)
Definition: ndminx.h:24
void Rectangle(int x1, int y1, int x2, int y2)
Definition: scrollview.cpp:606
bool write_spacing_info(FILE *f, const FontInfo &fi)
Definition: fontinfo.cpp:211
SWITCH_TYPE
Definition: intproto.cpp:73
uinT16 Bucket16For(FLOAT32 param, FLOAT32 offset, int num_buckets)
Definition: intproto.cpp:449
CLUSTERCONFIG Config
void BuildMenu(ScrollView *sv, bool menu_bar=true)
Definition: svmnode.cpp:121
uinT32 p[NUM_CP_BUCKETS][NUM_CP_BUCKETS][NUM_CP_BUCKETS][WERDS_PER_CP_VECTOR]
Definition: intproto.h:77
inT16 NumConfigs
Definition: protos.h:62
int TruncateParam(FLOAT32 Param, int Min, int Max, char *Id)
Definition: intproto.cpp:1913
#define MAX_LEVEL
uinT8 AngleStart
Definition: intproto.cpp:106
inT16 YStart
Definition: intproto.cpp:94
#define NULL
Definition: host.h:144
inT16 NumProtos
Definition: protos.h:59
unsigned int uinT32
Definition: host.h:103
inT16 PROTO_ID
Definition: matchdefs.h:41
void * Erealloc(void *ptr, int size)
Definition: emalloc.cpp:70
bool read_spacing_info(FILE *f, FontInfo *fi, bool swap)
Definition: fontinfo.cpp:177
void free_int_class(INT_CLASS int_class)
Definition: intproto.cpp:725
#define INT_DESCENDER
Definition: intproto.cpp:56
#define MaxNumClassesIn(T)
Definition: intproto.h:178
#define NUM_CP_BUCKETS
Definition: intproto.h:52
void AddProtoToProtoPruner(PROTO Proto, int ProtoId, INT_CLASS Class, bool debug)
Definition: intproto.cpp:381
void ClearFeatureSpaceWindow(NORM_METHOD norm_method, ScrollView *window)
Definition: intproto.cpp:1122
INT_TEMPLATES NewIntTemplates()
Definition: intproto.cpp:739
void GetNextFill(TABLE_FILLER *Filler, FILL_SPEC *Fill)
Definition: intproto.cpp:1576
#define PRUNER_Y
Definition: intproto.h:35
#define CPrunerWordIndexFor(c)
Definition: intproto.h:185
FLOAT32 BucketEnd(int Bucket, FLOAT32 Offset, int NumBuckets)
Definition: intproto.cpp:1244
#define FALSE
Definition: capi.h:29
inT16 EndDelta
Definition: intproto.cpp:95
#define CPrunerFor(T, c)
Definition: intproto.h:184
INT_CLASS Class[MAX_NUM_CLASSES]
Definition: intproto.h:124
#define OLD_WERDS_PER_CONFIG_VEC
Definition: intproto.cpp:115
UnicityTableEqEq< int > font_set
Definition: protos.h:65
PROTO_PRUNER ProtoPruner
Definition: intproto.h:96
#define INT_MIN_Y
Definition: intproto.cpp:66
#define MapParam(P, O, N)
Definition: intproto.cpp:125
#define MaxNumIntProtosIn(C)
Definition: intproto.h:168
_ConstTessMemberResultCallback_0_0< false, R, T1 >::base * NewPermanentTessCallback(const T1 *obj, R(T2::*member)() const)
Definition: tesscallback.h:116
#define MAX_NUM_CONFIGS
Definition: intproto.h:46
#define isnan(x)
Definition: mathfix.h:31
#define PRUNER_ANGLE
Definition: intproto.h:36
#define IndexForProto(P)
Definition: intproto.h:170
uinT8 Bucket8For(FLOAT32 param, FLOAT32 offset, int num_buckets)
Definition: intproto.cpp:445
int classify_num_cp_levels
Definition: intproto.cpp:190
#define PPrunerWordIndexFor(I)
Definition: intproto.h:173
PROTO_SET ProtoSets[MAX_NUM_PROTO_SETS]
Definition: intproto.h:111
void InitTableFiller(FLOAT32 EndPad, FLOAT32 SidePad, FLOAT32 AnglePad, PROTO Proto, TABLE_FILLER *Filler)
Definition: intproto.cpp:1644
FLOAT32 X
Definition: protos.h:47
uinT8 AngleEnd
Definition: intproto.cpp:106
struct INT_CLASS_STRUCT * INT_CLASS
FLOAT32 B
Definition: protos.h:45
#define ProtoForProtoId(C, P)
Definition: intproto.h:171
bool read_set(FILE *f, FontSet *fs, bool swap)
Definition: fontinfo.cpp:240
#define PI
Definition: const.h:19
#define SetForProto(P)
Definition: intproto.h:169
#define ClassForClassId(T, c)
Definition: intproto.h:181
ScrollView::Color GetMatchColorFor(FLOAT32 Evidence)
Definition: intproto.cpp:1550
inT16 YInit
Definition: intproto.cpp:82
void DisplayIntFeature(const INT_FEATURE_STRUCT *Feature, FLOAT32 Evidence)
Definition: intproto.cpp:628
double classify_cp_angle_pad_tight
Definition: intproto.cpp:196
SWITCH_TYPE Type
Definition: intproto.cpp:80
FLOAT32 Length
Definition: protos.h:50
bool write_info(FILE *f, const FontInfo &fi)
Definition: fontinfo.cpp:168
ScrollView * FeatureDisplayWindow
Definition: intproto.cpp:182
uinT16 ConfigLengths[MAX_NUM_CONFIGS]
Definition: intproto.h:113
void ShowMatchDisplay()
FLOAT32 Angle
Definition: protos.h:49
#define PRUNER_X
Definition: intproto.h:34
void DoFill(FILL_SPEC *FillSpec, CLASS_PRUNER_STRUCT *Pruner, register uinT32 ClassMask, register uinT32 ClassCount, register uinT32 WordIndex)
Definition: intproto.cpp:1264
void Efree(void *ptr)
Definition: emalloc.cpp:85
#define NUM_PP_PARAMS
Definition: intproto.h:50
short inT16
Definition: host.h:100
#define WERDS_PER_CP_VECTOR
Definition: intproto.h:61
void DrawTo(int x, int y)
Definition: scrollview.cpp:531
#define NUM_PP_BUCKETS
Definition: intproto.h:51
inT8 YStart
Definition: intproto.cpp:105
#define MAX_NUM_PROTO_SETS
Definition: intproto.h:49
double classify_cp_angle_pad_loose
Definition: intproto.cpp:192
double classify_cp_end_pad_medium
Definition: intproto.cpp:198
void Pen(Color color)
Definition: scrollview.cpp:726
ScrollView * CreateFeatureSpaceWindow(const char *name, int xpos, int ypos)
Definition: intproto.cpp:1976
#define GetPicoFeatureLength()
Definition: picofeat.h:59
FLOAT32 BucketStart(int Bucket, FLOAT32 Offset, int NumBuckets)
Definition: intproto.cpp:1223
#define INT_YCENTER
Definition: intproto.cpp:62
#define MAX_NUM_CLASS_PRUNERS
Definition: intproto.h:59
void Clear()
Definition: scrollview.cpp:595
double classify_pp_side_pad
Definition: intproto.cpp:205
#define XS
uinT8 AngleEnd
Definition: intproto.cpp:92
void cprintf(const char *format,...)
Definition: callcpp.cpp:40
double classify_cp_side_pad_tight
Definition: intproto.cpp:202
void DisplayIntProto(INT_CLASS Class, PROTO_ID ProtoId, FLOAT32 Evidence)
Definition: intproto.cpp:650
unsigned short uinT16
Definition: host.h:101
void Reverse16(void *ptr)
Definition: helpers.h:188
#define INT_VAR(name, val, comment)
Definition: params.h:277
void InitProtoDisplayWindowIfReqd()
Definition: intproto.cpp:1956
struct INT_TEMPLATES_STRUCT * INT_TEMPLATES
void RenderIntProto(ScrollView *window, INT_CLASS Class, PROTO_ID ProtoId, ScrollView::Color color)
Definition: intproto.cpp:1845
void Reverse32(void *ptr)
Definition: helpers.h:193
inT16 Delta
Definition: intproto.cpp:83
uinT32 * BIT_VECTOR
Definition: bitvec.h:28
uinT16 NumProtos
Definition: intproto.h:108
CONFIGS Configurations
Definition: protos.h:64
struct PROTO_SET_STRUCT * PROTO_SET
unsigned char BOOL8
Definition: host.h:113
#define TRUE
Definition: capi.h:28
Definition: points.h:189
void ConvertConfig(BIT_VECTOR Config, int ConfigId, INT_CLASS Class)
Definition: intproto.cpp:484
const char *const id_to_unichar(UNICHAR_ID id) const
Definition: unicharset.cpp:266
#define CircularIncrement(i, r)
Definition: intproto.cpp:122
#define test_bit(array, bit)
Definition: bitvec.h:61
void * Emalloc(int Size)
Definition: emalloc.cpp:35
#define NO_PROTO
Definition: matchdefs.h:42
#define CPrunerMaskFor(L, c)
Definition: intproto.h:187
#define OLD_MAX_NUM_CONFIGS
Definition: intproto.cpp:114
#define YS
void FillPPCircularBits(uinT32 ParamTable[NUM_PP_BUCKETS][WERDS_PER_PP_VECTOR], int Bit, FLOAT32 Center, FLOAT32 Spread, bool debug)
Definition: intproto.cpp:1338
void InitIntMatchWindowIfReqd()
Definition: intproto.cpp:1935
ScrollView * ProtoDisplayWindow
Definition: intproto.cpp:183
void InitFeatureDisplayWindowIfReqd()
Definition: intproto.cpp:1967
#define PROTOS_PER_PROTO_SET
Definition: intproto.h:48
int Modulo(int a, int b)
Definition: helpers.h:157
FLOAT32 x
Definition: fpoint.h:31
#define HV_TOLERANCE
Definition: intproto.cpp:71
#define INT_BASELINE
Definition: intproto.cpp:57
uinT8 CircBucketFor(FLOAT32 param, FLOAT32 offset, int num_buckets)
Definition: intproto.cpp:458
#define MAX_UINT8
Definition: host.h:121
CLASS_PRUNER_STRUCT * ClassPruners[MAX_NUM_CLASS_PRUNERS]
Definition: intproto.h:125
uinT8 AngleStart
Definition: intproto.cpp:92
void RenderIntFeature(ScrollView *window, const INT_FEATURE_STRUCT *Feature, ScrollView::Color color)
Definition: intproto.cpp:1808
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
Definition: helpers.h:115
#define INT_XCENTER
Definition: intproto.cpp:61
ScrollView * IntMatchWindow
Definition: intproto.cpp:181
#define NUM_BITS_PER_CLASS
Definition: intproto.h:54
unsigned char uinT8
Definition: host.h:99
#define ANGLE_SHIFT
Definition: intproto.h:39
FILL_SWITCH Switch[MAX_NUM_SWITCHES]
Definition: intproto.cpp:96
int size() const
Definition: unicharset.h:297
uinT8 NumConfigs
Definition: intproto.h:110
void AddProtoToClassPruner(PROTO Proto, CLASS_ID ClassId, INT_TEMPLATES Templates)
Definition: intproto.cpp:337
double classify_cp_side_pad_loose
Definition: intproto.cpp:200
#define UnusedClassIdIn(T, c)
Definition: intproto.h:180
FLOAT32 C
Definition: protos.h:46
#define INT_CAPHEIGHT
Definition: intproto.cpp:59
double classify_cp_end_pad_tight
Definition: intproto.cpp:199
void ZoomToRectangle(int x1, int y1, int x2, int y2)
Definition: scrollview.cpp:765
#define MAX_NUM_SWITCHES
Definition: intproto.cpp:76
bool read_info(FILE *f, FontInfo *fi, bool swap)
Definition: fontinfo.cpp:152
SVMenuNode * AddChild(const char *txt)
Definition: svmnode.cpp:59
char * parameter
Definition: scrollview.h:71
#define MAX_NUM_PROTOS
Definition: intproto.h:47
const T & get(int id) const
Return the object from an id.
#define INT_XRADIUS
Definition: intproto.cpp:63
#define MAX_NUM_CLASSES
Definition: matchdefs.h:31
#define INT_MIN_X
Definition: intproto.cpp:65
float FLOAT32
Definition: host.h:111
static void Update()
Definition: scrollview.cpp:715
#define ASSERT_HOST(x)
Definition: errcode.h:84
uinT8 * ProtoLengths
Definition: intproto.h:112
FLOAT32 A
Definition: protos.h:44
SVEventType type
Definition: scrollview.h:64
#define CPrunerBitIndexFor(c)
Definition: intproto.h:186
SVEvent * AwaitEvent(SVEventType type)
Definition: scrollview.cpp:449
#define INT_YRADIUS
Definition: intproto.cpp:64
NORM_METHOD
Definition: mfoutline.h:53
int command_id
Definition: scrollview.h:70
double classify_cp_side_pad_medium
Definition: intproto.cpp:201