00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "otvalid.h"
00020 #include "otvcommn.h"
00021 #include "otvgpos.h"
00022
00023
00024
00025
00026
00027
00028
00029
00030 #undef FT_COMPONENT
00031 #define FT_COMPONENT trace_otvgpos
00032
00033
00034 static void
00035 otv_Anchor_validate( FT_Bytes table,
00036 OTV_Validator valid );
00037
00038 static void
00039 otv_MarkArray_validate( FT_Bytes table,
00040 OTV_Validator valid );
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #define BaseArrayFunc otv_x_sxy
00052 #define LigatureAttachFunc otv_x_sxy
00053 #define Mark2ArrayFunc otv_x_sxy
00054
00055
00056
00057
00058 static void
00059 otv_x_sxy( FT_Bytes table,
00060 OTV_Validator valid )
00061 {
00062 FT_Bytes p = table;
00063 FT_UInt Count, count1, table_size;
00064
00065
00066 OTV_ENTER;
00067
00068 OTV_LIMIT_CHECK( 2 );
00069
00070 Count = FT_NEXT_USHORT( p );
00071
00072 OTV_TRACE(( " (Count = %d)\n", Count ));
00073
00074 OTV_LIMIT_CHECK( Count * valid->extra1 * 2 );
00075
00076 table_size = Count * valid->extra1 * 2 + 2;
00077
00078 for ( ; Count > 0; Count-- )
00079 for ( count1 = valid->extra1; count1 > 0; count1-- )
00080 {
00081 OTV_OPTIONAL_TABLE( anchor_offset );
00082
00083
00084 OTV_OPTIONAL_OFFSET( anchor_offset );
00085
00086 if ( valid->extra2 )
00087 {
00088 OTV_SIZE_CHECK( anchor_offset );
00089 if ( anchor_offset )
00090 otv_Anchor_validate( table + anchor_offset, valid );
00091 }
00092 else
00093 otv_Anchor_validate( table + anchor_offset, valid );
00094 }
00095
00096 OTV_EXIT;
00097 }
00098
00099
00100 #define MarkBasePosFormat1Func otv_u_O_O_u_O_O
00101 #define MarkLigPosFormat1Func otv_u_O_O_u_O_O
00102 #define MarkMarkPosFormat1Func otv_u_O_O_u_O_O
00103
00104
00105
00106 static void
00107 otv_u_O_O_u_O_O( FT_Bytes table,
00108 OTV_Validator valid )
00109 {
00110 FT_Bytes p = table;
00111 FT_UInt Coverage1, Coverage2, ClassCount;
00112 FT_UInt Array1, Array2;
00113 OTV_Validate_Func func;
00114
00115
00116 OTV_ENTER;
00117
00118 p += 2;
00119
00120 OTV_LIMIT_CHECK( 10 );
00121 Coverage1 = FT_NEXT_USHORT( p );
00122 Coverage2 = FT_NEXT_USHORT( p );
00123 ClassCount = FT_NEXT_USHORT( p );
00124 Array1 = FT_NEXT_USHORT( p );
00125 Array2 = FT_NEXT_USHORT( p );
00126
00127 otv_Coverage_validate( table + Coverage1, valid, -1 );
00128 otv_Coverage_validate( table + Coverage2, valid, -1 );
00129
00130 otv_MarkArray_validate( table + Array1, valid );
00131
00132 valid->nesting_level++;
00133 func = valid->func[valid->nesting_level];
00134 valid->extra1 = ClassCount;
00135
00136 func( table + Array2, valid );
00137
00138 valid->nesting_level--;
00139
00140 OTV_EXIT;
00141 }
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 static FT_UInt
00153 otv_value_length( FT_UInt format )
00154 {
00155 FT_UInt count;
00156
00157
00158 count = ( ( format & 0xAA ) >> 1 ) + ( format & 0x55 );
00159 count = ( ( count & 0xCC ) >> 2 ) + ( count & 0x33 );
00160 count = ( ( count & 0xF0 ) >> 4 ) + ( count & 0x0F );
00161
00162 return count * 2;
00163 }
00164
00165
00166
00167
00168 static void
00169 otv_ValueRecord_validate( FT_Bytes table,
00170 FT_UInt format,
00171 OTV_Validator valid )
00172 {
00173 FT_Bytes p = table;
00174 FT_UInt count;
00175
00176 #ifdef FT_DEBUG_LEVEL_TRACE
00177 FT_Int loop;
00178 FT_ULong res = 0;
00179
00180
00181 OTV_NAME_ENTER( "ValueRecord" );
00182
00183
00184 for ( loop = 7; loop >= 0; loop-- )
00185 {
00186 res <<= 4;
00187 res += ( format >> loop ) & 1;
00188 }
00189
00190 OTV_TRACE(( " (format 0b%08lx)\n", res ));
00191 #endif
00192
00193 if ( format >= 0x100 )
00194 FT_INVALID_FORMAT;
00195
00196 for ( count = 4; count > 0; count-- )
00197 {
00198 if ( format & 1 )
00199 {
00200
00201 OTV_LIMIT_CHECK( 2 );
00202 p += 2;
00203 }
00204
00205 format >>= 1;
00206 }
00207
00208 for ( count = 4; count > 0; count-- )
00209 {
00210 if ( format & 1 )
00211 {
00212 FT_PtrDist table_size;
00213
00214 OTV_OPTIONAL_TABLE( device );
00215
00216
00217
00218 OTV_LIMIT_CHECK( 2 );
00219 OTV_OPTIONAL_OFFSET( device );
00220
00221
00222
00223
00224
00225 table_size = p - valid->extra3;
00226
00227 OTV_SIZE_CHECK( device );
00228 if ( device )
00229 otv_Device_validate( valid->extra3 + device, valid );
00230 }
00231 format >>= 1;
00232 }
00233
00234 OTV_EXIT;
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 static void
00247 otv_Anchor_validate( FT_Bytes table,
00248 OTV_Validator valid )
00249 {
00250 FT_Bytes p = table;
00251 FT_UInt AnchorFormat;
00252
00253
00254 OTV_NAME_ENTER( "Anchor");
00255
00256 OTV_LIMIT_CHECK( 6 );
00257 AnchorFormat = FT_NEXT_USHORT( p );
00258
00259 OTV_TRACE(( " (format %d)\n", AnchorFormat ));
00260
00261 p += 4;
00262
00263 switch ( AnchorFormat )
00264 {
00265 case 1:
00266 break;
00267
00268 case 2:
00269 OTV_LIMIT_CHECK( 2 );
00270 break;
00271
00272 case 3:
00273 {
00274 FT_UInt table_size;
00275
00276 OTV_OPTIONAL_TABLE( XDeviceTable );
00277 OTV_OPTIONAL_TABLE( YDeviceTable );
00278
00279
00280 OTV_LIMIT_CHECK( 4 );
00281 OTV_OPTIONAL_OFFSET( XDeviceTable );
00282 OTV_OPTIONAL_OFFSET( YDeviceTable );
00283
00284 table_size = 6 + 4;
00285
00286 OTV_SIZE_CHECK( XDeviceTable );
00287 if ( XDeviceTable )
00288 otv_Device_validate( table + XDeviceTable, valid );
00289
00290 OTV_SIZE_CHECK( YDeviceTable );
00291 if ( YDeviceTable )
00292 otv_Device_validate( table + YDeviceTable, valid );
00293 }
00294 break;
00295
00296 default:
00297 FT_INVALID_FORMAT;
00298 }
00299
00300 OTV_EXIT;
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 static void
00313 otv_MarkArray_validate( FT_Bytes table,
00314 OTV_Validator valid )
00315 {
00316 FT_Bytes p = table;
00317 FT_UInt MarkCount;
00318
00319
00320 OTV_NAME_ENTER( "MarkArray" );
00321
00322 OTV_LIMIT_CHECK( 2 );
00323 MarkCount = FT_NEXT_USHORT( p );
00324
00325 OTV_TRACE(( " (MarkCount = %d)\n", MarkCount ));
00326
00327 OTV_LIMIT_CHECK( MarkCount * 4 );
00328
00329
00330 for ( ; MarkCount > 0; MarkCount-- )
00331 {
00332 p += 2;
00333
00334 otv_Anchor_validate( table + FT_NEXT_USHORT( p ), valid );
00335 }
00336
00337 OTV_EXIT;
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 static void
00352 otv_SinglePos_validate( FT_Bytes table,
00353 OTV_Validator valid )
00354 {
00355 FT_Bytes p = table;
00356 FT_UInt PosFormat;
00357
00358
00359 OTV_NAME_ENTER( "SinglePos" );
00360
00361 OTV_LIMIT_CHECK( 2 );
00362 PosFormat = FT_NEXT_USHORT( p );
00363
00364 OTV_TRACE(( " (format %d)\n", PosFormat ));
00365
00366 valid->extra3 = table;
00367
00368 switch ( PosFormat )
00369 {
00370 case 1:
00371 {
00372 FT_UInt Coverage, ValueFormat;
00373
00374
00375 OTV_LIMIT_CHECK( 4 );
00376 Coverage = FT_NEXT_USHORT( p );
00377 ValueFormat = FT_NEXT_USHORT( p );
00378
00379 otv_Coverage_validate( table + Coverage, valid, -1 );
00380 otv_ValueRecord_validate( p, ValueFormat, valid );
00381 }
00382 break;
00383
00384 case 2:
00385 {
00386 FT_UInt Coverage, ValueFormat, ValueCount, len_value;
00387
00388
00389 OTV_LIMIT_CHECK( 6 );
00390 Coverage = FT_NEXT_USHORT( p );
00391 ValueFormat = FT_NEXT_USHORT( p );
00392 ValueCount = FT_NEXT_USHORT( p );
00393
00394 OTV_TRACE(( " (ValueCount = %d)\n", ValueCount ));
00395
00396 len_value = otv_value_length( ValueFormat );
00397
00398 otv_Coverage_validate( table + Coverage, valid, ValueCount );
00399
00400 OTV_LIMIT_CHECK( ValueCount * len_value );
00401
00402
00403 for ( ; ValueCount > 0; ValueCount-- )
00404 {
00405 otv_ValueRecord_validate( p, ValueFormat, valid );
00406 p += len_value;
00407 }
00408 }
00409 break;
00410
00411 default:
00412 FT_INVALID_FORMAT;
00413 }
00414
00415 OTV_EXIT;
00416 }
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 static void
00428 otv_PairSet_validate( FT_Bytes table,
00429 FT_UInt format1,
00430 FT_UInt format2,
00431 OTV_Validator valid )
00432 {
00433 FT_Bytes p = table;
00434 FT_UInt value_len1, value_len2, PairValueCount;
00435
00436
00437 OTV_NAME_ENTER( "PairSet" );
00438
00439 OTV_LIMIT_CHECK( 2 );
00440 PairValueCount = FT_NEXT_USHORT( p );
00441
00442 OTV_TRACE(( " (PairValueCount = %d)\n", PairValueCount ));
00443
00444 value_len1 = otv_value_length( format1 );
00445 value_len2 = otv_value_length( format2 );
00446
00447 OTV_LIMIT_CHECK( PairValueCount * ( value_len1 + value_len2 + 2 ) );
00448
00449
00450 for ( ; PairValueCount > 0; PairValueCount-- )
00451 {
00452 p += 2;
00453
00454 if ( format1 )
00455 otv_ValueRecord_validate( p, format1, valid );
00456 p += value_len1;
00457
00458 if ( format2 )
00459 otv_ValueRecord_validate( p, format2, valid );
00460 p += value_len2;
00461 }
00462
00463 OTV_EXIT;
00464 }
00465
00466
00467
00468
00469 static void
00470 otv_PairPos_validate( FT_Bytes table,
00471 OTV_Validator valid )
00472 {
00473 FT_Bytes p = table;
00474 FT_UInt PosFormat;
00475
00476
00477 OTV_NAME_ENTER( "PairPos" );
00478
00479 OTV_LIMIT_CHECK( 2 );
00480 PosFormat = FT_NEXT_USHORT( p );
00481
00482 OTV_TRACE(( " (format %d)\n", PosFormat ));
00483
00484 valid->extra3 = table;
00485
00486 switch ( PosFormat )
00487 {
00488 case 1:
00489 {
00490 FT_UInt Coverage, ValueFormat1, ValueFormat2, PairSetCount;
00491
00492
00493 OTV_LIMIT_CHECK( 8 );
00494 Coverage = FT_NEXT_USHORT( p );
00495 ValueFormat1 = FT_NEXT_USHORT( p );
00496 ValueFormat2 = FT_NEXT_USHORT( p );
00497 PairSetCount = FT_NEXT_USHORT( p );
00498
00499 OTV_TRACE(( " (PairSetCount = %d)\n", PairSetCount ));
00500
00501 otv_Coverage_validate( table + Coverage, valid, -1 );
00502
00503 OTV_LIMIT_CHECK( PairSetCount * 2 );
00504
00505
00506 for ( ; PairSetCount > 0; PairSetCount-- )
00507 otv_PairSet_validate( table + FT_NEXT_USHORT( p ),
00508 ValueFormat1, ValueFormat2, valid );
00509 }
00510 break;
00511
00512 case 2:
00513 {
00514 FT_UInt Coverage, ValueFormat1, ValueFormat2, ClassDef1, ClassDef2;
00515 FT_UInt ClassCount1, ClassCount2, len_value1, len_value2, count;
00516
00517
00518 OTV_LIMIT_CHECK( 14 );
00519 Coverage = FT_NEXT_USHORT( p );
00520 ValueFormat1 = FT_NEXT_USHORT( p );
00521 ValueFormat2 = FT_NEXT_USHORT( p );
00522 ClassDef1 = FT_NEXT_USHORT( p );
00523 ClassDef2 = FT_NEXT_USHORT( p );
00524 ClassCount1 = FT_NEXT_USHORT( p );
00525 ClassCount2 = FT_NEXT_USHORT( p );
00526
00527 OTV_TRACE(( " (ClassCount1 = %d)\n", ClassCount1 ));
00528 OTV_TRACE(( " (ClassCount2 = %d)\n", ClassCount2 ));
00529
00530 len_value1 = otv_value_length( ValueFormat1 );
00531 len_value2 = otv_value_length( ValueFormat2 );
00532
00533 otv_Coverage_validate( table + Coverage, valid, -1 );
00534 otv_ClassDef_validate( table + ClassDef1, valid );
00535 otv_ClassDef_validate( table + ClassDef2, valid );
00536
00537 OTV_LIMIT_CHECK( ClassCount1 * ClassCount2 *
00538 ( len_value1 + len_value2 ) );
00539
00540
00541 for ( ; ClassCount1 > 0; ClassCount1-- )
00542 {
00543
00544 for ( count = ClassCount2; count > 0; count-- )
00545 {
00546 if ( ValueFormat1 )
00547
00548 otv_ValueRecord_validate( p, ValueFormat1, valid );
00549 p += len_value1;
00550
00551 if ( ValueFormat2 )
00552
00553 otv_ValueRecord_validate( p, ValueFormat2, valid );
00554 p += len_value2;
00555 }
00556 }
00557 }
00558 break;
00559
00560 default:
00561 FT_INVALID_FORMAT;
00562 }
00563
00564 OTV_EXIT;
00565 }
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 static void
00577 otv_CursivePos_validate( FT_Bytes table,
00578 OTV_Validator valid )
00579 {
00580 FT_Bytes p = table;
00581 FT_UInt PosFormat;
00582
00583
00584 OTV_NAME_ENTER( "CursivePos" );
00585
00586 OTV_LIMIT_CHECK( 2 );
00587 PosFormat = FT_NEXT_USHORT( p );
00588
00589 OTV_TRACE(( " (format %d)\n", PosFormat ));
00590
00591 switch ( PosFormat )
00592 {
00593 case 1:
00594 {
00595 FT_UInt table_size;
00596 FT_UInt Coverage, EntryExitCount;
00597
00598 OTV_OPTIONAL_TABLE( EntryAnchor );
00599 OTV_OPTIONAL_TABLE( ExitAnchor );
00600
00601
00602 OTV_LIMIT_CHECK( 4 );
00603 Coverage = FT_NEXT_USHORT( p );
00604 EntryExitCount = FT_NEXT_USHORT( p );
00605
00606 OTV_TRACE(( " (EntryExitCount = %d)\n", EntryExitCount ));
00607
00608 otv_Coverage_validate( table + Coverage, valid, EntryExitCount );
00609
00610 OTV_LIMIT_CHECK( EntryExitCount * 4 );
00611
00612 table_size = EntryExitCount * 4 + 4;
00613
00614
00615 for ( ; EntryExitCount > 0; EntryExitCount-- )
00616 {
00617 OTV_OPTIONAL_OFFSET( EntryAnchor );
00618 OTV_OPTIONAL_OFFSET( ExitAnchor );
00619
00620 OTV_SIZE_CHECK( EntryAnchor );
00621 if ( EntryAnchor )
00622 otv_Anchor_validate( table + EntryAnchor, valid );
00623
00624 OTV_SIZE_CHECK( ExitAnchor );
00625 if ( ExitAnchor )
00626 otv_Anchor_validate( table + ExitAnchor, valid );
00627 }
00628 }
00629 break;
00630
00631 default:
00632 FT_INVALID_FORMAT;
00633 }
00634
00635 OTV_EXIT;
00636 }
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 static void
00653 otv_MarkBasePos_validate( FT_Bytes table,
00654 OTV_Validator valid )
00655 {
00656 FT_Bytes p = table;
00657 FT_UInt PosFormat;
00658
00659
00660 OTV_NAME_ENTER( "MarkBasePos" );
00661
00662 OTV_LIMIT_CHECK( 2 );
00663 PosFormat = FT_NEXT_USHORT( p );
00664
00665 OTV_TRACE(( " (format %d)\n", PosFormat ));
00666
00667 switch ( PosFormat )
00668 {
00669 case 1:
00670 valid->extra2 = 1;
00671 OTV_NEST2( MarkBasePosFormat1, BaseArray );
00672 OTV_RUN( table, valid );
00673 break;
00674
00675 default:
00676 FT_INVALID_FORMAT;
00677 }
00678
00679 OTV_EXIT;
00680 }
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693 static void
00694 otv_MarkLigPos_validate( FT_Bytes table,
00695 OTV_Validator valid )
00696 {
00697 FT_Bytes p = table;
00698 FT_UInt PosFormat;
00699
00700
00701 OTV_NAME_ENTER( "MarkLigPos" );
00702
00703 OTV_LIMIT_CHECK( 2 );
00704 PosFormat = FT_NEXT_USHORT( p );
00705
00706 OTV_TRACE(( " (format %d)\n", PosFormat ));
00707
00708 switch ( PosFormat )
00709 {
00710 case 1:
00711 valid->extra2 = 1;
00712 OTV_NEST3( MarkLigPosFormat1, LigatureArray, LigatureAttach );
00713 OTV_RUN( table, valid );
00714 break;
00715
00716 default:
00717 FT_INVALID_FORMAT;
00718 }
00719
00720 OTV_EXIT;
00721 }
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734 static void
00735 otv_MarkMarkPos_validate( FT_Bytes table,
00736 OTV_Validator valid )
00737 {
00738 FT_Bytes p = table;
00739 FT_UInt PosFormat;
00740
00741
00742 OTV_NAME_ENTER( "MarkMarkPos" );
00743
00744 OTV_LIMIT_CHECK( 2 );
00745 PosFormat = FT_NEXT_USHORT( p );
00746
00747 OTV_TRACE(( " (format %d)\n", PosFormat ));
00748
00749 switch ( PosFormat )
00750 {
00751 case 1:
00752 valid->extra2 = 0;
00753 OTV_NEST2( MarkMarkPosFormat1, Mark2Array );
00754 OTV_RUN( table, valid );
00755 break;
00756
00757 default:
00758 FT_INVALID_FORMAT;
00759 }
00760
00761 OTV_EXIT;
00762 }
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775 static void
00776 otv_ContextPos_validate( FT_Bytes table,
00777 OTV_Validator valid )
00778 {
00779 FT_Bytes p = table;
00780 FT_UInt PosFormat;
00781
00782
00783 OTV_NAME_ENTER( "ContextPos" );
00784
00785 OTV_LIMIT_CHECK( 2 );
00786 PosFormat = FT_NEXT_USHORT( p );
00787
00788 OTV_TRACE(( " (format %d)\n", PosFormat ));
00789
00790 switch ( PosFormat )
00791 {
00792 case 1:
00793
00794
00795
00796
00797 valid->extra1 = valid->lookup_count;
00798 OTV_NEST3( ContextPosFormat1, PosRuleSet, PosRule );
00799 OTV_RUN( table, valid );
00800 break;
00801
00802 case 2:
00803
00804
00805
00806
00807 OTV_NEST3( ContextPosFormat2, PosClassSet, PosClassRule );
00808 OTV_RUN( table, valid );
00809 break;
00810
00811 case 3:
00812 OTV_NEST1( ContextPosFormat3 );
00813 OTV_RUN( table, valid );
00814 break;
00815
00816 default:
00817 FT_INVALID_FORMAT;
00818 }
00819
00820 OTV_EXIT;
00821 }
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834 static void
00835 otv_ChainContextPos_validate( FT_Bytes table,
00836 OTV_Validator valid )
00837 {
00838 FT_Bytes p = table;
00839 FT_UInt PosFormat;
00840
00841
00842 OTV_NAME_ENTER( "ChainContextPos" );
00843
00844 OTV_LIMIT_CHECK( 2 );
00845 PosFormat = FT_NEXT_USHORT( p );
00846
00847 OTV_TRACE(( " (format %d)\n", PosFormat ));
00848
00849 switch ( PosFormat )
00850 {
00851 case 1:
00852
00853
00854
00855
00856 valid->extra1 = valid->lookup_count;
00857 OTV_NEST3( ChainContextPosFormat1,
00858 ChainPosRuleSet, ChainPosRule );
00859 OTV_RUN( table, valid );
00860 break;
00861
00862 case 2:
00863
00864
00865
00866
00867 OTV_NEST3( ChainContextPosFormat2,
00868 ChainPosClassSet, ChainPosClassRule );
00869 OTV_RUN( table, valid );
00870 break;
00871
00872 case 3:
00873 OTV_NEST1( ChainContextPosFormat3 );
00874 OTV_RUN( table, valid );
00875 break;
00876
00877 default:
00878 FT_INVALID_FORMAT;
00879 }
00880
00881 OTV_EXIT;
00882 }
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895 static void
00896 otv_ExtensionPos_validate( FT_Bytes table,
00897 OTV_Validator valid )
00898 {
00899 FT_Bytes p = table;
00900 FT_UInt PosFormat;
00901
00902
00903 OTV_NAME_ENTER( "ExtensionPos" );
00904
00905 OTV_LIMIT_CHECK( 2 );
00906 PosFormat = FT_NEXT_USHORT( p );
00907
00908 OTV_TRACE(( " (format %d)\n", PosFormat ));
00909
00910 switch ( PosFormat )
00911 {
00912 case 1:
00913 {
00914 FT_UInt ExtensionLookupType;
00915 FT_ULong ExtensionOffset;
00916 OTV_Validate_Func validate;
00917
00918
00919 OTV_LIMIT_CHECK( 6 );
00920 ExtensionLookupType = FT_NEXT_USHORT( p );
00921 ExtensionOffset = FT_NEXT_ULONG( p );
00922
00923 if ( ExtensionLookupType == 0 || ExtensionLookupType >= 9 )
00924 FT_INVALID_DATA;
00925
00926 validate = valid->type_funcs[ExtensionLookupType - 1];
00927 validate( table + ExtensionOffset, valid );
00928 }
00929 break;
00930
00931 default:
00932 FT_INVALID_FORMAT;
00933 }
00934
00935 OTV_EXIT;
00936 }
00937
00938
00939 static const OTV_Validate_Func otv_gpos_validate_funcs[9] =
00940 {
00941 otv_SinglePos_validate,
00942 otv_PairPos_validate,
00943 otv_CursivePos_validate,
00944 otv_MarkBasePos_validate,
00945 otv_MarkLigPos_validate,
00946 otv_MarkMarkPos_validate,
00947 otv_ContextPos_validate,
00948 otv_ChainContextPos_validate,
00949 otv_ExtensionPos_validate
00950 };
00951
00952
00953
00954
00955
00956 FT_LOCAL_DEF( void )
00957 otv_GPOS_subtable_validate( FT_Bytes table,
00958 OTV_Validator valid )
00959 {
00960 valid->type_count = 9;
00961 valid->type_funcs = (OTV_Validate_Func*)otv_gpos_validate_funcs;
00962
00963 otv_Lookup_validate( table, valid );
00964 }
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977 FT_LOCAL_DEF( void )
00978 otv_GPOS_validate( FT_Bytes table,
00979 FT_UInt glyph_count,
00980 FT_Validator ftvalid )
00981 {
00982 OTV_ValidatorRec validrec;
00983 OTV_Validator valid = &validrec;
00984 FT_Bytes p = table;
00985 FT_UInt ScriptList, FeatureList, LookupList;
00986
00987
00988 valid->root = ftvalid;
00989
00990 FT_TRACE3(( "validating GPOS table\n" ));
00991 OTV_INIT;
00992
00993 OTV_LIMIT_CHECK( 10 );
00994
00995 if ( FT_NEXT_ULONG( p ) != 0x10000UL )
00996 FT_INVALID_FORMAT;
00997
00998 ScriptList = FT_NEXT_USHORT( p );
00999 FeatureList = FT_NEXT_USHORT( p );
01000 LookupList = FT_NEXT_USHORT( p );
01001
01002 valid->type_count = 9;
01003 valid->type_funcs = (OTV_Validate_Func*)otv_gpos_validate_funcs;
01004 valid->glyph_count = glyph_count;
01005
01006 otv_LookupList_validate( table + LookupList,
01007 valid );
01008 otv_FeatureList_validate( table + FeatureList, table + LookupList,
01009 valid );
01010 otv_ScriptList_validate( table + ScriptList, table + FeatureList,
01011 valid );
01012
01013 FT_TRACE4(( "\n" ));
01014 }
01015
01016
01017