📄 gxvcommn.c
字号:
} /* ================= eXtended State Table (for morx) =================== */ FT_LOCAL_DEF( void ) gxv_XStateTable_subtable_setup( FT_ULong table_size, FT_ULong classTable, FT_ULong stateArray, FT_ULong entryTable, FT_ULong* classTable_length_p, FT_ULong* stateArray_length_p, FT_ULong* entryTable_length_p, GXV_Validator valid ) { FT_ULong o[3]; FT_ULong* l[3]; FT_ULong buff[4]; o[0] = classTable; o[1] = stateArray; o[2] = entryTable; l[0] = classTable_length_p; l[1] = stateArray_length_p; l[2] = entryTable_length_p; gxv_set_length_by_ulong_offset( o, l, buff, 4, table_size, valid ); } static void gxv_XClassTable_lookupval_validate( FT_UShort glyph, GXV_LookupValueDesc value, GXV_Validator valid ) { FT_UNUSED( glyph ); if ( value.u >= valid->xstatetable.nClasses ) FT_INVALID_DATA; if ( value.u > valid->xstatetable.maxClassID ) valid->xstatetable.maxClassID = value.u; } /* +===============+ --------+ | lookup header | | +===============+ | | BinSrchHeader | | +===============+ | | lastGlyph[0] | | +---------------+ | | firstGlyph[0] | | head of lookup table +---------------+ | + | offset[0] | -> | offset [byte] +===============+ | + | lastGlyph[1] | | (glyphID - firstGlyph) * 2 [byte] +---------------+ | | firstGlyph[1] | | +---------------+ | | offset[1] | | +===============+ | | .... | | 16bit value array | +===============+ | | value | <-------+ .... */ static GXV_LookupValueDesc gxv_XClassTable_lookupfmt4_transit( FT_UShort relative_gindex, GXV_LookupValueDesc base_value, FT_Bytes lookuptbl_limit, GXV_Validator valid ) { FT_Bytes p; FT_Bytes limit; FT_UShort offset; GXV_LookupValueDesc value; /* XXX: check range? */ offset = (FT_UShort)( base_value.u + relative_gindex * sizeof ( FT_UShort ) ); p = valid->lookuptbl_head + offset; limit = lookuptbl_limit; GXV_LIMIT_CHECK ( 2 ); value.u = FT_NEXT_USHORT( p ); return value; } static void gxv_XStateArray_validate( FT_Bytes table, FT_ULong* length_p, FT_UShort maxClassID, FT_ULong stateSize, FT_UShort* maxState_p, FT_UShort* maxEntry_p, GXV_Validator valid ) { FT_Bytes p = table; FT_Bytes limit = table + *length_p; FT_UShort clazz; FT_UShort entry; FT_UNUSED( stateSize ); /* for the non-debugging case */ GXV_NAME_ENTER( "XStateArray" ); GXV_TRACE(( "parse % 3d bytes by stateSize=% 3d maxClassID=% 3d\n", (int)(*length_p), stateSize, (int)(maxClassID) )); /* * 2 states are predefined and must be described: * state 0 (start of text), 1 (start of line) */ GXV_LIMIT_CHECK( ( 1 + maxClassID ) * 2 * 2 ); *maxState_p = 0; *maxEntry_p = 0; /* read if enough to read another state */ while ( p + ( ( 1 + maxClassID ) * 2 ) <= limit ) { (*maxState_p)++; for ( clazz = 0; clazz <= maxClassID; clazz++ ) { entry = FT_NEXT_USHORT( p ); *maxEntry_p = (FT_UShort)FT_MAX( *maxEntry_p, entry ); } } GXV_TRACE(( "parsed: maxState=%d, maxEntry=%d\n", *maxState_p, *maxEntry_p )); *length_p = p - table; GXV_EXIT; } static void gxv_XEntryTable_validate( FT_Bytes table, FT_ULong* length_p, FT_UShort maxEntry, FT_ULong stateArray_length, FT_UShort maxClassID, FT_Bytes xstatetable_table, FT_Bytes xstatetable_limit, GXV_Validator valid ) { FT_Bytes p = table; FT_Bytes limit = table + *length_p; FT_UShort entry; FT_UShort state; FT_Int entrySize = 2 + 2 + GXV_GLYPHOFFSET_SIZE( xstatetable ); GXV_NAME_ENTER( "XEntryTable" ); GXV_TRACE(( "maxEntry=%d entrySize=%d\n", maxEntry, entrySize )); if ( ( p + ( maxEntry + 1 ) * entrySize ) > limit ) FT_INVALID_TOO_SHORT; for (entry = 0; entry <= maxEntry ; entry++ ) { FT_UShort newState_idx; FT_UShort flags; GXV_XStateTable_GlyphOffsetDesc glyphOffset; GXV_LIMIT_CHECK( 2 + 2 ); newState_idx = FT_NEXT_USHORT( p ); flags = FT_NEXT_USHORT( p ); if ( stateArray_length < (FT_ULong)( newState_idx * 2 ) ) { GXV_TRACE(( " newState index 0x%04x points out of stateArray\n", newState_idx )); if ( valid->root->level >= FT_VALIDATE_PARANOID ) FT_INVALID_OFFSET; } state = (FT_UShort)( newState_idx / ( 1 + maxClassID ) ); if ( 0 != ( newState_idx % ( 1 + maxClassID ) ) ) { FT_TRACE4(( "-> new state = %d (supposed)\n" "but newState index 0x%04x is not aligned to %d-classes\n", state, newState_idx, 1 + maxClassID )); if ( valid->root->level >= FT_VALIDATE_PARANOID ) FT_INVALID_OFFSET; } switch ( GXV_GLYPHOFFSET_FMT( xstatetable ) ) { case GXV_GLYPHOFFSET_NONE: glyphOffset.uc = 0; /* make compiler happy */ break; case GXV_GLYPHOFFSET_UCHAR: glyphOffset.uc = FT_NEXT_BYTE( p ); break; case GXV_GLYPHOFFSET_CHAR: glyphOffset.c = FT_NEXT_CHAR( p ); break; case GXV_GLYPHOFFSET_USHORT: glyphOffset.u = FT_NEXT_USHORT( p ); break; case GXV_GLYPHOFFSET_SHORT: glyphOffset.s = FT_NEXT_SHORT( p ); break; case GXV_GLYPHOFFSET_ULONG: glyphOffset.ul = FT_NEXT_ULONG( p ); break; case GXV_GLYPHOFFSET_LONG: glyphOffset.l = FT_NEXT_LONG( p ); break; default: if ( valid->root->level >= FT_VALIDATE_PARANOID ) FT_INVALID_FORMAT; goto Exit; } if ( NULL != valid->xstatetable.entry_validate_func ) valid->xstatetable.entry_validate_func( state, flags, glyphOffset, xstatetable_table, xstatetable_limit, valid ); } Exit: *length_p = p - table; GXV_EXIT; } FT_LOCAL_DEF( void ) gxv_XStateTable_validate( FT_Bytes table, FT_Bytes limit, GXV_Validator valid ) { /* StateHeader members */ FT_ULong classTable; /* offset to Class(Sub)Table */ FT_ULong stateArray; /* offset to StateArray */ FT_ULong entryTable; /* offset to EntryTable */ FT_ULong classTable_length; FT_ULong stateArray_length; FT_ULong entryTable_length; FT_UShort maxState; FT_UShort maxEntry; GXV_XStateTable_Subtable_Setup_Func setup_func; FT_Bytes p = table; GXV_NAME_ENTER( "XStateTable" ); GXV_TRACE(( "XStateTable header\n" )); GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 ); valid->xstatetable.nClasses = FT_NEXT_ULONG( p ); classTable = FT_NEXT_ULONG( p ); stateArray = FT_NEXT_ULONG( p ); entryTable = FT_NEXT_ULONG( p ); GXV_TRACE(( "nClasses =0x%08x\n", valid->xstatetable.nClasses )); GXV_TRACE(( "offset to classTable=0x%08x\n", classTable )); GXV_TRACE(( "offset to stateArray=0x%08x\n", stateArray )); GXV_TRACE(( "offset to entryTable=0x%08x\n", entryTable )); if ( valid->xstatetable.nClasses > 0xFFFFU ) FT_INVALID_DATA; GXV_TRACE(( "StateTable Subtables\n" )); if ( valid->xstatetable.optdata_load_func != NULL ) valid->xstatetable.optdata_load_func( p, limit, valid ); if ( valid->xstatetable.subtable_setup_func != NULL ) setup_func = valid->xstatetable.subtable_setup_func; else setup_func = gxv_XStateTable_subtable_setup; setup_func( limit - table, classTable, stateArray, entryTable, &classTable_length, &stateArray_length, &entryTable_length, valid ); if ( classTable != 0 ) { valid->xstatetable.maxClassID = 0; valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED; valid->lookupval_func = gxv_XClassTable_lookupval_validate; valid->lookupfmt4_trans = gxv_XClassTable_lookupfmt4_transit; gxv_LookupTable_validate( table + classTable, table + classTable + classTable_length, valid ); if ( valid->subtable_length < classTable_length ) classTable_length = valid->subtable_length; } else { /* XXX: check range? */ valid->xstatetable.maxClassID = (FT_UShort)( valid->xstatetable.nClasses - 1 ); } if ( stateArray != 0 ) gxv_XStateArray_validate( table + stateArray, &stateArray_length, valid->xstatetable.maxClassID, valid->xstatetable.nClasses, &maxState, &maxEntry, valid ); else { maxState = 1; /* 0:start of text, 1:start of line are predefined */ maxEntry = 0; } if ( maxEntry > 0 && entryTable == 0 ) FT_INVALID_OFFSET; if ( entryTable != 0 ) gxv_XEntryTable_validate( table + entryTable, &entryTable_length, maxEntry, stateArray_length, valid->xstatetable.maxClassID, table, limit, valid ); GXV_EXIT; } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** Table overlapping *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ static int gxv_compare_ranges( FT_Bytes table1_start, FT_ULong table1_length, FT_Bytes table2_start, FT_ULong table2_length ) { if ( table1_start == table2_start ) { if ( ( table1_length == 0 || table2_length == 0 ) ) goto Out; } else if ( table1_start < table2_start ) { if ( ( table1_start + table1_length ) <= table2_start ) goto Out; } else if ( table1_start > table2_start ) { if ( ( table1_start >= table2_start + table2_length ) ) goto Out; } return 1; Out: return 0; } FT_LOCAL_DEF( void ) gxv_odtect_add_range( FT_Bytes start, FT_ULong length, const FT_String* name, GXV_odtect_Range odtect ) { odtect->range[ odtect->nRanges ].start = start; odtect->range[ odtect->nRanges ].length = length; odtect->range[ odtect->nRanges ].name = (FT_String*)name; odtect->nRanges++; } FT_LOCAL_DEF( void ) gxv_odtect_validate( GXV_odtect_Range odtect, GXV_Validator valid ) { FT_UInt i, j; GXV_NAME_ENTER( "check overlap among multi ranges" ); for ( i = 0; i < odtect->nRanges; i++ ) for ( j = 0; j < i; j++ ) if ( 0 != gxv_compare_ranges( odtect->range[i].start, odtect->range[i].length, odtect->range[j].start, odtect->range[j].length ) ) { if ( odtect->range[i].name || odtect->range[j].name ) GXV_TRACE(( "found overlap between range %d and range %d\n", i, j )); else GXV_TRACE(( "found overlap between `%s' and `%s\'\n", odtect->range[i].name, odtect->range[j].name )); FT_INVALID_OFFSET; } GXV_EXIT; }/* END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -