source: trunk/poppler/freetype2/src/otvalid/otvgpos.c @ 251

Last change on this file since 251 was 251, checked in by Eugene Romanenko, 13 years ago

PDF plugin: freetype library updated to version 2.3.5

File size: 30.0 KB
Line 
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_UInt   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, ExtensionOffset;
915        OTV_Validate_Func  validate;
916
917
918        OTV_LIMIT_CHECK( 6 );
919        ExtensionLookupType = FT_NEXT_USHORT( p );
920        ExtensionOffset     = FT_NEXT_ULONG( p );
921
922        if ( ExtensionLookupType == 0 || ExtensionLookupType >= 9 )
923          FT_INVALID_DATA;
924
925        validate = valid->type_funcs[ExtensionLookupType - 1];
926        validate( table + ExtensionOffset, valid );
927      }
928      break;
929
930    default:
931      FT_INVALID_FORMAT;
932    }
933
934    OTV_EXIT;
935  }
936
937
938  static const OTV_Validate_Func  otv_gpos_validate_funcs[9] =
939  {
940    otv_SinglePos_validate,
941    otv_PairPos_validate,
942    otv_CursivePos_validate,
943    otv_MarkBasePos_validate,
944    otv_MarkLigPos_validate,
945    otv_MarkMarkPos_validate,
946    otv_ContextPos_validate,
947    otv_ChainContextPos_validate,
948    otv_ExtensionPos_validate
949  };
950
951
952  /* sets valid->type_count */
953  /* sets valid->type_funcs */
954
955  FT_LOCAL_DEF( void )
956  otv_GPOS_subtable_validate( FT_Bytes       table,
957                              OTV_Validator  valid )
958  {
959    valid->type_count = 9;
960    valid->type_funcs = (OTV_Validate_Func*)otv_gpos_validate_funcs;
961
962    otv_Lookup_validate( table, valid );
963  }
964
965
966  /*************************************************************************/
967  /*************************************************************************/
968  /*****                                                               *****/
969  /*****                          GPOS TABLE                           *****/
970  /*****                                                               *****/
971  /*************************************************************************/
972  /*************************************************************************/
973
974  /* sets valid->glyph_count */
975
976  FT_LOCAL_DEF( void )
977  otv_GPOS_validate( FT_Bytes      table,
978                     FT_UInt       glyph_count,
979                     FT_Validator  ftvalid )
980  {
981    OTV_ValidatorRec  validrec;
982    OTV_Validator     valid = &validrec;
983    FT_Bytes          p     = table;
984    FT_UInt           ScriptList, FeatureList, LookupList;
985
986
987    valid->root = ftvalid;
988
989    FT_TRACE3(( "validating GPOS table\n" ));
990    OTV_INIT;
991
992    OTV_LIMIT_CHECK( 10 );
993
994    if ( FT_NEXT_ULONG( p ) != 0x10000UL )      /* Version */
995      FT_INVALID_FORMAT;
996
997    ScriptList  = FT_NEXT_USHORT( p );
998    FeatureList = FT_NEXT_USHORT( p );
999    LookupList  = FT_NEXT_USHORT( p );
1000
1001    valid->type_count  = 9;
1002    valid->type_funcs  = (OTV_Validate_Func*)otv_gpos_validate_funcs;
1003    valid->glyph_count = glyph_count;
1004
1005    otv_LookupList_validate( table + LookupList,
1006                             valid );
1007    otv_FeatureList_validate( table + FeatureList, table + LookupList,
1008                              valid );
1009    otv_ScriptList_validate( table + ScriptList, table + FeatureList,
1010                             valid );
1011
1012    FT_TRACE4(( "\n" ));
1013  }
1014
1015
1016/* END */
Note: See TracBrowser for help on using the repository browser.