1
/***************************************************************************/
5
/* OpenType GSUB table validation (body). */
7
/* Copyright 2004, 2005, 2007 by */
8
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
10
/* This file is part of the FreeType project, and may only be used, */
11
/* modified, and distributed under the terms of the FreeType project */
12
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13
/* this file you indicate that you have read the license and */
14
/* understand and accept it fully. */
16
/***************************************************************************/
23
/*************************************************************************/
25
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
26
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
27
/* messages during execution. */
30
#define FT_COMPONENT trace_otvgsub
33
/*************************************************************************/
34
/*************************************************************************/
36
/***** GSUB LOOKUP TYPE 1 *****/
38
/*************************************************************************/
39
/*************************************************************************/
41
/* uses valid->glyph_count */
44
otv_SingleSubst_validate( FT_Bytes table,
51
OTV_NAME_ENTER( "SingleSubst" );
54
SubstFormat = FT_NEXT_USHORT( p );
56
OTV_TRACE(( " (format %d)\n", SubstFormat ));
58
switch ( SubstFormat )
60
case 1: /* SingleSubstFormat1 */
68
Coverage = table + FT_NEXT_USHORT( p );
69
DeltaGlyphID = FT_NEXT_SHORT( p );
71
otv_Coverage_validate( Coverage, valid, -1 );
73
idx = otv_Coverage_get_first( Coverage ) + DeltaGlyphID;
77
idx = otv_Coverage_get_last( Coverage ) + DeltaGlyphID;
78
if ( (FT_UInt)idx >= valid->glyph_count )
83
case 2: /* SingleSubstFormat2 */
85
FT_UInt Coverage, GlyphCount;
89
Coverage = FT_NEXT_USHORT( p );
90
GlyphCount = FT_NEXT_USHORT( p );
92
OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
94
otv_Coverage_validate( table + Coverage, valid, GlyphCount );
96
OTV_LIMIT_CHECK( GlyphCount * 2 );
99
for ( ; GlyphCount > 0; GlyphCount-- )
100
if ( FT_NEXT_USHORT( p ) >= valid->glyph_count )
113
/*************************************************************************/
114
/*************************************************************************/
116
/***** GSUB LOOKUP TYPE 2 *****/
118
/*************************************************************************/
119
/*************************************************************************/
121
/* sets valid->extra1 (glyph count) */
124
otv_MultipleSubst_validate( FT_Bytes table,
125
OTV_Validator valid )
131
OTV_NAME_ENTER( "MultipleSubst" );
133
OTV_LIMIT_CHECK( 2 );
134
SubstFormat = FT_NEXT_USHORT( p );
136
OTV_TRACE(( " (format %d)\n", SubstFormat ));
138
switch ( SubstFormat )
141
valid->extra1 = valid->glyph_count;
142
OTV_NEST2( MultipleSubstFormat1, Sequence );
143
OTV_RUN( table, valid );
154
/*************************************************************************/
155
/*************************************************************************/
157
/***** GSUB LOOKUP TYPE 3 *****/
159
/*************************************************************************/
160
/*************************************************************************/
162
/* sets valid->extra1 (glyph count) */
165
otv_AlternateSubst_validate( FT_Bytes table,
166
OTV_Validator valid )
172
OTV_NAME_ENTER( "AlternateSubst" );
174
OTV_LIMIT_CHECK( 2 );
175
SubstFormat = FT_NEXT_USHORT( p );
177
OTV_TRACE(( " (format %d)\n", SubstFormat ));
179
switch ( SubstFormat )
182
valid->extra1 = valid->glyph_count;
183
OTV_NEST2( AlternateSubstFormat1, AlternateSet );
184
OTV_RUN( table, valid );
195
/*************************************************************************/
196
/*************************************************************************/
198
/***** GSUB LOOKUP TYPE 4 *****/
200
/*************************************************************************/
201
/*************************************************************************/
203
#define LigatureFunc otv_Ligature_validate
205
/* uses valid->glyph_count */
208
otv_Ligature_validate( FT_Bytes table,
209
OTV_Validator valid )
212
FT_UInt LigatureGlyph, CompCount;
217
OTV_LIMIT_CHECK( 4 );
218
LigatureGlyph = FT_NEXT_USHORT( p );
219
if ( LigatureGlyph >= valid->glyph_count )
222
CompCount = FT_NEXT_USHORT( p );
224
OTV_TRACE(( " (CompCount = %d)\n", CompCount ));
226
if ( CompCount == 0 )
231
OTV_LIMIT_CHECK( CompCount * 2 ); /* Component */
233
/* no need to check the Component glyph indices */
240
otv_LigatureSubst_validate( FT_Bytes table,
241
OTV_Validator valid )
247
OTV_NAME_ENTER( "LigatureSubst" );
249
OTV_LIMIT_CHECK( 2 );
250
SubstFormat = FT_NEXT_USHORT( p );
252
OTV_TRACE(( " (format %d)\n", SubstFormat ));
254
switch ( SubstFormat )
257
OTV_NEST3( LigatureSubstFormat1, LigatureSet, Ligature );
258
OTV_RUN( table, valid );
269
/*************************************************************************/
270
/*************************************************************************/
272
/***** GSUB LOOKUP TYPE 5 *****/
274
/*************************************************************************/
275
/*************************************************************************/
277
/* sets valid->extra1 (lookup count) */
280
otv_ContextSubst_validate( FT_Bytes table,
281
OTV_Validator valid )
287
OTV_NAME_ENTER( "ContextSubst" );
289
OTV_LIMIT_CHECK( 2 );
290
SubstFormat = FT_NEXT_USHORT( p );
292
OTV_TRACE(( " (format %d)\n", SubstFormat ));
294
switch ( SubstFormat )
297
/* no need to check glyph indices/classes used as input for these */
298
/* context rules since even invalid glyph indices/classes return */
299
/* meaningful results */
301
valid->extra1 = valid->lookup_count;
302
OTV_NEST3( ContextSubstFormat1, SubRuleSet, SubRule );
303
OTV_RUN( table, valid );
307
/* no need to check glyph indices/classes used as input for these */
308
/* context rules since even invalid glyph indices/classes return */
309
/* meaningful results */
311
OTV_NEST3( ContextSubstFormat2, SubClassSet, SubClassRule );
312
OTV_RUN( table, valid );
316
OTV_NEST1( ContextSubstFormat3 );
317
OTV_RUN( table, valid );
328
/*************************************************************************/
329
/*************************************************************************/
331
/***** GSUB LOOKUP TYPE 6 *****/
333
/*************************************************************************/
334
/*************************************************************************/
336
/* sets valid->extra1 (lookup count) */
339
otv_ChainContextSubst_validate( FT_Bytes table,
340
OTV_Validator valid )
346
OTV_NAME_ENTER( "ChainContextSubst" );
348
OTV_LIMIT_CHECK( 2 );
349
SubstFormat = FT_NEXT_USHORT( p );
351
OTV_TRACE(( " (format %d)\n", SubstFormat ));
353
switch ( SubstFormat )
356
/* no need to check glyph indices/classes used as input for these */
357
/* context rules since even invalid glyph indices/classes return */
358
/* meaningful results */
360
valid->extra1 = valid->lookup_count;
361
OTV_NEST3( ChainContextSubstFormat1,
362
ChainSubRuleSet, ChainSubRule );
363
OTV_RUN( table, valid );
367
/* no need to check glyph indices/classes used as input for these */
368
/* context rules since even invalid glyph indices/classes return */
369
/* meaningful results */
371
OTV_NEST3( ChainContextSubstFormat2,
372
ChainSubClassSet, ChainSubClassRule );
373
OTV_RUN( table, valid );
377
OTV_NEST1( ChainContextSubstFormat3 );
378
OTV_RUN( table, valid );
389
/*************************************************************************/
390
/*************************************************************************/
392
/***** GSUB LOOKUP TYPE 7 *****/
394
/*************************************************************************/
395
/*************************************************************************/
397
/* uses valid->type_funcs */
400
otv_ExtensionSubst_validate( FT_Bytes table,
401
OTV_Validator valid )
407
OTV_NAME_ENTER( "ExtensionSubst" );
409
OTV_LIMIT_CHECK( 2 );
410
SubstFormat = FT_NEXT_USHORT( p );
412
OTV_TRACE(( " (format %d)\n", SubstFormat ));
414
switch ( SubstFormat )
416
case 1: /* ExtensionSubstFormat1 */
418
FT_UInt ExtensionLookupType;
419
FT_ULong ExtensionOffset;
420
OTV_Validate_Func validate;
423
OTV_LIMIT_CHECK( 6 );
424
ExtensionLookupType = FT_NEXT_USHORT( p );
425
ExtensionOffset = FT_NEXT_ULONG( p );
427
if ( ExtensionLookupType == 0 ||
428
ExtensionLookupType == 7 ||
429
ExtensionLookupType > 8 )
432
validate = valid->type_funcs[ExtensionLookupType - 1];
433
validate( table + ExtensionOffset, valid );
445
/*************************************************************************/
446
/*************************************************************************/
448
/***** GSUB LOOKUP TYPE 8 *****/
450
/*************************************************************************/
451
/*************************************************************************/
453
/* uses valid->glyph_count */
456
otv_ReverseChainSingleSubst_validate( FT_Bytes table,
457
OTV_Validator valid )
459
FT_Bytes p = table, Coverage;
461
FT_UInt BacktrackGlyphCount, LookaheadGlyphCount, GlyphCount;
464
OTV_NAME_ENTER( "ReverseChainSingleSubst" );
466
OTV_LIMIT_CHECK( 2 );
467
SubstFormat = FT_NEXT_USHORT( p );
469
OTV_TRACE(( " (format %d)\n", SubstFormat ));
471
switch ( SubstFormat )
473
case 1: /* ReverseChainSingleSubstFormat1 */
474
OTV_LIMIT_CHECK( 4 );
475
Coverage = table + FT_NEXT_USHORT( p );
476
BacktrackGlyphCount = FT_NEXT_USHORT( p );
478
OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
480
otv_Coverage_validate( Coverage, valid, -1 );
482
OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
484
for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
485
otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
487
LookaheadGlyphCount = FT_NEXT_USHORT( p );
489
OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
491
OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
493
for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
494
otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
496
GlyphCount = FT_NEXT_USHORT( p );
498
OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
500
if ( GlyphCount != otv_Coverage_get_count( Coverage ) )
503
OTV_LIMIT_CHECK( GlyphCount * 2 );
506
for ( ; GlyphCount > 0; GlyphCount-- )
507
if ( FT_NEXT_USHORT( p ) >= valid->glyph_count )
520
static const OTV_Validate_Func otv_gsub_validate_funcs[8] =
522
otv_SingleSubst_validate,
523
otv_MultipleSubst_validate,
524
otv_AlternateSubst_validate,
525
otv_LigatureSubst_validate,
526
otv_ContextSubst_validate,
527
otv_ChainContextSubst_validate,
528
otv_ExtensionSubst_validate,
529
otv_ReverseChainSingleSubst_validate
533
/*************************************************************************/
534
/*************************************************************************/
536
/***** GSUB TABLE *****/
538
/*************************************************************************/
539
/*************************************************************************/
541
/* sets valid->type_count */
542
/* sets valid->type_funcs */
543
/* sets valid->glyph_count */
546
otv_GSUB_validate( FT_Bytes table,
548
FT_Validator ftvalid )
550
OTV_ValidatorRec validrec;
551
OTV_Validator valid = &validrec;
553
FT_UInt ScriptList, FeatureList, LookupList;
556
valid->root = ftvalid;
558
FT_TRACE3(( "validating GSUB table\n" ));
561
OTV_LIMIT_CHECK( 10 );
563
if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */
566
ScriptList = FT_NEXT_USHORT( p );
567
FeatureList = FT_NEXT_USHORT( p );
568
LookupList = FT_NEXT_USHORT( p );
570
valid->type_count = 8;
571
valid->type_funcs = (OTV_Validate_Func*)otv_gsub_validate_funcs;
572
valid->glyph_count = glyph_count;
574
otv_LookupList_validate( table + LookupList,
576
otv_FeatureList_validate( table + FeatureList, table + LookupList,
578
otv_ScriptList_validate( table + ScriptList, table + FeatureList,