📄 gxvcommn.c
字号:
/*************************************************************************/ /*************************************************************************/ /***** *****/ /***** SFNT NAME *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ FT_LOCAL_DEF( void ) gxv_sfntName_validate( FT_UShort name_index, FT_UShort min_index, FT_UShort max_index, GXV_Validator valid ) { FT_SfntName name; FT_UInt i; FT_UInt nnames; GXV_NAME_ENTER( "sfntName" ); if ( name_index < min_index || max_index < name_index ) FT_INVALID_FORMAT; nnames = FT_Get_Sfnt_Name_Count( valid->face ); for ( i = 0; i < nnames; i++ ) { if ( FT_Get_Sfnt_Name( valid->face, i, &name ) != FT_Err_Ok ) continue ; if ( name.name_id == name_index ) goto Out; } GXV_TRACE(( " nameIndex = %d (UNTITLED)\n", name_index )); FT_INVALID_DATA; goto Exit; /* make compiler happy */ Out: FT_TRACE1(( " nameIndex = %d (", name_index )); GXV_TRACE_HEXDUMP_SFNTNAME( name ); FT_TRACE1(( ")\n" )); Exit: GXV_EXIT; } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** STATE TABLE *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /* -------------------------- Class Table --------------------------- */ /* * highestClass specifies how many classes are defined in this * Class Subtable. Apple spec does not mention whether undefined * holes in the class (e.g.: 0-3 are predefined, 4 is unused, 5 is used) * are permitted. At present, holes in a defined class are not checked. * -- suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp> */ static void gxv_ClassTable_validate( FT_Bytes table, FT_UShort* length_p, FT_UShort stateSize, FT_Byte* maxClassID_p, GXV_Validator valid ) { FT_Bytes p = table; FT_Bytes limit = table + *length_p; FT_UShort firstGlyph; FT_UShort nGlyphs; GXV_NAME_ENTER( "ClassTable" ); *maxClassID_p = 3; /* Classes 0, 2, and 3 are predefined */ GXV_LIMIT_CHECK( 2 + 2 ); firstGlyph = FT_NEXT_USHORT( p ); nGlyphs = FT_NEXT_USHORT( p ); GXV_TRACE(( " (firstGlyph = %d, nGlyphs = %d)\n", firstGlyph, nGlyphs )); if ( !nGlyphs ) goto Out; gxv_glyphid_validate( (FT_UShort)( firstGlyph + nGlyphs ), valid ); { FT_Byte nGlyphInClass[256]; FT_Byte classID; FT_UShort i; ft_memset( nGlyphInClass, 0, 256 ); for ( i = 0; i < nGlyphs; i++ ) { GXV_LIMIT_CHECK( 1 ); classID = FT_NEXT_BYTE( p ); switch ( classID ) { /* following classes should not appear in class array */ case 0: /* end of text */ case 2: /* out of bounds */ case 3: /* end of line */ FT_INVALID_DATA; break; case 1: /* out of bounds */ default: /* user-defined: 4 - ( stateSize - 1 ) */ if ( classID >= stateSize ) FT_INVALID_DATA; /* assign glyph to undefined state */ nGlyphInClass[classID]++; break; } } *length_p = (FT_UShort)( p - table ); /* scan max ClassID in use */ for ( i = 0; i < stateSize; i++ ) if ( ( 3 < i ) && ( nGlyphInClass[i] > 0 ) ) *maxClassID_p = (FT_Byte)i; /* XXX: Check Range? */ } Out: GXV_TRACE(( "Declared stateSize=0x%02x, Used maxClassID=0x%02x\n", stateSize, *maxClassID_p )); GXV_EXIT; } /* --------------------------- State Array ----------------------------- */ static void gxv_StateArray_validate( FT_Bytes table, FT_UShort* length_p, FT_Byte maxClassID, FT_UShort stateSize, FT_Byte* maxState_p, FT_Byte* maxEntry_p, GXV_Validator valid ) { FT_Bytes p = table; FT_Bytes limit = table + *length_p; FT_Byte clazz; FT_Byte entry; FT_UNUSED( stateSize ); /* for the non-debugging case */ GXV_NAME_ENTER( "StateArray" ); GXV_TRACE(( "parse %d bytes by stateSize=%d maxClassID=%d\n", (int)(*length_p), stateSize, (int)(maxClassID) )); /* * 2 states are predefined and must be described in StateArray: * state 0 (start of text), 1 (start of line) */ GXV_LIMIT_CHECK( ( 1 + maxClassID ) * 2 ); *maxState_p = 0; *maxEntry_p = 0; /* read if enough to read another state */ while ( p + ( 1 + maxClassID ) <= limit ) { (*maxState_p)++; for ( clazz = 0; clazz <= maxClassID; clazz++ ) { entry = FT_NEXT_BYTE( p ); *maxEntry_p = (FT_Byte)FT_MAX( *maxEntry_p, entry ); } } GXV_TRACE(( "parsed: maxState=%d, maxEntry=%d\n", *maxState_p, *maxEntry_p )); *length_p = (FT_UShort)( p - table ); GXV_EXIT; } /* --------------------------- Entry Table ----------------------------- */ static void gxv_EntryTable_validate( FT_Bytes table, FT_UShort* length_p, FT_Byte maxEntry, FT_UShort stateArray, FT_UShort stateArray_length, FT_Byte maxClassID, FT_Bytes statetable_table, FT_Bytes statetable_limit, GXV_Validator valid ) { FT_Bytes p = table; FT_Bytes limit = table + *length_p; FT_Byte entry; FT_Byte state; FT_Int entrySize = 2 + 2 + GXV_GLYPHOFFSET_SIZE( statetable ); GXV_XStateTable_GlyphOffsetDesc glyphOffset; GXV_NAME_ENTER( "EntryTable" ); GXV_TRACE(( "maxEntry=%d entrySize=%d\n", maxEntry, entrySize )); if ( ( maxEntry + 1 ) * entrySize > *length_p ) { if ( valid->root->level >= FT_VALIDATE_PARANOID ) FT_INVALID_TOO_SHORT; /* ftxvalidator and FontValidator both warn and continue */ maxEntry = (FT_Byte)( *length_p / entrySize - 1 ); GXV_TRACE(( "too large maxEntry, shrinking to %d fit EntryTable length\n", maxEntry )); } for ( entry = 0; entry <= maxEntry; entry++ ) { FT_UShort newState; FT_UShort flags; GXV_LIMIT_CHECK( 2 + 2 ); newState = FT_NEXT_USHORT( p ); flags = FT_NEXT_USHORT( p ); if ( newState < stateArray || stateArray + stateArray_length < newState ) { GXV_TRACE(( " newState offset 0x%04x is out of stateArray\n", newState )); if ( valid->root->level >= FT_VALIDATE_PARANOID ) FT_INVALID_OFFSET; continue; } if ( 0 != ( ( newState - stateArray ) % ( 1 + maxClassID ) ) ) { GXV_TRACE(( " newState offset 0x%04x is not aligned to %d-classes\n", newState, 1 + maxClassID )); if ( valid->root->level >= FT_VALIDATE_PARANOID ) FT_INVALID_OFFSET; continue; } state = (FT_Byte)( ( newState - stateArray ) / ( 1 + maxClassID ) ); switch ( GXV_GLYPHOFFSET_FMT( statetable ) ) { 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->statetable.entry_validate_func ) valid->statetable.entry_validate_func( state, flags, glyphOffset, statetable_table, statetable_limit, valid ); } Exit: *length_p = (FT_UShort)( p - table ); GXV_EXIT; } /* =========================== State Table ============================= */ FT_LOCAL_DEF( void ) gxv_StateTable_subtable_setup( FT_UShort table_size, FT_UShort classTable, FT_UShort stateArray, FT_UShort entryTable, FT_UShort* classTable_length_p, FT_UShort* stateArray_length_p, FT_UShort* entryTable_length_p, GXV_Validator valid ) { FT_UShort o[3]; FT_UShort* l[3]; FT_UShort 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_ushort_offset( o, l, buff, 3, table_size, valid ); } FT_LOCAL_DEF( void ) gxv_StateTable_validate( FT_Bytes table, FT_Bytes limit, GXV_Validator valid ) { FT_UShort stateSize; FT_UShort classTable; /* offset to Class(Sub)Table */ FT_UShort stateArray; /* offset to StateArray */ FT_UShort entryTable; /* offset to EntryTable */ FT_UShort classTable_length; FT_UShort stateArray_length; FT_UShort entryTable_length; FT_Byte maxClassID; FT_Byte maxState; FT_Byte maxEntry; GXV_StateTable_Subtable_Setup_Func setup_func; FT_Bytes p = table; GXV_NAME_ENTER( "StateTable" ); GXV_TRACE(( "StateTable header\n" )); GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 ); stateSize = FT_NEXT_USHORT( p ); classTable = FT_NEXT_USHORT( p ); stateArray = FT_NEXT_USHORT( p ); entryTable = FT_NEXT_USHORT( p ); GXV_TRACE(( "stateSize=0x%04x\n", stateSize )); GXV_TRACE(( "offset to classTable=0x%04x\n", classTable )); GXV_TRACE(( "offset to stateArray=0x%04x\n", stateArray )); GXV_TRACE(( "offset to entryTable=0x%04x\n", entryTable )); if ( stateSize > 0xFF ) FT_INVALID_DATA; if ( valid->statetable.optdata_load_func != NULL ) valid->statetable.optdata_load_func( p, limit, valid ); if ( valid->statetable.subtable_setup_func != NULL) setup_func = valid->statetable.subtable_setup_func; else setup_func = gxv_StateTable_subtable_setup; setup_func( (FT_UShort)( limit - table ), classTable, stateArray, entryTable, &classTable_length, &stateArray_length, &entryTable_length, valid ); GXV_TRACE(( "StateTable Subtables\n" )); if ( classTable != 0 ) gxv_ClassTable_validate( table + classTable, &classTable_length, stateSize, &maxClassID, valid ); else maxClassID = (FT_Byte)( stateSize - 1 ); if ( stateArray != 0 ) gxv_StateArray_validate( table + stateArray, &stateArray_length, maxClassID, stateSize, &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_EntryTable_validate( table + entryTable, &entryTable_length, maxEntry, stateArray, stateArray_length, maxClassID, table, limit, valid ); GXV_EXIT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -