otvgpos.c
来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· C语言 代码 · 共 1,017 行 · 第 1/3 页
C
1,017 行
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GPOS LOOKUP TYPE 1 *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* sets valid->extra3 (pointer to base table) */
static void
otv_SinglePos_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt PosFormat;
OTV_NAME_ENTER( "SinglePos" );
OTV_LIMIT_CHECK( 2 );
PosFormat = FT_NEXT_USHORT( p );
OTV_TRACE(( " (format %d)\n", PosFormat ));
valid->extra3 = table;
switch ( PosFormat )
{
case 1: /* SinglePosFormat1 */
{
FT_UInt Coverage, ValueFormat;
OTV_LIMIT_CHECK( 4 );
Coverage = FT_NEXT_USHORT( p );
ValueFormat = FT_NEXT_USHORT( p );
otv_Coverage_validate( table + Coverage, valid, -1 );
otv_ValueRecord_validate( p, ValueFormat, valid ); /* Value */
}
break;
case 2: /* SinglePosFormat2 */
{
FT_UInt Coverage, ValueFormat, ValueCount, len_value;
OTV_LIMIT_CHECK( 6 );
Coverage = FT_NEXT_USHORT( p );
ValueFormat = FT_NEXT_USHORT( p );
ValueCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (ValueCount = %d)\n", ValueCount ));
len_value = otv_value_length( ValueFormat );
otv_Coverage_validate( table + Coverage, valid, ValueCount );
OTV_LIMIT_CHECK( ValueCount * len_value );
/* Value */
for ( ; ValueCount > 0; ValueCount-- )
{
otv_ValueRecord_validate( p, ValueFormat, valid );
p += len_value;
}
}
break;
default:
FT_INVALID_FORMAT;
}
OTV_EXIT;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GPOS LOOKUP TYPE 2 *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
static void
otv_PairSet_validate( FT_Bytes table,
FT_UInt format1,
FT_UInt format2,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt value_len1, value_len2, PairValueCount;
OTV_NAME_ENTER( "PairSet" );
OTV_LIMIT_CHECK( 2 );
PairValueCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (PairValueCount = %d)\n", PairValueCount ));
value_len1 = otv_value_length( format1 );
value_len2 = otv_value_length( format2 );
OTV_LIMIT_CHECK( PairValueCount * ( value_len1 + value_len2 + 2 ) );
/* PairValueRecord */
for ( ; PairValueCount > 0; PairValueCount-- )
{
p += 2; /* skip SecondGlyph */
if ( format1 )
otv_ValueRecord_validate( p, format1, valid ); /* Value1 */
p += value_len1;
if ( format2 )
otv_ValueRecord_validate( p, format2, valid ); /* Value2 */
p += value_len2;
}
OTV_EXIT;
}
/* sets valid->extra3 (pointer to base table) */
static void
otv_PairPos_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt PosFormat;
OTV_NAME_ENTER( "PairPos" );
OTV_LIMIT_CHECK( 2 );
PosFormat = FT_NEXT_USHORT( p );
OTV_TRACE(( " (format %d)\n", PosFormat ));
valid->extra3 = table;
switch ( PosFormat )
{
case 1: /* PairPosFormat1 */
{
FT_UInt Coverage, ValueFormat1, ValueFormat2, PairSetCount;
OTV_LIMIT_CHECK( 8 );
Coverage = FT_NEXT_USHORT( p );
ValueFormat1 = FT_NEXT_USHORT( p );
ValueFormat2 = FT_NEXT_USHORT( p );
PairSetCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (PairSetCount = %d)\n", PairSetCount ));
otv_Coverage_validate( table + Coverage, valid, -1 );
OTV_LIMIT_CHECK( PairSetCount * 2 );
/* PairSetOffset */
for ( ; PairSetCount > 0; PairSetCount-- )
otv_PairSet_validate( table + FT_NEXT_USHORT( p ),
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, -1 );
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_FORMAT;
}
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, EntryExitCount );
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_FORMAT;
}
OTV_EXIT;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GPOS LOOKUP TYPE 4 *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* UNDOCUMENTED (in OpenType 1.5): */
/* BaseRecord tables can contain NULL pointers. */
/* sets valid->extra2 (1) */
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 = 1;
OTV_NEST2( MarkBasePosFormat1, BaseArray );
OTV_RUN( table, valid );
break;
default:
FT_INVALID_FORMAT;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?