~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/freetype/src/otvalid/otvgpos.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************/
 
2
/*                                                                         */
 
3
/*  otvgpos.c                                                              */
 
4
/*                                                                         */
 
5
/*    OpenType GPOS table validation (body).                               */
 
6
/*                                                                         */
 
7
/*  Copyright 2002, 2004, 2005, 2006, 2007, 2008 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 "otvalid.h"
 
20
#include "otvcommn.h"
 
21
#include "otvgpos.h"
 
22
 
 
23
 
 
24
  /*************************************************************************/
 
25
  /*                                                                       */
 
26
  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
 
27
  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
 
28
  /* messages during execution.                                            */
 
29
  /*                                                                       */
 
30
#undef  FT_COMPONENT
 
31
#define FT_COMPONENT  trace_otvgpos
 
32
 
 
33
 
 
34
  static void
 
35
  otv_Anchor_validate( FT_Bytes       table,
 
36
                       OTV_Validator  valid );
 
37
 
 
38
  static void
 
39
  otv_MarkArray_validate( FT_Bytes       table,
 
40
                          OTV_Validator  valid );
 
41
 
 
42
 
 
43
  /*************************************************************************/
 
44
  /*************************************************************************/
 
45
  /*****                                                               *****/
 
46
  /*****                      UTILITY FUNCTIONS                        *****/
 
47
  /*****                                                               *****/
 
48
  /*************************************************************************/
 
49
  /*************************************************************************/
 
50
 
 
51
#define BaseArrayFunc       otv_x_sxy
 
52
#define LigatureAttachFunc  otv_x_sxy
 
53
#define Mark2ArrayFunc      otv_x_sxy
 
54
 
 
55
  /* uses valid->extra1 (counter)                             */
 
56
  /* uses valid->extra2 (boolean to handle NULL anchor field) */
 
57
 
 
58
  static void
 
59
  otv_x_sxy( FT_Bytes       table,
 
60
             OTV_Validator  valid )
 
61
  {
 
62
    FT_Bytes  p = table;
 
63
    FT_UInt   Count, count1, table_size;
 
64
 
 
65
 
 
66
    OTV_ENTER;
 
67
 
 
68
    OTV_LIMIT_CHECK( 2 );
 
69
 
 
70
    Count = FT_NEXT_USHORT( p );
 
71
 
 
72
    OTV_TRACE(( " (Count = %d)\n", Count ));
 
73
 
 
74
    OTV_LIMIT_CHECK( Count * valid->extra1 * 2 );
 
75
 
 
76
    table_size = Count * valid->extra1 * 2 + 2;
 
77
 
 
78
    for ( ; Count > 0; Count-- )
 
79
      for ( count1 = valid->extra1; count1 > 0; count1-- )
 
80
      {
 
81
        OTV_OPTIONAL_TABLE( anchor_offset );
 
82
 
 
83
 
 
84
        OTV_OPTIONAL_OFFSET( anchor_offset );
 
85
 
 
86
        if ( valid->extra2 )
 
87
        {
 
88
          OTV_SIZE_CHECK( anchor_offset );
 
89
          if ( anchor_offset )
 
90
            otv_Anchor_validate( table + anchor_offset, valid );
 
91
        }
 
92
        else
 
93
          otv_Anchor_validate( table + anchor_offset, valid );
 
94
      }
 
95
 
 
96
    OTV_EXIT;
 
97
  }
 
98
 
 
99
 
 
100
#define MarkBasePosFormat1Func  otv_u_O_O_u_O_O
 
101
#define MarkLigPosFormat1Func   otv_u_O_O_u_O_O
 
102
#define MarkMarkPosFormat1Func  otv_u_O_O_u_O_O
 
103
 
 
104
  /* sets valid->extra1 (class count) */
 
105
 
 
106
  static void
 
107
  otv_u_O_O_u_O_O( FT_Bytes       table,
 
108
                   OTV_Validator  valid )
 
109
  {
 
110
    FT_Bytes           p = table;
 
111
    FT_UInt            Coverage1, Coverage2, ClassCount;
 
112
    FT_UInt            Array1, Array2;
 
113
    OTV_Validate_Func  func;
 
114
 
 
115
 
 
116
    OTV_ENTER;
 
117
 
 
118
    p += 2;     /* skip PosFormat */
 
119
 
 
120
    OTV_LIMIT_CHECK( 10 );
 
121
    Coverage1  = FT_NEXT_USHORT( p );
 
122
    Coverage2  = FT_NEXT_USHORT( p );
 
123
    ClassCount = FT_NEXT_USHORT( p );
 
124
    Array1     = FT_NEXT_USHORT( p );
 
125
    Array2     = FT_NEXT_USHORT( p );
 
126
 
 
127
    otv_Coverage_validate( table + Coverage1, valid, -1 );
 
128
    otv_Coverage_validate( table + Coverage2, valid, -1 );
 
129
 
 
130
    otv_MarkArray_validate( table + Array1, valid );
 
131
 
 
132
    valid->nesting_level++;
 
133
    func          = valid->func[valid->nesting_level];
 
134
    valid->extra1 = ClassCount;
 
135
 
 
136
    func( table + Array2, valid );
 
137
 
 
138
    valid->nesting_level--;
 
139
 
 
140
    OTV_EXIT;
 
141
  }
 
142
 
 
143
 
 
144
  /*************************************************************************/
 
145
  /*************************************************************************/
 
146
  /*****                                                               *****/
 
147
  /*****                        VALUE RECORDS                          *****/
 
148
  /*****                                                               *****/
 
149
  /*************************************************************************/
 
150
  /*************************************************************************/
 
151
 
 
152
  static FT_UInt
 
153
  otv_value_length( FT_UInt  format )
 
154
  {
 
155
    FT_UInt  count;
 
156
 
 
157
 
 
158
    count = ( ( format & 0xAA ) >> 1 ) + ( format & 0x55 );
 
159
    count = ( ( count  & 0xCC ) >> 2 ) + ( count  & 0x33 );
 
160
    count = ( ( count  & 0xF0 ) >> 4 ) + ( count  & 0x0F );
 
161
 
 
162
    return count * 2;
 
163
  }
 
164
 
 
165
 
 
166
  /* uses valid->extra3 (pointer to base table) */
 
167
 
 
168
  static void
 
169
  otv_ValueRecord_validate( FT_Bytes       table,
 
170
                            FT_UInt        format,
 
171
                            OTV_Validator  valid )
 
172
  {
 
173
    FT_Bytes  p = table;
 
174
    FT_UInt   count;
 
175
 
 
176
#ifdef FT_DEBUG_LEVEL_TRACE
 
177
    FT_Int    loop;
 
178
    FT_ULong  res = 0;
 
179
 
 
180
 
 
181
    OTV_NAME_ENTER( "ValueRecord" );
 
182
 
 
183
    /* display `format' in dual representation */
 
184
    for ( loop = 7; loop >= 0; loop-- )
 
185
    {
 
186
      res <<= 4;
 
187
      res  += ( format >> loop ) & 1;
 
188
    }
 
189
 
 
190
    OTV_TRACE(( " (format 0b%08lx)\n", res ));
 
191
#endif
 
192
 
 
193
    if ( format >= 0x100 )
 
194
      FT_INVALID_FORMAT;
 
195
 
 
196
    for ( count = 4; count > 0; count-- )
 
197
    {
 
198
      if ( format & 1 )
 
199
      {
 
200
        /* XPlacement, YPlacement, XAdvance, YAdvance */
 
201
        OTV_LIMIT_CHECK( 2 );
 
202
        p += 2;
 
203
      }
 
204
 
 
205
      format >>= 1;
 
206
    }
 
207
 
 
208
    for ( count = 4; count > 0; count-- )
 
209
    {
 
210
      if ( format & 1 )
 
211
      {
 
212
        FT_PtrDist  table_size;
 
213
 
 
214
        OTV_OPTIONAL_TABLE( device );
 
215
 
 
216
 
 
217
        /* XPlaDevice, YPlaDevice, XAdvDevice, YAdvDevice */
 
218
        OTV_LIMIT_CHECK( 2 );
 
219
        OTV_OPTIONAL_OFFSET( device );
 
220
 
 
221
        /* XXX: this value is usually too small, especially if the current */
 
222
        /* ValueRecord is part of an array -- getting the correct table    */
 
223
        /* size is probably not worth the trouble                          */
 
224
 
 
225
        table_size = p - valid->extra3;
 
226
 
 
227
        OTV_SIZE_CHECK( device );
 
228
        if ( device )
 
229
          otv_Device_validate( valid->extra3 + device, valid );
 
230
      }
 
231
      format >>= 1;
 
232
    }
 
233
 
 
234
    OTV_EXIT;
 
235
  }
 
236
 
 
237
 
 
238
  /*************************************************************************/
 
239
  /*************************************************************************/
 
240
  /*****                                                               *****/
 
241
  /*****                           ANCHORS                             *****/
 
242
  /*****                                                               *****/
 
243
  /*************************************************************************/
 
244
  /*************************************************************************/
 
245
 
 
246
  static void
 
247
  otv_Anchor_validate( FT_Bytes       table,
 
248
                       OTV_Validator  valid )
 
249
  {
 
250
    FT_Bytes  p = table;
 
251
    FT_UInt   AnchorFormat;
 
252
 
 
253
 
 
254
    OTV_NAME_ENTER( "Anchor");
 
255
 
 
256
    OTV_LIMIT_CHECK( 6 );
 
257
    AnchorFormat = FT_NEXT_USHORT( p );
 
258
 
 
259
    OTV_TRACE(( " (format %d)\n", AnchorFormat ));
 
260
 
 
261
    p += 4;     /* skip XCoordinate and YCoordinate */
 
262
 
 
263
    switch ( AnchorFormat )
 
264
    {
 
265
    case 1:
 
266
      break;
 
267
 
 
268
    case 2:
 
269
      OTV_LIMIT_CHECK( 2 );  /* AnchorPoint */
 
270
      break;
 
271
 
 
272
    case 3:
 
273
      {
 
274
        FT_UInt   table_size;
 
275
 
 
276
        OTV_OPTIONAL_TABLE( XDeviceTable );
 
277
        OTV_OPTIONAL_TABLE( YDeviceTable );
 
278
 
 
279
 
 
280
        OTV_LIMIT_CHECK( 4 );
 
281
        OTV_OPTIONAL_OFFSET( XDeviceTable );
 
282
        OTV_OPTIONAL_OFFSET( YDeviceTable );
 
283
 
 
284
        table_size = 6 + 4;
 
285
 
 
286
        OTV_SIZE_CHECK( XDeviceTable );
 
287
        if ( XDeviceTable )
 
288
          otv_Device_validate( table + XDeviceTable, valid );
 
289
 
 
290
        OTV_SIZE_CHECK( YDeviceTable );
 
291
        if ( YDeviceTable )
 
292
          otv_Device_validate( table + YDeviceTable, valid );
 
293
      }
 
294
      break;
 
295
 
 
296
    default:
 
297
      FT_INVALID_FORMAT;
 
298
    }
 
299
 
 
300
    OTV_EXIT;
 
301
  }
 
302
 
 
303
 
 
304
  /*************************************************************************/
 
305
  /*************************************************************************/
 
306
  /*****                                                               *****/
 
307
  /*****                         MARK ARRAYS                           *****/
 
308
  /*****                                                               *****/
 
309
  /*************************************************************************/
 
310
  /*************************************************************************/
 
311
 
 
312
  static void
 
313
  otv_MarkArray_validate( FT_Bytes       table,
 
314
                          OTV_Validator  valid )
 
315
  {
 
316
    FT_Bytes  p = table;
 
317
    FT_UInt   MarkCount;
 
318
 
 
319
 
 
320
    OTV_NAME_ENTER( "MarkArray" );
 
321
 
 
322
    OTV_LIMIT_CHECK( 2 );
 
323
    MarkCount = FT_NEXT_USHORT( p );
 
324
 
 
325
    OTV_TRACE(( " (MarkCount = %d)\n", MarkCount ));
 
326
 
 
327
    OTV_LIMIT_CHECK( MarkCount * 4 );
 
328
 
 
329
    /* MarkRecord */
 
330
    for ( ; MarkCount > 0; MarkCount-- )
 
331
    {
 
332
      p += 2;   /* skip Class */
 
333
      /* MarkAnchor */
 
334
      otv_Anchor_validate( table + FT_NEXT_USHORT( p ), valid );
 
335
    }
 
336
 
 
337
    OTV_EXIT;
 
338
  }
 
339
 
 
340
 
 
341
  /*************************************************************************/
 
342
  /*************************************************************************/
 
343
  /*****                                                               *****/
 
344
  /*****                     GPOS LOOKUP TYPE 1                        *****/
 
345
  /*****                                                               *****/
 
346
  /*************************************************************************/
 
347
  /*************************************************************************/
 
348
 
 
349
  /* sets valid->extra3 (pointer to base table) */
 
350
 
 
351
  static void
 
352
  otv_SinglePos_validate( FT_Bytes       table,
 
353
                          OTV_Validator  valid )
 
354
  {
 
355
    FT_Bytes  p = table;
 
356
    FT_UInt   PosFormat;
 
357
 
 
358
 
 
359
    OTV_NAME_ENTER( "SinglePos" );
 
360
 
 
361
    OTV_LIMIT_CHECK( 2 );
 
362
    PosFormat = FT_NEXT_USHORT( p );
 
363
 
 
364
    OTV_TRACE(( " (format %d)\n", PosFormat ));
 
365
 
 
366
    valid->extra3 = table;
 
367
 
 
368
    switch ( PosFormat )
 
369
    {
 
370
    case 1:     /* SinglePosFormat1 */
 
371
      {
 
372
        FT_UInt  Coverage, ValueFormat;
 
373
 
 
374
 
 
375
        OTV_LIMIT_CHECK( 4 );
 
376
        Coverage    = FT_NEXT_USHORT( p );
 
377
        ValueFormat = FT_NEXT_USHORT( p );
 
378
 
 
379
        otv_Coverage_validate( table + Coverage, valid, -1 );
 
380
        otv_ValueRecord_validate( p, ValueFormat, valid ); /* Value */
 
381
      }
 
382
      break;
 
383
 
 
384
    case 2:     /* SinglePosFormat2 */
 
385
      {
 
386
        FT_UInt  Coverage, ValueFormat, ValueCount, len_value;
 
387
 
 
388
 
 
389
        OTV_LIMIT_CHECK( 6 );
 
390
        Coverage    = FT_NEXT_USHORT( p );
 
391
        ValueFormat = FT_NEXT_USHORT( p );
 
392
        ValueCount  = FT_NEXT_USHORT( p );
 
393
 
 
394
        OTV_TRACE(( " (ValueCount = %d)\n", ValueCount ));
 
395
 
 
396
        len_value = otv_value_length( ValueFormat );
 
397
 
 
398
        otv_Coverage_validate( table + Coverage, valid, ValueCount );
 
399
 
 
400
        OTV_LIMIT_CHECK( ValueCount * len_value );
 
401
 
 
402
        /* Value */
 
403
        for ( ; ValueCount > 0; ValueCount-- )
 
404
        {
 
405
          otv_ValueRecord_validate( p, ValueFormat, valid );
 
406
          p += len_value;
 
407
        }
 
408
      }
 
409
      break;
 
410
 
 
411
    default:
 
412
      FT_INVALID_FORMAT;
 
413
    }
 
414
 
 
415
    OTV_EXIT;
 
416
  }
 
417
 
 
418
 
 
419
  /*************************************************************************/
 
420
  /*************************************************************************/
 
421
  /*****                                                               *****/
 
422
  /*****                     GPOS LOOKUP TYPE 2                        *****/
 
423
  /*****                                                               *****/
 
424
  /*************************************************************************/
 
425
  /*************************************************************************/
 
426
 
 
427
  static void
 
428
  otv_PairSet_validate( FT_Bytes       table,
 
429
                        FT_UInt        format1,
 
430
                        FT_UInt        format2,
 
431
                        OTV_Validator  valid )
 
432
  {
 
433
    FT_Bytes  p = table;
 
434
    FT_UInt   value_len1, value_len2, PairValueCount;
 
435
 
 
436
 
 
437
    OTV_NAME_ENTER( "PairSet" );
 
438
 
 
439
    OTV_LIMIT_CHECK( 2 );
 
440
    PairValueCount = FT_NEXT_USHORT( p );
 
441
 
 
442
    OTV_TRACE(( " (PairValueCount = %d)\n", PairValueCount ));
 
443
 
 
444
    value_len1 = otv_value_length( format1 );
 
445
    value_len2 = otv_value_length( format2 );
 
446
 
 
447
    OTV_LIMIT_CHECK( PairValueCount * ( value_len1 + value_len2 + 2 ) );
 
448
 
 
449
    /* PairValueRecord */
 
450
    for ( ; PairValueCount > 0; PairValueCount-- )
 
451
    {
 
452
      p += 2;       /* skip SecondGlyph */
 
453
 
 
454
      if ( format1 )
 
455
        otv_ValueRecord_validate( p, format1, valid ); /* Value1 */
 
456
      p += value_len1;
 
457
 
 
458
      if ( format2 )
 
459
        otv_ValueRecord_validate( p, format2, valid ); /* Value2 */
 
460
      p += value_len2;
 
461
    }
 
462
 
 
463
    OTV_EXIT;
 
464
  }
 
465
 
 
466
 
 
467
  /* sets valid->extra3 (pointer to base table) */
 
468
 
 
469
  static void
 
470
  otv_PairPos_validate( FT_Bytes       table,
 
471
                        OTV_Validator  valid )
 
472
  {
 
473
    FT_Bytes  p = table;
 
474
    FT_UInt   PosFormat;
 
475
 
 
476
 
 
477
    OTV_NAME_ENTER( "PairPos" );
 
478
 
 
479
    OTV_LIMIT_CHECK( 2 );
 
480
    PosFormat = FT_NEXT_USHORT( p );
 
481
 
 
482
    OTV_TRACE(( " (format %d)\n", PosFormat ));
 
483
 
 
484
    valid->extra3 = table;
 
485
 
 
486
    switch ( PosFormat )
 
487
    {
 
488
    case 1:     /* PairPosFormat1 */
 
489
      {
 
490
        FT_UInt  Coverage, ValueFormat1, ValueFormat2, PairSetCount;
 
491
 
 
492
 
 
493
        OTV_LIMIT_CHECK( 8 );
 
494
        Coverage     = FT_NEXT_USHORT( p );
 
495
        ValueFormat1 = FT_NEXT_USHORT( p );
 
496
        ValueFormat2 = FT_NEXT_USHORT( p );
 
497
        PairSetCount = FT_NEXT_USHORT( p );
 
498
 
 
499
        OTV_TRACE(( " (PairSetCount = %d)\n", PairSetCount ));
 
500
 
 
501
        otv_Coverage_validate( table + Coverage, valid, -1 );
 
502
 
 
503
        OTV_LIMIT_CHECK( PairSetCount * 2 );
 
504
 
 
505
        /* PairSetOffset */
 
506
        for ( ; PairSetCount > 0; PairSetCount-- )
 
507
          otv_PairSet_validate( table + FT_NEXT_USHORT( p ),
 
508
                                ValueFormat1, ValueFormat2, valid );
 
509
      }
 
510
      break;
 
511
 
 
512
    case 2:     /* PairPosFormat2 */
 
513
      {
 
514
        FT_UInt  Coverage, ValueFormat1, ValueFormat2, ClassDef1, ClassDef2;
 
515
        FT_UInt  ClassCount1, ClassCount2, len_value1, len_value2, count;
 
516
 
 
517
 
 
518
        OTV_LIMIT_CHECK( 14 );
 
519
        Coverage     = FT_NEXT_USHORT( p );
 
520
        ValueFormat1 = FT_NEXT_USHORT( p );
 
521
        ValueFormat2 = FT_NEXT_USHORT( p );
 
522
        ClassDef1    = FT_NEXT_USHORT( p );
 
523
        ClassDef2    = FT_NEXT_USHORT( p );
 
524
        ClassCount1  = FT_NEXT_USHORT( p );
 
525
        ClassCount2  = FT_NEXT_USHORT( p );
 
526
 
 
527
        OTV_TRACE(( " (ClassCount1 = %d)\n", ClassCount1 ));
 
528
        OTV_TRACE(( " (ClassCount2 = %d)\n", ClassCount2 ));
 
529
 
 
530
        len_value1 = otv_value_length( ValueFormat1 );
 
531
        len_value2 = otv_value_length( ValueFormat2 );
 
532
 
 
533
        otv_Coverage_validate( table + Coverage, valid, -1 );
 
534
        otv_ClassDef_validate( table + ClassDef1, valid );
 
535
        otv_ClassDef_validate( table + ClassDef2, valid );
 
536
 
 
537
        OTV_LIMIT_CHECK( ClassCount1 * ClassCount2 *
 
538
                     ( len_value1 + len_value2 ) );
 
539
 
 
540
        /* Class1Record */
 
541
        for ( ; ClassCount1 > 0; ClassCount1-- )
 
542
        {
 
543
          /* Class2Record */
 
544
          for ( count = ClassCount2; count > 0; count-- )
 
545
          {
 
546
            if ( ValueFormat1 )
 
547
              /* Value1 */
 
548
              otv_ValueRecord_validate( p, ValueFormat1, valid );
 
549
            p += len_value1;
 
550
 
 
551
            if ( ValueFormat2 )
 
552
              /* Value2 */
 
553
              otv_ValueRecord_validate( p, ValueFormat2, valid );
 
554
            p += len_value2;
 
555
          }
 
556
        }
 
557
      }
 
558
      break;
 
559
 
 
560
    default:
 
561
      FT_INVALID_FORMAT;
 
562
    }
 
563
 
 
564
    OTV_EXIT;
 
565
  }
 
566
 
 
567
 
 
568
  /*************************************************************************/
 
569
  /*************************************************************************/
 
570
  /*****                                                               *****/
 
571
  /*****                     GPOS LOOKUP TYPE 3                        *****/
 
572
  /*****                                                               *****/
 
573
  /*************************************************************************/
 
574
  /*************************************************************************/
 
575
 
 
576
  static void
 
577
  otv_CursivePos_validate( FT_Bytes       table,
 
578
                           OTV_Validator  valid )
 
579
  {
 
580
    FT_Bytes  p = table;
 
581
    FT_UInt   PosFormat;
 
582
 
 
583
 
 
584
    OTV_NAME_ENTER( "CursivePos" );
 
585
 
 
586
    OTV_LIMIT_CHECK( 2 );
 
587
    PosFormat = FT_NEXT_USHORT( p );
 
588
 
 
589
    OTV_TRACE(( " (format %d)\n", PosFormat ));
 
590
 
 
591
    switch ( PosFormat )
 
592
    {
 
593
    case 1:     /* CursivePosFormat1 */
 
594
      {
 
595
        FT_UInt   table_size;
 
596
        FT_UInt   Coverage, EntryExitCount;
 
597
 
 
598
        OTV_OPTIONAL_TABLE( EntryAnchor );
 
599
        OTV_OPTIONAL_TABLE( ExitAnchor  );
 
600
 
 
601
 
 
602
        OTV_LIMIT_CHECK( 4 );
 
603
        Coverage       = FT_NEXT_USHORT( p );
 
604
        EntryExitCount = FT_NEXT_USHORT( p );
 
605
 
 
606
        OTV_TRACE(( " (EntryExitCount = %d)\n", EntryExitCount ));
 
607
 
 
608
        otv_Coverage_validate( table + Coverage, valid, EntryExitCount );
 
609
 
 
610
        OTV_LIMIT_CHECK( EntryExitCount * 4 );
 
611
 
 
612
        table_size = EntryExitCount * 4 + 4;
 
613
 
 
614
        /* EntryExitRecord */
 
615
        for ( ; EntryExitCount > 0; EntryExitCount-- )
 
616
        {
 
617
          OTV_OPTIONAL_OFFSET( EntryAnchor );
 
618
          OTV_OPTIONAL_OFFSET( ExitAnchor  );
 
619
 
 
620
          OTV_SIZE_CHECK( EntryAnchor );
 
621
          if ( EntryAnchor )
 
622
            otv_Anchor_validate( table + EntryAnchor, valid );
 
623
 
 
624
          OTV_SIZE_CHECK( ExitAnchor );
 
625
          if ( ExitAnchor )
 
626
            otv_Anchor_validate( table + ExitAnchor, valid );
 
627
        }
 
628
      }
 
629
      break;
 
630
 
 
631
    default:
 
632
      FT_INVALID_FORMAT;
 
633
    }
 
634
 
 
635
    OTV_EXIT;
 
636
  }
 
637
 
 
638
 
 
639
  /*************************************************************************/
 
640
  /*************************************************************************/
 
641
  /*****                                                               *****/
 
642
  /*****                     GPOS LOOKUP TYPE 4                        *****/
 
643
  /*****                                                               *****/
 
644
  /*************************************************************************/
 
645
  /*************************************************************************/
 
646
 
 
647
  /* UNDOCUMENTED (in OpenType 1.5):              */
 
648
  /* BaseRecord tables can contain NULL pointers. */
 
649
 
 
650
  /* sets valid->extra2 (1) */
 
651
 
 
652
  static void
 
653
  otv_MarkBasePos_validate( FT_Bytes       table,
 
654
                            OTV_Validator  valid )
 
655
  {
 
656
    FT_Bytes  p = table;
 
657
    FT_UInt   PosFormat;
 
658
 
 
659
 
 
660
    OTV_NAME_ENTER( "MarkBasePos" );
 
661
 
 
662
    OTV_LIMIT_CHECK( 2 );
 
663
    PosFormat = FT_NEXT_USHORT( p );
 
664
 
 
665
    OTV_TRACE(( " (format %d)\n", PosFormat ));
 
666
 
 
667
    switch ( PosFormat )
 
668
    {
 
669
    case 1:
 
670
      valid->extra2 = 1;
 
671
      OTV_NEST2( MarkBasePosFormat1, BaseArray );
 
672
      OTV_RUN( table, valid );
 
673
      break;
 
674
 
 
675
    default:
 
676
      FT_INVALID_FORMAT;
 
677
    }
 
678
 
 
679
    OTV_EXIT;
 
680
  }
 
681
 
 
682
 
 
683
  /*************************************************************************/
 
684
  /*************************************************************************/
 
685
  /*****                                                               *****/
 
686
  /*****                     GPOS LOOKUP TYPE 5                        *****/
 
687
  /*****                                                               *****/
 
688
  /*************************************************************************/
 
689
  /*************************************************************************/
 
690
 
 
691
  /* sets valid->extra2 (1) */
 
692
 
 
693
  static void
 
694
  otv_MarkLigPos_validate( FT_Bytes       table,
 
695
                           OTV_Validator  valid )
 
696
  {
 
697
    FT_Bytes  p = table;
 
698
    FT_UInt   PosFormat;
 
699
 
 
700
 
 
701
    OTV_NAME_ENTER( "MarkLigPos" );
 
702
 
 
703
    OTV_LIMIT_CHECK( 2 );
 
704
    PosFormat = FT_NEXT_USHORT( p );
 
705
 
 
706
    OTV_TRACE(( " (format %d)\n", PosFormat ));
 
707
 
 
708
    switch ( PosFormat )
 
709
    {
 
710
    case 1:
 
711
      valid->extra2 = 1;
 
712
      OTV_NEST3( MarkLigPosFormat1, LigatureArray, LigatureAttach );
 
713
      OTV_RUN( table, valid );
 
714
      break;
 
715
 
 
716
    default:
 
717
      FT_INVALID_FORMAT;
 
718
    }
 
719
 
 
720
    OTV_EXIT;
 
721
  }
 
722
 
 
723
 
 
724
  /*************************************************************************/
 
725
  /*************************************************************************/
 
726
  /*****                                                               *****/
 
727
  /*****                     GPOS LOOKUP TYPE 6                        *****/
 
728
  /*****                                                               *****/
 
729
  /*************************************************************************/
 
730
  /*************************************************************************/
 
731
 
 
732
  /* sets valid->extra2 (0) */
 
733
 
 
734
  static void
 
735
  otv_MarkMarkPos_validate( FT_Bytes       table,
 
736
                            OTV_Validator  valid )
 
737
  {
 
738
    FT_Bytes  p = table;
 
739
    FT_UInt   PosFormat;
 
740
 
 
741
 
 
742
    OTV_NAME_ENTER( "MarkMarkPos" );
 
743
 
 
744
    OTV_LIMIT_CHECK( 2 );
 
745
    PosFormat = FT_NEXT_USHORT( p );
 
746
 
 
747
    OTV_TRACE(( " (format %d)\n", PosFormat ));
 
748
 
 
749
    switch ( PosFormat )
 
750
    {
 
751
    case 1:
 
752
      valid->extra2 = 0;
 
753
      OTV_NEST2( MarkMarkPosFormat1, Mark2Array );
 
754
      OTV_RUN( table, valid );
 
755
      break;
 
756
 
 
757
    default:
 
758
      FT_INVALID_FORMAT;
 
759
    }
 
760
 
 
761
    OTV_EXIT;
 
762
  }
 
763
 
 
764
 
 
765
  /*************************************************************************/
 
766
  /*************************************************************************/
 
767
  /*****                                                               *****/
 
768
  /*****                     GPOS LOOKUP TYPE 7                        *****/
 
769
  /*****                                                               *****/
 
770
  /*************************************************************************/
 
771
  /*************************************************************************/
 
772
 
 
773
  /* sets valid->extra1 (lookup count) */
 
774
 
 
775
  static void
 
776
  otv_ContextPos_validate( FT_Bytes       table,
 
777
                           OTV_Validator  valid )
 
778
  {
 
779
    FT_Bytes  p = table;
 
780
    FT_UInt   PosFormat;
 
781
 
 
782
 
 
783
    OTV_NAME_ENTER( "ContextPos" );
 
784
 
 
785
    OTV_LIMIT_CHECK( 2 );
 
786
    PosFormat = FT_NEXT_USHORT( p );
 
787
 
 
788
    OTV_TRACE(( " (format %d)\n", PosFormat ));
 
789
 
 
790
    switch ( PosFormat )
 
791
    {
 
792
    case 1:
 
793
      /* no need to check glyph indices/classes used as input for these */
 
794
      /* context rules since even invalid glyph indices/classes return  */
 
795
      /* meaningful results                                             */
 
796
 
 
797
      valid->extra1 = valid->lookup_count;
 
798
      OTV_NEST3( ContextPosFormat1, PosRuleSet, PosRule );
 
799
      OTV_RUN( table, valid );
 
800
      break;
 
801
 
 
802
    case 2:
 
803
      /* no need to check glyph indices/classes used as input for these */
 
804
      /* context rules since even invalid glyph indices/classes return  */
 
805
      /* meaningful results                                             */
 
806
 
 
807
      OTV_NEST3( ContextPosFormat2, PosClassSet, PosClassRule );
 
808
      OTV_RUN( table, valid );
 
809
      break;
 
810
 
 
811
    case 3:
 
812
      OTV_NEST1( ContextPosFormat3 );
 
813
      OTV_RUN( table, valid );
 
814
      break;
 
815
 
 
816
    default:
 
817
      FT_INVALID_FORMAT;
 
818
    }
 
819
 
 
820
    OTV_EXIT;
 
821
  }
 
822
 
 
823
 
 
824
  /*************************************************************************/
 
825
  /*************************************************************************/
 
826
  /*****                                                               *****/
 
827
  /*****                     GPOS LOOKUP TYPE 8                        *****/
 
828
  /*****                                                               *****/
 
829
  /*************************************************************************/
 
830
  /*************************************************************************/
 
831
 
 
832
  /* sets valid->extra1 (lookup count) */
 
833
 
 
834
  static void
 
835
  otv_ChainContextPos_validate( FT_Bytes       table,
 
836
                                OTV_Validator  valid )
 
837
  {
 
838
    FT_Bytes  p = table;
 
839
    FT_UInt   PosFormat;
 
840
 
 
841
 
 
842
    OTV_NAME_ENTER( "ChainContextPos" );
 
843
 
 
844
    OTV_LIMIT_CHECK( 2 );
 
845
    PosFormat = FT_NEXT_USHORT( p );
 
846
 
 
847
    OTV_TRACE(( " (format %d)\n", PosFormat ));
 
848
 
 
849
    switch ( PosFormat )
 
850
    {
 
851
    case 1:
 
852
      /* no need to check glyph indices/classes used as input for these */
 
853
      /* context rules since even invalid glyph indices/classes return  */
 
854
      /* meaningful results                                             */
 
855
 
 
856
      valid->extra1 = valid->lookup_count;
 
857
      OTV_NEST3( ChainContextPosFormat1,
 
858
                 ChainPosRuleSet, ChainPosRule );
 
859
      OTV_RUN( table, valid );
 
860
      break;
 
861
 
 
862
    case 2:
 
863
      /* no need to check glyph indices/classes used as input for these */
 
864
      /* context rules since even invalid glyph indices/classes return  */
 
865
      /* meaningful results                                             */
 
866
 
 
867
      OTV_NEST3( ChainContextPosFormat2,
 
868
                 ChainPosClassSet, ChainPosClassRule );
 
869
      OTV_RUN( table, valid );
 
870
      break;
 
871
 
 
872
    case 3:
 
873
      OTV_NEST1( ChainContextPosFormat3 );
 
874
      OTV_RUN( table, valid );
 
875
      break;
 
876
 
 
877
    default:
 
878
      FT_INVALID_FORMAT;
 
879
    }
 
880
 
 
881
    OTV_EXIT;
 
882
  }
 
883
 
 
884
 
 
885
  /*************************************************************************/
 
886
  /*************************************************************************/
 
887
  /*****                                                               *****/
 
888
  /*****                     GPOS LOOKUP TYPE 9                        *****/
 
889
  /*****                                                               *****/
 
890
  /*************************************************************************/
 
891
  /*************************************************************************/
 
892
 
 
893
  /* uses valid->type_funcs */
 
894
 
 
895
  static void
 
896
  otv_ExtensionPos_validate( FT_Bytes       table,
 
897
                             OTV_Validator  valid )
 
898
  {
 
899
    FT_Bytes  p = table;
 
900
    FT_UInt   PosFormat;
 
901
 
 
902
 
 
903
    OTV_NAME_ENTER( "ExtensionPos" );
 
904
 
 
905
    OTV_LIMIT_CHECK( 2 );
 
906
    PosFormat = FT_NEXT_USHORT( p );
 
907
 
 
908
    OTV_TRACE(( " (format %d)\n", PosFormat ));
 
909
 
 
910
    switch ( PosFormat )
 
911
    {
 
912
    case 1:     /* ExtensionPosFormat1 */
 
913
      {
 
914
        FT_UInt            ExtensionLookupType;
 
915
        FT_ULong           ExtensionOffset;
 
916
        OTV_Validate_Func  validate;
 
917
 
 
918
 
 
919
        OTV_LIMIT_CHECK( 6 );
 
920
        ExtensionLookupType = FT_NEXT_USHORT( p );
 
921
        ExtensionOffset     = FT_NEXT_ULONG( p );
 
922
 
 
923
        if ( ExtensionLookupType == 0 || ExtensionLookupType >= 9 )
 
924
          FT_INVALID_DATA;
 
925
 
 
926
        validate = valid->type_funcs[ExtensionLookupType - 1];
 
927
        validate( table + ExtensionOffset, valid );
 
928
      }
 
929
      break;
 
930
 
 
931
    default:
 
932
      FT_INVALID_FORMAT;
 
933
    }
 
934
 
 
935
    OTV_EXIT;
 
936
  }
 
937
 
 
938
 
 
939
  static const OTV_Validate_Func  otv_gpos_validate_funcs[9] =
 
940
  {
 
941
    otv_SinglePos_validate,
 
942
    otv_PairPos_validate,
 
943
    otv_CursivePos_validate,
 
944
    otv_MarkBasePos_validate,
 
945
    otv_MarkLigPos_validate,
 
946
    otv_MarkMarkPos_validate,
 
947
    otv_ContextPos_validate,
 
948
    otv_ChainContextPos_validate,
 
949
    otv_ExtensionPos_validate
 
950
  };
 
951
 
 
952
 
 
953
  /* sets valid->type_count */
 
954
  /* sets valid->type_funcs */
 
955
 
 
956
  FT_LOCAL_DEF( void )
 
957
  otv_GPOS_subtable_validate( FT_Bytes       table,
 
958
                              OTV_Validator  valid )
 
959
  {
 
960
    valid->type_count = 9;
 
961
    valid->type_funcs = (OTV_Validate_Func*)otv_gpos_validate_funcs;
 
962
 
 
963
    otv_Lookup_validate( table, valid );
 
964
  }
 
965
 
 
966
 
 
967
  /*************************************************************************/
 
968
  /*************************************************************************/
 
969
  /*****                                                               *****/
 
970
  /*****                          GPOS TABLE                           *****/
 
971
  /*****                                                               *****/
 
972
  /*************************************************************************/
 
973
  /*************************************************************************/
 
974
 
 
975
  /* sets valid->glyph_count */
 
976
 
 
977
  FT_LOCAL_DEF( void )
 
978
  otv_GPOS_validate( FT_Bytes      table,
 
979
                     FT_UInt       glyph_count,
 
980
                     FT_Validator  ftvalid )
 
981
  {
 
982
    OTV_ValidatorRec  validrec;
 
983
    OTV_Validator     valid = &validrec;
 
984
    FT_Bytes          p     = table;
 
985
    FT_UInt           ScriptList, FeatureList, LookupList;
 
986
 
 
987
 
 
988
    valid->root = ftvalid;
 
989
 
 
990
    FT_TRACE3(( "validating GPOS table\n" ));
 
991
    OTV_INIT;
 
992
 
 
993
    OTV_LIMIT_CHECK( 10 );
 
994
 
 
995
    if ( FT_NEXT_ULONG( p ) != 0x10000UL )      /* Version */
 
996
      FT_INVALID_FORMAT;
 
997
 
 
998
    ScriptList  = FT_NEXT_USHORT( p );
 
999
    FeatureList = FT_NEXT_USHORT( p );
 
1000
    LookupList  = FT_NEXT_USHORT( p );
 
1001
 
 
1002
    valid->type_count  = 9;
 
1003
    valid->type_funcs  = (OTV_Validate_Func*)otv_gpos_validate_funcs;
 
1004
    valid->glyph_count = glyph_count;
 
1005
 
 
1006
    otv_LookupList_validate( table + LookupList,
 
1007
                             valid );
 
1008
    otv_FeatureList_validate( table + FeatureList, table + LookupList,
 
1009
                              valid );
 
1010
    otv_ScriptList_validate( table + ScriptList, table + FeatureList,
 
1011
                             valid );
 
1012
 
 
1013
    FT_TRACE4(( "\n" ));
 
1014
  }
 
1015
 
 
1016
 
 
1017
/* END */