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
,