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

Last change on this file since 275 was 275, checked in by rbri, 12 years ago

PDF plugin: freetype library updated to version 2.3.11

File size: 17.6 KB
Line 
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 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, -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 >= 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, GlyphCount );
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_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 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_FORMAT;
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_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 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_FORMAT;
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_FORMAT;
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_FORMAT;
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;
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 = valid->type_funcs[ExtensionLookupType - 1];
433        validate( table + ExtensionOffset, valid );
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 valid->glyph_count */
454
455  static void
456  otv_ReverseChainSingleSubst_validate( FT_Bytes       table,
457                                        OTV_Validator  valid )
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, valid, -1 );
481
482      OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
483
484      for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
485        otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -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 ), valid, -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 ) >= valid->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 valid->type_count  */
542  /* sets valid->type_funcs  */
543  /* sets valid->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  validrec;
551    OTV_Validator     valid = &validrec;
552    FT_Bytes          p     = table;
553    FT_UInt           ScriptList, FeatureList, LookupList;
554
555
556    valid->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    valid->type_count  = 8;
571    valid->type_funcs  = (OTV_Validate_Func*)otv_gsub_validate_funcs;
572    valid->glyph_count = glyph_count;
573
574    otv_LookupList_validate( table + LookupList,
575                             valid );
576    otv_FeatureList_validate( table + FeatureList, table + LookupList,
577                              valid );
578    otv_ScriptList_validate( table + ScriptList, table + FeatureList,
579                             valid );
580
581    FT_TRACE4(( "\n" ));
582  }
583
584
585/* END */
Note: See TracBrowser for help on using the repository browser.