tizen 2.3.1 release
[framework/graphics/freetype.git] / src / otvalid / otvgsub.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  otvgsub.c                                                              */
4 /*                                                                         */
5 /*    OpenType GSUB table validation (body).                               */
6 /*                                                                         */
7 /*  Copyright 2004, 2005, 2007 by                                          */
8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9 /*                                                                         */
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.                                        */
15 /*                                                                         */
16 /***************************************************************************/
17
18
19 #include "otvalid.h"
20 #include "otvcommn.h"
21
22
23   /*************************************************************************/
24   /*                                                                       */
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.                                            */
28   /*                                                                       */
29 #undef  FT_COMPONENT
30 #define FT_COMPONENT  trace_otvgsub
31
32
33   /*************************************************************************/
34   /*************************************************************************/
35   /*****                                                               *****/
36   /*****                  GSUB LOOKUP TYPE 1                           *****/
37   /*****                                                               *****/
38   /*************************************************************************/
39   /*************************************************************************/
40
41   /* uses otvalid->glyph_count */
42
43   static void
44   otv_SingleSubst_validate( FT_Bytes       table,
45                             OTV_Validator  otvalid )
46   {
47     FT_Bytes  p = table;
48     FT_UInt   SubstFormat;
49
50
51     OTV_NAME_ENTER( "SingleSubst" );
52
53     OTV_LIMIT_CHECK( 2 );
54     SubstFormat = FT_NEXT_USHORT( p );
55
56     OTV_TRACE(( " (format %d)\n", SubstFormat ));
57
58     switch ( SubstFormat )
59     {
60     case 1:     /* SingleSubstFormat1 */
61       {
62         FT_Bytes  Coverage;
63         FT_Int    DeltaGlyphID;
64         FT_Long   idx;
65
66
67         OTV_LIMIT_CHECK( 4 );
68         Coverage     = table + FT_NEXT_USHORT( p );
69         DeltaGlyphID = FT_NEXT_SHORT( p );
70
71         otv_Coverage_validate( Coverage, otvalid, -1 );
72
73         idx = otv_Coverage_get_first( Coverage ) + DeltaGlyphID;
74         if ( idx < 0 )
75           FT_INVALID_DATA;
76
77         idx = otv_Coverage_get_last( Coverage ) + DeltaGlyphID;
78         if ( (FT_UInt)idx >= otvalid->glyph_count )
79           FT_INVALID_DATA;
80       }
81       break;
82
83     case 2:     /* SingleSubstFormat2 */
84       {
85         FT_UInt  Coverage, GlyphCount;
86
87
88         OTV_LIMIT_CHECK( 4 );
89         Coverage   = FT_NEXT_USHORT( p );
90         GlyphCount = FT_NEXT_USHORT( p );
91
92         OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
93
94         otv_Coverage_validate( table + Coverage, otvalid, GlyphCount );
95
96         OTV_LIMIT_CHECK( GlyphCount * 2 );
97
98         /* Substitute */
99         for ( ; GlyphCount > 0; GlyphCount-- )
100           if ( FT_NEXT_USHORT( p ) >= otvalid->glyph_count )
101             FT_INVALID_GLYPH_ID;
102       }
103       break;
104
105     default:
106       FT_INVALID_FORMAT;
107     }
108
109     OTV_EXIT;
110   }
111
112
113   /*************************************************************************/
114   /*************************************************************************/
115   /*****                                                               *****/
116   /*****                  GSUB LOOKUP TYPE 2                           *****/
117   /*****                                                               *****/
118   /*************************************************************************/
119   /*************************************************************************/
120
121   /* sets otvalid->extra1 (glyph count) */
122
123   static void
124   otv_MultipleSubst_validate( FT_Bytes       table,
125                               OTV_Validator  otvalid )
126   {
127     FT_Bytes  p = table;
128     FT_UInt   SubstFormat;
129
130
131     OTV_NAME_ENTER( "MultipleSubst" );
132
133     OTV_LIMIT_CHECK( 2 );
134     SubstFormat = FT_NEXT_USHORT( p );
135
136     OTV_TRACE(( " (format %d)\n", SubstFormat ));
137
138     switch ( SubstFormat )
139     {
140     case 1:
141       otvalid->extra1 = otvalid->glyph_count;
142       OTV_NEST2( MultipleSubstFormat1, Sequence );
143       OTV_RUN( table, otvalid );
144       break;
145
146     default:
147       FT_INVALID_FORMAT;
148     }
149
150     OTV_EXIT;
151   }
152
153
154   /*************************************************************************/
155   /*************************************************************************/
156   /*****                                                               *****/
157   /*****                    GSUB LOOKUP TYPE 3                         *****/
158   /*****                                                               *****/
159   /*************************************************************************/
160   /*************************************************************************/
161
162   /* sets otvalid->extra1 (glyph count) */
163
164   static void
165   otv_AlternateSubst_validate( FT_Bytes       table,
166                                OTV_Validator  otvalid )
167   {
168     FT_Bytes  p = table;
169     FT_UInt   SubstFormat;
170
171
172     OTV_NAME_ENTER( "AlternateSubst" );
173
174     OTV_LIMIT_CHECK( 2 );
175     SubstFormat = FT_NEXT_USHORT( p );
176
177     OTV_TRACE(( " (format %d)\n", SubstFormat ));
178
179     switch ( SubstFormat )
180     {
181     case 1:
182       otvalid->extra1 = otvalid->glyph_count;
183       OTV_NEST2( AlternateSubstFormat1, AlternateSet );
184       OTV_RUN( table, otvalid );
185       break;
186
187     default:
188       FT_INVALID_FORMAT;
189     }
190
191     OTV_EXIT;
192   }
193
194
195   /*************************************************************************/
196   /*************************************************************************/
197   /*****                                                               *****/
198   /*****                    GSUB LOOKUP TYPE 4                         *****/
199   /*****                                                               *****/
200   /*************************************************************************/
201   /*************************************************************************/
202
203 #define LigatureFunc  otv_Ligature_validate
204
205   /* uses otvalid->glyph_count */
206
207   static void
208   otv_Ligature_validate( FT_Bytes       table,
209                          OTV_Validator  otvalid )
210   {
211     FT_Bytes  p = table;
212     FT_UInt   LigatureGlyph, CompCount;
213
214
215     OTV_ENTER;
216
217     OTV_LIMIT_CHECK( 4 );
218     LigatureGlyph = FT_NEXT_USHORT( p );
219     if ( LigatureGlyph >= otvalid->glyph_count )
220       FT_INVALID_DATA;
221
222     CompCount = FT_NEXT_USHORT( p );
223
224     OTV_TRACE(( " (CompCount = %d)\n", CompCount ));
225
226     if ( CompCount == 0 )
227       FT_INVALID_DATA;
228
229     CompCount--;
230
231     OTV_LIMIT_CHECK( CompCount * 2 );     /* Component */
232
233     /* no need to check the Component glyph indices */
234
235     OTV_EXIT;
236   }
237
238
239   static void
240   otv_LigatureSubst_validate( FT_Bytes       table,
241                               OTV_Validator  otvalid )
242   {
243     FT_Bytes  p = table;
244     FT_UInt   SubstFormat;
245
246
247     OTV_NAME_ENTER( "LigatureSubst" );
248
249     OTV_LIMIT_CHECK( 2 );
250     SubstFormat = FT_NEXT_USHORT( p );
251
252     OTV_TRACE(( " (format %d)\n", SubstFormat ));
253
254     switch ( SubstFormat )
255     {
256     case 1:
257       OTV_NEST3( LigatureSubstFormat1, LigatureSet, Ligature );
258       OTV_RUN( table, otvalid );
259       break;
260
261     default:
262       FT_INVALID_FORMAT;
263     }
264
265     OTV_EXIT;
266   }
267
268
269   /*************************************************************************/
270   /*************************************************************************/
271   /*****                                                               *****/
272   /*****                  GSUB LOOKUP TYPE 5                           *****/
273   /*****                                                               *****/
274   /*************************************************************************/
275   /*************************************************************************/
276
277   /* sets otvalid->extra1 (lookup count) */
278
279   static void
280   otv_ContextSubst_validate( FT_Bytes       table,
281                              OTV_Validator  otvalid )
282   {
283     FT_Bytes  p = table;
284     FT_UInt   SubstFormat;
285
286
287     OTV_NAME_ENTER( "ContextSubst" );
288
289     OTV_LIMIT_CHECK( 2 );
290     SubstFormat = FT_NEXT_USHORT( p );
291
292     OTV_TRACE(( " (format %d)\n", SubstFormat ));
293
294     switch ( SubstFormat )
295     {
296     case 1:
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                                             */
300
301       otvalid->extra1 = otvalid->lookup_count;
302       OTV_NEST3( ContextSubstFormat1, SubRuleSet, SubRule );
303       OTV_RUN( table, otvalid );
304       break;
305
306     case 2:
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                                             */
310
311       OTV_NEST3( ContextSubstFormat2, SubClassSet, SubClassRule );
312       OTV_RUN( table, otvalid );
313       break;
314
315     case 3:
316       OTV_NEST1( ContextSubstFormat3 );
317       OTV_RUN( table, otvalid );
318       break;
319
320     default:
321       FT_INVALID_FORMAT;
322     }
323
324     OTV_EXIT;
325   }
326
327
328   /*************************************************************************/
329   /*************************************************************************/
330   /*****                                                               *****/
331   /*****                    GSUB LOOKUP TYPE 6                         *****/
332   /*****                                                               *****/
333   /*************************************************************************/
334   /*************************************************************************/
335
336   /* sets otvalid->extra1 (lookup count)            */
337
338   static void
339   otv_ChainContextSubst_validate( FT_Bytes       table,
340                                   OTV_Validator  otvalid )
341   {
342     FT_Bytes  p = table;
343     FT_UInt   SubstFormat;
344
345
346     OTV_NAME_ENTER( "ChainContextSubst" );
347
348     OTV_LIMIT_CHECK( 2 );
349     SubstFormat = FT_NEXT_USHORT( p );
350
351     OTV_TRACE(( " (format %d)\n", SubstFormat ));
352
353     switch ( SubstFormat )
354     {
355     case 1:
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                                             */
359
360       otvalid->extra1 = otvalid->lookup_count;
361       OTV_NEST3( ChainContextSubstFormat1,
362                  ChainSubRuleSet, ChainSubRule );
363       OTV_RUN( table, otvalid );
364       break;
365
366     case 2:
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                                             */
370
371       OTV_NEST3( ChainContextSubstFormat2,
372                  ChainSubClassSet, ChainSubClassRule );
373       OTV_RUN( table, otvalid );
374       break;
375
376     case 3:
377       OTV_NEST1( ChainContextSubstFormat3 );
378       OTV_RUN( table, otvalid );
379       break;
380
381     default:
382       FT_INVALID_FORMAT;
383     }
384
385     OTV_EXIT;
386   }
387
388
389   /*************************************************************************/
390   /*************************************************************************/
391   /*****                                                               *****/
392   /*****                    GSUB LOOKUP TYPE 7                         *****/
393   /*****                                                               *****/
394   /*************************************************************************/
395   /*************************************************************************/
396
397   /* uses otvalid->type_funcs */
398
399   static void
400   otv_ExtensionSubst_validate( FT_Bytes       table,
401                                OTV_Validator  otvalid )
402   {
403     FT_Bytes  p = table;
404     FT_UInt   SubstFormat;
405
406
407     OTV_NAME_ENTER( "ExtensionSubst" );
408
409     OTV_LIMIT_CHECK( 2 );
410     SubstFormat = FT_NEXT_USHORT( p );
411
412     OTV_TRACE(( " (format %d)\n", SubstFormat ));
413
414     switch ( SubstFormat )
415     {
416     case 1:     /* ExtensionSubstFormat1 */
417       {
418         FT_UInt            ExtensionLookupType;
419         FT_ULong           ExtensionOffset;
420         OTV_Validate_Func  validate;
421
422
423         OTV_LIMIT_CHECK( 6 );
424         ExtensionLookupType = FT_NEXT_USHORT( p );
425         ExtensionOffset     = FT_NEXT_ULONG( p );
426
427         if ( ExtensionLookupType == 0 ||
428              ExtensionLookupType == 7 ||
429              ExtensionLookupType > 8  )
430           FT_INVALID_DATA;
431
432         validate = otvalid->type_funcs[ExtensionLookupType - 1];
433         validate( table + ExtensionOffset, otvalid );
434       }
435       break;
436
437     default:
438       FT_INVALID_FORMAT;
439     }
440
441     OTV_EXIT;
442   }
443
444
445   /*************************************************************************/
446   /*************************************************************************/
447   /*****                                                               *****/
448   /*****                    GSUB LOOKUP TYPE 8                         *****/
449   /*****                                                               *****/
450   /*************************************************************************/
451   /*************************************************************************/
452
453   /* uses otvalid->glyph_count */
454
455   static void
456   otv_ReverseChainSingleSubst_validate( FT_Bytes       table,
457                                         OTV_Validator  otvalid )
458   {
459     FT_Bytes  p = table, Coverage;
460     FT_UInt   SubstFormat;
461     FT_UInt   BacktrackGlyphCount, LookaheadGlyphCount, GlyphCount;
462
463
464     OTV_NAME_ENTER( "ReverseChainSingleSubst" );
465
466     OTV_LIMIT_CHECK( 2 );
467     SubstFormat = FT_NEXT_USHORT( p );
468
469     OTV_TRACE(( " (format %d)\n", SubstFormat ));
470
471     switch ( SubstFormat )
472     {
473     case 1:     /* ReverseChainSingleSubstFormat1 */
474       OTV_LIMIT_CHECK( 4 );
475       Coverage            = table + FT_NEXT_USHORT( p );
476       BacktrackGlyphCount = FT_NEXT_USHORT( p );
477
478       OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
479
480       otv_Coverage_validate( Coverage, otvalid, -1 );
481
482       OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
483
484       for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
485         otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
486
487       LookaheadGlyphCount = FT_NEXT_USHORT( p );
488
489       OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
490
491       OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
492
493       for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
494         otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
495
496       GlyphCount = FT_NEXT_USHORT( p );
497
498       OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
499
500       if ( GlyphCount != otv_Coverage_get_count( Coverage ) )
501         FT_INVALID_DATA;
502
503       OTV_LIMIT_CHECK( GlyphCount * 2 );
504
505       /* Substitute */
506       for ( ; GlyphCount > 0; GlyphCount-- )
507         if ( FT_NEXT_USHORT( p ) >= otvalid->glyph_count )
508           FT_INVALID_DATA;
509
510       break;
511
512     default:
513       FT_INVALID_FORMAT;
514     }
515
516     OTV_EXIT;
517   }
518
519
520   static const OTV_Validate_Func  otv_gsub_validate_funcs[8] =
521   {
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
530   };
531
532
533   /*************************************************************************/
534   /*************************************************************************/
535   /*****                                                               *****/
536   /*****                          GSUB TABLE                           *****/
537   /*****                                                               *****/
538   /*************************************************************************/
539   /*************************************************************************/
540
541   /* sets otvalid->type_count  */
542   /* sets otvalid->type_funcs  */
543   /* sets otvalid->glyph_count */
544
545   FT_LOCAL_DEF( void )
546   otv_GSUB_validate( FT_Bytes      table,
547                      FT_UInt       glyph_count,
548                      FT_Validator  ftvalid )
549   {
550     OTV_ValidatorRec  otvalidrec;
551     OTV_Validator     otvalid = &otvalidrec;
552     FT_Bytes          p       = table;
553     FT_UInt           ScriptList, FeatureList, LookupList;
554
555
556     otvalid->root = ftvalid;
557
558     FT_TRACE3(( "validating GSUB table\n" ));
559     OTV_INIT;
560
561     OTV_LIMIT_CHECK( 10 );
562
563     if ( FT_NEXT_ULONG( p ) != 0x10000UL )      /* Version */
564       FT_INVALID_FORMAT;
565
566     ScriptList  = FT_NEXT_USHORT( p );
567     FeatureList = FT_NEXT_USHORT( p );
568     LookupList  = FT_NEXT_USHORT( p );
569
570     otvalid->type_count  = 8;
571     otvalid->type_funcs  = (OTV_Validate_Func*)otv_gsub_validate_funcs;
572     otvalid->glyph_count = glyph_count;
573
574     otv_LookupList_validate( table + LookupList,
575                              otvalid );
576     otv_FeatureList_validate( table + FeatureList, table + LookupList,
577                               otvalid );
578     otv_ScriptList_validate( table + ScriptList, table + FeatureList,
579                              otvalid );
580
581     FT_TRACE4(( "\n" ));
582   }
583
584
585 /* END */