Ditch the renderer system in sdl1.3 and use the 'old fashioned' sdl/opengl context. This gives us more flexibility and less problem in receiving video events (expecially on mobile platform) as well as not having to care to reset the gl context every time sdl interferes.
This is a major sdl1.3 update so it should be tested with care (working great on ios)
/***************************************************************************/
/* */
/* otvcommn.c */
/* */
/* OpenType common tables validation (body). */
/* */
/* Copyright 2004, 2005, 2006, 2007 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#include "otvcommn.h"
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_otvcommon
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** COVERAGE TABLE *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_LOCAL_DEF( void )
otv_Coverage_validate( FT_Bytes table,
OTV_Validator valid,
FT_Int expected_count )
{
FT_Bytes p = table;
FT_UInt CoverageFormat;
FT_UInt total = 0;
OTV_NAME_ENTER( "Coverage" );
OTV_LIMIT_CHECK( 4 );
CoverageFormat = FT_NEXT_USHORT( p );
OTV_TRACE(( " (format %d)\n", CoverageFormat ));
switch ( CoverageFormat )
{
case 1: /* CoverageFormat1 */
{
FT_UInt GlyphCount;
FT_UInt i;
GlyphCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
OTV_LIMIT_CHECK( GlyphCount * 2 ); /* GlyphArray */
for ( i = 0; i < GlyphCount; ++i )
{
FT_UInt gid;
gid = FT_NEXT_USHORT( p );
if ( gid >= valid->glyph_count )
FT_INVALID_GLYPH_ID;
}
total = GlyphCount;
}
break;
case 2: /* CoverageFormat2 */
{
FT_UInt n, RangeCount;
FT_UInt Start, End, StartCoverageIndex, last = 0;
RangeCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (RangeCount = %d)\n", RangeCount ));
OTV_LIMIT_CHECK( RangeCount * 6 );
/* RangeRecord */
for ( n = 0; n < RangeCount; n++ )
{
Start = FT_NEXT_USHORT( p );
End = FT_NEXT_USHORT( p );
StartCoverageIndex = FT_NEXT_USHORT( p );
if ( Start > End || StartCoverageIndex != total )
FT_INVALID_DATA;
if ( End >= valid->glyph_count )
FT_INVALID_GLYPH_ID;
if ( n > 0 && Start <= last )
FT_INVALID_DATA;
total += End - Start + 1;
last = End;
}
}
break;
default:
FT_INVALID_FORMAT;
}
/* Generally, a coverage table offset has an associated count field. */
/* The number of glyphs in the table should match this field. If */
/* there is no associated count, a value of -1 tells us not to check. */
if ( expected_count != -1 && (FT_UInt)expected_count != total )
FT_INVALID_DATA;
OTV_EXIT;
}
FT_LOCAL_DEF( FT_UInt )
otv_Coverage_get_first( FT_Bytes table )
{
FT_Bytes p = table;
p += 4; /* skip CoverageFormat and Glyph/RangeCount */
return FT_NEXT_USHORT( p );
}
FT_LOCAL_DEF( FT_UInt )
otv_Coverage_get_last( FT_Bytes table )
{
FT_Bytes p = table;
FT_UInt CoverageFormat = FT_NEXT_USHORT( p );
FT_UInt count = FT_NEXT_USHORT( p ); /* Glyph/RangeCount */
FT_UInt result = 0;
switch ( CoverageFormat )
{
case 1:
p += ( count - 1 ) * 2;
result = FT_NEXT_USHORT( p );
break;
case 2:
p += ( count - 1 ) * 6 + 2;
result = FT_NEXT_USHORT( p );
break;
default:
;
}
return result;
}
FT_LOCAL_DEF( FT_UInt )
otv_Coverage_get_count( FT_Bytes table )
{
FT_Bytes p = table;
FT_UInt CoverageFormat = FT_NEXT_USHORT( p );
FT_UInt count = FT_NEXT_USHORT( p ); /* Glyph/RangeCount */
FT_UInt result = 0;
switch ( CoverageFormat )
{
case 1:
return count;
case 2:
{
FT_UInt Start, End;
for ( ; count > 0; count-- )
{
Start = FT_NEXT_USHORT( p );
End = FT_NEXT_USHORT( p );
p += 2; /* skip StartCoverageIndex */
result += End - Start + 1;
}
}
break;
default:
;
}
return result;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** CLASS DEFINITION TABLE *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_LOCAL_DEF( void )
otv_ClassDef_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt ClassFormat;
OTV_NAME_ENTER( "ClassDef" );
OTV_LIMIT_CHECK( 4 );
ClassFormat = FT_NEXT_USHORT( p );
OTV_TRACE(( " (format %d)\n", ClassFormat ));
switch ( ClassFormat )
{
case 1: /* ClassDefFormat1 */
{
FT_UInt StartGlyph;
FT_UInt GlyphCount;
OTV_LIMIT_CHECK( 4 );
StartGlyph = FT_NEXT_USHORT( p );
GlyphCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
OTV_LIMIT_CHECK( GlyphCount * 2 ); /* ClassValueArray */
if ( StartGlyph + GlyphCount - 1 >= valid->glyph_count )
FT_INVALID_GLYPH_ID;
}
break;
case 2: /* ClassDefFormat2 */
{
FT_UInt n, ClassRangeCount;
FT_UInt Start, End, last = 0;
ClassRangeCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (ClassRangeCount = %d)\n", ClassRangeCount ));
OTV_LIMIT_CHECK( ClassRangeCount * 6 );
/* ClassRangeRecord */
for ( n = 0; n < ClassRangeCount; n++ )
{
Start = FT_NEXT_USHORT( p );
End = FT_NEXT_USHORT( p );
p += 2; /* skip Class */
if ( Start > End || ( n > 0 && Start <= last ) )
FT_INVALID_DATA;
if ( End >= valid->glyph_count )
FT_INVALID_GLYPH_ID;
last = End;
}
}
break;
default:
FT_INVALID_FORMAT;
}
/* no need to check glyph indices used as input to class definition */
/* tables since even invalid glyph indices return a meaningful result */
OTV_EXIT;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** DEVICE TABLE *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_LOCAL_DEF( void )
otv_Device_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt StartSize, EndSize, DeltaFormat, count;
OTV_NAME_ENTER( "Device" );
OTV_LIMIT_CHECK( 8 );
StartSize = FT_NEXT_USHORT( p );
EndSize = FT_NEXT_USHORT( p );
DeltaFormat = FT_NEXT_USHORT( p );
if ( DeltaFormat < 1 || DeltaFormat > 3 )
FT_INVALID_FORMAT;
if ( EndSize < StartSize )
FT_INVALID_DATA;
count = EndSize - StartSize + 1;
OTV_LIMIT_CHECK( ( 1 << DeltaFormat ) * count / 8 ); /* DeltaValue */
OTV_EXIT;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** LOOKUPS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* uses valid->type_count */
/* uses valid->type_funcs */
FT_LOCAL_DEF( void )
otv_Lookup_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt LookupType, SubTableCount;
OTV_Validate_Func validate;
OTV_NAME_ENTER( "Lookup" );
OTV_LIMIT_CHECK( 6 );
LookupType = FT_NEXT_USHORT( p );
p += 2; /* skip LookupFlag */
SubTableCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (type %d)\n", LookupType ));
if ( LookupType == 0 || LookupType > valid->type_count )
FT_INVALID_DATA;
validate = valid->type_funcs[LookupType - 1];
OTV_TRACE(( " (SubTableCount = %d)\n", SubTableCount ));
OTV_LIMIT_CHECK( SubTableCount * 2 );
/* SubTable */
for ( ; SubTableCount > 0; SubTableCount-- )
validate( table + FT_NEXT_USHORT( p ), valid );
OTV_EXIT;
}
/* uses valid->lookup_count */
FT_LOCAL_DEF( void )
otv_LookupList_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt LookupCount;
OTV_NAME_ENTER( "LookupList" );
OTV_LIMIT_CHECK( 2 );
LookupCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
OTV_LIMIT_CHECK( LookupCount * 2 );
valid->lookup_count = LookupCount;
/* Lookup */
for ( ; LookupCount > 0; LookupCount-- )
otv_Lookup_validate( table + FT_NEXT_USHORT( p ), valid );
OTV_EXIT;
}
static FT_UInt
otv_LookupList_get_count( FT_Bytes table )
{
return FT_NEXT_USHORT( table );
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** FEATURES *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* uses valid->lookup_count */
FT_LOCAL_DEF( void )
otv_Feature_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt LookupCount;
OTV_NAME_ENTER( "Feature" );
OTV_LIMIT_CHECK( 4 );
p += 2; /* skip FeatureParams (unused) */
LookupCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
OTV_LIMIT_CHECK( LookupCount * 2 );
/* LookupListIndex */
for ( ; LookupCount > 0; LookupCount-- )
if ( FT_NEXT_USHORT( p ) >= valid->lookup_count )
FT_INVALID_DATA;
OTV_EXIT;
}
static FT_UInt
otv_Feature_get_count( FT_Bytes table )
{
return FT_NEXT_USHORT( table );
}
/* sets valid->lookup_count */
FT_LOCAL_DEF( void )
otv_FeatureList_validate( FT_Bytes table,
FT_Bytes lookups,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt FeatureCount;
OTV_NAME_ENTER( "FeatureList" );
OTV_LIMIT_CHECK( 2 );
FeatureCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (FeatureCount = %d)\n", FeatureCount ));
OTV_LIMIT_CHECK( FeatureCount * 2 );
valid->lookup_count = otv_LookupList_get_count( lookups );
/* FeatureRecord */
for ( ; FeatureCount > 0; FeatureCount-- )
{
p += 4; /* skip FeatureTag */
/* Feature */
otv_Feature_validate( table + FT_NEXT_USHORT( p ), valid );
}
OTV_EXIT;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** LANGUAGE SYSTEM *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* uses valid->extra1 (number of features) */
FT_LOCAL_DEF( void )
otv_LangSys_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt ReqFeatureIndex;
FT_UInt FeatureCount;
OTV_NAME_ENTER( "LangSys" );
OTV_LIMIT_CHECK( 6 );
p += 2; /* skip LookupOrder (unused) */
ReqFeatureIndex = FT_NEXT_USHORT( p );
FeatureCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (ReqFeatureIndex = %d)\n", ReqFeatureIndex ));
OTV_TRACE(( " (FeatureCount = %d)\n", FeatureCount ));
if ( ReqFeatureIndex != 0xFFFFU && ReqFeatureIndex >= valid->extra1 )
FT_INVALID_DATA;
OTV_LIMIT_CHECK( FeatureCount * 2 );
/* FeatureIndex */
for ( ; FeatureCount > 0; FeatureCount-- )
if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
FT_INVALID_DATA;
OTV_EXIT;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** SCRIPTS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_LOCAL_DEF( void )
otv_Script_validate( FT_Bytes table,
OTV_Validator valid )
{
FT_UInt DefaultLangSys, LangSysCount;
FT_Bytes p = table;
OTV_NAME_ENTER( "Script" );
OTV_LIMIT_CHECK( 4 );
DefaultLangSys = FT_NEXT_USHORT( p );
LangSysCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (LangSysCount = %d)\n", LangSysCount ));
if ( DefaultLangSys != 0 )
otv_LangSys_validate( table + DefaultLangSys, valid );
OTV_LIMIT_CHECK( LangSysCount * 6 );
/* LangSysRecord */
for ( ; LangSysCount > 0; LangSysCount-- )
{
p += 4; /* skip LangSysTag */
/* LangSys */
otv_LangSys_validate( table + FT_NEXT_USHORT( p ), valid );
}
OTV_EXIT;
}
/* sets valid->extra1 (number of features) */
FT_LOCAL_DEF( void )
otv_ScriptList_validate( FT_Bytes table,
FT_Bytes features,
OTV_Validator valid )
{
FT_UInt ScriptCount;
FT_Bytes p = table;
OTV_NAME_ENTER( "ScriptList" );
OTV_LIMIT_CHECK( 2 );
ScriptCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (ScriptCount = %d)\n", ScriptCount ));
OTV_LIMIT_CHECK( ScriptCount * 6 );
valid->extra1 = otv_Feature_get_count( features );
/* ScriptRecord */
for ( ; ScriptCount > 0; ScriptCount-- )
{
p += 4; /* skip ScriptTag */
otv_Script_validate( table + FT_NEXT_USHORT( p ), valid ); /* Script */
}
OTV_EXIT;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** UTILITY FUNCTIONS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
u: uint16
ux: unit16 [x]
s: struct
sx: struct [x]
sxy: struct [x], using external y count
x: uint16 x
C: Coverage
O: Offset
On: Offset (NULL)
Ox: Offset [x]
Onx: Offset (NULL) [x]
*/
FT_LOCAL_DEF( void )
otv_x_Ox( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt Count;
OTV_Validate_Func func;
OTV_ENTER;
OTV_LIMIT_CHECK( 2 );
Count = FT_NEXT_USHORT( p );
OTV_TRACE(( " (Count = %d)\n", Count ));
OTV_LIMIT_CHECK( Count * 2 );
valid->nesting_level++;
func = valid->func[valid->nesting_level];
for ( ; Count > 0; Count-- )
func( table + FT_NEXT_USHORT( p ), valid );
valid->nesting_level--;
OTV_EXIT;
}
FT_LOCAL_DEF( void )
otv_u_C_x_Ox( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt Count, Coverage;
OTV_Validate_Func func;
OTV_ENTER;
p += 2; /* skip Format */
OTV_LIMIT_CHECK( 4 );
Coverage = FT_NEXT_USHORT( p );
Count = FT_NEXT_USHORT( p );
OTV_TRACE(( " (Count = %d)\n", Count ));
otv_Coverage_validate( table + Coverage, valid, Count );
OTV_LIMIT_CHECK( Count * 2 );
valid->nesting_level++;
func = valid->func[valid->nesting_level];
for ( ; Count > 0; Count-- )
func( table + FT_NEXT_USHORT( p ), valid );
valid->nesting_level--;
OTV_EXIT;
}
/* uses valid->extra1 (if > 0: array value limit) */
FT_LOCAL_DEF( void )
otv_x_ux( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt Count;
OTV_ENTER;
OTV_LIMIT_CHECK( 2 );
Count = FT_NEXT_USHORT( p );
OTV_TRACE(( " (Count = %d)\n", Count ));
OTV_LIMIT_CHECK( Count * 2 );
if ( valid->extra1 )
{
for ( ; Count > 0; Count-- )
if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
FT_INVALID_DATA;
}
OTV_EXIT;
}
/* `ux' in the function's name is not really correct since only x-1 */
/* elements are tested */
/* uses valid->extra1 (array value limit) */
FT_LOCAL_DEF( void )
otv_x_y_ux_sy( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt Count1, Count2;
OTV_ENTER;
OTV_LIMIT_CHECK( 4 );
Count1 = FT_NEXT_USHORT( p );
Count2 = FT_NEXT_USHORT( p );
OTV_TRACE(( " (Count1 = %d)\n", Count1 ));
OTV_TRACE(( " (Count2 = %d)\n", Count2 ));
if ( Count1 == 0 )
FT_INVALID_DATA;
OTV_LIMIT_CHECK( ( Count1 - 1 ) * 2 + Count2 * 4 );
p += ( Count1 - 1 ) * 2;
for ( ; Count2 > 0; Count2-- )
{
if ( FT_NEXT_USHORT( p ) >= Count1 )
FT_INVALID_DATA;
if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
FT_INVALID_DATA;
}
OTV_EXIT;
}
/* `uy' in the function's name is not really correct since only y-1 */
/* elements are tested */
/* uses valid->extra1 (array value limit) */
FT_LOCAL_DEF( void )
otv_x_ux_y_uy_z_uz_p_sp( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt BacktrackCount, InputCount, LookaheadCount;
FT_UInt Count;
OTV_ENTER;
OTV_LIMIT_CHECK( 2 );
BacktrackCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (BacktrackCount = %d)\n", BacktrackCount ));
OTV_LIMIT_CHECK( BacktrackCount * 2 + 2 );
p += BacktrackCount * 2;
InputCount = FT_NEXT_USHORT( p );
if ( InputCount == 0 )
FT_INVALID_DATA;
OTV_TRACE(( " (InputCount = %d)\n", InputCount ));
OTV_LIMIT_CHECK( InputCount * 2 );
p += ( InputCount - 1 ) * 2;
LookaheadCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (LookaheadCount = %d)\n", LookaheadCount ));
OTV_LIMIT_CHECK( LookaheadCount * 2 + 2 );
p += LookaheadCount * 2;
Count = FT_NEXT_USHORT( p );
OTV_TRACE(( " (Count = %d)\n", Count ));
OTV_LIMIT_CHECK( Count * 4 );
for ( ; Count > 0; Count-- )
{
if ( FT_NEXT_USHORT( p ) >= InputCount )
FT_INVALID_DATA;
if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
FT_INVALID_DATA;
}
OTV_EXIT;
}
/* sets valid->extra1 (valid->lookup_count) */
FT_LOCAL_DEF( void )
otv_u_O_O_x_Onx( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt Coverage, ClassDef, ClassSetCount;
OTV_Validate_Func func;
OTV_ENTER;
p += 2; /* skip Format */
OTV_LIMIT_CHECK( 6 );
Coverage = FT_NEXT_USHORT( p );
ClassDef = FT_NEXT_USHORT( p );
ClassSetCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (ClassSetCount = %d)\n", ClassSetCount ));
otv_Coverage_validate( table + Coverage, valid, -1 );
otv_ClassDef_validate( table + ClassDef, valid );
OTV_LIMIT_CHECK( ClassSetCount * 2 );
valid->nesting_level++;
func = valid->func[valid->nesting_level];
valid->extra1 = valid->lookup_count;
for ( ; ClassSetCount > 0; ClassSetCount-- )
{
FT_UInt offset = FT_NEXT_USHORT( p );
if ( offset )
func( table + offset, valid );
}
valid->nesting_level--;
OTV_EXIT;
}
/* uses valid->lookup_count */
FT_LOCAL_DEF( void )
otv_u_x_y_Ox_sy( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt GlyphCount, Count, count1;
OTV_ENTER;
p += 2; /* skip Format */
OTV_LIMIT_CHECK( 4 );
GlyphCount = FT_NEXT_USHORT( p );
Count = FT_NEXT_USHORT( p );
OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
OTV_TRACE(( " (Count = %d)\n", Count ));
OTV_LIMIT_CHECK( GlyphCount * 2 + Count * 4 );
for ( count1 = GlyphCount; count1 > 0; count1-- )
otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
for ( ; Count > 0; Count-- )
{
if ( FT_NEXT_USHORT( p ) >= GlyphCount )
FT_INVALID_DATA;
if ( FT_NEXT_USHORT( p ) >= valid->lookup_count )
FT_INVALID_DATA;
}
OTV_EXIT;
}
/* sets valid->extra1 (valid->lookup_count) */
FT_LOCAL_DEF( void )
otv_u_O_O_O_O_x_Onx( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt Coverage;
FT_UInt BacktrackClassDef, InputClassDef, LookaheadClassDef;
FT_UInt ChainClassSetCount;
OTV_Validate_Func func;
OTV_ENTER;
p += 2; /* skip Format */
OTV_LIMIT_CHECK( 10 );
Coverage = FT_NEXT_USHORT( p );
BacktrackClassDef = FT_NEXT_USHORT( p );
InputClassDef = FT_NEXT_USHORT( p );
LookaheadClassDef = FT_NEXT_USHORT( p );
ChainClassSetCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (ChainClassSetCount = %d)\n", ChainClassSetCount ));
otv_Coverage_validate( table + Coverage, valid, -1 );
otv_ClassDef_validate( table + BacktrackClassDef, valid );
otv_ClassDef_validate( table + InputClassDef, valid );
otv_ClassDef_validate( table + LookaheadClassDef, valid );
OTV_LIMIT_CHECK( ChainClassSetCount * 2 );
valid->nesting_level++;
func = valid->func[valid->nesting_level];
valid->extra1 = valid->lookup_count;
for ( ; ChainClassSetCount > 0; ChainClassSetCount-- )
{
FT_UInt offset = FT_NEXT_USHORT( p );
if ( offset )
func( table + offset, valid );
}
valid->nesting_level--;
OTV_EXIT;
}
/* uses valid->lookup_count */
FT_LOCAL_DEF( void )
otv_u_x_Ox_y_Oy_z_Oz_p_sp( FT_Bytes table,
OTV_Validator valid )
{
FT_Bytes p = table;
FT_UInt BacktrackGlyphCount, InputGlyphCount, LookaheadGlyphCount;
FT_UInt count1, count2;
OTV_ENTER;
p += 2; /* skip Format */
OTV_LIMIT_CHECK( 2 );
BacktrackGlyphCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
InputGlyphCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (InputGlyphCount = %d)\n", InputGlyphCount ));
OTV_LIMIT_CHECK( InputGlyphCount * 2 + 2 );
for ( count1 = InputGlyphCount; count1 > 0; count1-- )
otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
LookaheadGlyphCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
count2 = FT_NEXT_USHORT( p );
OTV_TRACE(( " (Count = %d)\n", count2 ));
OTV_LIMIT_CHECK( count2 * 4 );
for ( ; count2 > 0; count2-- )
{
if ( FT_NEXT_USHORT( p ) >= InputGlyphCount )
FT_INVALID_DATA;
if ( FT_NEXT_USHORT( p ) >= valid->lookup_count )
FT_INVALID_DATA;
}
OTV_EXIT;
}
FT_LOCAL_DEF( FT_UInt )
otv_GSUBGPOS_get_Lookup_count( FT_Bytes table )
{
FT_Bytes p = table + 8;
return otv_LookupList_get_count( table + FT_NEXT_USHORT( p ) );
}
FT_LOCAL_DEF( FT_UInt )
otv_GSUBGPOS_have_MarkAttachmentType_flag( FT_Bytes table )
{
FT_Bytes p, lookup;
FT_UInt count;
if ( !table )
return 0;
/* LookupList */
p = table + 8;
table += FT_NEXT_USHORT( p );
/* LookupCount */
p = table;
count = FT_NEXT_USHORT( p );
for ( ; count > 0; count-- )
{
FT_Bytes oldp;
/* Lookup */
lookup = table + FT_NEXT_USHORT( p );
oldp = p;
/* LookupFlag */
p = lookup + 2;
if ( FT_NEXT_USHORT( p ) & 0xFF00U )
return 1;
p = oldp;
}
return 0;
}
/* END */