38#define FT_COMPONENT gxvcommon
50 gxv_compare_ushort_offset(
const void* a,
53 return *(FT_UShort*)a - *(FT_UShort*)b;
58 gxv_set_length_by_ushort_offset( FT_UShort* offset,
63 GXV_Validator gxvalid )
68 for ( i = 0; i < nmemb; i++ )
71 for ( i = 0; i < nmemb; i++ )
75 ft_qsort( buff, ( nmemb + 1 ),
sizeof ( FT_UShort ),
76 gxv_compare_ushort_offset );
78 if ( buff[nmemb] > limit )
81 for ( i = 0; i < nmemb; i++ )
86 for ( j = 0; j < nmemb; j++ )
87 if ( buff[j] == offset[i] )
93 *(length[i]) = (FT_UShort)( buff[j + 1] - buff[j] );
95 if ( 0 != offset[i] && 0 == *(length[i]) )
109 FT_COMPARE_DEF(
int )
110 gxv_compare_ulong_offset(
const void* a,
113 FT_ULong a_ = *(FT_ULong*)a;
114 FT_ULong b_ = *(FT_ULong*)b;
127 gxv_set_length_by_ulong_offset( FT_ULong* offset,
132 GXV_Validator gxvalid)
137 for ( i = 0; i < nmemb; i++ )
140 for ( i = 0; i < nmemb; i++ )
144 ft_qsort( buff, ( nmemb + 1 ),
sizeof ( FT_ULong ),
145 gxv_compare_ulong_offset );
147 if ( buff[nmemb] > limit )
150 for ( i = 0; i < nmemb; i++ )
155 for ( j = 0; j < nmemb; j++ )
156 if ( buff[j] == offset[i] )
162 *(length[i]) = buff[j + 1] - buff[j];
164 if ( 0 != offset[i] && 0 == *(length[i]) )
180 gxv_array_getlimits_byte( FT_Bytes table,
184 GXV_Validator gxvalid )
197 GXV_LIMIT_CHECK( 1 );
198 val = FT_NEXT_BYTE( p );
200 *min = (FT_Byte)FT_MIN( *min, val );
201 *max = (FT_Byte)FT_MAX( *max, val );
204 gxvalid->subtable_length = (FT_ULong)( p - table );
209 gxv_array_getlimits_ushort( FT_Bytes table,
213 GXV_Validator gxvalid )
226 GXV_LIMIT_CHECK( 2 );
227 val = FT_NEXT_USHORT( p );
229 *min = (FT_Byte)FT_MIN( *min, val );
230 *max = (FT_Byte)FT_MAX( *max, val );
233 gxvalid->subtable_length = (FT_ULong)( p - table );
249 FT_UShort searchRange;
250 FT_UShort entrySelector;
251 FT_UShort rangeShift;
257 gxv_BinSrchHeader_check_consistency( GXV_BinSrchHeader* binSrchHeader,
258 GXV_Validator gxvalid )
260 FT_UShort searchRange;
261 FT_UShort entrySelector;
262 FT_UShort rangeShift;
265 if ( binSrchHeader->unitSize == 0 )
268 if ( binSrchHeader->nUnits == 0 )
270 if ( binSrchHeader->searchRange == 0 &&
271 binSrchHeader->entrySelector == 0 &&
272 binSrchHeader->rangeShift == 0 )
278 for ( searchRange = 1, entrySelector = 1;
279 ( searchRange * 2 ) <= binSrchHeader->nUnits &&
280 searchRange < 0x8000U;
281 searchRange *= 2, entrySelector++ )
285 searchRange = (FT_UShort)( searchRange * binSrchHeader->unitSize );
286 rangeShift = (FT_UShort)( binSrchHeader->nUnits * binSrchHeader->unitSize
289 if ( searchRange != binSrchHeader->searchRange ||
290 entrySelector != binSrchHeader->entrySelector ||
291 rangeShift != binSrchHeader->rangeShift )
293 GXV_TRACE((
"Inconsistency found in BinSrchHeader\n" ));
294 GXV_TRACE((
"originally: unitSize=%d, nUnits=%d, "
295 "searchRange=%d, entrySelector=%d, "
297 binSrchHeader->unitSize, binSrchHeader->nUnits,
298 binSrchHeader->searchRange, binSrchHeader->entrySelector,
299 binSrchHeader->rangeShift ));
300 GXV_TRACE((
"calculated: unitSize=%d, nUnits=%d, "
301 "searchRange=%d, entrySelector=%d, "
303 binSrchHeader->unitSize, binSrchHeader->nUnits,
304 searchRange, entrySelector, rangeShift ));
306 GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
327 gxv_BinSrchHeader_validate( FT_Bytes table,
329 FT_UShort* unitSize_p,
331 GXV_Validator gxvalid )
334 GXV_BinSrchHeader binSrchHeader;
337 GXV_NAME_ENTER(
"BinSrchHeader validate" );
339 if ( *unitSize_p == 0 )
341 GXV_LIMIT_CHECK( 2 );
342 binSrchHeader.unitSize = FT_NEXT_USHORT( p );
345 binSrchHeader.unitSize = *unitSize_p;
347 if ( *nUnits_p == 0 )
349 GXV_LIMIT_CHECK( 2 );
350 binSrchHeader.nUnits = FT_NEXT_USHORT( p );
353 binSrchHeader.nUnits = *nUnits_p;
355 GXV_LIMIT_CHECK( 2 + 2 + 2 );
356 binSrchHeader.searchRange = FT_NEXT_USHORT( p );
357 binSrchHeader.entrySelector = FT_NEXT_USHORT( p );
358 binSrchHeader.rangeShift = FT_NEXT_USHORT( p );
359 GXV_TRACE((
"nUnits %d\n", binSrchHeader.nUnits ));
361 gxv_BinSrchHeader_check_consistency( &binSrchHeader, gxvalid );
363 if ( *unitSize_p == 0 )
364 *unitSize_p = binSrchHeader.unitSize;
366 if ( *nUnits_p == 0 )
367 *nUnits_p = binSrchHeader.nUnits;
369 gxvalid->subtable_length = (FT_ULong)( p - table );
382#define GXV_LOOKUP_VALUE_LOAD( P, SIGNSPEC ) \
383 ( P += 2, gxv_lookup_value_load( P - 2, SIGNSPEC ) )
385 static GXV_LookupValueDesc
386 gxv_lookup_value_load( FT_Bytes p,
387 GXV_LookupValue_SignSpec signspec )
389 GXV_LookupValueDesc v;
392 if ( signspec == GXV_LOOKUPVALUE_UNSIGNED )
393 v.u = FT_NEXT_USHORT( p );
395 v.s = FT_NEXT_SHORT( p );
401#define GXV_UNITSIZE_VALIDATE( FORMAT, UNITSIZE, NUNITS, CORRECTSIZE ) \
403 if ( UNITSIZE != CORRECTSIZE ) \
405 FT_ERROR(( "unitSize=%d differs from" \
406 " expected unitSize=%d" \
407 " in LookupTable %s\n", \
408 UNITSIZE, CORRECTSIZE, FORMAT )); \
409 if ( UNITSIZE != 0 && NUNITS != 0 ) \
411 FT_ERROR(( " cannot validate anymore\n" )); \
415 FT_ERROR(( " forcibly continues\n" )); \
422 gxv_LookupTable_fmt0_validate( FT_Bytes table,
424 GXV_Validator gxvalid )
429 GXV_LookupValueDesc value;
432 GXV_NAME_ENTER(
"LookupTable format 0" );
434 GXV_LIMIT_CHECK( 2 * gxvalid->face->num_glyphs );
436 for ( i = 0; i < gxvalid->face->num_glyphs; i++ )
438 GXV_LIMIT_CHECK( 2 );
439 if ( p + 2 >= limit )
441 GXV_TRACE((
"too short, glyphs %d - %ld are missing\n",
442 i, gxvalid->face->num_glyphs ));
443 GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
447 value = GXV_LOOKUP_VALUE_LOAD( p, gxvalid->lookupval_sign );
448 gxvalid->lookupval_func( i, &value, gxvalid );
451 gxvalid->subtable_length = (FT_ULong)( p - table );
473 gxv_LookupTable_fmt2_skip_endmarkers( FT_Bytes table,
475 GXV_Validator gxvalid )
480 while ( ( p + 4 ) < gxvalid->root->limit )
482 if ( p[0] != 0xFF || p[1] != 0xFF ||
483 p[2] != 0xFF || p[3] != 0xFF )
488 gxvalid->subtable_length = (FT_ULong)( p - table );
493 gxv_LookupTable_fmt2_validate( FT_Bytes table,
495 GXV_Validator gxvalid )
504 FT_UShort firstGlyph;
505 GXV_LookupValueDesc value;
508 GXV_NAME_ENTER(
"LookupTable format 2" );
510 unitSize = nUnits = 0;
511 gxv_BinSrchHeader_validate( p, limit, &unitSize, &nUnits, gxvalid );
512 p += gxvalid->subtable_length;
514 GXV_UNITSIZE_VALIDATE(
"format2", unitSize, nUnits, 6 );
516 for ( unit = 0, gid = 0; unit < nUnits; unit++ )
518 GXV_LIMIT_CHECK( 2 + 2 + 2 );
519 lastGlyph = FT_NEXT_USHORT( p );
520 firstGlyph = FT_NEXT_USHORT( p );
521 value = GXV_LOOKUP_VALUE_LOAD( p, gxvalid->lookupval_sign );
523 gxv_glyphid_validate( firstGlyph, gxvalid );
524 gxv_glyphid_validate( lastGlyph, gxvalid );
526 if ( lastGlyph < gid )
528 GXV_TRACE((
"reverse ordered segment specification:"
529 " lastGlyph[%d]=%d < lastGlyph[%d]=%d\n",
530 unit, lastGlyph, unit - 1 , gid ));
531 GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
534 if ( lastGlyph < firstGlyph )
536 GXV_TRACE((
"reverse ordered range specification at unit %d:"
537 " lastGlyph %d < firstGlyph %d ",
538 unit, lastGlyph, firstGlyph ));
539 GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
541 if ( gxvalid->root->level == FT_VALIDATE_TIGHT )
544 FT_TRACE4((
"continuing with exchanged values\n" ));
546 firstGlyph = lastGlyph;
550 for ( gid = firstGlyph; gid <= lastGlyph; gid++ )
551 gxvalid->lookupval_func( gid, &value, gxvalid );
554 gxv_LookupTable_fmt2_skip_endmarkers( p, unitSize, gxvalid );
555 p += gxvalid->subtable_length;
557 gxvalid->subtable_length = (FT_ULong)( p - table );
564 gxv_LookupTable_fmt4_validate( FT_Bytes table,
566 GXV_Validator gxvalid )
575 FT_UShort firstGlyph;
576 GXV_LookupValueDesc base_value;
577 GXV_LookupValueDesc value;
580 GXV_NAME_ENTER(
"LookupTable format 4" );
582 unitSize = nUnits = 0;
583 gxv_BinSrchHeader_validate( p, limit, &unitSize, &nUnits, gxvalid );
584 p += gxvalid->subtable_length;
586 GXV_UNITSIZE_VALIDATE(
"format4", unitSize, nUnits, 6 );
588 for ( unit = 0, gid = 0; unit < nUnits; unit++ )
590 GXV_LIMIT_CHECK( 2 + 2 );
591 lastGlyph = FT_NEXT_USHORT( p );
592 firstGlyph = FT_NEXT_USHORT( p );
594 gxv_glyphid_validate( firstGlyph, gxvalid );
595 gxv_glyphid_validate( lastGlyph, gxvalid );
597 if ( lastGlyph < gid )
599 GXV_TRACE((
"reverse ordered segment specification:"
600 " lastGlyph[%d]=%d < lastGlyph[%d]=%d\n",
601 unit, lastGlyph, unit - 1 , gid ));
602 GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
605 if ( lastGlyph < firstGlyph )
607 GXV_TRACE((
"reverse ordered range specification at unit %d:"
608 " lastGlyph %d < firstGlyph %d ",
609 unit, lastGlyph, firstGlyph ));
610 GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
612 if ( gxvalid->root->level == FT_VALIDATE_TIGHT )
615 FT_TRACE4((
"continuing with exchanged values\n" ));
617 firstGlyph = lastGlyph;
621 GXV_LIMIT_CHECK( 2 );
622 base_value = GXV_LOOKUP_VALUE_LOAD( p, GXV_LOOKUPVALUE_UNSIGNED );
624 for ( gid = firstGlyph; gid <= lastGlyph; gid++ )
626 value = gxvalid->lookupfmt4_trans( (FT_UShort)( gid - firstGlyph ),
631 gxvalid->lookupval_func( gid, &value, gxvalid );
635 gxv_LookupTable_fmt2_skip_endmarkers( p, unitSize, gxvalid );
636 p += gxvalid->subtable_length;
638 gxvalid->subtable_length = (FT_ULong)( p - table );
645 gxv_LookupTable_fmt6_skip_endmarkers( FT_Bytes table,
647 GXV_Validator gxvalid )
652 while ( p < gxvalid->root->limit )
654 if ( p[0] != 0xFF || p[1] != 0xFF )
659 gxvalid->subtable_length = (FT_ULong)( p - table );
664 gxv_LookupTable_fmt6_validate( FT_Bytes table,
666 GXV_Validator gxvalid )
670 FT_UShort prev_glyph;
675 GXV_LookupValueDesc value;
678 GXV_NAME_ENTER(
"LookupTable format 6" );
680 unitSize = nUnits = 0;
681 gxv_BinSrchHeader_validate( p, limit, &unitSize, &nUnits, gxvalid );
682 p += gxvalid->subtable_length;
684 GXV_UNITSIZE_VALIDATE(
"format6", unitSize, nUnits, 4 );
686 for ( unit = 0, prev_glyph = 0; unit < nUnits; unit++ )
688 GXV_LIMIT_CHECK( 2 + 2 );
689 glyph = FT_NEXT_USHORT( p );
690 value = GXV_LOOKUP_VALUE_LOAD( p, gxvalid->lookupval_sign );
692 if ( gxv_glyphid_validate( glyph, gxvalid ) )
693 GXV_TRACE((
" endmarker found within defined range"
694 " (entry %d < nUnits=%d)\n",
697 if ( prev_glyph > glyph )
699 GXV_TRACE((
"current gid 0x%04x < previous gid 0x%04x\n",
700 glyph, prev_glyph ));
701 GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
705 gxvalid->lookupval_func( glyph, &value, gxvalid );
708 gxv_LookupTable_fmt6_skip_endmarkers( p, unitSize, gxvalid );
709 p += gxvalid->subtable_length;
711 gxvalid->subtable_length = (FT_ULong)( p - table );
718 gxv_LookupTable_fmt8_validate( FT_Bytes table,
720 GXV_Validator gxvalid )
725 GXV_LookupValueDesc value;
726 FT_UShort firstGlyph;
727 FT_UShort glyphCount;
730 GXV_NAME_ENTER(
"LookupTable format 8" );
733 GXV_LIMIT_CHECK( 2 + 2 );
734 firstGlyph = FT_NEXT_USHORT( p );
735 glyphCount = FT_NEXT_USHORT( p );
737 gxv_glyphid_validate( firstGlyph, gxvalid );
738 gxv_glyphid_validate( (FT_UShort)( firstGlyph + glyphCount ), gxvalid );
741 for ( i = 0; i < glyphCount; i++ )
743 GXV_LIMIT_CHECK( 2 );
744 value = GXV_LOOKUP_VALUE_LOAD( p, gxvalid->lookupval_sign );
745 gxvalid->lookupval_func( (FT_UShort)( firstGlyph + i ), &value, gxvalid );
748 gxvalid->subtable_length = (FT_ULong)( p - table );
754 gxv_LookupTable_validate( FT_Bytes table,
756 GXV_Validator gxvalid )
761 GXV_Validate_Func fmt_funcs_table[] =
763 gxv_LookupTable_fmt0_validate,
765 gxv_LookupTable_fmt2_validate,
767 gxv_LookupTable_fmt4_validate,
769 gxv_LookupTable_fmt6_validate,
771 gxv_LookupTable_fmt8_validate,
774 GXV_Validate_Func func;
777 GXV_NAME_ENTER(
"LookupTable" );
780 gxvalid->lookuptbl_head = table;
783 GXV_LIMIT_CHECK( 2 );
784 format = FT_NEXT_USHORT( p );
785 GXV_TRACE((
" (format %d)\n", format ));
790 func = fmt_funcs_table[format];
794 func( p, limit, gxvalid );
795 p += gxvalid->subtable_length;
797 gxvalid->subtable_length = (FT_ULong)( p - table );
811 FT_LOCAL_DEF( FT_Int )
812 gxv_glyphid_validate( FT_UShort gid,
813 GXV_Validator gxvalid )
818 if ( gid == 0xFFFFU )
824 face = gxvalid->face;
825 if ( face->num_glyphs < gid )
827 GXV_TRACE((
" gxv_glyphid_check() gid overflow: num_glyphs %ld < %d\n",
828 face->num_glyphs, gid ));
829 GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
845 gxv_ctlPoint_validate( FT_UShort gid,
847 GXV_Validator gxvalid )
857 face = gxvalid->face;
859 error = FT_Load_Glyph( face,
861 FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM );
866 outline = glyph->outline;
867 n_points = (FT_UShort)outline.n_points;
869 if ( !( ctl_point < n_points ) )
883 gxv_sfntName_validate( FT_UShort name_index,
886 GXV_Validator gxvalid )
893 GXV_NAME_ENTER(
"sfntName" );
895 if ( name_index < min_index || max_index < name_index )
898 nnames = FT_Get_Sfnt_Name_Count( gxvalid->face );
899 for ( i = 0; i < nnames; i++ )
901 if ( FT_Get_Sfnt_Name( gxvalid->face, i, &name ) != FT_Err_Ok )
904 if ( name.name_id == name_index )
908 GXV_TRACE((
" nameIndex = %d (UNTITLED)\n", name_index ));
913 FT_TRACE1((
" nameIndex = %d (", name_index ));
914 GXV_TRACE_HEXDUMP_SFNTNAME( name );
915 FT_TRACE1((
")\n" ));
941 gxv_ClassTable_validate( FT_Bytes table,
944 FT_Byte* maxClassID_p,
945 GXV_Validator gxvalid )
948 FT_Bytes limit = table + *length_p;
949 FT_UShort firstGlyph;
953 GXV_NAME_ENTER(
"ClassTable" );
957 GXV_LIMIT_CHECK( 2 + 2 );
958 firstGlyph = FT_NEXT_USHORT( p );
959 nGlyphs = FT_NEXT_USHORT( p );
961 GXV_TRACE((
" (firstGlyph = %d, nGlyphs = %d)\n", firstGlyph, nGlyphs ));
966 gxv_glyphid_validate( (FT_UShort)( firstGlyph + nGlyphs ), gxvalid );
969 FT_Byte nGlyphInClass[256];
974 FT_MEM_ZERO( nGlyphInClass, 256 );
977 for ( i = 0; i < nGlyphs; i++ )
979 GXV_LIMIT_CHECK( 1 );
980 classID = FT_NEXT_BYTE( p );
992 if ( classID >= stateSize )
995 nGlyphInClass[classID]++;
999 *length_p = (FT_UShort)( p - table );
1002 for ( i = 0; i < stateSize; i++ )
1003 if ( ( 3 < i ) && ( nGlyphInClass[i] > 0 ) )
1004 *maxClassID_p = (FT_Byte)i;
1008 GXV_TRACE((
"Declared stateSize=0x%02x, Used maxClassID=0x%02x\n",
1009 stateSize, *maxClassID_p ));
1017 gxv_StateArray_validate( FT_Bytes table,
1018 FT_UShort* length_p,
1020 FT_UShort stateSize,
1021 FT_Byte* maxState_p,
1022 FT_Byte* maxEntry_p,
1023 GXV_Validator gxvalid )
1026 FT_Bytes limit = table + *length_p;
1030 FT_UNUSED( stateSize );
1033 GXV_NAME_ENTER(
"StateArray" );
1035 GXV_TRACE((
"parse %d bytes by stateSize=%d maxClassID=%d\n",
1036 (
int)( *length_p ), stateSize, (
int)maxClassID ));
1042 GXV_LIMIT_CHECK( ( 1 + maxClassID ) * 2 );
1048 while ( p + ( 1 + maxClassID ) <= limit )
1051 for ( clazz = 0; clazz <= maxClassID; clazz++ )
1053 entry = FT_NEXT_BYTE( p );
1054 *maxEntry_p = (FT_Byte)FT_MAX( *maxEntry_p, entry );
1057 GXV_TRACE((
"parsed: maxState=%d, maxEntry=%d\n",
1058 *maxState_p, *maxEntry_p ));
1060 *length_p = (FT_UShort)( p - table );
1069 gxv_EntryTable_validate( FT_Bytes table,
1070 FT_UShort* length_p,
1072 FT_UShort stateArray,
1073 FT_UShort stateArray_length,
1075 FT_Bytes statetable_table,
1076 FT_Bytes statetable_limit,
1077 GXV_Validator gxvalid )
1080 FT_Bytes limit = table + *length_p;
1083 FT_Int entrySize = 2 + 2 + GXV_GLYPHOFFSET_SIZE( statetable );
1085 GXV_XStateTable_GlyphOffsetDesc glyphOffset;
1088 GXV_NAME_ENTER(
"EntryTable" );
1090 GXV_TRACE((
"maxEntry=%d entrySize=%d\n", maxEntry, entrySize ));
1092 if ( ( maxEntry + 1 ) * entrySize > *length_p )
1094 GXV_SET_ERR_IF_PARANOID( FT_INVALID_TOO_SHORT );
1097 maxEntry = (FT_Byte)( *length_p / entrySize - 1 );
1098 GXV_TRACE((
"too large maxEntry, shrinking to %d fit EntryTable length\n",
1102 for ( entry = 0; entry <= maxEntry; entry++ )
1108 GXV_LIMIT_CHECK( 2 + 2 );
1109 newState = FT_NEXT_USHORT( p );
1110 flags = FT_NEXT_USHORT( p );
1113 if ( newState < stateArray ||
1114 stateArray + stateArray_length < newState )
1116 GXV_TRACE((
" newState offset 0x%04x is out of stateArray\n",
1118 GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
1122 if ( 0 != ( ( newState - stateArray ) % ( 1 + maxClassID ) ) )
1124 GXV_TRACE((
" newState offset 0x%04x is not aligned to %d-classes\n",
1125 newState, 1 + maxClassID ));
1126 GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
1130 state = (FT_Byte)( ( newState - stateArray ) / ( 1 + maxClassID ) );
1132 switch ( GXV_GLYPHOFFSET_FMT( statetable ) )
1134 case GXV_GLYPHOFFSET_NONE:
1138 case GXV_GLYPHOFFSET_UCHAR:
1139 glyphOffset.uc = FT_NEXT_BYTE( p );
1142 case GXV_GLYPHOFFSET_CHAR:
1143 glyphOffset.c = FT_NEXT_CHAR( p );
1146 case GXV_GLYPHOFFSET_USHORT:
1147 glyphOffset.u = FT_NEXT_USHORT( p );
1150 case GXV_GLYPHOFFSET_SHORT:
1151 glyphOffset.s = FT_NEXT_SHORT( p );
1154 case GXV_GLYPHOFFSET_ULONG:
1155 glyphOffset.ul = FT_NEXT_ULONG( p );
1158 case GXV_GLYPHOFFSET_LONG:
1159 glyphOffset.l = FT_NEXT_LONG( p );
1163 if ( gxvalid->statetable.entry_validate_func )
1164 gxvalid->statetable.entry_validate_func( state,
1172 *length_p = (FT_UShort)( p - table );
1180 FT_LOCAL_DEF(
void )
1181 gxv_StateTable_subtable_setup( FT_UShort table_size,
1182 FT_UShort classTable,
1183 FT_UShort stateArray,
1184 FT_UShort entryTable,
1185 FT_UShort* classTable_length_p,
1186 FT_UShort* stateArray_length_p,
1187 FT_UShort* entryTable_length_p,
1188 GXV_Validator gxvalid )
1198 l[0] = classTable_length_p;
1199 l[1] = stateArray_length_p;
1200 l[2] = entryTable_length_p;
1202 gxv_set_length_by_ushort_offset( o, l, buff, 3, table_size, gxvalid );
1206 FT_LOCAL_DEF(
void )
1207 gxv_StateTable_validate( FT_Bytes table,
1209 GXV_Validator gxvalid )
1211 FT_UShort stateSize;
1212 FT_UShort classTable;
1213 FT_UShort stateArray;
1214 FT_UShort entryTable;
1216 FT_UShort classTable_length;
1217 FT_UShort stateArray_length;
1218 FT_UShort entryTable_length;
1223 GXV_StateTable_Subtable_Setup_Func setup_func;
1228 GXV_NAME_ENTER(
"StateTable" );
1230 GXV_TRACE((
"StateTable header\n" ));
1232 GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 );
1233 stateSize = FT_NEXT_USHORT( p );
1234 classTable = FT_NEXT_USHORT( p );
1235 stateArray = FT_NEXT_USHORT( p );
1236 entryTable = FT_NEXT_USHORT( p );
1238 GXV_TRACE((
"stateSize=0x%04x\n", stateSize ));
1239 GXV_TRACE((
"offset to classTable=0x%04x\n", classTable ));
1240 GXV_TRACE((
"offset to stateArray=0x%04x\n", stateArray ));
1241 GXV_TRACE((
"offset to entryTable=0x%04x\n", entryTable ));
1243 if ( stateSize > 0xFF )
1246 if ( gxvalid->statetable.optdata_load_func )
1247 gxvalid->statetable.optdata_load_func( p, limit, gxvalid );
1249 if ( gxvalid->statetable.subtable_setup_func )
1250 setup_func = gxvalid->statetable.subtable_setup_func;
1252 setup_func = gxv_StateTable_subtable_setup;
1254 setup_func( (FT_UShort)( limit - table ),
1263 GXV_TRACE((
"StateTable Subtables\n" ));
1265 if ( classTable != 0 )
1266 gxv_ClassTable_validate( table + classTable,
1272 maxClassID = (FT_Byte)( stateSize - 1 );
1274 if ( stateArray != 0 )
1275 gxv_StateArray_validate( table + stateArray,
1290 if ( maxEntry > 0 && entryTable == 0 )
1293 if ( entryTable != 0 )
1294 gxv_EntryTable_validate( table + entryTable,
1310 FT_LOCAL_DEF(
void )
1311 gxv_XStateTable_subtable_setup( FT_ULong table_size,
1312 FT_ULong classTable,
1313 FT_ULong stateArray,
1314 FT_ULong entryTable,
1315 FT_ULong* classTable_length_p,
1316 FT_ULong* stateArray_length_p,
1317 FT_ULong* entryTable_length_p,
1318 GXV_Validator gxvalid )
1328 l[0] = classTable_length_p;
1329 l[1] = stateArray_length_p;
1330 l[2] = entryTable_length_p;
1332 gxv_set_length_by_ulong_offset( o, l, buff, 3, table_size, gxvalid );
1337 gxv_XClassTable_lookupval_validate( FT_UShort glyph,
1338 GXV_LookupValueCPtr value_p,
1339 GXV_Validator gxvalid )
1343 if ( value_p->u >= gxvalid->xstatetable.nClasses )
1345 if ( value_p->u > gxvalid->xstatetable.maxClassID )
1346 gxvalid->xstatetable.maxClassID = value_p->u;
1376 static GXV_LookupValueDesc
1377 gxv_XClassTable_lookupfmt4_transit( FT_UShort relative_gindex,
1378 GXV_LookupValueCPtr base_value_p,
1379 FT_Bytes lookuptbl_limit,
1380 GXV_Validator gxvalid )
1385 GXV_LookupValueDesc value;
1388 offset = (FT_UShort)( base_value_p->u +
1389 relative_gindex * sizeof ( FT_UShort ) );
1391 p = gxvalid->lookuptbl_head + offset;
1392 limit = lookuptbl_limit;
1394 GXV_LIMIT_CHECK ( 2 );
1395 value.u = FT_NEXT_USHORT( p );
1402 gxv_XStateArray_validate( FT_Bytes table,
1404 FT_UShort maxClassID,
1406 FT_UShort* maxState_p,
1407 FT_UShort* maxEntry_p,
1408 GXV_Validator gxvalid )
1411 FT_Bytes limit = table + *length_p;
1415 FT_UNUSED( stateSize );
1418 GXV_NAME_ENTER(
"XStateArray" );
1420 GXV_TRACE((
"parse % 3d bytes by stateSize=% 3d maxClassID=% 3d\n",
1421 (
int)( *length_p ), (
int)stateSize, (
int)maxClassID ));
1427 GXV_LIMIT_CHECK( ( 1 + maxClassID ) * 2 * 2 );
1433 while ( p + ( ( 1 + maxClassID ) * 2 ) <= limit )
1436 for ( clazz = 0; clazz <= maxClassID; clazz++ )
1438 entry = FT_NEXT_USHORT( p );
1439 *maxEntry_p = (FT_UShort)FT_MAX( *maxEntry_p, entry );
1442 GXV_TRACE((
"parsed: maxState=%d, maxEntry=%d\n",
1443 *maxState_p, *maxEntry_p ));
1445 *length_p = (FT_ULong)( p - table );
1452 gxv_XEntryTable_validate( FT_Bytes table,
1455 FT_ULong stateArray_length,
1456 FT_UShort maxClassID,
1457 FT_Bytes xstatetable_table,
1458 FT_Bytes xstatetable_limit,
1459 GXV_Validator gxvalid )
1462 FT_Bytes limit = table + *length_p;
1465 FT_Int entrySize = 2 + 2 + GXV_GLYPHOFFSET_SIZE( xstatetable );
1468 GXV_NAME_ENTER(
"XEntryTable" );
1469 GXV_TRACE((
"maxEntry=%d entrySize=%d\n", maxEntry, entrySize ));
1471 if ( ( p + ( maxEntry + 1 ) * entrySize ) > limit )
1472 FT_INVALID_TOO_SHORT;
1474 for (entry = 0; entry <= maxEntry; entry++ )
1476 FT_UShort newState_idx;
1478 GXV_XStateTable_GlyphOffsetDesc glyphOffset;
1481 GXV_LIMIT_CHECK( 2 + 2 );
1482 newState_idx = FT_NEXT_USHORT( p );
1483 flags = FT_NEXT_USHORT( p );
1485 if ( stateArray_length < (FT_ULong)( newState_idx * 2 ) )
1487 GXV_TRACE((
" newState index 0x%04x points out of stateArray\n",
1489 GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
1492 state = (FT_UShort)( newState_idx / ( 1 + maxClassID ) );
1493 if ( 0 != ( newState_idx % ( 1 + maxClassID ) ) )
1495 FT_TRACE4((
"-> new state = %d (supposed)\n",
1497 FT_TRACE4((
"but newState index 0x%04x"
1498 " is not aligned to %d-classes\n",
1499 newState_idx, 1 + maxClassID ));
1500 GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
1503 switch ( GXV_GLYPHOFFSET_FMT( xstatetable ) )
1505 case GXV_GLYPHOFFSET_NONE:
1509 case GXV_GLYPHOFFSET_UCHAR:
1510 glyphOffset.uc = FT_NEXT_BYTE( p );
1513 case GXV_GLYPHOFFSET_CHAR:
1514 glyphOffset.c = FT_NEXT_CHAR( p );
1517 case GXV_GLYPHOFFSET_USHORT:
1518 glyphOffset.u = FT_NEXT_USHORT( p );
1521 case GXV_GLYPHOFFSET_SHORT:
1522 glyphOffset.s = FT_NEXT_SHORT( p );
1525 case GXV_GLYPHOFFSET_ULONG:
1526 glyphOffset.ul = FT_NEXT_ULONG( p );
1529 case GXV_GLYPHOFFSET_LONG:
1530 glyphOffset.l = FT_NEXT_LONG( p );
1534 GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT );
1538 if ( gxvalid->xstatetable.entry_validate_func )
1539 gxvalid->xstatetable.entry_validate_func( state,
1548 *length_p = (FT_ULong)( p - table );
1554 FT_LOCAL_DEF(
void )
1555 gxv_XStateTable_validate( FT_Bytes table,
1557 GXV_Validator gxvalid )
1560 FT_ULong classTable;
1561 FT_ULong stateArray;
1562 FT_ULong entryTable;
1564 FT_ULong classTable_length;
1565 FT_ULong stateArray_length;
1566 FT_ULong entryTable_length;
1570 GXV_XStateTable_Subtable_Setup_Func setup_func;
1575 GXV_NAME_ENTER(
"XStateTable" );
1577 GXV_TRACE((
"XStateTable header\n" ));
1579 GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
1580 gxvalid->xstatetable.nClasses = FT_NEXT_ULONG( p );
1581 classTable = FT_NEXT_ULONG( p );
1582 stateArray = FT_NEXT_ULONG( p );
1583 entryTable = FT_NEXT_ULONG( p );
1585 GXV_TRACE((
"nClasses =0x%08lx\n", gxvalid->xstatetable.nClasses ));
1586 GXV_TRACE((
"offset to classTable=0x%08lx\n", classTable ));
1587 GXV_TRACE((
"offset to stateArray=0x%08lx\n", stateArray ));
1588 GXV_TRACE((
"offset to entryTable=0x%08lx\n", entryTable ));
1590 if ( gxvalid->xstatetable.nClasses > 0xFFFFU )
1593 GXV_TRACE((
"StateTable Subtables\n" ));
1595 if ( gxvalid->xstatetable.optdata_load_func )
1596 gxvalid->xstatetable.optdata_load_func( p, limit, gxvalid );
1598 if ( gxvalid->xstatetable.subtable_setup_func )
1599 setup_func = gxvalid->xstatetable.subtable_setup_func;
1601 setup_func = gxv_XStateTable_subtable_setup;
1603 setup_func( (FT_ULong)( limit - table ),
1612 if ( classTable != 0 )
1614 gxvalid->xstatetable.maxClassID = 0;
1615 gxvalid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
1616 gxvalid->lookupval_func = gxv_XClassTable_lookupval_validate;
1617 gxvalid->lookupfmt4_trans = gxv_XClassTable_lookupfmt4_transit;
1618 gxv_LookupTable_validate( table + classTable,
1619 table + classTable + classTable_length,
1622 if ( gxvalid->subtable_length < classTable_length )
1623 classTable_length = gxvalid->subtable_length;
1629 gxvalid->xstatetable.maxClassID =
1630 (FT_UShort)( gxvalid->xstatetable.nClasses - 1 );
1633 if ( stateArray != 0 )
1634 gxv_XStateArray_validate( table + stateArray,
1636 gxvalid->xstatetable.maxClassID,
1637 gxvalid->xstatetable.nClasses,
1649 if ( maxEntry > 0 && entryTable == 0 )
1652 if ( entryTable != 0 )
1653 gxv_XEntryTable_validate( table + entryTable,
1657 gxvalid->xstatetable.maxClassID,
1675 gxv_compare_ranges( FT_Bytes table1_start,
1676 FT_ULong table1_length,
1677 FT_Bytes table2_start,
1678 FT_ULong table2_length )
1680 if ( table1_start == table2_start )
1682 if ( ( table1_length == 0 || table2_length == 0 ) )
1685 else if ( table1_start < table2_start )
1687 if ( ( table1_start + table1_length ) <= table2_start )
1690 else if ( table1_start > table2_start )
1692 if ( ( table1_start >= table2_start + table2_length ) )
1702 FT_LOCAL_DEF(
void )
1703 gxv_odtect_add_range( FT_Bytes start,
1705 const FT_String* name,
1706 GXV_odtect_Range odtect )
1708 odtect->range[odtect->nRanges].start = start;
1709 odtect->range[odtect->nRanges].length = length;
1710 odtect->range[odtect->nRanges].name = (FT_String*)name;
1715 FT_LOCAL_DEF(
void )
1716 gxv_odtect_validate( GXV_odtect_Range odtect,
1717 GXV_Validator gxvalid )
1722 GXV_NAME_ENTER(
"check overlap among multi ranges" );
1724 for ( i = 0; i < odtect->nRanges; i++ )
1725 for ( j = 0; j < i; j++ )
1726 if ( 0 != gxv_compare_ranges( odtect->range[i].start,
1727 odtect->range[i].length,
1728 odtect->range[j].start,
1729 odtect->range[j].length ) )
1731#ifdef FT_DEBUG_LEVEL_TRACE
1732 if ( odtect->range[i].name || odtect->range[j].name )
1733 GXV_TRACE((
"found overlap between range %u and range %u\n",
1736 GXV_TRACE((
"found overlap between `%s' and `%s\'\n",
1737 odtect->range[i].name,
1738 odtect->range[j].name ));