📄 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 + -