CoolFace
Datasetpublic

GSaha567/seq_level_training_data

sourceHugging Faceupdated 8mo agoView on Hugging Face
0likes52downloads
shard_000049.csv80672 linesDownload Raw Back to root
1text,length,is_long_context,metric_val,label_metric2"/******************************************************************************3 ** Filename:    intproto.c4 ** Purpose:     Definition of data structures for integer protos.5 ** Author:      Dan Johnson6 **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 at11 ** http://www.apache.org/licenses/LICENSE-2.012 ** Unless required by applicable law or agreed to in writing, software13 ** 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 and16 ** limitations under the License.17 ******************************************************************************/18/*-----------------------------------------------------------------------------19          Include Files and Type Defines20-----------------------------------------------------------------------------*/21 22#define _USE_MATH_DEFINES // for M_PI23 24// Include automatically generated configuration file if running autoconf.25#ifdef HAVE_CONFIG_H26#  include ""config_auto.h""27#endif28 29#include ""intproto.h""30 31#include ""classify.h""32#include ""fontinfo.h""33#include ""mfoutline.h""34#include ""picofeat.h""35#include ""points.h""36#include ""shapetable.h""37#ifndef GRAPHICS_DISABLED38#include ""svmnode.h""39#endif40 41#include ""helpers.h""42 43#include <algorithm>44#include <cassert>45#include <cmath> // for M_PI, std::floor46#include <cstdio>47 48namespace tesseract {49 50/* match debug display constants*/51#define PROTO_PRUNER_SCALE (4.0)52 53#define INT_DESCENDER (0.0 * INT_CHAR_NORM_RANGE)54#define INT_BASELINE (0.25 * INT_CHAR_NORM_RANGE)55#define INT_XHEIGHT (0.75 * INT_CHAR_NORM_RANGE)56#define INT_CAPHEIGHT (1.0 * INT_CHAR_NORM_RANGE)57 58#define INT_XCENTER (0.5 * INT_CHAR_NORM_RANGE)59#define INT_YCENTER (0.5 * INT_CHAR_NORM_RANGE)60#define INT_XRADIUS (0.2 * INT_CHAR_NORM_RANGE)61#define INT_YRADIUS (0.2 * INT_CHAR_NORM_RANGE)62#define INT_MIN_X 063#define INT_MIN_Y 064#define INT_MAX_X INT_CHAR_NORM_RANGE65#define INT_MAX_Y INT_CHAR_NORM_RANGE66 67/** define pad used to snap near horiz/vertical protos to horiz/vertical */68#define HV_TOLERANCE (0.0025) /* approx 0.9 degrees */69 70typedef enum { StartSwitch, EndSwitch, LastSwitch } SWITCH_TYPE;71#define MAX_NUM_SWITCHES 372 73struct FILL_SWITCH {74  SWITCH_TYPE Type;75  int8_t X, Y;76  int16_t YInit;77  int16_t Delta;78};79 80struct TABLE_FILLER {81  uint8_t NextSwitch;82  uint8_t AngleStart, AngleEnd;83  int8_t X;84  int16_t YStart, YEnd;85  int16_t StartDelta, EndDelta;86  FILL_SWITCH Switch[MAX_NUM_SWITCHES];87};88 89struct FILL_SPEC {90  int8_t X;91  int8_t YStart, YEnd;92  uint8_t AngleStart, AngleEnd;93};94 95/* constants for conversion from old inttemp format */96#define OLD_MAX_NUM_CONFIGS 3297#define OLD_WERDS_PER_CONFIG_VEC ((OLD_MAX_NUM_CONFIGS + BITS_PER_WERD - 1) / BITS_PER_WERD)98 99/*-----------------------------------------------------------------------------100            Macros101-----------------------------------------------------------------------------*/102/** macro for performing circular increments of bucket indices */103#define CircularIncrement(i, r) (((i) < (r)-1) ? ((i)++) : ((i) = 0))104 105/** macro for mapping floats to ints without bounds checking */106#define MapParam(P, O, N) (std::floor(((P) + (O)) * (N)))107 108/*---------------------------------------------------------------------------109            Private Function Prototypes110----------------------------------------------------------------------------*/111float BucketStart(int Bucket, float Offset, int NumBuckets);112 113float BucketEnd(int Bucket, float Offset, int NumBuckets);114 115void DoFill(FILL_SPEC *FillSpec, CLASS_PRUNER_STRUCT *Pruner, uint32_t ClassMask,116            uint32_t ClassCount, uint32_t WordIndex);117 118bool FillerDone(TABLE_FILLER *Filler);119 120void FillPPCircularBits(uint32_t ParamTable[NUM_PP_BUCKETS][WERDS_PER_PP_VECTOR], int Bit,121                        float Center, float Spread, bool debug);122 123void FillPPLinearBits(uint32_t ParamTable[NUM_PP_BUCKETS][WERDS_PER_PP_VECTOR], int Bit,124                      float Center, float Spread, bool debug);125 126void GetCPPadsForLevel(int Level, float *EndPad, float *SidePad, float *AnglePad);127 128ScrollView::Color GetMatchColorFor(float Evidence);129 130void GetNextFill(TABLE_FILLER *Filler, FILL_SPEC *Fill);131 132void InitTableFiller(float EndPad, float SidePad, float AnglePad, PROTO_STRUCT *Proto,133                     TABLE_FILLER *Filler);134 135#ifndef GRAPHICS_DISABLED136void RenderIntFeature(ScrollView *window, const INT_FEATURE_STRUCT *Feature,137                      ScrollView::Color color);138 139void RenderIntProto(ScrollView *window, INT_CLASS_STRUCT *Class, PROTO_ID ProtoId, ScrollView::Color color);140#endif // !GRAPHICS_DISABLED141 142/*-----------------------------------------------------------------------------143        Global Data Definitions and Declarations144-----------------------------------------------------------------------------*/145 146#ifndef GRAPHICS_DISABLED147/* global display lists used to display proto and feature match information*/148static ScrollView *IntMatchWindow = nullptr;149static ScrollView *FeatureDisplayWindow = nullptr;150static ScrollView *ProtoDisplayWindow = nullptr;151#endif152 153/*-----------------------------------------------------------------------------154        Variables155-----------------------------------------------------------------------------*/156 157/* control knobs */158static INT_VAR(classify_num_cp_levels, 3, ""Number of Class Pruner Levels"");159static double_VAR(classify_cp_angle_pad_loose, 45.0, ""Class Pruner Angle Pad Loose"");160static double_VAR(classify_cp_angle_pad_medium, 20.0, ""Class Pruner Angle Pad Medium"");161static double_VAR(classify_cp_angle_pad_tight, 10.0, ""CLass Pruner Angle Pad Tight"");162static double_VAR(classify_cp_end_pad_loose, 0.5, ""Class Pruner End Pad Loose"");163static double_VAR(classify_cp_end_pad_medium, 0.5, ""Class Pruner End Pad Medium"");164static double_VAR(classify_cp_end_pad_tight, 0.5, ""Class Pruner End Pad Tight"");165static double_VAR(classify_cp_side_pad_loose, 2.5, ""Class Pruner Side Pad Loose"");166static double_VAR(classify_cp_side_pad_medium, 1.2, ""Class Pruner Side Pad Medium"");167static double_VAR(classify_cp_side_pad_tight, 0.6, ""Class Pruner Side Pad Tight"");168static double_VAR(classify_pp_angle_pad, 45.0, ""Proto Pruner Angle Pad"");169static double_VAR(classify_pp_end_pad, 0.5, ""Proto Prune End Pad"");170static double_VAR(classify_pp_side_pad, 2.5, ""Proto Pruner Side Pad"");171 172/**173 * This routine truncates Param to lie within the range174 * of Min-Max inclusive.175 *176 * @param Param   parameter value to be truncated177 * @param Min, Max  parameter limits (inclusive)178 *179 * @return Truncated parameter.180 */181static int TruncateParam(float Param, int Min, int Max) {182  int result;183  if (Param < Min) {184    result = Min;185  } else if (Param > Max) {186    result = Max;187  } else {188    result = static_cast<int>(std::floor(Param));189  }190  return result;191}192 193/*-----------------------------------------------------------------------------194              Public Code195-----------------------------------------------------------------------------*/196/// Builds a feature from an FCOORD for position with all the necessary197/// clipping and rounding.198INT_FEATURE_STRUCT::INT_FEATURE_STRUCT(const FCOORD &pos, uint8_t theta)199    : X(ClipToRange<int16_t>(static_cast<int16_t>(pos.x() + 0.5), 0, 255))200    , Y(ClipToRange<int16_t>(static_cast<int16_t>(pos.y() + 0.5), 0, 255))201    , Theta(theta)202    , CP_misses(0) {}203/** Builds a feature from ints with all the necessary clipping and casting. */204INT_FEATURE_STRUCT::INT_FEATURE_STRUCT(int x, int y, int theta)205    : X(static_cast<uint8_t>(ClipToRange<int>(x, 0, UINT8_MAX)))206    , Y(static_cast<uint8_t>(ClipToRange<int>(y, 0, UINT8_MAX)))207    , Theta(static_cast<uint8_t>(ClipToRange<int>(theta, 0, UINT8_MAX)))208    , CP_misses(0) {}209 210/**211 * This routine adds a new class structure to a set of212 * templates. Classes have to be added to Templates in213 * the order of increasing ClassIds.214 *215 * @param Templates templates to add new class to216 * @param ClassId   class id to associate new class with217 * @param Class   class data structure to add to templates218 *219 * Globals: none220 */221void AddIntClass(INT_TEMPLATES_STRUCT *Templates, CLASS_ID ClassId, INT_CLASS_STRUCT *Class) {222  int Pruner;223 224  assert(LegalClassId(ClassId));225  if (static_cast<unsigned>(ClassId) != Templates->NumClasses) {226    fprintf(stderr,227            ""Please make sure that classes are added to templates""228            "" in increasing order of ClassIds\\n"");229    exit(1);230  }231  ClassForClassId(Templates, ClassId) = Class;232  Templates->NumClasses++;233 234  if (Templates->NumClasses > MaxNumClassesIn(Templates)) {235    Pruner = Templates->NumClassPruners++;236    Templates->ClassPruners[Pruner] = new CLASS_PRUNER_STRUCT;237    memset(Templates->ClassPruners[Pruner], 0, sizeof(CLASS_PRUNER_STRUCT));238  }239} /* AddIntClass */240 241/**242 * This routine returns the index of the next free config243 * in Class.244 *245 * @param Class class to add new configuration to246 *247 * Globals: none248 *249 * @return Index of next free config.250 */251int AddIntConfig(INT_CLASS_STRUCT *Class) {252  int Index;253 254  assert(Class->NumConfigs < MAX_NUM_CONFIGS);255 256  Index = Class->NumConfigs++;257  Class->ConfigLengths[Index] = 0;258  return Index;259} /* AddIntConfig */260 261/**262 * This routine allocates the next free proto in Class and263 * returns its index.264 *265 * @param Class class to add new proto to266 *267 * Globals: none268 *269 * @return Proto index of new proto.270 */271int AddIntProto(INT_CLASS_STRUCT *Class) {272  if (Class->NumProtos >= MAX_NUM_PROTOS) {273    return (NO_PROTO);274  }275 276  int Index = Class->NumProtos++;277 278  if (Class->NumProtos > MaxNumIntProtosIn(Class)) {279    int ProtoSetId = Class->NumProtoSets++;280    auto ProtoSet = new PROTO_SET_STRUCT;281    Class->ProtoSets[ProtoSetId] = ProtoSet;282    memset(ProtoSet, 0, sizeof(*ProtoSet));283 284    /* reallocate space for the proto lengths and install in class */285    Class->ProtoLengths.resize(MaxNumIntProtosIn(Class));286  }287 288  /* initialize proto so its length is zero and it isn't in any configs */289  Class->ProtoLengths[Index] = 0;290  auto Proto = ProtoForProtoId(Class, Index);291  for (uint32_t *Word = Proto->Configs; Word < Proto->Configs + WERDS_PER_CONFIG_VEC; *Word++ = 0) {292  }293 294  return (Index);295}296 297/**298 * This routine adds Proto to the class pruning tables299 * for the specified class in Templates.300 *301 * Globals:302 *  - classify_num_cp_levels number of levels used in the class pruner303 * @param Proto   floating-pt proto to add to class pruner304 * @param ClassId   class id corresponding to Proto305 * @param Templates set of templates containing class pruner306 */307void AddProtoToClassPruner(PROTO_STRUCT *Proto, CLASS_ID ClassId, INT_TEMPLATES_STRUCT *Templates)308#define MAX_LEVEL 2309{310  CLASS_PRUNER_STRUCT *Pruner;311  uint32_t ClassMask;312  uint32_t ClassCount;313  uint32_t WordIndex;314  int Level;315  float EndPad, SidePad, AnglePad;316  TABLE_FILLER TableFiller;317  FILL_SPEC FillSpec;318 319  Pruner = CPrunerFor(Templates, ClassId);320  WordIndex = CPrunerWordIndexFor(ClassId);321  ClassMask = CPrunerMaskFor(MAX_LEVEL, ClassId);322 323  for (Level = classify_num_cp_levels - 1; Level >= 0; Level--) {324    GetCPPadsForLevel(Level, &EndPad, &SidePad, &AnglePad);325    ClassCount = CPrunerMaskFor(Level, ClassId);326    InitTableFiller(EndPad, SidePad, AnglePad, Proto, &TableFiller);327 328    while (!FillerDone(&TableFiller)) {329      GetNextFill(&TableFiller, &FillSpec);330      DoFill(&FillSpec, Pruner, ClassMask, ClassCount, WordIndex);331    }332  }333} /* AddProtoToClassPruner */334 335/**336 * This routine updates the proto pruner lookup tables337 * for Class to include a new proto identified by ProtoId338 * and described by Proto.339 * @param Proto floating-pt proto to be added to proto pruner340 * @param ProtoId id of proto341 * @param Class integer class that contains desired proto pruner342 * @param debug debug flag343 * @note Globals: none344 */345void AddProtoToProtoPruner(PROTO_STRUCT *Proto, int ProtoId, INT_CLASS_STRUCT *Class, bool debug) {346  float X, Y, Length;347  float Pad;348 349  if (ProtoId >= Class->NumProtos) {350    tprintf(""AddProtoToProtoPruner:assert failed: %d < %d"", ProtoId, Class->NumProtos);351  }352  assert(ProtoId < Class->NumProtos);353 354  int Index = IndexForProto(ProtoId);355  auto ProtoSet = Class->ProtoSets[SetForProto(ProtoId)];356 357  float Angle = Proto->Angle;358#ifndef _WIN32359  assert(!std::isnan(Angle));360#endif361 362  FillPPCircularBits(ProtoSet->ProtoPruner[PRUNER_ANGLE], Index, Angle + ANGLE_SHIFT,363                     classify_pp_angle_pad / 360.0, debug);364 365  Angle *= 2.0 * M_PI;366  Length = Proto->Length;367 368  X = Proto->X + X_SHIFT;369  Pad = std::max(fabs(std::cos(Angle)) * (Length / 2.0 + classify_pp_end_pad * GetPicoFeatureLength()),370                 fabs(std::sin(Angle)) * (classify_pp_side_pad * GetPicoFeatureLength()));371 372  FillPPLinearBits(ProtoSet->ProtoPruner[PRUNER_X], Index, X, Pad, debug);373 374  Y = Proto->Y + Y_SHIFT;375  Pad = std::max(fabs(std::sin(Angle)) * (Length / 2.0 + classify_pp_end_pad * GetPicoFeatureLength()),376                 fabs(std::cos(Angle)) * (classify_pp_side_pad * GetPicoFeatureLength()));377 378  FillPPLinearBits(ProtoSet->ProtoPruner[PRUNER_Y], Index, Y, Pad, debug);379} /* AddProtoToProtoPruner */380 381/**382 * Returns a quantized bucket for the given param shifted by offset,383 * notionally (param + offset) * num_buckets, but clipped and casted to the384 * appropriate type.385 */386uint8_t Bucket8For(float param, float offset, int num_buckets) {387  int bucket = IntCastRounded(MapParam(param, offset, num_buckets));388  return static_cast<uint8_t>(ClipToRange<int>(bucket, 0, num_buckets - 1));389}390uint16_t Bucket16For(float param, float offset, int num_buckets) {391  int bucket = IntCastRounded(MapParam(param, offset, num_buckets));392  return static_cast<uint16_t>(ClipToRange<int>(bucket, 0, num_buckets - 1));393}394 395/**396 * Returns a quantized bucket for the given circular param shifted by offset,397 * notionally (param + offset) * num_buckets, but modded and casted to the398 * appropriate type.399 */400uint8_t CircBucketFor(float param, float offset, int num_buckets) {401  int bucket = IntCastRounded(MapParam(param, offset, num_buckets));402  return static_cast<uint8_t>(Modulo(bucket, num_buckets));403} /* CircBucketFor */404 405#ifndef GRAPHICS_DISABLED406/**407 * This routine clears the global feature and proto408 * display lists.409 *410 * Globals:411 * - FeatureShapes display list for features412 * - ProtoShapes display list for protos413 */414void UpdateMatchDisplay() {415  if (IntMatchWindow != nullptr) {416    IntMatchWindow->Update();417  }418} /* ClearMatchDisplay */419#endif420 421/**422 * This operation updates the config vectors of all protos423 * in Class to indicate that the protos with 1's in Config424 * belong to a new configuration identified by ConfigId.425 * It is assumed that the length of the Config bit vector is426 * equal to the number of protos in Class.427 * @param Config    config to be added to class428 * @param ConfigId  id to be used for new config429 * @param Class   class to add new config to430 */431void ConvertConfig(BIT_VECTOR Config, int ConfigId, INT_CLASS_STRUCT *Class) {432  int ProtoId;433  INT_PROTO_STRUCT *Proto;434  int TotalLength;435 436  for (ProtoId = 0, TotalLength = 0; ProtoId < Class->NumProtos; ProtoId++) {437    if (test_bit(Config, ProtoId)) {438      Proto = ProtoForProtoId(Class, ProtoId);439      SET_BIT(Proto->Configs, ConfigId);440      TotalLength += Class->ProtoLengths[ProtoId];441    }442  }443  Class->ConfigLengths[ConfigId] = TotalLength;444} /* ConvertConfig */445 446/**447 * This routine converts Proto to integer format and448 * installs it as ProtoId in Class.449 * @param Proto floating-pt proto to be converted to integer format450 * @param ProtoId id of proto451 * @param Class integer class to add converted proto to452 */453void Classify::ConvertProto(PROTO_STRUCT *Proto, int ProtoId, INT_CLASS_STRUCT *Class) {454  assert(ProtoId < Class->NumProtos);455 456  INT_PROTO_STRUCT *P = ProtoForProtoId(Class, ProtoId);457 458  float Param = Proto->A * 128;459  P->A = TruncateParam(Param, -128, 127);460 461  Param = -Proto->B * 256;462  P->B = TruncateParam(Param, 0, 255);463 464  Param = Proto->C * 128;465  P->C = TruncateParam(Param, -128, 127);466 467  Param = Proto->Angle * 256;468  if (Param < 0 || Param >= 256) {469    P->Angle = 0;470  } else {471    P->Angle = static_cast<uint8_t>(Param);472  }473 474  /* round proto length to nearest integer number of pico-features */475  Param = (Proto->Length / GetPicoFeatureLength()) + 0.5;476  Class->ProtoLengths[ProtoId] = TruncateParam(Param, 1, 255);477  if (classify_learning_debug_level >= 2) {478    tprintf(""Converted ffeat to (A=%d,B=%d,C=%d,L=%d)"", P->A, P->B, P->C,479            Class->ProtoLengths[ProtoId]);480  }481} /* ConvertProto */482 483/**484 * This routine converts from the old floating point format485 * to the new integer format.486 * @param FloatProtos prototypes in old floating pt format487 * @param target_unicharset the UNICHARSET to use488 * @return New set of training templates in integer format.489 * @note Globals: none490 */491INT_TEMPLATES_STRUCT *Classify::CreateIntTemplates(CLASSES FloatProtos,492                                           const UNICHARSET &target_unicharset) {493  CLASS_TYPE FClass;494  INT_CLASS_STRUCT *IClass;495  int ProtoId;496  int ConfigId;497 498  auto IntTemplates = new INT_TEMPLATES_STRUCT;499 500  for (unsigned ClassId = 0; ClassId < target_unicharset.size(); ClassId++) {501    FClass = &(FloatProtos[ClassId]);502    if (FClass->NumProtos == 0 && FClass->NumConfigs == 0 &&503        strcmp(target_unicharset.id_to_unichar(ClassId), "" "") != 0) {504      tprintf(""Warning: no protos/configs for %s in CreateIntTemplates()\\n"",505              target_unicharset.id_to_unichar(ClassId));506    }507    assert(UnusedClassIdIn(IntTemplates, ClassId));508    IClass = new INT_CLASS_STRUCT(FClass->NumProtos, FClass->NumConfigs);509    FontSet fs{FClass->font_set.size()};510    for (unsigned i = 0; i < fs.size(); ++i) {511      fs[i] = FClass->font_set.at(i);512    }513    if (this->fontset_table_.contains(fs)) {514      IClass->font_set_id = this->fontset_table_.get_index(fs);515    } else {516      IClass->font_set_id = this->fontset_table_.push_back(fs);517    }518    AddIntClass(IntTemplates, ClassId, IClass);519 520    for (ProtoId = 0; ProtoId < FClass->NumProtos; ProtoId++) {521      AddIntProto(IClass);522      ConvertProto(ProtoIn(FClass, ProtoId), ProtoId, IClass);523      AddProtoToProtoPruner(ProtoIn(FClass, ProtoId), ProtoId, IClass,524                            classify_learning_debug_level >= 2);525      AddProtoToClassPruner(ProtoIn(FClass, ProtoId), ClassId, IntTemplates);526    }527 528    for (ConfigId = 0; ConfigId < FClass->NumConfigs; ConfigId++) {529      AddIntConfig(IClass);530      ConvertConfig(FClass->Configurations[ConfigId], ConfigId, IClass);531    }532  }533  return (IntTemplates);534} /* CreateIntTemplates */535 536#ifndef GRAPHICS_DISABLED537/**538 * This routine renders the specified feature into a539 * global display list.540 *541 * Globals:542 * - FeatureShapes global display list for features543 * @param Feature   pico-feature to be displayed544 * @param Evidence  best evidence for this feature (0-1)545 */546void DisplayIntFeature(const INT_FEATURE_STRUCT *Feature, float Evidence) {547  ScrollView::Color color = GetMatchColorFor(Evidence);548  RenderIntFeature(IntMatchWindow, Feature, color);549  if (FeatureDisplayWindow) {550    RenderIntFeature(FeatureDisplayWindow, Feature, color);551  }552} /* DisplayIntFeature */553 554/**555 * This routine renders the specified proto into a556 * global display list.557 *558 * Globals:559 * - ProtoShapes global display list for protos560 * @param Class   class to take proto from561 * @param ProtoId   id of proto in Class to be displayed562 * @param Evidence  total evidence for proto (0-1)563 */564void DisplayIntProto(INT_CLASS_STRUCT *Class, PROTO_ID ProtoId, float Evidence) {565  ScrollView::Color color = GetMatchColorFor(Evidence);566  RenderIntProto(IntMatchWindow, Class, ProtoId, color);567  if (ProtoDisplayWindow) {568    RenderIntProto(ProtoDisplayWindow, Class, ProtoId, color);569  }570} /* DisplayIntProto */571#endif572 573/// This constructor creates a new integer class data structure574/// and returns it.  Sufficient space is allocated575/// to handle the specified number of protos and configs.576/// @param MaxNumProtos  number of protos to allocate space for577/// @param MaxNumConfigs number of configs to allocate space for578INT_CLASS_STRUCT::INT_CLASS_STRUCT(int MaxNumProtos, int MaxNumConfigs) :579  NumProtos(0),580  NumProtoSets((MaxNumProtos + PROTOS_PER_PROTO_SET - 1) / PROTOS_PER_PROTO_SET),581  NumConfigs(0),582  ProtoLengths(MaxNumIntProtosIn(this))583{584  assert(MaxNumConfigs <= MAX_NUM_CONFIGS);585  assert(NumProtoSets <= MAX_NUM_PROTO_SETS);586 587  for (int i = 0; i < NumProtoSets; i++) {588    /* allocate space for a proto set, install in class, and initialize */589    auto ProtoSet = new PROTO_SET_STRUCT;590    memset(ProtoSet, 0, sizeof(*ProtoSet));591    ProtoSets[i] = ProtoSet;592 593    /* allocate space for the proto lengths and install in class */594  }595  memset(ConfigLengths, 0, sizeof(ConfigLengths));596}597 598INT_CLASS_STRUCT::~INT_CLASS_STRUCT() {599  for (int i = 0; i < NumProtoSets; i++) {600    delete ProtoSets[i];601  }602}603 604/// This constructor allocates a new set of integer templates605/// initialized to hold 0 classes.606INT_TEMPLATES_STRUCT::INT_TEMPLATES_STRUCT() {607  NumClasses = 0;608  NumClassPruners = 0;609 610  for (int i = 0; i < MAX_NUM_CLASSES; i++) {611    ClassForClassId(this, i) = nullptr;612  }613}614 615INT_TEMPLATES_STRUCT::~INT_TEMPLATES_STRUCT() {616  for (unsigned i = 0; i < NumClasses; i++) {617    delete Class[i];618  }619  for (unsigned i = 0; i < NumClassPruners; i++) {620    delete ClassPruners[i];621  }622}623 624/**625 * This routine reads a set of integer templates from626 * File.  File must already be open and must be in the627 * correct binary format.628 * @param  fp open file to read templates from629 * @return Pointer to integer templates read from File.630 * @note Globals: none631 */632INT_TEMPLATES_STRUCT *Classify::ReadIntTemplates(TFile *fp) {633  int j, w, x, y, z;634  INT_TEMPLATES_STRUCT *Templates;635  CLASS_PRUNER_STRUCT *Pruner;636  INT_CLASS_STRUCT *Class;637 638  /* variables for conversion from older inttemp formats */639  int b, bit_number, last_cp_bit_number, new_b, new_i, new_w;640  CLASS_ID class_id, max_class_id;641  std::vector<CLASS_ID> ClassIdFor(MAX_NUM_CLASSES);642  std::vector<CLASS_PRUNER_STRUCT *> TempClassPruner(MAX_NUM_CLASS_PRUNERS);643  uint32_t SetBitsForMask =          // word with NUM_BITS_PER_CLASS644      (1 << NUM_BITS_PER_CLASS) - 1; // set starting at bit 0645  uint32_t Mask, NewMask, ClassBits;646  unsigned MaxNumConfigs = MAX_NUM_CONFIGS;647  unsigned WerdsPerConfigVec = WERDS_PER_CONFIG_VEC;648 649  /* first read the high level template struct */650  Templates = new INT_TEMPLATES_STRUCT;651  // Read Templates in parts for 64 bit compatibility.652  uint32_t unicharset_size;653  if (fp->FReadEndian(&unicharset_size, sizeof(unicharset_size), 1) != 1) {654    tprintf(""Bad read of inttemp!\\n"");655  }656  int32_t version_id = 0;657  if (fp->FReadEndian(&version_id, sizeof(version_id), 1) != 1 ||658      fp->FReadEndian(&Templates->NumClassPruners, sizeof(Templates->NumClassPruners), 1) != 1) {659    tprintf(""Bad read of inttemp!\\n"");660  }661  if (version_id < 0) {662    // This file has a version id!663    version_id = -version_id;664    if (fp->FReadEndian(&Templates->NumClasses, sizeof(Templates->NumClasses), 1) != 1) {665      tprintf(""Bad read of inttemp!\\n"");666    }667  } else {668    Templates->NumClasses = version_id;669  }670 671  if (version_id < 3) {672    MaxNumConfigs = OLD_MAX_NUM_CONFIGS;673    WerdsPerConfigVec = OLD_WERDS_PER_CONFIG_VEC;674  }675 676  if (version_id < 2) {677    std::vector<int16_t> IndexFor(MAX_NUM_CLASSES);678    if (fp->FReadEndian(&IndexFor[0], sizeof(IndexFor[0]), unicharset_size) != unicharset_size) {679      tprintf(""Bad read of inttemp!\\n"");680    }681    if (fp->FReadEndian(&ClassIdFor[0], sizeof(ClassIdFor[0]), Templates->NumClasses) !=682        Templates->NumClasses) {683      tprintf(""Bad read of inttemp!\\n"");684    }685  }686 687  /* then read in the class pruners */688  const unsigned kNumBuckets = NUM_CP_BUCKETS * NUM_CP_BUCKETS * NUM_CP_BUCKETS * WERDS_PER_CP_VECTOR;689  for (unsigned i = 0; i < Templates->NumClassPruners; i++) {690    Pruner = new CLASS_PRUNER_STRUCT;691    if (fp->FReadEndian(Pruner, sizeof(Pruner->p[0][0][0][0]), kNumBuckets) != kNumBuckets) {692      tprintf(""Bad read of inttemp!\\n"");693    }694    if (version_id < 2) {695      TempClassPruner[i] = Pruner;696    } else {697      Templates->ClassPruners[i] = Pruner;698    }699  }700 701  /* fix class pruners if they came from an old version of inttemp */702  if (version_id < 2) {703    // Allocate enough class pruners to cover all the class ids.704    max_class_id = 0;705    for (unsigned i = 0; i < Templates->NumClasses; i++) {706      if (ClassIdFor[i] > max_class_id) {707        max_class_id = ClassIdFor[i];708      }709    }710    for (int i = 0; i <= CPrunerIdFor(max_class_id); i++) {711      Templates->ClassPruners[i] = new CLASS_PRUNER_STRUCT;712      memset(Templates->ClassPruners[i], 0, sizeof(CLASS_PRUNER_STRUCT));713    }714    // Convert class pruners from the old format (indexed by class index)715    // to the new format (indexed by class id).716    last_cp_bit_number = NUM_BITS_PER_CLASS * Templates->NumClasses - 1;717    for (unsigned i = 0; i < Templates->NumClassPruners; i++) {718      for (x = 0; x < NUM_CP_BUCKETS; x++) {719        for (y = 0; y < NUM_CP_BUCKETS; y++) {720          for (z = 0; z < NUM_CP_BUCKETS; z++) {721            for (w = 0; w < WERDS_PER_CP_VECTOR; w++) {722              if (TempClassPruner[i]->p[x][y][z][w] == 0) {723                continue;724              }725              for (b = 0; b < BITS_PER_WERD; b += NUM_BITS_PER_CLASS) {726                bit_number = i * BITS_PER_CP_VECTOR + w * BITS_PER_WERD + b;727                if (bit_number > last_cp_bit_number) {728                  break; // the rest of the bits in this word are not used729                }730                class_id = ClassIdFor[bit_number / NUM_BITS_PER_CLASS];731                // Single out NUM_BITS_PER_CLASS bits relating to class_id.732                Mask = SetBitsForMask << b;733                ClassBits = TempClassPruner[i]->p[x][y][z][w] & Mask;734                // Move these bits to the new position in which they should735                // appear (indexed corresponding to the class_id).736                new_i = CPrunerIdFor(class_id);737                new_w = CPrunerWordIndexFor(class_id);738                new_b = CPrunerBitIndexFor(class_id) * NUM_BITS_PER_CLASS;739                if (new_b > b) {740                  ClassBits <<= (new_b - b);741                } else {742                  ClassBits >>= (b - new_b);743                }744                // Copy bits relating to class_id to the correct position745                // in Templates->ClassPruner.746                NewMask = SetBitsForMask << new_b;747                Templates->ClassPruners[new_i]->p[x][y][z][new_w] &= ~NewMask;748                Templates->ClassPruners[new_i]->p[x][y][z][new_w] |= ClassBits;749              }750            }751          }752        }753      }754    }755    for (unsigned i = 0; i < Templates->NumClassPruners; i++) {756      delete TempClassPruner[i];757    }758  }759 760  /* then read in each class */761  for (unsigned i = 0; i < Templates->NumClasses; i++) {762    /* first read in the high level struct for the class */763    Class = new INT_CLASS_STRUCT;764    if (fp->FReadEndian(&Class->NumProtos, sizeof(Class->NumProtos), 1) != 1 ||765        fp->FRead(&Class->NumProtoSets, sizeof(Class->NumProtoSets), 1) != 1 ||766        fp->FRead(&Class->NumConfigs, sizeof(Class->NumConfigs), 1) != 1) {767      tprintf(""Bad read of inttemp!\\n"");768    }769    if (version_id == 0) {770      // Only version 0 writes 5 pointless pointers to the file.771      for (j = 0; j < 5; ++j) {772        int32_t junk;773        if (fp->FRead(&junk, sizeof(junk), 1) != 1) {774          tprintf(""Bad read of inttemp!\\n"");775        }776      }777    }778    unsigned num_configs = version_id < 4 ? MaxNumConfigs : Class->NumConfigs;779    ASSERT_HOST(num_configs <= MaxNumConfigs);780    if (fp->FReadEndian(Class->ConfigLengths, sizeof(uint16_t), num_configs) != num_configs) {781      tprintf(""Bad read of inttemp!\\n"");782    }783    if (version_id < 2) {784      ClassForClassId(Templates, ClassIdFor[i]) = Class;785    } else {786      ClassForClassId(Templates, i) = Class;787    }788 789    /* then read in the proto lengths */790    Class->ProtoLengths.clear();791    if (MaxNumIntProtosIn(Class) > 0) {792      Class->ProtoLengths.resize(MaxNumIntProtosIn(Class));793      if (fp->FRead(&Class->ProtoLengths[0], sizeof(uint8_t), MaxNumIntProtosIn(Class)) !=794          MaxNumIntProtosIn(Class)) {795        tprintf(""Bad read of inttemp!\\n"");796      }797    }798 799    /* then read in the proto sets */800    for (j = 0; j < Class->NumProtoSets; j++) {801      auto ProtoSet = new PROTO_SET_STRUCT;802      unsigned num_buckets = NUM_PP_PARAMS * NUM_PP_BUCKETS * WERDS_PER_PP_VECTOR;803      if (fp->FReadEndian(&ProtoSet->ProtoPruner, sizeof(ProtoSet->ProtoPruner[0][0][0]),804                          num_buckets) != num_buckets) {805        tprintf(""Bad read of inttemp!\\n"");806      }807      for (x = 0; x < PROTOS_PER_PROTO_SET; x++) {808        if (fp->FRead(&ProtoSet->Protos[x].A, sizeof(ProtoSet->Protos[x].A), 1) != 1 ||809            fp->FRead(&ProtoSet->Protos[x].B, sizeof(ProtoSet->Protos[x].B), 1) != 1 ||810            fp->FRead(&ProtoSet->Protos[x].C, sizeof(ProtoSet->Protos[x].C), 1) != 1 ||811            fp->FRead(&ProtoSet->Protos[x].Angle, sizeof(ProtoSet->Protos[x].Angle), 1) != 1) {812          tprintf(""Bad read of inttemp!\\n"");813        }814        if (fp->FReadEndian(&ProtoSet->Protos[x].Configs, sizeof(ProtoSet->Protos[x].Configs[0]),815                            WerdsPerConfigVec) != WerdsPerConfigVec) {816          tprintf(""Bad read of inttemp!\\n"");817        }818      }819      Class->ProtoSets[j] = ProtoSet;820    }821    if (version_id < 4) {822      Class->font_set_id = -1;823    } else {824      fp->FReadEndian(&Class->font_set_id, sizeof(Class->font_set_id), 1);825    }826  }827 828  if (version_id < 2) {829    /* add an empty nullptr class with class id 0 */830    assert(UnusedClassIdIn(Templates, 0));831    ClassForClassId(Templates, 0) = new INT_CLASS_STRUCT(1, 1);832    ClassForClassId(Templates, 0)->font_set_id = -1;833    Templates->NumClasses++;834    /* make sure the classes are contiguous */835    for (unsigned i = 0; i < MAX_NUM_CLASSES; i++) {836      if (i < Templates->NumClasses) {837        if (ClassForClassId(Templates, i) == nullptr) {838          fprintf(stderr, ""Non-contiguous class ids in inttemp\\n"");839          exit(1);840        }841      } else {842        if (ClassForClassId(Templates, i) != nullptr) {843          fprintf(stderr, ""Class id %u exceeds NumClassesIn (Templates) %u\\n"", i,844                  Templates->NumClasses);845          exit(1);846        }847      }848    }849  }850  if (version_id >= 4) {851    using namespace std::placeholders; // for _1, _2852    this->fontinfo_table_.read(fp, std::bind(read_info, _1, _2));853    if (version_id >= 5) {854      this->fontinfo_table_.read(fp, std::bind(read_spacing_info, _1, _2));855    }856    this->fontset_table_.read(fp, [](auto *f, auto *fs) { return f->DeSerialize(*fs); } );857  }858 859  return (Templates);860} /* ReadIntTemplates */861 862#ifndef GRAPHICS_DISABLED863/**864 * This routine sends the shapes in the global display865 * lists to the match debugger window.866 *867 * Globals:868 * - FeatureShapes display list containing feature matches869 * - ProtoShapes display list containing proto matches870 */871void Classify::ShowMatchDisplay() {872  InitIntMatchWindowIfReqd();873  if (ProtoDisplayWindow) {874    ProtoDisplayWindow->Clear();875  }876  if (FeatureDisplayWindow) {877    FeatureDisplayWindow->Clear();878  }879  ClearFeatureSpaceWindow(static_cast<NORM_METHOD>(static_cast<int>(classify_norm_method)),880                          IntMatchWindow);881  IntMatchWindow->ZoomToRectangle(INT_MIN_X, INT_MIN_Y, INT_MAX_X, INT_MAX_Y);882  if (ProtoDisplayWindow) {883    ProtoDisplayWindow->ZoomToRectangle(INT_MIN_X, INT_MIN_Y, INT_MAX_X, INT_MAX_Y);884  }885  if (FeatureDisplayWindow) {886    FeatureDisplayWindow->ZoomToRectangle(INT_MIN_X, INT_MIN_Y, INT_MAX_X, INT_MAX_Y);887  }888} /* ShowMatchDisplay */889 890/// Clears the given window and draws the featurespace guides for the891/// appropriate normalization method.892void ClearFeatureSpaceWindow(NORM_METHOD norm_method, ScrollView *window) {893  window->Clear();894 895  window->Pen(ScrollView::GREY);896  // Draw the feature space limit rectangle.897  window->Rectangle(0, 0, INT_MAX_X, INT_MAX_Y);898  if (norm_method == baseline) {899    window->SetCursor(0, INT_DESCENDER);900    window->DrawTo(INT_MAX_X, INT_DESCENDER);901    window->SetCursor(0, INT_BASELINE);902    window->DrawTo(INT_MAX_X, INT_BASELINE);903    window->SetCursor(0, INT_XHEIGHT);904    window->DrawTo(INT_MAX_X, INT_XHEIGHT);905    window->SetCursor(0, INT_CAPHEIGHT);906    window->DrawTo(INT_MAX_X, INT_CAPHEIGHT);907  } else {908    window->Rectangle(INT_XCENTER - INT_XRADIUS, INT_YCENTER - INT_YRADIUS,909                      INT_XCENTER + INT_XRADIUS, INT_YCENTER + INT_YRADIUS);910  }911}912#endif913 914/**915 * This routine writes Templates to File.  The format916 * is an efficient binary format.  File must already be open917 * for writing.918 * @param File open file to write templates to919 * @param Templates templates to save into File920 * @param target_unicharset the UNICHARSET to use921 */922void Classify::WriteIntTemplates(FILE *File, INT_TEMPLATES_STRUCT *Templates,923                                 const UNICHARSET &target_unicharset) {924  INT_CLASS_STRUCT *Class;925  auto unicharset_size = target_unicharset.size();926  int version_id = -5; // When negated by the reader -1 becomes +1 etc.927 928  if (Templates->NumClasses != unicharset_size) {929    tprintf(930        ""Warning: executing WriteIntTemplates() with %d classes in""931        "" Templates, while target_unicharset size is %zu\\n"",932        Templates->NumClasses, unicharset_size);933  }934 935  /* first write the high level template struct */936  fwrite(&unicharset_size, sizeof(unicharset_size), 1, File);937  fwrite(&version_id, sizeof(version_id), 1, File);938  fwrite(&Templates->NumClassPruners, sizeof(Templates->NumClassPruners), 1, File);939  fwrite(&Templates->NumClasses, sizeof(Templates->NumClasses), 1, File);940 941  /* then write out the class pruners */942  for (unsigned i = 0; i < Templates->NumClassPruners; i++) {943    fwrite(Templates->ClassPruners[i], sizeof(CLASS_PRUNER_STRUCT), 1, File);944  }945 946  /* then write out each class */947  for (unsigned i = 0; i < Templates->NumClasses; i++) {948    Class = Templates->Class[i];949 950    /* first write out the high level struct for the class */951    fwrite(&Class->NumProtos, sizeof(Class->NumProtos), 1, File);952    fwrite(&Class->NumProtoSets, sizeof(Class->NumProtoSets), 1, File);953    ASSERT_HOST(Class->NumConfigs == this->fontset_table_.at(Class->font_set_id).size());954    fwrite(&Class->NumConfigs, sizeof(Class->NumConfigs), 1, File);955    for (int j = 0; j < Class->NumConfigs; ++j) {956      fwrite(&Class->ConfigLengths[j], sizeof(uint16_t), 1, File);957    }958 959    /* then write out the proto lengths */960    if (MaxNumIntProtosIn(Class) > 0) {961      fwrite(&Class->ProtoLengths[0], sizeof(uint8_t), MaxNumIntProtosIn(Class), File);962    }963 964    /* then write out the proto sets */965    for (int j = 0; j < Class->NumProtoSets; j++) {966      fwrite(Class->ProtoSets[j], sizeof(PROTO_SET_STRUCT), 1, File);967    }968 969    /* then write the fonts info */970    fwrite(&Class->font_set_id, sizeof(int), 1, File);971  }972 973  /* Write the fonts info tables */974  using namespace std::placeholders; // for _1, _2975  this->fontinfo_table_.write(File, std::bind(write_info, _1, _2));976  this->fontinfo_table_.write(File, std::bind(write_spacing_info, _1, _2));977  this->fontset_table_.write(File, std::bind(write_set, _1, _2));978} /* WriteIntTemplates */979 980/*-----------------------------------------------------------------------------981              Private Code982-----------------------------------------------------------------------------*/983/**984 * This routine returns the parameter value which985 * corresponds to the beginning of the specified bucket.986 * The bucket number should have been generated using the987 * BucketFor() function with parameters Offset and NumBuckets.988 * @param Bucket    bucket whose start is to be computed989 * @param Offset    offset used to map params to buckets990 * @param NumBuckets  total number of buckets991 * @return Param value corresponding to start position of Bucket.992 * @note Globals: none993 */994float BucketStart(int Bucket, float Offset, int NumBuckets) {995  return static_cast<float>(Bucket) / NumBuckets - Offset;996 997} /* BucketStart */998 999/**1000 * This routine returns the parameter value which1001 * corresponds to the end of the specified bucket.1002 * The bucket number should have been generated using the1003 * BucketFor() function with parameters Offset and NumBuckets.1004 * @param Bucket    bucket whose end is to be computed1005 * @param Offset    offset used to map params to buckets1006 * @param NumBuckets  total number of buckets1007 * @return Param value corresponding to end position of Bucket.1008 * @note Globals: none1009 */1010float BucketEnd(int Bucket, float Offset, int NumBuckets) {1011  return static_cast<float>(Bucket + 1) / NumBuckets - Offset;1012} /* BucketEnd */1013 1014/**1015 * This routine fills in the section of a class pruner1016 * corresponding to a single x value for a single proto of1017 * a class.1018 * @param FillSpec  specifies which bits to fill in pruner1019 * @param Pruner    class pruner to be filled1020 * @param ClassMask indicates which bits to change in each word1021 * @param ClassCount  indicates what to change bits to1022 * @param WordIndex indicates which word to change1023 */1024void DoFill(FILL_SPEC *FillSpec, CLASS_PRUNER_STRUCT *Pruner, uint32_t ClassMask,1025            uint32_t ClassCount, uint32_t WordIndex) {1026  int X, Y, Angle;1027  uint32_t OldWord;1028 1029  X = FillSpec->X;1030  if (X < 0) {1031    X = 0;1032  }1033  if (X >= NUM_CP_BUCKETS) {1034    X = NUM_CP_BUCKETS - 1;1035  }1036 1037  if (FillSpec->YStart < 0) {1038    FillSpec->YStart = 0;1039  }1040  if (FillSpec->YEnd >= NUM_CP_BUCKETS) {1041    FillSpec->YEnd = NUM_CP_BUCKETS - 1;1042  }1043 1044  for (Y = FillSpec->YStart; Y <= FillSpec->YEnd; Y++) {1045    for (Angle = FillSpec->AngleStart;; CircularIncrement(Angle, NUM_CP_BUCKETS)) {1046      OldWord = Pruner->p[X][Y][Angle][WordIndex];1047      if (ClassCount > (OldWord & ClassMask)) {1048        OldWord &= ~ClassMask;1049        OldWord |= ClassCount;1050        Pruner->p[X][Y][Angle][WordIndex] = OldWord;1051      }1052      if (Angle == FillSpec->AngleEnd) {1053        break;1054      }1055    }1056  }1057} /* DoFill */1058 1059/**1060 * Return true if the specified table filler is done, i.e.1061 * if it has no more lines to fill.1062 * @param Filler    table filler to check if done1063 * @return true if no more lines to fill, false otherwise.1064 * @note Globals: none1065 */1066bool FillerDone(TABLE_FILLER *Filler) {1067  FILL_SWITCH *Next;1068 1069  Next = &(Filler->Switch[Filler->NextSwitch]);1070 1071  return Filler->X > Next->X && Next->Type == LastSwitch;1072 1073} /* FillerDone */1074 1075/**1076 * This routine sets Bit in each bit vector whose1077 * bucket lies within the range Center +- Spread.  The fill1078 * is done for a circular dimension, i.e. bucket 0 is adjacent1079 * to the last bucket.  It is assumed that Center and Spread1080 * are expressed in a circular coordinate system whose range1081 * is 0 to 1.1082 * @param ParamTable  table of bit vectors, one per param bucket1083 * @param Bit bit position in vectors to be filled1084 * @param Center center of filled area1085 * @param Spread spread of filled area1086 * @param debug debug flag1087 */1088void FillPPCircularBits(uint32_t ParamTable[NUM_PP_BUCKETS][WERDS_PER_PP_VECTOR], int Bit,1089                        float Center, float Spread, bool debug) {1090  int i, FirstBucket, LastBucket;1091 1092  if (Spread > 0.5) {1093    Spread = 0.5;1094  }1095 1096  FirstBucket = static_cast<int>(std::floor((Center - Spread) * NUM_PP_BUCKETS));1097  if (FirstBucket < 0) {1098    FirstBucket += NUM_PP_BUCKETS;1099  }1100 1101  LastBucket = static_cast<int>(std::floor((Center + Spread) * NUM_PP_BUCKETS));1102  if (LastBucket >= NUM_PP_BUCKETS) {1103    LastBucket -= NUM_PP_BUCKETS;1104  }1105  if (debug) {1106    tprintf(""Circular fill from %d to %d"", FirstBucket, LastBucket);1107  }1108  for (i = FirstBucket; true; CircularIncrement(i, NUM_PP_BUCKETS)) {1109    SET_BIT(ParamTable[i], Bit);1110 1111    /* exit loop after we have set the bit for the last bucket */1112    if (i == LastBucket) {1113      break;1114    }1115  }1116 1117} /* FillPPCircularBits */1118 1119/**1120 * This routine sets Bit in each bit vector whose1121 * bucket lies within the range Center +- Spread.  The fill1122 * is done for a linear dimension, i.e. there is no wrap-around1123 * for this dimension.  It is assumed that Center and Spread1124 * are expressed in a linear coordinate system whose range1125 * is approximately 0 to 1.  Values outside this range will1126 * be clipped.1127 * @param ParamTable table of bit vectors, one per param bucket1128 * @param Bit bit number being filled1129 * @param Center center of filled area1130 * @param Spread spread of filled area1131 * @param debug debug flag1132 */1133void FillPPLinearBits(uint32_t ParamTable[NUM_PP_BUCKETS][WERDS_PER_PP_VECTOR], int Bit,1134                      float Center, float Spread, bool debug) {1135  int i, FirstBucket, LastBucket;1136 1137  FirstBucket = static_cast<int>(std::floor((Center - Spread) * NUM_PP_BUCKETS));1138  if (FirstBucket < 0) {1139    FirstBucket = 0;1140  }1141 1142  LastBucket = static_cast<int>(std::floor((Center + Spread) * NUM_PP_BUCKETS));1143  if (LastBucket >= NUM_PP_BUCKETS) {1144    LastBucket = NUM_PP_BUCKETS - 1;1145  }1146 1147  if (debug) {1148    tprintf(""Linear fill from %d to %d"", FirstBucket, LastBucket);1149  }1150  for (i = FirstBucket; i <= LastBucket; i++) {1151    SET_BIT(ParamTable[i], Bit);1152  }1153 1154} /* FillPPLinearBits */1155 1156/*---------------------------------------------------------------------------*/1157#ifndef GRAPHICS_DISABLED1158/**1159 * This routine prompts the user with Prompt and waits1160 * for the user to enter something in the debug window.1161 * @param Prompt prompt to print while waiting for input from window1162 * @param adaptive_on1163 * @param pretrained_on1164 * @param shape_id1165 * @return Character entered in the debug window.1166 * @note Globals: none1167 */1168CLASS_ID Classify::GetClassToDebug(const char *Prompt, bool *adaptive_on, bool *pretrained_on,1169                                   int *shape_id) {1170  tprintf(""%s\\n"", Prompt);1171  SVEvent *ev;1172  SVEventType ev_type;1173  int unichar_id = INVALID_UNICHAR_ID;1174  // Wait until a click or popup event.1175  do {1176    ev = IntMatchWindow->AwaitEvent(SVET_ANY);1177    ev_type = ev->type;1178    if (ev_type == SVET_POPUP) {1179      if (ev->command_id == IDA_SHAPE_INDEX) {1180        if (shape_table_ != nullptr) {1181          *shape_id = atoi(ev->parameter);1182          *adaptive_on = false;1183          *pretrained_on = true;1184          if (*shape_id >= 0 && static_cast<unsigned>(*shape_id) < shape_table_->NumShapes()) {1185            int font_id;1186            shape_table_->GetFirstUnicharAndFont(*shape_id, &unichar_id, &font_id);1187            tprintf(""Shape %d, first unichar=%d, font=%d\\n"", *shape_id, unichar_id, font_id);1188            return unichar_id;1189          }1190          tprintf(""Shape index '%s' not found in shape table\\n"", ev->parameter);1191        } else {1192          tprintf(""No shape table loaded!\\n"");1193        }1194      } else {1195        if (unicharset.contains_unichar(ev->parameter)) {1196          unichar_id = unicharset.unichar_to_id(ev->parameter);1197          if (ev->command_id == IDA_ADAPTIVE) {1198            *adaptive_on = true;1199            *pretrained_on = false;1200            *shape_id = -1;

Showing the first 1,200 of 80672 lines. Download the file for the rest.