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 otvalid->glyph_count */
44 otv_SingleSubst_validate( FT_Bytes table,
45 OTV_Validator otvalid )
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, otvalid, -1 );
73 idx = otv_Coverage_get_first( Coverage ) + DeltaGlyphID;
77 idx = otv_Coverage_get_last( Coverage ) + DeltaGlyphID;
78 if ( (FT_UInt)idx >= otvalid->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, otvalid, GlyphCount );
96 OTV_LIMIT_CHECK( GlyphCount * 2 );
99 for ( ; GlyphCount > 0; GlyphCount-- )
100 if ( FT_NEXT_USHORT( p ) >= otvalid->glyph_count )
113 /*************************************************************************/
114 /*************************************************************************/
116 /***** GSUB LOOKUP TYPE 2 *****/
118 /*************************************************************************/
119 /*************************************************************************/
121 /* sets otvalid->extra1 (glyph count) */
124 otv_MultipleSubst_validate( FT_Bytes table,
125 OTV_Validator otvalid )
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 otvalid->extra1 = otvalid->glyph_count;
142 OTV_NEST2( MultipleSubstFormat1, Sequence );
143 OTV_RUN( table, otvalid );
154 /*************************************************************************/
155 /*************************************************************************/
157 /***** GSUB LOOKUP TYPE 3 *****/
159 /*************************************************************************/
160 /*************************************************************************/
162 /* sets otvalid->extra1 (glyph count) */
165 otv_AlternateSubst_validate( FT_Bytes table,
166 OTV_Validator otvalid )
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 otvalid->extra1 = otvalid->glyph_count;
183 OTV_NEST2( AlternateSubstFormat1, AlternateSet );
184 OTV_RUN( table, otvalid );
195 /*************************************************************************/
196 /*************************************************************************/
198 /***** GSUB LOOKUP TYPE 4 *****/
200 /*************************************************************************/
201 /*************************************************************************/
203 #define LigatureFunc otv_Ligature_validate
205 /* uses otvalid->glyph_count */
208 otv_Ligature_validate( FT_Bytes table,
209 OTV_Validator otvalid )
212 FT_UInt LigatureGlyph, CompCount;
217 OTV_LIMIT_CHECK( 4 );
218 LigatureGlyph = FT_NEXT_USHORT( p );
219 if ( LigatureGlyph >= otvalid->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 otvalid )
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, otvalid );
269 /*************************************************************************/
270 /*************************************************************************/
272 /***** GSUB LOOKUP TYPE 5 *****/
274 /*************************************************************************/
275 /*************************************************************************/
277 /* sets otvalid->extra1 (lookup count) */
280 otv_ContextSubst_validate( FT_Bytes table,
281 OTV_Validator otvalid )
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 otvalid->extra1 = otvalid->lookup_count;
302 OTV_NEST3( ContextSubstFormat1, SubRuleSet, SubRule );
303 OTV_RUN( table, otvalid );
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, otvalid );
316 OTV_NEST1( ContextSubstFormat3 );
317 OTV_RUN( table, otvalid );
328 /*************************************************************************/
329 /*************************************************************************/
331 /***** GSUB LOOKUP TYPE 6 *****/
333 /*************************************************************************/
334 /*************************************************************************/
336 /* sets otvalid->extra1 (lookup count) */
339 otv_ChainContextSubst_validate( FT_Bytes table,
340 OTV_Validator otvalid )
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 otvalid->extra1 = otvalid->lookup_count;
361 OTV_NEST3( ChainContextSubstFormat1,
362 ChainSubRuleSet, ChainSubRule );
363 OTV_RUN( table, otvalid );
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, otvalid );
377 OTV_NEST1( ChainContextSubstFormat3 );
378 OTV_RUN( table, otvalid );
389 /*************************************************************************/
390 /*************************************************************************/
392 /***** GSUB LOOKUP TYPE 7 *****/
394 /*************************************************************************/
395 /*************************************************************************/
397 /* uses otvalid->type_funcs */
400 otv_ExtensionSubst_validate( FT_Bytes table,
401 OTV_Validator otvalid )
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 = otvalid->type_funcs[ExtensionLookupType - 1];
433 validate( table + ExtensionOffset, otvalid );
445 /*************************************************************************/
446 /*************************************************************************/
448 /***** GSUB LOOKUP TYPE 8 *****/
450 /*************************************************************************/
451 /*************************************************************************/
453 /* uses otvalid->glyph_count */
456 otv_ReverseChainSingleSubst_validate( FT_Bytes table,
457 OTV_Validator otvalid )
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, otvalid, -1 );
482 OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
484 for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
485 otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -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 ), otvalid, -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 ) >= otvalid->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 otvalid->type_count */
542 /* sets otvalid->type_funcs */
543 /* sets otvalid->glyph_count */
546 otv_GSUB_validate( FT_Bytes table,
548 FT_Validator ftvalid )
550 OTV_ValidatorRec otvalidrec;
551 OTV_Validator otvalid = &otvalidrec;
553 FT_UInt ScriptList, FeatureList, LookupList;
556 otvalid->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 otvalid->type_count = 8;
571 otvalid->type_funcs = (OTV_Validate_Func*)otv_gsub_validate_funcs;
572 otvalid->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,