📄 otvgpos.c
字号:
ValueFormat1, ValueFormat2, valid );
}
break;
case 2: /* PairPosFormat2 */
{
FT_UInt Coverage, ValueFormat1, ValueFormat2, ClassDef1, ClassDef2;
FT_UInt ClassCount1, ClassCount2, len_value1, len_value2, count;
OTV_LIMIT_CHECK( 14 );
Coverage = FT_NEXT_USHORT( p );
ValueFormat1 = FT_NEXT_USHORT( p );
ValueFormat2 = FT_NEXT_USHORT( p );
ClassDef1 = FT_NEXT_USHORT( p );
ClassDef2 = FT_NEXT_USHORT( p );
ClassCount1 = FT_NEXT_USHORT( p );
ClassCount2 = FT_NEXT_USHORT( p );
OTV_TRACE(( " (ClassCount1 = %d)\n", ClassCount1 ));
OTV_TRACE(( " (ClassCount2 = %d)\n", ClassCount2 ));
len_value1 = otv_value_length( ValueFormat1 );
len_value2 = otv_value_length( ValueFormat2 );
otv_Coverage_validate( table + Coverage, valid );
otv_ClassDef_validate( table + ClassDef1, valid );
otv_ClassDef_validate( table + ClassDef2, valid );
OTV_LIMIT_CHECK( ClassCount1 * ClassCount2 *
( len_value1 + len_value2 ) );
/* Class1Record */
for ( ; ClassCount1 > 0; ClassCount1-- )
{
/* Class2Record */
for ( count = ClassCount2; count > 0; count-- )
{
if ( ValueFormat1 )
/* Value1 */
otv_ValueRecord_validate( p, ValueFormat1, valid );
p += len_value1;
if ( ValueFormat2 )
/* Value2 */
otv_ValueRecord_validate( p, ValueFormat2, valid );
p += len_value2;
}
}
}
break;
default:
FT_INVALID_DATA;
}
OTV_EXIT;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GPOS LOOKUP TYPE 3 *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
static void
otv_CursivePos_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt PosFormat;
OTV_NAME_ENTER( "CursivePos" );
OTV_LIMIT_CHECK( 2 );
PosFormat = FT_NEXT_USHORT( p );
OTV_TRACE(( " (format %d)\n", PosFormat ));
switch ( PosFormat )
{
case 1: /* CursivePosFormat1 */
{
FT_UInt table_size;
FT_UInt Coverage, EntryExitCount;
OTV_OPTIONAL_TABLE( EntryAnchor );
OTV_OPTIONAL_TABLE( ExitAnchor );
OTV_LIMIT_CHECK( 4 );
Coverage = FT_NEXT_USHORT( p );
EntryExitCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (EntryExitCount = %d)\n", EntryExitCount ));
otv_Coverage_validate( table + Coverage, valid );
OTV_LIMIT_CHECK( EntryExitCount * 4 );
table_size = EntryExitCount * 4 + 4;
/* EntryExitRecord */
for ( ; EntryExitCount > 0; EntryExitCount-- )
{
OTV_OPTIONAL_OFFSET( EntryAnchor );
OTV_OPTIONAL_OFFSET( ExitAnchor );
OTV_SIZE_CHECK( EntryAnchor );
if ( EntryAnchor )
otv_Anchor_validate( table + EntryAnchor, valid );
OTV_SIZE_CHECK( ExitAnchor );
if ( ExitAnchor )
otv_Anchor_validate( table + ExitAnchor, valid );
}
}
break;
default:
FT_INVALID_DATA;
}
OTV_EXIT;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GPOS LOOKUP TYPE 4 *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* sets valid->extra2 (0) */
static void
otv_MarkBasePos_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt PosFormat;
OTV_NAME_ENTER( "MarkBasePos" );
OTV_LIMIT_CHECK( 2 );
PosFormat = FT_NEXT_USHORT( p );
OTV_TRACE(( " (format %d)\n", PosFormat ));
switch ( PosFormat )
{
case 1:
valid->extra2 = 0;
OTV_NEST2( MarkBasePosFormat1, BaseArray );
OTV_RUN( table, valid );
break;
default:
FT_INVALID_DATA;
}
OTV_EXIT;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GPOS LOOKUP TYPE 5 *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* sets valid->extra2 (1) */
static void
otv_MarkLigPos_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt PosFormat;
OTV_NAME_ENTER( "MarkLigPos" );
OTV_LIMIT_CHECK( 2 );
PosFormat = FT_NEXT_USHORT( p );
OTV_TRACE(( " (format %d)\n", PosFormat ));
switch ( PosFormat )
{
case 1:
valid->extra2 = 1;
OTV_NEST3( MarkLigPosFormat1, LigatureArray, LigatureAttach );
OTV_RUN( table, valid );
break;
default:
FT_INVALID_DATA;
}
OTV_EXIT;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GPOS LOOKUP TYPE 6 *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* sets valid->extra2 (0) */
static void
otv_MarkMarkPos_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt PosFormat;
OTV_NAME_ENTER( "MarkMarkPos" );
OTV_LIMIT_CHECK( 2 );
PosFormat = FT_NEXT_USHORT( p );
OTV_TRACE(( " (format %d)\n", PosFormat ));
switch ( PosFormat )
{
case 1:
valid->extra2 = 0;
OTV_NEST2( MarkMarkPosFormat1, Mark2Array );
OTV_RUN( table, valid );
break;
default:
FT_INVALID_DATA;
}
OTV_EXIT;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GPOS LOOKUP TYPE 7 *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* sets valid->extra1 (lookup count) */
static void
otv_ContextPos_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt PosFormat;
OTV_NAME_ENTER( "ContextPos" );
OTV_LIMIT_CHECK( 2 );
PosFormat = FT_NEXT_USHORT( p );
OTV_TRACE(( " (format %d)\n", PosFormat ));
switch ( PosFormat )
{
case 1:
/* no need to check glyph indices/classes used as input for these */
/* context rules since even invalid glyph indices/classes return */
/* meaningful results */
valid->extra1 = valid->lookup_count;
OTV_NEST3( ContextPosFormat1, PosRuleSet, PosRule );
OTV_RUN( table, valid );
break;
case 2:
/* no need to check glyph indices/classes used as input for these */
/* context rules since even invalid glyph indices/classes return */
/* meaningful results */
OTV_NEST3( ContextPosFormat2, PosClassSet, PosClassRule );
OTV_RUN( table, valid );
break;
case 3:
OTV_NEST1( ContextPosFormat3 );
OTV_RUN( table, valid );
break;
default:
FT_INVALID_DATA;
}
OTV_EXIT;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GPOS LOOKUP TYPE 8 *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* sets valid->extra1 (lookup count) */
static void
otv_ChainContextPos_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt PosFormat;
OTV_NAME_ENTER( "ChainContextPos" );
OTV_LIMIT_CHECK( 2 );
PosFormat = FT_NEXT_USHORT( p );
OTV_TRACE(( " (format %d)\n", PosFormat ));
switch ( PosFormat )
{
case 1:
/* no need to check glyph indices/classes used as input for these */
/* context rules since even invalid glyph indices/classes return */
/* meaningful results */
valid->extra1 = valid->lookup_count;
OTV_NEST3( ChainContextPosFormat1,
ChainPosRuleSet, ChainPosRule );
OTV_RUN( table, valid );
break;
case 2:
/* no need to check glyph indices/classes used as input for these */
/* context rules since even invalid glyph indices/classes return */
/* meaningful results */
OTV_NEST3( ChainContextPosFormat2,
ChainPosClassSet, ChainPosClassRule );
OTV_RUN( table, valid );
break;
case 3:
OTV_NEST1( ChainContextPosFormat3 );
OTV_RUN( table, valid );
break;
default:
FT_INVALID_DATA;
}
OTV_EXIT;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GPOS LOOKUP TYPE 9 *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* uses valid->type_funcs */
static void
otv_ExtensionPos_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt PosFormat;
OTV_NAME_ENTER( "ExtensionPos" );
OTV_LIMIT_CHECK( 2 );
PosFormat = FT_NEXT_USHORT( p );
OTV_TRACE(( " (format %d)\n", PosFormat ));
switch ( PosFormat )
{
case 1: /* ExtensionPosFormat1 */
{
FT_UInt ExtensionLookupType, ExtensionOffset;
OTV_Validate_Func validate;
OTV_LIMIT_CHECK( 6 );
ExtensionLookupType = FT_NEXT_USHORT( p );
ExtensionOffset = FT_NEXT_ULONG( p );
if ( ExtensionLookupType == 0 || ExtensionLookupType >= 9 )
FT_INVALID_DATA;
validate = valid->type_funcs[ExtensionLookupType - 1];
validate( table + ExtensionOffset, valid );
}
break;
default:
FT_INVALID_DATA;
}
OTV_EXIT;
}
static const OTV_Validate_Func otv_gpos_validate_funcs[9] =
{
otv_SinglePos_validate,
otv_PairPos_validate,
otv_CursivePos_validate,
otv_MarkBasePos_validate,
otv_MarkLigPos_validate,
otv_MarkMarkPos_validate,
otv_ContextPos_validate,
otv_ChainContextPos_validate,
otv_ExtensionPos_validate
};
/* sets valid->type_count */
/* sets valid->type_funcs */
FT_LOCAL_DEF( void )
otv_GPOS_subtable_validate( FT_Bytes table,
OTV_Validator valid )
{
valid->type_count = 9;
valid->type_funcs = (OTV_Validate_Func*)otv_gpos_validate_funcs;
otv_Lookup_validate( table, valid );
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GPOS TABLE *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* sets valid->glyph_count */
FT_LOCAL_DEF( void )
otv_GPOS_validate( FT_Bytes table,
FT_UInt glyph_count,
FT_Validator ftvalid )
{
OTV_ValidatorRec validrec;
OTV_Validator valid = &validrec;
FT_Bytes p = table;
FT_UInt ScriptList, FeatureList, LookupList;
valid->root = ftvalid;
FT_TRACE3(( "validating GPOS table\n" ));
OTV_INIT;
OTV_LIMIT_CHECK( 10 );
if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */
FT_INVALID_DATA;
ScriptList = FT_NEXT_USHORT( p );
FeatureList = FT_NEXT_USHORT( p );
LookupList = FT_NEXT_USHORT( p );
valid->type_count = 9;
valid->type_funcs = (OTV_Validate_Func*)otv_gpos_validate_funcs;
valid->glyph_count = glyph_count;
otv_LookupList_validate( table + LookupList,
valid );
otv_FeatureList_validate( table + FeatureList, table + LookupList,
valid );
otv_ScriptList_validate( table + ScriptList, table + FeatureList,
valid );
FT_TRACE4(( "\n" ));
}
/* END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -