source: trunk/poppler/freetype2/src/otvalid/otvgsub.c @ 182

Last change on this file since 182 was 150, checked in by Eugene Romanenko, 15 years ago

update freetype to 2.2.1

File size: 18.1 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  otvgsub.c                                                              */
4/*                                                                         */
5/*    OpenType GSUB table validation (body).                               */
6/*                                                                         */
7/*  Copyright 2004, 2005 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 valid->glyph_count */
42
43  static void
44  otv_SingleSubst_validate( FT_Bytes       table,
45                            OTV_Validator  valid )
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, valid );
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 >= valid->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, valid );
95
96        OTV_LIMIT_CHECK( GlyphCount * 2 );
97
98        /* Substitute */
99        for ( ; GlyphCount > 0; GlyphCount-- )
100          if ( FT_NEXT_USHORT( p ) >= valid->glyph_count )
101            FT_INVALID_DATA;
102      }
103      break;
104
105    default:
106      FT_INVALID_DATA;
107    }
108
109    OTV_EXIT;
110  }
111
112
113  /*************************************************************************/
114  /*************************************************************************/
115  /*****                                                               *****/
116  /*****                  GSUB LOOKUP TYPE 2                           *****/
117  /*****                                                               *****/
118  /*************************************************************************/
119  /*************************************************************************/
120
121  /* sets valid->extra1 (glyph count) */
122
123  static void
124  otv_MultipleSubst_validate( FT_Bytes       table,
125                              OTV_Validator  valid )
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      valid->extra1 = valid->glyph_count;
142      OTV_NEST2( MultipleSubstFormat1, Sequence );
143      OTV_RUN( table, valid );
144      break;
145
146    default:
147      FT_INVALID_DATA;
148    }
149
150    OTV_EXIT;
151  }
152
153
154  /*************************************************************************/
155  /*************************************************************************/
156  /*****                                                               *****/
157  /*****                    GSUB LOOKUP TYPE 3                         *****/
158  /*****                                                               *****/
159  /*************************************************************************/
160  /*************************************************************************/
161
162  /* sets valid->extra1 (glyph count) */
163
164  static void
165  otv_AlternateSubst_validate( FT_Bytes       table,
166                               OTV_Validator  valid )
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      valid->extra1 = valid->glyph_count;
183      OTV_NEST2( AlternateSubstFormat1, AlternateSet );
184      OTV_RUN( table, valid );
185      break;
186
187    default:
188      FT_INVALID_DATA;
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 valid->glyph_count */
206
207  static void
208  otv_Ligature_validate( FT_Bytes       table,
209                         OTV_Validator  valid )
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 >= valid->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  valid )
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, valid );
259      break;
260
261    default:
262      FT_INVALID_DATA;
263    }
264
265    OTV_EXIT;
266  }
267
268
269  /*************************************************************************/
270  /*************************************************************************/
271  /*****                                                               *****/
272  /*****                  GSUB LOOKUP TYPE 5                           *****/
273  /*****                                                               *****/
274  /*************************************************************************/
275  /*************************************************************************/
276
277  /* sets valid->extra1 (lookup count) */
278
279  static void
280  otv_ContextSubst_validate( FT_Bytes       table,
281                             OTV_Validator  valid )
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      valid->extra1 = valid->lookup_count;
302      OTV_NEST3( ContextSubstFormat1, SubRuleSet, SubRule );
303      OTV_RUN( table, valid );
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, valid );
313      break;
314
315    case 3:
316      OTV_NEST1( ContextSubstFormat3 );
317      OTV_RUN( table, valid );
318      break;
319
320    default:
321      FT_INVALID_DATA;
322    }
323
324    OTV_EXIT;
325  }
326
327
328  /*************************************************************************/
329  /*************************************************************************/
330  /*****                                                               *****/
331  /*****                    GSUB LOOKUP TYPE 6                         *****/
332  /*****                                                               *****/
333  /*************************************************************************/
334  /*************************************************************************/
335
336  /* sets valid->extra1 (lookup count)            */
337
338  static void
339  otv_ChainContextSubst_validate( FT_Bytes       table,
340                                  OTV_Validator  valid )
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      valid->extra1 = valid->lookup_count;
361      OTV_NEST3( ChainContextSubstFormat1,
362                 ChainSubRuleSet, ChainSubRule );
363      OTV_RUN( table, valid );
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, valid );
374      break;
375
376    case 3:
377      OTV_NEST1( ChainContextSubstFormat3 );
378      OTV_RUN( table, valid );
379      break;
380
381    default:
382      FT_INVALID_DATA;
383    }
384
385    OTV_EXIT;
386  }
387
388
389  /*************************************************************************/
390  /*************************************************************************/
391  /*****                                                               *****/
392  /*****                    GSUB LOOKUP TYPE 7                         *****/
393  /*****                                                               *****/
394  /*************************************************************************/
395  /*************************************************************************/
396
397  /* uses valid->type_funcs */
398
399  static void
400  otv_ExtensionSubst_validate( FT_Bytes       table,
401                               OTV_Validator  valid )
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, ExtensionOffset;
419        OTV_Validate_Func  validate;
420
421
422        OTV_LIMIT_CHECK( 6 );
423        ExtensionLookupType = FT_NEXT_USHORT( p );
424        ExtensionOffset     = FT_NEXT_ULONG( p );
425
426        if ( ExtensionLookupType == 0 ||
427             ExtensionLookupType == 7 ||
428             ExtensionLookupType > 8  )
429          FT_INVALID_DATA;
430
431        validate = valid->type_funcs[ExtensionLookupType - 1];
432        validate( table + ExtensionOffset, valid );
433      }
434      break;
435
436    default:
437      FT_INVALID_DATA;
438    }
439
440    OTV_EXIT;
441  }
442
443
444  /*************************************************************************/
445  /*************************************************************************/
446  /*****                                                               *****/
447  /*****                    GSUB LOOKUP TYPE 8                         *****/
448  /*****                                                               *****/
449  /*************************************************************************/
450  /*************************************************************************/
451
452  /* uses valid->glyph_count */
453
454  static void
455  otv_ReverseChainSingleSubst_validate( FT_Bytes       table,
456                                        OTV_Validator  valid )
457  {
458    FT_Bytes  p = table, Coverage;
459    FT_UInt   SubstFormat;
460    FT_UInt   BacktrackGlyphCount, LookaheadGlyphCount, GlyphCount;
461
462
463    OTV_NAME_ENTER( "ReverseChainSingleSubst" );
464
465    OTV_LIMIT_CHECK( 2 );
466    SubstFormat = FT_NEXT_USHORT( p );
467
468    OTV_TRACE(( " (format %d)\n", SubstFormat ));
469
470    switch ( SubstFormat )
471    {
472    case 1:     /* ReverseChainSingleSubstFormat1 */
473      OTV_LIMIT_CHECK( 4 );
474      Coverage            = table + FT_NEXT_USHORT( p );
475      BacktrackGlyphCount = FT_NEXT_USHORT( p );
476
477      OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
478
479      otv_Coverage_validate( Coverage, valid );
480
481      OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
482
483      for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
484        otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid );
485
486      LookaheadGlyphCount = FT_NEXT_USHORT( p );
487
488      OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
489
490      OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
491
492      for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
493        otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid );
494
495      GlyphCount = FT_NEXT_USHORT( p );
496
497      OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
498
499      if ( GlyphCount != otv_Coverage_get_count( Coverage ) )
500        FT_INVALID_DATA;
501
502      OTV_LIMIT_CHECK( GlyphCount * 2 );
503
504      /* Substitute */
505      for ( ; GlyphCount > 0; GlyphCount-- )
506        if ( FT_NEXT_USHORT( p ) >= valid->glyph_count )
507          FT_INVALID_DATA;
508
509      break;
510
511    default:
512      FT_INVALID_DATA;
513    }
514
515    OTV_EXIT;
516  }
517
518
519  static const OTV_Validate_Func  otv_gsub_validate_funcs[8] =
520  {
521    otv_SingleSubst_validate,
522    otv_MultipleSubst_validate,
523    otv_AlternateSubst_validate,
524    otv_LigatureSubst_validate,
525    otv_ContextSubst_validate,
526    otv_ChainContextSubst_validate,
527    otv_ExtensionSubst_validate,
528    otv_ReverseChainSingleSubst_validate
529  };
530
531
532  /*************************************************************************/
533  /*************************************************************************/
534  /*****                                                               *****/
535  /*****                          GSUB TABLE                           *****/
536  /*****                                                               *****/
537  /*************************************************************************/
538  /*************************************************************************/
539
540  /* sets valid->type_count  */
541  /* sets valid->type_funcs  */
542  /* sets valid->glyph_count */
543
544  FT_LOCAL_DEF( void )
545  otv_GSUB_validate( FT_Bytes      table,
546                     FT_UInt       glyph_count,
547                     FT_Validator  ftvalid )
548  {
549    OTV_ValidatorRec  validrec;
550    OTV_Validator     valid = &validrec;
551    FT_Bytes          p     = table;
552    FT_UInt           ScriptList, FeatureList, LookupList;
553
554
555    valid->root = ftvalid;
556
557    FT_TRACE3(( "validating GSUB table\n" ));
558    OTV_INIT;
559
560    OTV_LIMIT_CHECK( 10 );
561
562    if ( FT_NEXT_ULONG( p ) != 0x10000UL )      /* Version */
563      FT_INVALID_DATA;
564
565    ScriptList  = FT_NEXT_USHORT( p );
566    FeatureList = FT_NEXT_USHORT( p );
567    LookupList  = FT_NEXT_USHORT( p );
568
569    valid->type_count  = 8;
570    valid->type_funcs  = (OTV_Validate_Func*)otv_gsub_validate_funcs;
571    valid->glyph_count = glyph_count;
572
573    otv_LookupList_validate( table + LookupList,
574                             valid );
575    otv_FeatureList_validate( table + FeatureList, table + LookupList,
576                              valid );
577    otv_ScriptList_validate( table + ScriptList, table + FeatureList,
578                             valid );
579
580    FT_TRACE4(( "\n" ));
581  }
582
583
584/* END */
Note: See TracBrowser for help on using the repository browser.