~ubuntu-branches/ubuntu/wily/hedgewars/wily

« back to all changes in this revision

Viewing changes to misc/libfreetype/src/otvalid/otvgpos.c

  • Committer: Package Import Robot
  • Author(s): Dmitry E. Oboukhov
  • Date: 2011-09-23 10:16:55 UTC
  • mfrom: (1.2.11 upstream)
  • Revision ID: package-import@ubuntu.com-20110923101655-3977th2gc5n0a3pv
Tags: 0.9.16-1
* New upstream version.
 + Downloadable content! Simply click to install any content.
   New voices, hats, maps, themes, translations, music, scripts...
   Hedgewars is now more customisable than ever before! As time goes
   by we will be soliciting community content to feature on this page,
   so remember to check it from time to time. If you decide you want
   to go back to standard Hedgewars, just remove the Data directory
   from your Hedgewars config directory.
 + 3-D rendering! Diorama-like rendering of the game in a variety
   of 3D modes. Let us know which ones work best for you, we didn't
   really have the equipment to test them all.
 + Resizable game window.
 + New utilities! The Time Box will remove one of your hedgehogs
   from the game for a while, protecting from attack until it returns,
   somewhere else on the map. Land spray will allow you to build bridges,
   seal up holes, or just make life unpleasant for your enemies.
 + New single player: Bamboo Thicket, That Sinking Feeling, Newton and
   the Tree and multi-player: The Specialists, Space Invaders,
   Racer - scripts! And a ton more script hooks for scripters
 + New twists on old weapons. Drill strike, seduction and fire have
   been adjusted. Defective mines have been added, rope can attach to
   hogs/crates/barrels again, grenades now have variable bounce (use
   precise key + 1-5). Portal gun is now more usable in flight and
   all game actions are a lot faster.
 + New theme - Golf, dozens of new community hats and a new
   localised Default voice, Ukranian.

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 */