Disabling auto-refresh of game list by default, as it is causing bugs sometimes
[open-ps2-loader.git] / thirdparty / freetype-2.3.12 / src / otvalid / otvgpos.c
blob49b46183a3289e33658e63f067bb195f67c70e2f
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 /***************************************************************************/
19 #include "otvalid.h"
20 #include "otvcommn.h"
21 #include "otvgpos.h"
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
34 static void
35 otv_Anchor_validate( FT_Bytes table,
36 OTV_Validator valid );
38 static void
39 otv_MarkArray_validate( FT_Bytes table,
40 OTV_Validator valid );
43 /*************************************************************************/
44 /*************************************************************************/
45 /***** *****/
46 /***** UTILITY FUNCTIONS *****/
47 /***** *****/
48 /*************************************************************************/
49 /*************************************************************************/
51 #define BaseArrayFunc otv_x_sxy
52 #define LigatureAttachFunc otv_x_sxy
53 #define Mark2ArrayFunc otv_x_sxy
55 /* uses valid->extra1 (counter) */
56 /* uses valid->extra2 (boolean to handle NULL anchor field) */
58 static void
59 otv_x_sxy( FT_Bytes table,
60 OTV_Validator valid )
62 FT_Bytes p = table;
63 FT_UInt Count, count1, table_size;
66 OTV_ENTER;
68 OTV_LIMIT_CHECK( 2 );
70 Count = FT_NEXT_USHORT( p );
72 OTV_TRACE(( " (Count = %d)\n", Count ));
74 OTV_LIMIT_CHECK( Count * valid->extra1 * 2 );
76 table_size = Count * valid->extra1 * 2 + 2;
78 for ( ; Count > 0; Count-- )
79 for ( count1 = valid->extra1; count1 > 0; count1-- )
81 OTV_OPTIONAL_TABLE( anchor_offset );
84 OTV_OPTIONAL_OFFSET( anchor_offset );
86 if ( valid->extra2 )
88 OTV_SIZE_CHECK( anchor_offset );
89 if ( anchor_offset )
90 otv_Anchor_validate( table + anchor_offset, valid );
92 else
93 otv_Anchor_validate( table + anchor_offset, valid );
96 OTV_EXIT;
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
104 /* sets valid->extra1 (class count) */
106 static void
107 otv_u_O_O_u_O_O( FT_Bytes table,
108 OTV_Validator valid )
110 FT_Bytes p = table;
111 FT_UInt Coverage1, Coverage2, ClassCount;
112 FT_UInt Array1, Array2;
113 OTV_Validate_Func func;
116 OTV_ENTER;
118 p += 2; /* skip PosFormat */
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 );
127 otv_Coverage_validate( table + Coverage1, valid, -1 );
128 otv_Coverage_validate( table + Coverage2, valid, -1 );
130 otv_MarkArray_validate( table + Array1, valid );
132 valid->nesting_level++;
133 func = valid->func[valid->nesting_level];
134 valid->extra1 = ClassCount;
136 func( table + Array2, valid );
138 valid->nesting_level--;
140 OTV_EXIT;
144 /*************************************************************************/
145 /*************************************************************************/
146 /***** *****/
147 /***** VALUE RECORDS *****/
148 /***** *****/
149 /*************************************************************************/
150 /*************************************************************************/
152 static FT_UInt
153 otv_value_length( FT_UInt format )
155 FT_UInt count;
158 count = ( ( format & 0xAA ) >> 1 ) + ( format & 0x55 );
159 count = ( ( count & 0xCC ) >> 2 ) + ( count & 0x33 );
160 count = ( ( count & 0xF0 ) >> 4 ) + ( count & 0x0F );
162 return count * 2;
166 /* uses valid->extra3 (pointer to base table) */
168 static void
169 otv_ValueRecord_validate( FT_Bytes table,
170 FT_UInt format,
171 OTV_Validator valid )
173 FT_Bytes p = table;
174 FT_UInt count;
176 #ifdef FT_DEBUG_LEVEL_TRACE
177 FT_Int loop;
178 FT_ULong res = 0;
181 OTV_NAME_ENTER( "ValueRecord" );
183 /* display `format' in dual representation */
184 for ( loop = 7; loop >= 0; loop-- )
186 res <<= 4;
187 res += ( format >> loop ) & 1;
190 OTV_TRACE(( " (format 0b%08lx)\n", res ));
191 #endif
193 if ( format >= 0x100 )
194 FT_INVALID_FORMAT;
196 for ( count = 4; count > 0; count-- )
198 if ( format & 1 )
200 /* XPlacement, YPlacement, XAdvance, YAdvance */
201 OTV_LIMIT_CHECK( 2 );
202 p += 2;
205 format >>= 1;
208 for ( count = 4; count > 0; count-- )
210 if ( format & 1 )
212 FT_PtrDist table_size;
214 OTV_OPTIONAL_TABLE( device );
217 /* XPlaDevice, YPlaDevice, XAdvDevice, YAdvDevice */
218 OTV_LIMIT_CHECK( 2 );
219 OTV_OPTIONAL_OFFSET( device );
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 */
225 table_size = p - valid->extra3;
227 OTV_SIZE_CHECK( device );
228 if ( device )
229 otv_Device_validate( valid->extra3 + device, valid );
231 format >>= 1;
234 OTV_EXIT;
238 /*************************************************************************/
239 /*************************************************************************/
240 /***** *****/
241 /***** ANCHORS *****/
242 /***** *****/
243 /*************************************************************************/
244 /*************************************************************************/
246 static void
247 otv_Anchor_validate( FT_Bytes table,
248 OTV_Validator valid )
250 FT_Bytes p = table;
251 FT_UInt AnchorFormat;
254 OTV_NAME_ENTER( "Anchor");
256 OTV_LIMIT_CHECK( 6 );
257 AnchorFormat = FT_NEXT_USHORT( p );
259 OTV_TRACE(( " (format %d)\n", AnchorFormat ));
261 p += 4; /* skip XCoordinate and YCoordinate */
263 switch ( AnchorFormat )
265 case 1:
266 break;
268 case 2:
269 OTV_LIMIT_CHECK( 2 ); /* AnchorPoint */
270 break;
272 case 3:
274 FT_UInt table_size;
276 OTV_OPTIONAL_TABLE( XDeviceTable );
277 OTV_OPTIONAL_TABLE( YDeviceTable );
280 OTV_LIMIT_CHECK( 4 );
281 OTV_OPTIONAL_OFFSET( XDeviceTable );
282 OTV_OPTIONAL_OFFSET( YDeviceTable );
284 table_size = 6 + 4;
286 OTV_SIZE_CHECK( XDeviceTable );
287 if ( XDeviceTable )
288 otv_Device_validate( table + XDeviceTable, valid );
290 OTV_SIZE_CHECK( YDeviceTable );
291 if ( YDeviceTable )
292 otv_Device_validate( table + YDeviceTable, valid );
294 break;
296 default:
297 FT_INVALID_FORMAT;
300 OTV_EXIT;
304 /*************************************************************************/
305 /*************************************************************************/
306 /***** *****/
307 /***** MARK ARRAYS *****/
308 /***** *****/
309 /*************************************************************************/
310 /*************************************************************************/
312 static void
313 otv_MarkArray_validate( FT_Bytes table,
314 OTV_Validator valid )
316 FT_Bytes p = table;
317 FT_UInt MarkCount;
320 OTV_NAME_ENTER( "MarkArray" );
322 OTV_LIMIT_CHECK( 2 );
323 MarkCount = FT_NEXT_USHORT( p );
325 OTV_TRACE(( " (MarkCount = %d)\n", MarkCount ));
327 OTV_LIMIT_CHECK( MarkCount * 4 );
329 /* MarkRecord */
330 for ( ; MarkCount > 0; MarkCount-- )
332 p += 2; /* skip Class */
333 /* MarkAnchor */
334 otv_Anchor_validate( table + FT_NEXT_USHORT( p ), valid );
337 OTV_EXIT;
341 /*************************************************************************/
342 /*************************************************************************/
343 /***** *****/
344 /***** GPOS LOOKUP TYPE 1 *****/
345 /***** *****/
346 /*************************************************************************/
347 /*************************************************************************/
349 /* sets valid->extra3 (pointer to base table) */
351 static void
352 otv_SinglePos_validate( FT_Bytes table,
353 OTV_Validator valid )
355 FT_Bytes p = table;
356 FT_UInt PosFormat;
359 OTV_NAME_ENTER( "SinglePos" );
361 OTV_LIMIT_CHECK( 2 );
362 PosFormat = FT_NEXT_USHORT( p );
364 OTV_TRACE(( " (format %d)\n", PosFormat ));
366 valid->extra3 = table;
368 switch ( PosFormat )
370 case 1: /* SinglePosFormat1 */
372 FT_UInt Coverage, ValueFormat;
375 OTV_LIMIT_CHECK( 4 );
376 Coverage = FT_NEXT_USHORT( p );
377 ValueFormat = FT_NEXT_USHORT( p );
379 otv_Coverage_validate( table + Coverage, valid, -1 );
380 otv_ValueRecord_validate( p, ValueFormat, valid ); /* Value */
382 break;
384 case 2: /* SinglePosFormat2 */
386 FT_UInt Coverage, ValueFormat, ValueCount, len_value;
389 OTV_LIMIT_CHECK( 6 );
390 Coverage = FT_NEXT_USHORT( p );
391 ValueFormat = FT_NEXT_USHORT( p );
392 ValueCount = FT_NEXT_USHORT( p );
394 OTV_TRACE(( " (ValueCount = %d)\n", ValueCount ));
396 len_value = otv_value_length( ValueFormat );
398 otv_Coverage_validate( table + Coverage, valid, ValueCount );
400 OTV_LIMIT_CHECK( ValueCount * len_value );
402 /* Value */
403 for ( ; ValueCount > 0; ValueCount-- )
405 otv_ValueRecord_validate( p, ValueFormat, valid );
406 p += len_value;
409 break;
411 default:
412 FT_INVALID_FORMAT;
415 OTV_EXIT;
419 /*************************************************************************/
420 /*************************************************************************/
421 /***** *****/
422 /***** GPOS LOOKUP TYPE 2 *****/
423 /***** *****/
424 /*************************************************************************/
425 /*************************************************************************/
427 static void
428 otv_PairSet_validate( FT_Bytes table,
429 FT_UInt format1,
430 FT_UInt format2,
431 OTV_Validator valid )
433 FT_Bytes p = table;
434 FT_UInt value_len1, value_len2, PairValueCount;
437 OTV_NAME_ENTER( "PairSet" );
439 OTV_LIMIT_CHECK( 2 );
440 PairValueCount = FT_NEXT_USHORT( p );
442 OTV_TRACE(( " (PairValueCount = %d)\n", PairValueCount ));
444 value_len1 = otv_value_length( format1 );
445 value_len2 = otv_value_length( format2 );
447 OTV_LIMIT_CHECK( PairValueCount * ( value_len1 + value_len2 + 2 ) );
449 /* PairValueRecord */
450 for ( ; PairValueCount > 0; PairValueCount-- )
452 p += 2; /* skip SecondGlyph */
454 if ( format1 )
455 otv_ValueRecord_validate( p, format1, valid ); /* Value1 */
456 p += value_len1;
458 if ( format2 )
459 otv_ValueRecord_validate( p, format2, valid ); /* Value2 */
460 p += value_len2;
463 OTV_EXIT;
467 /* sets valid->extra3 (pointer to base table) */
469 static void
470 otv_PairPos_validate( FT_Bytes table,
471 OTV_Validator valid )
473 FT_Bytes p = table;
474 FT_UInt PosFormat;
477 OTV_NAME_ENTER( "PairPos" );
479 OTV_LIMIT_CHECK( 2 );
480 PosFormat = FT_NEXT_USHORT( p );
482 OTV_TRACE(( " (format %d)\n", PosFormat ));
484 valid->extra3 = table;
486 switch ( PosFormat )
488 case 1: /* PairPosFormat1 */
490 FT_UInt Coverage, ValueFormat1, ValueFormat2, PairSetCount;
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 );
499 OTV_TRACE(( " (PairSetCount = %d)\n", PairSetCount ));
501 otv_Coverage_validate( table + Coverage, valid, -1 );
503 OTV_LIMIT_CHECK( PairSetCount * 2 );
505 /* PairSetOffset */
506 for ( ; PairSetCount > 0; PairSetCount-- )
507 otv_PairSet_validate( table + FT_NEXT_USHORT( p ),
508 ValueFormat1, ValueFormat2, valid );
510 break;
512 case 2: /* PairPosFormat2 */
514 FT_UInt Coverage, ValueFormat1, ValueFormat2, ClassDef1, ClassDef2;
515 FT_UInt ClassCount1, ClassCount2, len_value1, len_value2, count;
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 );
527 OTV_TRACE(( " (ClassCount1 = %d)\n", ClassCount1 ));
528 OTV_TRACE(( " (ClassCount2 = %d)\n", ClassCount2 ));
530 len_value1 = otv_value_length( ValueFormat1 );
531 len_value2 = otv_value_length( ValueFormat2 );
533 otv_Coverage_validate( table + Coverage, valid, -1 );
534 otv_ClassDef_validate( table + ClassDef1, valid );
535 otv_ClassDef_validate( table + ClassDef2, valid );
537 OTV_LIMIT_CHECK( ClassCount1 * ClassCount2 *
538 ( len_value1 + len_value2 ) );
540 /* Class1Record */
541 for ( ; ClassCount1 > 0; ClassCount1-- )
543 /* Class2Record */
544 for ( count = ClassCount2; count > 0; count-- )
546 if ( ValueFormat1 )
547 /* Value1 */
548 otv_ValueRecord_validate( p, ValueFormat1, valid );
549 p += len_value1;
551 if ( ValueFormat2 )
552 /* Value2 */
553 otv_ValueRecord_validate( p, ValueFormat2, valid );
554 p += len_value2;
558 break;
560 default:
561 FT_INVALID_FORMAT;
564 OTV_EXIT;
568 /*************************************************************************/
569 /*************************************************************************/
570 /***** *****/
571 /***** GPOS LOOKUP TYPE 3 *****/
572 /***** *****/
573 /*************************************************************************/
574 /*************************************************************************/
576 static void
577 otv_CursivePos_validate( FT_Bytes table,
578 OTV_Validator valid )
580 FT_Bytes p = table;
581 FT_UInt PosFormat;
584 OTV_NAME_ENTER( "CursivePos" );
586 OTV_LIMIT_CHECK( 2 );
587 PosFormat = FT_NEXT_USHORT( p );
589 OTV_TRACE(( " (format %d)\n", PosFormat ));
591 switch ( PosFormat )
593 case 1: /* CursivePosFormat1 */
595 FT_UInt table_size;
596 FT_UInt Coverage, EntryExitCount;
598 OTV_OPTIONAL_TABLE( EntryAnchor );
599 OTV_OPTIONAL_TABLE( ExitAnchor );
602 OTV_LIMIT_CHECK( 4 );
603 Coverage = FT_NEXT_USHORT( p );
604 EntryExitCount = FT_NEXT_USHORT( p );
606 OTV_TRACE(( " (EntryExitCount = %d)\n", EntryExitCount ));
608 otv_Coverage_validate( table + Coverage, valid, EntryExitCount );
610 OTV_LIMIT_CHECK( EntryExitCount * 4 );
612 table_size = EntryExitCount * 4 + 4;
614 /* EntryExitRecord */
615 for ( ; EntryExitCount > 0; EntryExitCount-- )
617 OTV_OPTIONAL_OFFSET( EntryAnchor );
618 OTV_OPTIONAL_OFFSET( ExitAnchor );
620 OTV_SIZE_CHECK( EntryAnchor );
621 if ( EntryAnchor )
622 otv_Anchor_validate( table + EntryAnchor, valid );
624 OTV_SIZE_CHECK( ExitAnchor );
625 if ( ExitAnchor )
626 otv_Anchor_validate( table + ExitAnchor, valid );
629 break;
631 default:
632 FT_INVALID_FORMAT;
635 OTV_EXIT;
639 /*************************************************************************/
640 /*************************************************************************/
641 /***** *****/
642 /***** GPOS LOOKUP TYPE 4 *****/
643 /***** *****/
644 /*************************************************************************/
645 /*************************************************************************/
647 /* UNDOCUMENTED (in OpenType 1.5): */
648 /* BaseRecord tables can contain NULL pointers. */
650 /* sets valid->extra2 (1) */
652 static void
653 otv_MarkBasePos_validate( FT_Bytes table,
654 OTV_Validator valid )
656 FT_Bytes p = table;
657 FT_UInt PosFormat;
660 OTV_NAME_ENTER( "MarkBasePos" );
662 OTV_LIMIT_CHECK( 2 );
663 PosFormat = FT_NEXT_USHORT( p );
665 OTV_TRACE(( " (format %d)\n", PosFormat ));
667 switch ( PosFormat )
669 case 1:
670 valid->extra2 = 1;
671 OTV_NEST2( MarkBasePosFormat1, BaseArray );
672 OTV_RUN( table, valid );
673 break;
675 default:
676 FT_INVALID_FORMAT;
679 OTV_EXIT;
683 /*************************************************************************/
684 /*************************************************************************/
685 /***** *****/
686 /***** GPOS LOOKUP TYPE 5 *****/
687 /***** *****/
688 /*************************************************************************/
689 /*************************************************************************/
691 /* sets valid->extra2 (1) */
693 static void
694 otv_MarkLigPos_validate( FT_Bytes table,
695 OTV_Validator valid )
697 FT_Bytes p = table;
698 FT_UInt PosFormat;
701 OTV_NAME_ENTER( "MarkLigPos" );
703 OTV_LIMIT_CHECK( 2 );
704 PosFormat = FT_NEXT_USHORT( p );
706 OTV_TRACE(( " (format %d)\n", PosFormat ));
708 switch ( PosFormat )
710 case 1:
711 valid->extra2 = 1;
712 OTV_NEST3( MarkLigPosFormat1, LigatureArray, LigatureAttach );
713 OTV_RUN( table, valid );
714 break;
716 default:
717 FT_INVALID_FORMAT;
720 OTV_EXIT;
724 /*************************************************************************/
725 /*************************************************************************/
726 /***** *****/
727 /***** GPOS LOOKUP TYPE 6 *****/
728 /***** *****/
729 /*************************************************************************/
730 /*************************************************************************/
732 /* sets valid->extra2 (0) */
734 static void
735 otv_MarkMarkPos_validate( FT_Bytes table,
736 OTV_Validator valid )
738 FT_Bytes p = table;
739 FT_UInt PosFormat;
742 OTV_NAME_ENTER( "MarkMarkPos" );
744 OTV_LIMIT_CHECK( 2 );
745 PosFormat = FT_NEXT_USHORT( p );
747 OTV_TRACE(( " (format %d)\n", PosFormat ));
749 switch ( PosFormat )
751 case 1:
752 valid->extra2 = 0;
753 OTV_NEST2( MarkMarkPosFormat1, Mark2Array );
754 OTV_RUN( table, valid );
755 break;
757 default:
758 FT_INVALID_FORMAT;
761 OTV_EXIT;
765 /*************************************************************************/
766 /*************************************************************************/
767 /***** *****/
768 /***** GPOS LOOKUP TYPE 7 *****/
769 /***** *****/
770 /*************************************************************************/
771 /*************************************************************************/
773 /* sets valid->extra1 (lookup count) */
775 static void
776 otv_ContextPos_validate( FT_Bytes table,
777 OTV_Validator valid )
779 FT_Bytes p = table;
780 FT_UInt PosFormat;
783 OTV_NAME_ENTER( "ContextPos" );
785 OTV_LIMIT_CHECK( 2 );
786 PosFormat = FT_NEXT_USHORT( p );
788 OTV_TRACE(( " (format %d)\n", PosFormat ));
790 switch ( PosFormat )
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 */
797 valid->extra1 = valid->lookup_count;
798 OTV_NEST3( ContextPosFormat1, PosRuleSet, PosRule );
799 OTV_RUN( table, valid );
800 break;
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 */
807 OTV_NEST3( ContextPosFormat2, PosClassSet, PosClassRule );
808 OTV_RUN( table, valid );
809 break;
811 case 3:
812 OTV_NEST1( ContextPosFormat3 );
813 OTV_RUN( table, valid );
814 break;
816 default:
817 FT_INVALID_FORMAT;
820 OTV_EXIT;
824 /*************************************************************************/
825 /*************************************************************************/
826 /***** *****/
827 /***** GPOS LOOKUP TYPE 8 *****/
828 /***** *****/
829 /*************************************************************************/
830 /*************************************************************************/
832 /* sets valid->extra1 (lookup count) */
834 static void
835 otv_ChainContextPos_validate( FT_Bytes table,
836 OTV_Validator valid )
838 FT_Bytes p = table;
839 FT_UInt PosFormat;
842 OTV_NAME_ENTER( "ChainContextPos" );
844 OTV_LIMIT_CHECK( 2 );
845 PosFormat = FT_NEXT_USHORT( p );
847 OTV_TRACE(( " (format %d)\n", PosFormat ));
849 switch ( PosFormat )
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 */
856 valid->extra1 = valid->lookup_count;
857 OTV_NEST3( ChainContextPosFormat1,
858 ChainPosRuleSet, ChainPosRule );
859 OTV_RUN( table, valid );
860 break;
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 */
867 OTV_NEST3( ChainContextPosFormat2,
868 ChainPosClassSet, ChainPosClassRule );
869 OTV_RUN( table, valid );
870 break;
872 case 3:
873 OTV_NEST1( ChainContextPosFormat3 );
874 OTV_RUN( table, valid );
875 break;
877 default:
878 FT_INVALID_FORMAT;
881 OTV_EXIT;
885 /*************************************************************************/
886 /*************************************************************************/
887 /***** *****/
888 /***** GPOS LOOKUP TYPE 9 *****/
889 /***** *****/
890 /*************************************************************************/
891 /*************************************************************************/
893 /* uses valid->type_funcs */
895 static void
896 otv_ExtensionPos_validate( FT_Bytes table,
897 OTV_Validator valid )
899 FT_Bytes p = table;
900 FT_UInt PosFormat;
903 OTV_NAME_ENTER( "ExtensionPos" );
905 OTV_LIMIT_CHECK( 2 );
906 PosFormat = FT_NEXT_USHORT( p );
908 OTV_TRACE(( " (format %d)\n", PosFormat ));
910 switch ( PosFormat )
912 case 1: /* ExtensionPosFormat1 */
914 FT_UInt ExtensionLookupType;
915 FT_ULong ExtensionOffset;
916 OTV_Validate_Func validate;
919 OTV_LIMIT_CHECK( 6 );
920 ExtensionLookupType = FT_NEXT_USHORT( p );
921 ExtensionOffset = FT_NEXT_ULONG( p );
923 if ( ExtensionLookupType == 0 || ExtensionLookupType >= 9 )
924 FT_INVALID_DATA;
926 validate = valid->type_funcs[ExtensionLookupType - 1];
927 validate( table + ExtensionOffset, valid );
929 break;
931 default:
932 FT_INVALID_FORMAT;
935 OTV_EXIT;
939 static const OTV_Validate_Func otv_gpos_validate_funcs[9] =
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
953 /* sets valid->type_count */
954 /* sets valid->type_funcs */
956 FT_LOCAL_DEF( void )
957 otv_GPOS_subtable_validate( FT_Bytes table,
958 OTV_Validator valid )
960 valid->type_count = 9;
961 valid->type_funcs = (OTV_Validate_Func*)otv_gpos_validate_funcs;
963 otv_Lookup_validate( table, valid );
967 /*************************************************************************/
968 /*************************************************************************/
969 /***** *****/
970 /***** GPOS TABLE *****/
971 /***** *****/
972 /*************************************************************************/
973 /*************************************************************************/
975 /* sets valid->glyph_count */
977 FT_LOCAL_DEF( void )
978 otv_GPOS_validate( FT_Bytes table,
979 FT_UInt glyph_count,
980 FT_Validator ftvalid )
982 OTV_ValidatorRec validrec;
983 OTV_Validator valid = &validrec;
984 FT_Bytes p = table;
985 FT_UInt ScriptList, FeatureList, LookupList;
988 valid->root = ftvalid;
990 FT_TRACE3(( "validating GPOS table\n" ));
991 OTV_INIT;
993 OTV_LIMIT_CHECK( 10 );
995 if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */
996 FT_INVALID_FORMAT;
998 ScriptList = FT_NEXT_USHORT( p );
999 FeatureList = FT_NEXT_USHORT( p );
1000 LookupList = FT_NEXT_USHORT( p );
1002 valid->type_count = 9;
1003 valid->type_funcs = (OTV_Validate_Func*)otv_gpos_validate_funcs;
1004 valid->glyph_count = glyph_count;
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 );
1013 FT_TRACE4(( "\n" ));
1017 /* END */