misc/libfreetype/src/otvalid/otvgsub.c
changeset 9372 915436ff64ab
parent 9371 f3840de881bd
child 9373 b769a8e38cbd
equal deleted inserted replaced
9371:f3840de881bd 9372:915436ff64ab
     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 */