Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/***************************************************************************/
2
/*                                                                         */
3
/*  otvcommn.c                                                             */
4
/*                                                                         */
5
/*    OpenType common tables validation (body).                            */
6
/*                                                                         */
7
/*  Copyright 2004, 2005, 2006, 2007 by                                    */
8
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9
/*                                                                         */
10
/*  This file is part of the FreeType project, and may only be used,       */
11
/*  modified, and distributed under the terms of the FreeType project      */
12
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13
/*  this file you indicate that you have read the license and              */
14
/*  understand and accept it fully.                                        */
15
/*                                                                         */
16
/***************************************************************************/
17
 
18
 
19
#include "otvcommn.h"
20
 
21
 
22
  /*************************************************************************/
23
  /*                                                                       */
24
  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
25
  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
26
  /* messages during execution.                                            */
27
  /*                                                                       */
28
#undef  FT_COMPONENT
29
#define FT_COMPONENT  trace_otvcommon
30
 
31
 
32
  /*************************************************************************/
33
  /*************************************************************************/
34
  /*****                                                               *****/
35
  /*****                       COVERAGE TABLE                          *****/
36
  /*****                                                               *****/
37
  /*************************************************************************/
38
  /*************************************************************************/
39
 
40
  FT_LOCAL_DEF( void )
41
  otv_Coverage_validate( FT_Bytes       table,
42
                         OTV_Validator  valid,
43
                         FT_Int         expected_count )
44
  {
45
    FT_Bytes  p = table;
46
    FT_UInt   CoverageFormat;
47
    FT_UInt   total = 0;
48
 
49
 
50
    OTV_NAME_ENTER( "Coverage" );
51
 
52
    OTV_LIMIT_CHECK( 4 );
53
    CoverageFormat = FT_NEXT_USHORT( p );
54
 
55
    OTV_TRACE(( " (format %d)\n", CoverageFormat ));
56
 
57
    switch ( CoverageFormat )
58
    {
59
    case 1:     /* CoverageFormat1 */
60
      {
61
        FT_UInt  GlyphCount;
62
        FT_UInt  i;
63
 
64
 
65
        GlyphCount = FT_NEXT_USHORT( p );
66
 
67
        OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
68
 
69
        OTV_LIMIT_CHECK( GlyphCount * 2 );        /* GlyphArray */
70
 
71
        for ( i = 0; i < GlyphCount; ++i )
72
        {
73
          FT_UInt  gid;
74
 
75
 
76
          gid = FT_NEXT_USHORT( p );
77
          if ( gid >= valid->glyph_count )
78
            FT_INVALID_GLYPH_ID;
79
        }
80
 
81
        total = GlyphCount;
82
      }
83
      break;
84
 
85
    case 2:     /* CoverageFormat2 */
86
      {
87
        FT_UInt  n, RangeCount;
88
        FT_UInt  Start, End, StartCoverageIndex, last = 0;
89
 
90
 
91
        RangeCount = FT_NEXT_USHORT( p );
92
 
93
        OTV_TRACE(( " (RangeCount = %d)\n", RangeCount ));
94
 
95
        OTV_LIMIT_CHECK( RangeCount * 6 );
96
 
97
        /* RangeRecord */
98
        for ( n = 0; n < RangeCount; n++ )
99
        {
100
          Start              = FT_NEXT_USHORT( p );
101
          End                = FT_NEXT_USHORT( p );
102
          StartCoverageIndex = FT_NEXT_USHORT( p );
103
 
104
          if ( Start > End || StartCoverageIndex != total )
105
            FT_INVALID_DATA;
106
 
107
          if ( End >= valid->glyph_count )
108
            FT_INVALID_GLYPH_ID;
109
 
110
          if ( n > 0 && Start <= last )
111
            FT_INVALID_DATA;
112
 
113
          total += End - Start + 1;
114
          last   = End;
115
        }
116
      }
117
      break;
118
 
119
    default:
120
      FT_INVALID_FORMAT;
121
    }
122
 
123
    /* Generally, a coverage table offset has an associated count field.  */
124
    /* The number of glyphs in the table should match this field.  If     */
125
    /* there is no associated count, a value of -1 tells us not to check. */
126
    if ( expected_count != -1 && (FT_UInt)expected_count != total )
127
      FT_INVALID_DATA;
128
 
129
    OTV_EXIT;
130
  }
131
 
132
 
133
  FT_LOCAL_DEF( FT_UInt )
134
  otv_Coverage_get_first( FT_Bytes  table )
135
  {
136
    FT_Bytes  p = table;
137
 
138
 
139
    p += 4;     /* skip CoverageFormat and Glyph/RangeCount */
140
 
141
    return FT_NEXT_USHORT( p );
142
  }
143
 
144
 
145
  FT_LOCAL_DEF( FT_UInt )
146
  otv_Coverage_get_last( FT_Bytes  table )
147
  {
148
    FT_Bytes  p = table;
149
    FT_UInt   CoverageFormat = FT_NEXT_USHORT( p );
150
    FT_UInt   count          = FT_NEXT_USHORT( p );     /* Glyph/RangeCount */
151
    FT_UInt   result = 0;
152
 
153
 
154
    switch ( CoverageFormat )
155
    {
156
    case 1:
157
      p += ( count - 1 ) * 2;
158
      result = FT_NEXT_USHORT( p );
159
      break;
160
 
161
    case 2:
162
      p += ( count - 1 ) * 6 + 2;
163
      result = FT_NEXT_USHORT( p );
164
      break;
165
 
166
    default:
167
      ;
168
    }
169
 
170
    return result;
171
  }
172
 
173
 
174
  FT_LOCAL_DEF( FT_UInt )
175
  otv_Coverage_get_count( FT_Bytes  table )
176
  {
177
    FT_Bytes  p              = table;
178
    FT_UInt   CoverageFormat = FT_NEXT_USHORT( p );
179
    FT_UInt   count          = FT_NEXT_USHORT( p );     /* Glyph/RangeCount */
180
    FT_UInt   result         = 0;
181
 
182
 
183
    switch ( CoverageFormat )
184
    {
185
    case 1:
186
      return count;
187
 
188
    case 2:
189
      {
190
        FT_UInt  Start, End;
191
 
192
 
193
        for ( ; count > 0; count-- )
194
        {
195
          Start = FT_NEXT_USHORT( p );
196
          End   = FT_NEXT_USHORT( p );
197
          p    += 2;                    /* skip StartCoverageIndex */
198
 
199
          result += End - Start + 1;
200
        }
201
      }
202
      break;
203
 
204
    default:
205
      ;
206
    }
207
 
208
    return result;
209
  }
210
 
211
 
212
  /*************************************************************************/
213
  /*************************************************************************/
214
  /*****                                                               *****/
215
  /*****                   CLASS DEFINITION TABLE                      *****/
216
  /*****                                                               *****/
217
  /*************************************************************************/
218
  /*************************************************************************/
219
 
220
  FT_LOCAL_DEF( void )
221
  otv_ClassDef_validate( FT_Bytes       table,
222
                         OTV_Validator  valid )
223
  {
224
    FT_Bytes  p = table;
225
    FT_UInt   ClassFormat;
226
 
227
 
228
    OTV_NAME_ENTER( "ClassDef" );
229
 
230
    OTV_LIMIT_CHECK( 4 );
231
    ClassFormat = FT_NEXT_USHORT( p );
232
 
233
    OTV_TRACE(( " (format %d)\n", ClassFormat ));
234
 
235
    switch ( ClassFormat )
236
    {
237
    case 1:     /* ClassDefFormat1 */
238
      {
239
        FT_UInt  StartGlyph;
240
        FT_UInt  GlyphCount;
241
 
242
 
243
        OTV_LIMIT_CHECK( 4 );
244
 
245
        StartGlyph = FT_NEXT_USHORT( p );
246
        GlyphCount = FT_NEXT_USHORT( p );
247
 
248
        OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
249
 
250
        OTV_LIMIT_CHECK( GlyphCount * 2 );    /* ClassValueArray */
251
 
252
        if ( StartGlyph + GlyphCount - 1 >= valid->glyph_count )
253
          FT_INVALID_GLYPH_ID;
254
      }
255
      break;
256
 
257
    case 2:     /* ClassDefFormat2 */
258
      {
259
        FT_UInt  n, ClassRangeCount;
260
        FT_UInt  Start, End, last = 0;
261
 
262
 
263
        ClassRangeCount = FT_NEXT_USHORT( p );
264
 
265
        OTV_TRACE(( " (ClassRangeCount = %d)\n", ClassRangeCount ));
266
 
267
        OTV_LIMIT_CHECK( ClassRangeCount * 6 );
268
 
269
        /* ClassRangeRecord */
270
        for ( n = 0; n < ClassRangeCount; n++ )
271
        {
272
          Start = FT_NEXT_USHORT( p );
273
          End   = FT_NEXT_USHORT( p );
274
          p    += 2;                        /* skip Class */
275
 
276
          if ( Start > End || ( n > 0 && Start <= last ) )
277
            FT_INVALID_DATA;
278
 
279
          if ( End >= valid->glyph_count )
280
            FT_INVALID_GLYPH_ID;
281
 
282
          last = End;
283
        }
284
      }
285
      break;
286
 
287
    default:
288
      FT_INVALID_FORMAT;
289
    }
290
 
291
    /* no need to check glyph indices used as input to class definition   */
292
    /* tables since even invalid glyph indices return a meaningful result */
293
 
294
    OTV_EXIT;
295
  }
296
 
297
 
298
  /*************************************************************************/
299
  /*************************************************************************/
300
  /*****                                                               *****/
301
  /*****                      DEVICE TABLE                             *****/
302
  /*****                                                               *****/
303
  /*************************************************************************/
304
  /*************************************************************************/
305
 
306
  FT_LOCAL_DEF( void )
307
  otv_Device_validate( FT_Bytes       table,
308
                       OTV_Validator  valid )
309
  {
310
    FT_Bytes  p = table;
311
    FT_UInt   StartSize, EndSize, DeltaFormat, count;
312
 
313
 
314
    OTV_NAME_ENTER( "Device" );
315
 
316
    OTV_LIMIT_CHECK( 8 );
317
    StartSize   = FT_NEXT_USHORT( p );
318
    EndSize     = FT_NEXT_USHORT( p );
319
    DeltaFormat = FT_NEXT_USHORT( p );
320
 
321
    if ( DeltaFormat < 1 || DeltaFormat > 3 )
322
      FT_INVALID_FORMAT;
323
 
324
    if ( EndSize < StartSize )
325
      FT_INVALID_DATA;
326
 
327
    count = EndSize - StartSize + 1;
328
    OTV_LIMIT_CHECK( ( 1 << DeltaFormat ) * count / 8 );  /* DeltaValue */
329
 
330
    OTV_EXIT;
331
  }
332
 
333
 
334
  /*************************************************************************/
335
  /*************************************************************************/
336
  /*****                                                               *****/
337
  /*****                         LOOKUPS                               *****/
338
  /*****                                                               *****/
339
  /*************************************************************************/
340
  /*************************************************************************/
341
 
342
  /* uses valid->type_count */
343
  /* uses valid->type_funcs */
344
 
345
  FT_LOCAL_DEF( void )
346
  otv_Lookup_validate( FT_Bytes       table,
347
                       OTV_Validator  valid )
348
  {
349
    FT_Bytes           p = table;
350
    FT_UInt            LookupType, SubTableCount;
351
    OTV_Validate_Func  validate;
352
 
353
 
354
    OTV_NAME_ENTER( "Lookup" );
355
 
356
    OTV_LIMIT_CHECK( 6 );
357
    LookupType    = FT_NEXT_USHORT( p );
358
    p            += 2;                      /* skip LookupFlag */
359
    SubTableCount = FT_NEXT_USHORT( p );
360
 
361
    OTV_TRACE(( " (type %d)\n", LookupType ));
362
 
363
    if ( LookupType == 0 || LookupType > valid->type_count )
364
      FT_INVALID_DATA;
365
 
366
    validate = valid->type_funcs[LookupType - 1];
367
 
368
    OTV_TRACE(( " (SubTableCount = %d)\n", SubTableCount ));
369
 
370
    OTV_LIMIT_CHECK( SubTableCount * 2 );
371
 
372
    /* SubTable */
373
    for ( ; SubTableCount > 0; SubTableCount-- )
374
      validate( table + FT_NEXT_USHORT( p ), valid );
375
 
376
    OTV_EXIT;
377
  }
378
 
379
 
380
  /* uses valid->lookup_count */
381
 
382
  FT_LOCAL_DEF( void )
383
  otv_LookupList_validate( FT_Bytes       table,
384
                           OTV_Validator  valid )
385
  {
386
    FT_Bytes  p = table;
387
    FT_UInt   LookupCount;
388
 
389
 
390
    OTV_NAME_ENTER( "LookupList" );
391
 
392
    OTV_LIMIT_CHECK( 2 );
393
    LookupCount = FT_NEXT_USHORT( p );
394
 
395
    OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
396
 
397
    OTV_LIMIT_CHECK( LookupCount * 2 );
398
 
399
    valid->lookup_count = LookupCount;
400
 
401
    /* Lookup */
402
    for ( ; LookupCount > 0; LookupCount-- )
403
      otv_Lookup_validate( table + FT_NEXT_USHORT( p ), valid );
404
 
405
    OTV_EXIT;
406
  }
407
 
408
 
409
  static FT_UInt
410
  otv_LookupList_get_count( FT_Bytes  table )
411
  {
412
    return FT_NEXT_USHORT( table );
413
  }
414
 
415
 
416
  /*************************************************************************/
417
  /*************************************************************************/
418
  /*****                                                               *****/
419
  /*****                        FEATURES                               *****/
420
  /*****                                                               *****/
421
  /*************************************************************************/
422
  /*************************************************************************/
423
 
424
  /* uses valid->lookup_count */
425
 
426
  FT_LOCAL_DEF( void )
427
  otv_Feature_validate( FT_Bytes       table,
428
                        OTV_Validator  valid )
429
  {
430
    FT_Bytes  p = table;
431
    FT_UInt   LookupCount;
432
 
433
 
434
    OTV_NAME_ENTER( "Feature" );
435
 
436
    OTV_LIMIT_CHECK( 4 );
437
    p           += 2;                   /* skip FeatureParams (unused) */
438
    LookupCount  = FT_NEXT_USHORT( p );
439
 
440
    OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
441
 
442
    OTV_LIMIT_CHECK( LookupCount * 2 );
443
 
444
    /* LookupListIndex */
445
    for ( ; LookupCount > 0; LookupCount-- )
446
      if ( FT_NEXT_USHORT( p ) >= valid->lookup_count )
447
        FT_INVALID_DATA;
448
 
449
    OTV_EXIT;
450
  }
451
 
452
 
453
  static FT_UInt
454
  otv_Feature_get_count( FT_Bytes  table )
455
  {
456
    return FT_NEXT_USHORT( table );
457
  }
458
 
459
 
460
  /* sets valid->lookup_count */
461
 
462
  FT_LOCAL_DEF( void )
463
  otv_FeatureList_validate( FT_Bytes       table,
464
                            FT_Bytes       lookups,
465
                            OTV_Validator  valid )
466
  {
467
    FT_Bytes  p = table;
468
    FT_UInt   FeatureCount;
469
 
470
 
471
    OTV_NAME_ENTER( "FeatureList" );
472
 
473
    OTV_LIMIT_CHECK( 2 );
474
    FeatureCount = FT_NEXT_USHORT( p );
475
 
476
    OTV_TRACE(( " (FeatureCount = %d)\n", FeatureCount ));
477
 
478
    OTV_LIMIT_CHECK( FeatureCount * 2 );
479
 
480
    valid->lookup_count = otv_LookupList_get_count( lookups );
481
 
482
    /* FeatureRecord */
483
    for ( ; FeatureCount > 0; FeatureCount-- )
484
    {
485
      p += 4;       /* skip FeatureTag */
486
 
487
      /* Feature */
488
      otv_Feature_validate( table + FT_NEXT_USHORT( p ), valid );
489
    }
490
 
491
    OTV_EXIT;
492
  }
493
 
494
 
495
  /*************************************************************************/
496
  /*************************************************************************/
497
  /*****                                                               *****/
498
  /*****                       LANGUAGE SYSTEM                         *****/
499
  /*****                                                               *****/
500
  /*************************************************************************/
501
  /*************************************************************************/
502
 
503
 
504
  /* uses valid->extra1 (number of features) */
505
 
506
  FT_LOCAL_DEF( void )
507
  otv_LangSys_validate( FT_Bytes       table,
508
                        OTV_Validator  valid )
509
  {
510
    FT_Bytes  p = table;
511
    FT_UInt   ReqFeatureIndex;
512
    FT_UInt   FeatureCount;
513
 
514
 
515
    OTV_NAME_ENTER( "LangSys" );
516
 
517
    OTV_LIMIT_CHECK( 6 );
518
    p              += 2;                    /* skip LookupOrder (unused) */
519
    ReqFeatureIndex = FT_NEXT_USHORT( p );
520
    FeatureCount    = FT_NEXT_USHORT( p );
521
 
522
    OTV_TRACE(( " (ReqFeatureIndex = %d)\n", ReqFeatureIndex ));
523
    OTV_TRACE(( " (FeatureCount = %d)\n",    FeatureCount    ));
524
 
525
    if ( ReqFeatureIndex != 0xFFFFU && ReqFeatureIndex >= valid->extra1 )
526
      FT_INVALID_DATA;
527
 
528
    OTV_LIMIT_CHECK( FeatureCount * 2 );
529
 
530
    /* FeatureIndex */
531
    for ( ; FeatureCount > 0; FeatureCount-- )
532
      if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
533
        FT_INVALID_DATA;
534
 
535
    OTV_EXIT;
536
  }
537
 
538
 
539
  /*************************************************************************/
540
  /*************************************************************************/
541
  /*****                                                               *****/
542
  /*****                           SCRIPTS                             *****/
543
  /*****                                                               *****/
544
  /*************************************************************************/
545
  /*************************************************************************/
546
 
547
  FT_LOCAL_DEF( void )
548
  otv_Script_validate( FT_Bytes       table,
549
                       OTV_Validator  valid )
550
  {
551
    FT_UInt   DefaultLangSys, LangSysCount;
552
    FT_Bytes  p = table;
553
 
554
 
555
    OTV_NAME_ENTER( "Script" );
556
 
557
    OTV_LIMIT_CHECK( 4 );
558
    DefaultLangSys = FT_NEXT_USHORT( p );
559
    LangSysCount   = FT_NEXT_USHORT( p );
560
 
561
    OTV_TRACE(( " (LangSysCount = %d)\n", LangSysCount ));
562
 
563
    if ( DefaultLangSys != 0 )
564
      otv_LangSys_validate( table + DefaultLangSys, valid );
565
 
566
    OTV_LIMIT_CHECK( LangSysCount * 6 );
567
 
568
    /* LangSysRecord */
569
    for ( ; LangSysCount > 0; LangSysCount-- )
570
    {
571
      p += 4;       /* skip LangSysTag */
572
 
573
      /* LangSys */
574
      otv_LangSys_validate( table + FT_NEXT_USHORT( p ), valid );
575
    }
576
 
577
    OTV_EXIT;
578
  }
579
 
580
 
581
  /* sets valid->extra1 (number of features) */
582
 
583
  FT_LOCAL_DEF( void )
584
  otv_ScriptList_validate( FT_Bytes       table,
585
                           FT_Bytes       features,
586
                           OTV_Validator  valid )
587
  {
588
    FT_UInt   ScriptCount;
589
    FT_Bytes  p = table;
590
 
591
 
592
    OTV_NAME_ENTER( "ScriptList" );
593
 
594
    OTV_LIMIT_CHECK( 2 );
595
    ScriptCount = FT_NEXT_USHORT( p );
596
 
597
    OTV_TRACE(( " (ScriptCount = %d)\n", ScriptCount ));
598
 
599
    OTV_LIMIT_CHECK( ScriptCount * 6 );
600
 
601
    valid->extra1 = otv_Feature_get_count( features );
602
 
603
    /* ScriptRecord */
604
    for ( ; ScriptCount > 0; ScriptCount-- )
605
    {
606
      p += 4;       /* skip ScriptTag */
607
 
608
      otv_Script_validate( table + FT_NEXT_USHORT( p ), valid ); /* Script */
609
    }
610
 
611
    OTV_EXIT;
612
  }
613
 
614
 
615
  /*************************************************************************/
616
  /*************************************************************************/
617
  /*****                                                               *****/
618
  /*****                      UTILITY FUNCTIONS                        *****/
619
  /*****                                                               *****/
620
  /*************************************************************************/
621
  /*************************************************************************/
622
 
623
  /*
624
     u:   uint16
625
     ux:  unit16 [x]
626
 
627
     s:   struct
628
     sx:  struct [x]
629
     sxy: struct [x], using external y count
630
 
631
     x:   uint16 x
632
 
633
     C:   Coverage
634
 
635
     O:   Offset
636
     On:  Offset (NULL)
637
     Ox:  Offset [x]
638
     Onx: Offset (NULL) [x]
639
  */
640
 
641
  FT_LOCAL_DEF( void )
642
  otv_x_Ox( FT_Bytes       table,
643
            OTV_Validator  valid )
644
  {
645
    FT_Bytes           p = table;
646
    FT_UInt            Count;
647
    OTV_Validate_Func  func;
648
 
649
 
650
    OTV_ENTER;
651
 
652
    OTV_LIMIT_CHECK( 2 );
653
    Count = FT_NEXT_USHORT( p );
654
 
655
    OTV_TRACE(( " (Count = %d)\n", Count ));
656
 
657
    OTV_LIMIT_CHECK( Count * 2 );
658
 
659
    valid->nesting_level++;
660
    func = valid->func[valid->nesting_level];
661
 
662
    for ( ; Count > 0; Count-- )
663
      func( table + FT_NEXT_USHORT( p ), valid );
664
 
665
    valid->nesting_level--;
666
 
667
    OTV_EXIT;
668
  }
669
 
670
 
671
  FT_LOCAL_DEF( void )
672
  otv_u_C_x_Ox( FT_Bytes       table,
673
                OTV_Validator  valid )
674
  {
675
    FT_Bytes           p = table;
676
    FT_UInt            Count, Coverage;
677
    OTV_Validate_Func  func;
678
 
679
 
680
    OTV_ENTER;
681
 
682
    p += 2;     /* skip Format */
683
 
684
    OTV_LIMIT_CHECK( 4 );
685
    Coverage = FT_NEXT_USHORT( p );
686
    Count    = FT_NEXT_USHORT( p );
687
 
688
    OTV_TRACE(( " (Count = %d)\n", Count ));
689
 
690
    otv_Coverage_validate( table + Coverage, valid, Count );
691
 
692
    OTV_LIMIT_CHECK( Count * 2 );
693
 
694
    valid->nesting_level++;
695
    func = valid->func[valid->nesting_level];
696
 
697
    for ( ; Count > 0; Count-- )
698
      func( table + FT_NEXT_USHORT( p ), valid );
699
 
700
    valid->nesting_level--;
701
 
702
    OTV_EXIT;
703
  }
704
 
705
 
706
  /* uses valid->extra1 (if > 0: array value limit) */
707
 
708
  FT_LOCAL_DEF( void )
709
  otv_x_ux( FT_Bytes       table,
710
            OTV_Validator  valid )
711
  {
712
    FT_Bytes  p = table;
713
    FT_UInt   Count;
714
 
715
 
716
    OTV_ENTER;
717
 
718
    OTV_LIMIT_CHECK( 2 );
719
    Count = FT_NEXT_USHORT( p );
720
 
721
    OTV_TRACE(( " (Count = %d)\n", Count ));
722
 
723
    OTV_LIMIT_CHECK( Count * 2 );
724
 
725
    if ( valid->extra1 )
726
    {
727
      for ( ; Count > 0; Count-- )
728
        if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
729
          FT_INVALID_DATA;
730
    }
731
 
732
    OTV_EXIT;
733
  }
734
 
735
 
736
  /* `ux' in the function's name is not really correct since only x-1 */
737
  /* elements are tested                                              */
738
 
739
  /* uses valid->extra1 (array value limit) */
740
 
741
  FT_LOCAL_DEF( void )
742
  otv_x_y_ux_sy( FT_Bytes       table,
743
                 OTV_Validator  valid )
744
  {
745
    FT_Bytes  p = table;
746
    FT_UInt   Count1, Count2;
747
 
748
 
749
    OTV_ENTER;
750
 
751
    OTV_LIMIT_CHECK( 4 );
752
    Count1 = FT_NEXT_USHORT( p );
753
    Count2 = FT_NEXT_USHORT( p );
754
 
755
    OTV_TRACE(( " (Count1 = %d)\n", Count1 ));
756
    OTV_TRACE(( " (Count2 = %d)\n", Count2 ));
757
 
758
    if ( Count1 == 0 )
759
      FT_INVALID_DATA;
760
 
761
    OTV_LIMIT_CHECK( ( Count1 - 1 ) * 2 + Count2 * 4 );
762
    p += ( Count1 - 1 ) * 2;
763
 
764
    for ( ; Count2 > 0; Count2-- )
765
    {
766
      if ( FT_NEXT_USHORT( p ) >= Count1 )
767
        FT_INVALID_DATA;
768
 
769
      if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
770
        FT_INVALID_DATA;
771
    }
772
 
773
    OTV_EXIT;
774
  }
775
 
776
 
777
  /* `uy' in the function's name is not really correct since only y-1 */
778
  /* elements are tested                                              */
779
 
780
  /* uses valid->extra1 (array value limit) */
781
 
782
  FT_LOCAL_DEF( void )
783
  otv_x_ux_y_uy_z_uz_p_sp( FT_Bytes       table,
784
                           OTV_Validator  valid )
785
  {
786
    FT_Bytes  p = table;
787
    FT_UInt   BacktrackCount, InputCount, LookaheadCount;
788
    FT_UInt   Count;
789
 
790
 
791
    OTV_ENTER;
792
 
793
    OTV_LIMIT_CHECK( 2 );
794
    BacktrackCount = FT_NEXT_USHORT( p );
795
 
796
    OTV_TRACE(( " (BacktrackCount = %d)\n", BacktrackCount ));
797
 
798
    OTV_LIMIT_CHECK( BacktrackCount * 2 + 2 );
799
    p += BacktrackCount * 2;
800
 
801
    InputCount = FT_NEXT_USHORT( p );
802
    if ( InputCount == 0 )
803
      FT_INVALID_DATA;
804
 
805
    OTV_TRACE(( " (InputCount = %d)\n", InputCount ));
806
 
807
    OTV_LIMIT_CHECK( InputCount * 2 );
808
    p += ( InputCount - 1 ) * 2;
809
 
810
    LookaheadCount = FT_NEXT_USHORT( p );
811
 
812
    OTV_TRACE(( " (LookaheadCount = %d)\n", LookaheadCount ));
813
 
814
    OTV_LIMIT_CHECK( LookaheadCount * 2 + 2 );
815
    p += LookaheadCount * 2;
816
 
817
    Count = FT_NEXT_USHORT( p );
818
 
819
    OTV_TRACE(( " (Count = %d)\n", Count ));
820
 
821
    OTV_LIMIT_CHECK( Count * 4 );
822
 
823
    for ( ; Count > 0; Count-- )
824
    {
825
      if ( FT_NEXT_USHORT( p ) >= InputCount )
826
        FT_INVALID_DATA;
827
 
828
      if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
829
        FT_INVALID_DATA;
830
    }
831
 
832
    OTV_EXIT;
833
  }
834
 
835
 
836
  /* sets valid->extra1 (valid->lookup_count) */
837
 
838
  FT_LOCAL_DEF( void )
839
  otv_u_O_O_x_Onx( FT_Bytes       table,
840
                   OTV_Validator  valid )
841
  {
842
    FT_Bytes           p = table;
843
    FT_UInt            Coverage, ClassDef, ClassSetCount;
844
    OTV_Validate_Func  func;
845
 
846
 
847
    OTV_ENTER;
848
 
849
    p += 2;     /* skip Format */
850
 
851
    OTV_LIMIT_CHECK( 6 );
852
    Coverage      = FT_NEXT_USHORT( p );
853
    ClassDef      = FT_NEXT_USHORT( p );
854
    ClassSetCount = FT_NEXT_USHORT( p );
855
 
856
    OTV_TRACE(( " (ClassSetCount = %d)\n", ClassSetCount ));
857
 
858
    otv_Coverage_validate( table + Coverage, valid, -1 );
859
    otv_ClassDef_validate( table + ClassDef, valid );
860
 
861
    OTV_LIMIT_CHECK( ClassSetCount * 2 );
862
 
863
    valid->nesting_level++;
864
    func          = valid->func[valid->nesting_level];
865
    valid->extra1 = valid->lookup_count;
866
 
867
    for ( ; ClassSetCount > 0; ClassSetCount-- )
868
    {
869
      FT_UInt  offset = FT_NEXT_USHORT( p );
870
 
871
 
872
      if ( offset )
873
        func( table + offset, valid );
874
    }
875
 
876
    valid->nesting_level--;
877
 
878
    OTV_EXIT;
879
  }
880
 
881
 
882
  /* uses valid->lookup_count */
883
 
884
  FT_LOCAL_DEF( void )
885
  otv_u_x_y_Ox_sy( FT_Bytes       table,
886
                   OTV_Validator  valid )
887
  {
888
    FT_Bytes  p = table;
889
    FT_UInt   GlyphCount, Count, count1;
890
 
891
 
892
    OTV_ENTER;
893
 
894
    p += 2;     /* skip Format */
895
 
896
    OTV_LIMIT_CHECK( 4 );
897
    GlyphCount = FT_NEXT_USHORT( p );
898
    Count      = FT_NEXT_USHORT( p );
899
 
900
    OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
901
    OTV_TRACE(( " (Count = %d)\n",      Count      ));
902
 
903
    OTV_LIMIT_CHECK( GlyphCount * 2 + Count * 4 );
904
 
905
    for ( count1 = GlyphCount; count1 > 0; count1-- )
906
      otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
907
 
908
    for ( ; Count > 0; Count-- )
909
    {
910
      if ( FT_NEXT_USHORT( p ) >= GlyphCount )
911
        FT_INVALID_DATA;
912
 
913
      if ( FT_NEXT_USHORT( p ) >= valid->lookup_count )
914
        FT_INVALID_DATA;
915
    }
916
 
917
    OTV_EXIT;
918
  }
919
 
920
 
921
  /* sets valid->extra1 (valid->lookup_count)    */
922
 
923
  FT_LOCAL_DEF( void )
924
  otv_u_O_O_O_O_x_Onx( FT_Bytes       table,
925
                       OTV_Validator  valid )
926
  {
927
    FT_Bytes           p = table;
928
    FT_UInt            Coverage;
929
    FT_UInt            BacktrackClassDef, InputClassDef, LookaheadClassDef;
930
    FT_UInt            ChainClassSetCount;
931
    OTV_Validate_Func  func;
932
 
933
 
934
    OTV_ENTER;
935
 
936
    p += 2;     /* skip Format */
937
 
938
    OTV_LIMIT_CHECK( 10 );
939
    Coverage           = FT_NEXT_USHORT( p );
940
    BacktrackClassDef  = FT_NEXT_USHORT( p );
941
    InputClassDef      = FT_NEXT_USHORT( p );
942
    LookaheadClassDef  = FT_NEXT_USHORT( p );
943
    ChainClassSetCount = FT_NEXT_USHORT( p );
944
 
945
    OTV_TRACE(( " (ChainClassSetCount = %d)\n", ChainClassSetCount ));
946
 
947
    otv_Coverage_validate( table + Coverage, valid, -1 );
948
 
949
    otv_ClassDef_validate( table + BacktrackClassDef,  valid );
950
    otv_ClassDef_validate( table + InputClassDef, valid );
951
    otv_ClassDef_validate( table + LookaheadClassDef, valid );
952
 
953
    OTV_LIMIT_CHECK( ChainClassSetCount * 2 );
954
 
955
    valid->nesting_level++;
956
    func          = valid->func[valid->nesting_level];
957
    valid->extra1 = valid->lookup_count;
958
 
959
    for ( ; ChainClassSetCount > 0; ChainClassSetCount-- )
960
    {
961
      FT_UInt  offset = FT_NEXT_USHORT( p );
962
 
963
 
964
      if ( offset )
965
        func( table + offset, valid );
966
    }
967
 
968
    valid->nesting_level--;
969
 
970
    OTV_EXIT;
971
  }
972
 
973
 
974
  /* uses valid->lookup_count */
975
 
976
  FT_LOCAL_DEF( void )
977
  otv_u_x_Ox_y_Oy_z_Oz_p_sp( FT_Bytes       table,
978
                             OTV_Validator  valid )
979
  {
980
    FT_Bytes  p = table;
981
    FT_UInt   BacktrackGlyphCount, InputGlyphCount, LookaheadGlyphCount;
982
    FT_UInt   count1, count2;
983
 
984
 
985
    OTV_ENTER;
986
 
987
    p += 2;     /* skip Format */
988
 
989
    OTV_LIMIT_CHECK( 2 );
990
    BacktrackGlyphCount = FT_NEXT_USHORT( p );
991
 
992
    OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
993
 
994
    OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
995
 
996
    for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
997
      otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
998
 
999
    InputGlyphCount = FT_NEXT_USHORT( p );
1000
 
1001
    OTV_TRACE(( " (InputGlyphCount = %d)\n", InputGlyphCount ));
1002
 
1003
    OTV_LIMIT_CHECK( InputGlyphCount * 2 + 2 );
1004
 
1005
    for ( count1 = InputGlyphCount; count1 > 0; count1-- )
1006
      otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
1007
 
1008
    LookaheadGlyphCount = FT_NEXT_USHORT( p );
1009
 
1010
    OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
1011
 
1012
    OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
1013
 
1014
    for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
1015
      otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
1016
 
1017
    count2 = FT_NEXT_USHORT( p );
1018
 
1019
    OTV_TRACE(( " (Count = %d)\n", count2 ));
1020
 
1021
    OTV_LIMIT_CHECK( count2 * 4 );
1022
 
1023
    for ( ; count2 > 0; count2-- )
1024
    {
1025
      if ( FT_NEXT_USHORT( p ) >= InputGlyphCount )
1026
        FT_INVALID_DATA;
1027
 
1028
      if ( FT_NEXT_USHORT( p ) >= valid->lookup_count )
1029
        FT_INVALID_DATA;
1030
    }
1031
 
1032
    OTV_EXIT;
1033
  }
1034
 
1035
 
1036
  FT_LOCAL_DEF( FT_UInt )
1037
  otv_GSUBGPOS_get_Lookup_count( FT_Bytes  table )
1038
  {
1039
    FT_Bytes  p = table + 8;
1040
 
1041
 
1042
    return otv_LookupList_get_count( table + FT_NEXT_USHORT( p ) );
1043
  }
1044
 
1045
 
1046
  FT_LOCAL_DEF( FT_UInt )
1047
  otv_GSUBGPOS_have_MarkAttachmentType_flag( FT_Bytes  table )
1048
  {
1049
    FT_Bytes  p, lookup;
1050
    FT_UInt   count;
1051
 
1052
 
1053
    if ( !table )
1054
      return 0;
1055
 
1056
    /* LookupList */
1057
    p      = table + 8;
1058
    table += FT_NEXT_USHORT( p );
1059
 
1060
    /* LookupCount */
1061
    p     = table;
1062
    count = FT_NEXT_USHORT( p );
1063
 
1064
    for ( ; count > 0; count-- )
1065
    {
1066
      FT_Bytes  oldp;
1067
 
1068
 
1069
      /* Lookup */
1070
      lookup = table + FT_NEXT_USHORT( p );
1071
 
1072
      oldp = p;
1073
 
1074
      /* LookupFlag */
1075
      p = lookup + 2;
1076
      if ( FT_NEXT_USHORT( p ) & 0xFF00U )
1077
        return 1;
1078
 
1079
      p = oldp;
1080
    }
1081
 
1082
    return 0;
1083
  }
1084
 
1085
 
1086
/* END */