Merge 25584, 25588.
[reactos.git] / reactos / dll / 3rdparty / freetype / src / otvalid / otvgpos.c
1 /***************************************************************************/
2 /* */
3 /* otvgpos.c */
4 /* */
5 /* OpenType GPOS table validation (body). */
6 /* */
7 /* Copyright 2002, 2004, 2005, 2006 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 );
128 otv_Coverage_validate( table + Coverage2, valid );
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_DATA;
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_DATA;
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 );
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 );
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_DATA;
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 );
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 );
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_DATA;
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 );
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_DATA;
633 }
634
635 OTV_EXIT;
636 }
637
638
639 /*************************************************************************/
640 /*************************************************************************/
641 /***** *****/
642 /***** GPOS LOOKUP TYPE 4 *****/
643 /***** *****/
644 /*************************************************************************/
645 /*************************************************************************/
646
647 /* sets valid->extra2 (0) */
648
649 static void
650 otv_MarkBasePos_validate( FT_Bytes table,
651 OTV_Validator valid )
652 {
653 FT_Bytes p = table;
654 FT_UInt PosFormat;
655
656
657 OTV_NAME_ENTER( "MarkBasePos" );
658
659 OTV_LIMIT_CHECK( 2 );
660 PosFormat = FT_NEXT_USHORT( p );
661
662 OTV_TRACE(( " (format %d)\n", PosFormat ));
663
664 switch ( PosFormat )
665 {
666 case 1:
667 valid->extra2 = 0;
668 OTV_NEST2( MarkBasePosFormat1, BaseArray );
669 OTV_RUN( table, valid );
670 break;
671
672 default:
673 FT_INVALID_DATA;
674 }
675
676 OTV_EXIT;
677 }
678
679
680 /*************************************************************************/
681 /*************************************************************************/
682 /***** *****/
683 /***** GPOS LOOKUP TYPE 5 *****/
684 /***** *****/
685 /*************************************************************************/
686 /*************************************************************************/
687
688 /* sets valid->extra2 (1) */
689
690 static void
691 otv_MarkLigPos_validate( FT_Bytes table,
692 OTV_Validator valid )
693 {
694 FT_Bytes p = table;
695 FT_UInt PosFormat;
696
697
698 OTV_NAME_ENTER( "MarkLigPos" );
699
700 OTV_LIMIT_CHECK( 2 );
701 PosFormat = FT_NEXT_USHORT( p );
702
703 OTV_TRACE(( " (format %d)\n", PosFormat ));
704
705 switch ( PosFormat )
706 {
707 case 1:
708 valid->extra2 = 1;
709 OTV_NEST3( MarkLigPosFormat1, LigatureArray, LigatureAttach );
710 OTV_RUN( table, valid );
711 break;
712
713 default:
714 FT_INVALID_DATA;
715 }
716
717 OTV_EXIT;
718 }
719
720
721 /*************************************************************************/
722 /*************************************************************************/
723 /***** *****/
724 /***** GPOS LOOKUP TYPE 6 *****/
725 /***** *****/
726 /*************************************************************************/
727 /*************************************************************************/
728
729 /* sets valid->extra2 (0) */
730
731 static void
732 otv_MarkMarkPos_validate( FT_Bytes table,
733 OTV_Validator valid )
734 {
735 FT_Bytes p = table;
736 FT_UInt PosFormat;
737
738
739 OTV_NAME_ENTER( "MarkMarkPos" );
740
741 OTV_LIMIT_CHECK( 2 );
742 PosFormat = FT_NEXT_USHORT( p );
743
744 OTV_TRACE(( " (format %d)\n", PosFormat ));
745
746 switch ( PosFormat )
747 {
748 case 1:
749 valid->extra2 = 0;
750 OTV_NEST2( MarkMarkPosFormat1, Mark2Array );
751 OTV_RUN( table, valid );
752 break;
753
754 default:
755 FT_INVALID_DATA;
756 }
757
758 OTV_EXIT;
759 }
760
761
762 /*************************************************************************/
763 /*************************************************************************/
764 /***** *****/
765 /***** GPOS LOOKUP TYPE 7 *****/
766 /***** *****/
767 /*************************************************************************/
768 /*************************************************************************/
769
770 /* sets valid->extra1 (lookup count) */
771
772 static void
773 otv_ContextPos_validate( FT_Bytes table,
774 OTV_Validator valid )
775 {
776 FT_Bytes p = table;
777 FT_UInt PosFormat;
778
779
780 OTV_NAME_ENTER( "ContextPos" );
781
782 OTV_LIMIT_CHECK( 2 );
783 PosFormat = FT_NEXT_USHORT( p );
784
785 OTV_TRACE(( " (format %d)\n", PosFormat ));
786
787 switch ( PosFormat )
788 {
789 case 1:
790 /* no need to check glyph indices/classes used as input for these */
791 /* context rules since even invalid glyph indices/classes return */
792 /* meaningful results */
793
794 valid->extra1 = valid->lookup_count;
795 OTV_NEST3( ContextPosFormat1, PosRuleSet, PosRule );
796 OTV_RUN( table, valid );
797 break;
798
799 case 2:
800 /* no need to check glyph indices/classes used as input for these */
801 /* context rules since even invalid glyph indices/classes return */
802 /* meaningful results */
803
804 OTV_NEST3( ContextPosFormat2, PosClassSet, PosClassRule );
805 OTV_RUN( table, valid );
806 break;
807
808 case 3:
809 OTV_NEST1( ContextPosFormat3 );
810 OTV_RUN( table, valid );
811 break;
812
813 default:
814 FT_INVALID_DATA;
815 }
816
817 OTV_EXIT;
818 }
819
820
821 /*************************************************************************/
822 /*************************************************************************/
823 /***** *****/
824 /***** GPOS LOOKUP TYPE 8 *****/
825 /***** *****/
826 /*************************************************************************/
827 /*************************************************************************/
828
829 /* sets valid->extra1 (lookup count) */
830
831 static void
832 otv_ChainContextPos_validate( FT_Bytes table,
833 OTV_Validator valid )
834 {
835 FT_Bytes p = table;
836 FT_UInt PosFormat;
837
838
839 OTV_NAME_ENTER( "ChainContextPos" );
840
841 OTV_LIMIT_CHECK( 2 );
842 PosFormat = FT_NEXT_USHORT( p );
843
844 OTV_TRACE(( " (format %d)\n", PosFormat ));
845
846 switch ( PosFormat )
847 {
848 case 1:
849 /* no need to check glyph indices/classes used as input for these */
850 /* context rules since even invalid glyph indices/classes return */
851 /* meaningful results */
852
853 valid->extra1 = valid->lookup_count;
854 OTV_NEST3( ChainContextPosFormat1,
855 ChainPosRuleSet, ChainPosRule );
856 OTV_RUN( table, valid );
857 break;
858
859 case 2:
860 /* no need to check glyph indices/classes used as input for these */
861 /* context rules since even invalid glyph indices/classes return */
862 /* meaningful results */
863
864 OTV_NEST3( ChainContextPosFormat2,
865 ChainPosClassSet, ChainPosClassRule );
866 OTV_RUN( table, valid );
867 break;
868
869 case 3:
870 OTV_NEST1( ChainContextPosFormat3 );
871 OTV_RUN( table, valid );
872 break;
873
874 default:
875 FT_INVALID_DATA;
876 }
877
878 OTV_EXIT;
879 }
880
881
882 /*************************************************************************/
883 /*************************************************************************/
884 /***** *****/
885 /***** GPOS LOOKUP TYPE 9 *****/
886 /***** *****/
887 /*************************************************************************/
888 /*************************************************************************/
889
890 /* uses valid->type_funcs */
891
892 static void
893 otv_ExtensionPos_validate( FT_Bytes table,
894 OTV_Validator valid )
895 {
896 FT_Bytes p = table;
897 FT_UInt PosFormat;
898
899
900 OTV_NAME_ENTER( "ExtensionPos" );
901
902 OTV_LIMIT_CHECK( 2 );
903 PosFormat = FT_NEXT_USHORT( p );
904
905 OTV_TRACE(( " (format %d)\n", PosFormat ));
906
907 switch ( PosFormat )
908 {
909 case 1: /* ExtensionPosFormat1 */
910 {
911 FT_UInt ExtensionLookupType, ExtensionOffset;
912 OTV_Validate_Func validate;
913
914
915 OTV_LIMIT_CHECK( 6 );
916 ExtensionLookupType = FT_NEXT_USHORT( p );
917 ExtensionOffset = FT_NEXT_ULONG( p );
918
919 if ( ExtensionLookupType == 0 || ExtensionLookupType >= 9 )
920 FT_INVALID_DATA;
921
922 validate = valid->type_funcs[ExtensionLookupType - 1];
923 validate( table + ExtensionOffset, valid );
924 }
925 break;
926
927 default:
928 FT_INVALID_DATA;
929 }
930
931 OTV_EXIT;
932 }
933
934
935 static const OTV_Validate_Func otv_gpos_validate_funcs[9] =
936 {
937 otv_SinglePos_validate,
938 otv_PairPos_validate,
939 otv_CursivePos_validate,
940 otv_MarkBasePos_validate,
941 otv_MarkLigPos_validate,
942 otv_MarkMarkPos_validate,
943 otv_ContextPos_validate,
944 otv_ChainContextPos_validate,
945 otv_ExtensionPos_validate
946 };
947
948
949 /* sets valid->type_count */
950 /* sets valid->type_funcs */
951
952 FT_LOCAL_DEF( void )
953 otv_GPOS_subtable_validate( FT_Bytes table,
954 OTV_Validator valid )
955 {
956 valid->type_count = 9;
957 valid->type_funcs = (OTV_Validate_Func*)otv_gpos_validate_funcs;
958
959 otv_Lookup_validate( table, valid );
960 }
961
962
963 /*************************************************************************/
964 /*************************************************************************/
965 /***** *****/
966 /***** GPOS TABLE *****/
967 /***** *****/
968 /*************************************************************************/
969 /*************************************************************************/
970
971 /* sets valid->glyph_count */
972
973 FT_LOCAL_DEF( void )
974 otv_GPOS_validate( FT_Bytes table,
975 FT_UInt glyph_count,
976 FT_Validator ftvalid )
977 {
978 OTV_ValidatorRec validrec;
979 OTV_Validator valid = &validrec;
980 FT_Bytes p = table;
981 FT_UInt ScriptList, FeatureList, LookupList;
982
983
984 valid->root = ftvalid;
985
986 FT_TRACE3(( "validating GPOS table\n" ));
987 OTV_INIT;
988
989 OTV_LIMIT_CHECK( 10 );
990
991 if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */
992 FT_INVALID_DATA;
993
994 ScriptList = FT_NEXT_USHORT( p );
995 FeatureList = FT_NEXT_USHORT( p );
996 LookupList = FT_NEXT_USHORT( p );
997
998 valid->type_count = 9;
999 valid->type_funcs = (OTV_Validate_Func*)otv_gpos_validate_funcs;
1000 valid->glyph_count = glyph_count;
1001
1002 otv_LookupList_validate( table + LookupList,
1003 valid );
1004 otv_FeatureList_validate( table + FeatureList, table + LookupList,
1005 valid );
1006 otv_ScriptList_validate( table + ScriptList, table + FeatureList,
1007 valid );
1008
1009 FT_TRACE4(( "\n" ));
1010 }
1011
1012
1013 /* END */