otvgsub.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  otvgsub.c                                                              */
00004 /*                                                                         */
00005 /*    OpenType GSUB table validation (body).                               */
00006 /*                                                                         */
00007 /*  Copyright 2004, 2005, 2007 by                                          */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019 #include "otvalid.h"
00020 #include "otvcommn.h"
00021 
00022 
00023   /*************************************************************************/
00024   /*                                                                       */
00025   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00026   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00027   /* messages during execution.                                            */
00028   /*                                                                       */
00029 #undef  FT_COMPONENT
00030 #define FT_COMPONENT  trace_otvgsub
00031 
00032 
00033   /*************************************************************************/
00034   /*************************************************************************/
00035   /*****                                                               *****/
00036   /*****                  GSUB LOOKUP TYPE 1                           *****/
00037   /*****                                                               *****/
00038   /*************************************************************************/
00039   /*************************************************************************/
00040 
00041   /* uses valid->glyph_count */
00042 
00043   static void
00044   otv_SingleSubst_validate( FT_Bytes       table,
00045                             OTV_Validator  valid )
00046   {
00047     FT_Bytes  p = table;
00048     FT_UInt   SubstFormat;
00049 
00050 
00051     OTV_NAME_ENTER( "SingleSubst" );
00052 
00053     OTV_LIMIT_CHECK( 2 );
00054     SubstFormat = FT_NEXT_USHORT( p );
00055 
00056     OTV_TRACE(( " (format %d)\n", SubstFormat ));
00057 
00058     switch ( SubstFormat )
00059     {
00060     case 1:     /* SingleSubstFormat1 */
00061       {
00062         FT_Bytes  Coverage;
00063         FT_Int    DeltaGlyphID;
00064         FT_Long   idx;
00065 
00066 
00067         OTV_LIMIT_CHECK( 4 );
00068         Coverage     = table + FT_NEXT_USHORT( p );
00069         DeltaGlyphID = FT_NEXT_SHORT( p );
00070 
00071         otv_Coverage_validate( Coverage, valid, -1 );
00072 
00073         idx = otv_Coverage_get_first( Coverage ) + DeltaGlyphID;
00074         if ( idx < 0 )
00075           FT_INVALID_DATA;
00076 
00077         idx = otv_Coverage_get_last( Coverage ) + DeltaGlyphID;
00078         if ( (FT_UInt)idx >= valid->glyph_count )
00079           FT_INVALID_DATA;
00080       }
00081       break;
00082 
00083     case 2:     /* SingleSubstFormat2 */
00084       {
00085         FT_UInt  Coverage, GlyphCount;
00086 
00087 
00088         OTV_LIMIT_CHECK( 4 );
00089         Coverage   = FT_NEXT_USHORT( p );
00090         GlyphCount = FT_NEXT_USHORT( p );
00091 
00092         OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
00093 
00094         otv_Coverage_validate( table + Coverage, valid, GlyphCount );
00095 
00096         OTV_LIMIT_CHECK( GlyphCount * 2 );
00097 
00098         /* Substitute */
00099         for ( ; GlyphCount > 0; GlyphCount-- )
00100           if ( FT_NEXT_USHORT( p ) >= valid->glyph_count )
00101             FT_INVALID_GLYPH_ID;
00102       }
00103       break;
00104 
00105     default:
00106       FT_INVALID_FORMAT;
00107     }
00108 
00109     OTV_EXIT;
00110   }
00111 
00112 
00113   /*************************************************************************/
00114   /*************************************************************************/
00115   /*****                                                               *****/
00116   /*****                  GSUB LOOKUP TYPE 2                           *****/
00117   /*****                                                               *****/
00118   /*************************************************************************/
00119   /*************************************************************************/
00120 
00121   /* sets valid->extra1 (glyph count) */
00122 
00123   static void
00124   otv_MultipleSubst_validate( FT_Bytes       table,
00125                               OTV_Validator  valid )
00126   {
00127     FT_Bytes  p = table;
00128     FT_UInt   SubstFormat;
00129 
00130 
00131     OTV_NAME_ENTER( "MultipleSubst" );
00132 
00133     OTV_LIMIT_CHECK( 2 );
00134     SubstFormat = FT_NEXT_USHORT( p );
00135 
00136     OTV_TRACE(( " (format %d)\n", SubstFormat ));
00137 
00138     switch ( SubstFormat )
00139     {
00140     case 1:
00141       valid->extra1 = valid->glyph_count;
00142       OTV_NEST2( MultipleSubstFormat1, Sequence );
00143       OTV_RUN( table, valid );
00144       break;
00145 
00146     default:
00147       FT_INVALID_FORMAT;
00148     }
00149 
00150     OTV_EXIT;
00151   }
00152 
00153 
00154   /*************************************************************************/
00155   /*************************************************************************/
00156   /*****                                                               *****/
00157   /*****                    GSUB LOOKUP TYPE 3                         *****/
00158   /*****                                                               *****/
00159   /*************************************************************************/
00160   /*************************************************************************/
00161 
00162   /* sets valid->extra1 (glyph count) */
00163 
00164   static void
00165   otv_AlternateSubst_validate( FT_Bytes       table,
00166                                OTV_Validator  valid )
00167   {
00168     FT_Bytes  p = table;
00169     FT_UInt   SubstFormat;
00170 
00171 
00172     OTV_NAME_ENTER( "AlternateSubst" );
00173 
00174     OTV_LIMIT_CHECK( 2 );
00175     SubstFormat = FT_NEXT_USHORT( p );
00176 
00177     OTV_TRACE(( " (format %d)\n", SubstFormat ));
00178 
00179     switch ( SubstFormat )
00180     {
00181     case 1:
00182       valid->extra1 = valid->glyph_count;
00183       OTV_NEST2( AlternateSubstFormat1, AlternateSet );
00184       OTV_RUN( table, valid );
00185       break;
00186 
00187     default:
00188       FT_INVALID_FORMAT;
00189     }
00190 
00191     OTV_EXIT;
00192   }
00193 
00194 
00195   /*************************************************************************/
00196   /*************************************************************************/
00197   /*****                                                               *****/
00198   /*****                    GSUB LOOKUP TYPE 4                         *****/
00199   /*****                                                               *****/
00200   /*************************************************************************/
00201   /*************************************************************************/
00202 
00203 #define LigatureFunc  otv_Ligature_validate
00204 
00205   /* uses valid->glyph_count */
00206 
00207   static void
00208   otv_Ligature_validate( FT_Bytes       table,
00209                          OTV_Validator  valid )
00210   {
00211     FT_Bytes  p = table;
00212     FT_UInt   LigatureGlyph, CompCount;
00213 
00214 
00215     OTV_ENTER;
00216 
00217     OTV_LIMIT_CHECK( 4 );
00218     LigatureGlyph = FT_NEXT_USHORT( p );
00219     if ( LigatureGlyph >= valid->glyph_count )
00220       FT_INVALID_DATA;
00221 
00222     CompCount = FT_NEXT_USHORT( p );
00223 
00224     OTV_TRACE(( " (CompCount = %d)\n", CompCount ));
00225 
00226     if ( CompCount == 0 )
00227       FT_INVALID_DATA;
00228 
00229     CompCount--;
00230 
00231     OTV_LIMIT_CHECK( CompCount * 2 );     /* Component */
00232 
00233     /* no need to check the Component glyph indices */
00234 
00235     OTV_EXIT;
00236   }
00237 
00238 
00239   static void
00240   otv_LigatureSubst_validate( FT_Bytes       table,
00241                               OTV_Validator  valid )
00242   {
00243     FT_Bytes  p = table;
00244     FT_UInt   SubstFormat;
00245 
00246 
00247     OTV_NAME_ENTER( "LigatureSubst" );
00248 
00249     OTV_LIMIT_CHECK( 2 );
00250     SubstFormat = FT_NEXT_USHORT( p );
00251 
00252     OTV_TRACE(( " (format %d)\n", SubstFormat ));
00253 
00254     switch ( SubstFormat )
00255     {
00256     case 1:
00257       OTV_NEST3( LigatureSubstFormat1, LigatureSet, Ligature );
00258       OTV_RUN( table, valid );
00259       break;
00260 
00261     default:
00262       FT_INVALID_FORMAT;
00263     }
00264 
00265     OTV_EXIT;
00266   }
00267 
00268 
00269   /*************************************************************************/
00270   /*************************************************************************/
00271   /*****                                                               *****/
00272   /*****                  GSUB LOOKUP TYPE 5                           *****/
00273   /*****                                                               *****/
00274   /*************************************************************************/
00275   /*************************************************************************/
00276 
00277   /* sets valid->extra1 (lookup count) */
00278 
00279   static void
00280   otv_ContextSubst_validate( FT_Bytes       table,
00281                              OTV_Validator  valid )
00282   {
00283     FT_Bytes  p = table;
00284     FT_UInt   SubstFormat;
00285 
00286 
00287     OTV_NAME_ENTER( "ContextSubst" );
00288 
00289     OTV_LIMIT_CHECK( 2 );
00290     SubstFormat = FT_NEXT_USHORT( p );
00291 
00292     OTV_TRACE(( " (format %d)\n", SubstFormat ));
00293 
00294     switch ( SubstFormat )
00295     {
00296     case 1:
00297       /* no need to check glyph indices/classes used as input for these */
00298       /* context rules since even invalid glyph indices/classes return  */
00299       /* meaningful results                                             */
00300 
00301       valid->extra1 = valid->lookup_count;
00302       OTV_NEST3( ContextSubstFormat1, SubRuleSet, SubRule );
00303       OTV_RUN( table, valid );
00304       break;
00305 
00306     case 2:
00307       /* no need to check glyph indices/classes used as input for these */
00308       /* context rules since even invalid glyph indices/classes return  */
00309       /* meaningful results                                             */
00310 
00311       OTV_NEST3( ContextSubstFormat2, SubClassSet, SubClassRule );
00312       OTV_RUN( table, valid );
00313       break;
00314 
00315     case 3:
00316       OTV_NEST1( ContextSubstFormat3 );
00317       OTV_RUN( table, valid );
00318       break;
00319 
00320     default:
00321       FT_INVALID_FORMAT;
00322     }
00323 
00324     OTV_EXIT;
00325   }
00326 
00327 
00328   /*************************************************************************/
00329   /*************************************************************************/
00330   /*****                                                               *****/
00331   /*****                    GSUB LOOKUP TYPE 6                         *****/
00332   /*****                                                               *****/
00333   /*************************************************************************/
00334   /*************************************************************************/
00335 
00336   /* sets valid->extra1 (lookup count)            */
00337 
00338   static void
00339   otv_ChainContextSubst_validate( FT_Bytes       table,
00340                                   OTV_Validator  valid )
00341   {
00342     FT_Bytes  p = table;
00343     FT_UInt   SubstFormat;
00344 
00345 
00346     OTV_NAME_ENTER( "ChainContextSubst" );
00347 
00348     OTV_LIMIT_CHECK( 2 );
00349     SubstFormat = FT_NEXT_USHORT( p );
00350 
00351     OTV_TRACE(( " (format %d)\n", SubstFormat ));
00352 
00353     switch ( SubstFormat )
00354     {
00355     case 1:
00356       /* no need to check glyph indices/classes used as input for these */
00357       /* context rules since even invalid glyph indices/classes return  */
00358       /* meaningful results                                             */
00359 
00360       valid->extra1 = valid->lookup_count;
00361       OTV_NEST3( ChainContextSubstFormat1,
00362                  ChainSubRuleSet, ChainSubRule );
00363       OTV_RUN( table, valid );
00364       break;
00365 
00366     case 2:
00367       /* no need to check glyph indices/classes used as input for these */
00368       /* context rules since even invalid glyph indices/classes return  */
00369       /* meaningful results                                             */
00370 
00371       OTV_NEST3( ChainContextSubstFormat2,
00372                  ChainSubClassSet, ChainSubClassRule );
00373       OTV_RUN( table, valid );
00374       break;
00375 
00376     case 3:
00377       OTV_NEST1( ChainContextSubstFormat3 );
00378       OTV_RUN( table, valid );
00379       break;
00380 
00381     default:
00382       FT_INVALID_FORMAT;
00383     }
00384 
00385     OTV_EXIT;
00386   }
00387 
00388 
00389   /*************************************************************************/
00390   /*************************************************************************/
00391   /*****                                                               *****/
00392   /*****                    GSUB LOOKUP TYPE 7                         *****/
00393   /*****                                                               *****/
00394   /*************************************************************************/
00395   /*************************************************************************/
00396 
00397   /* uses valid->type_funcs */
00398 
00399   static void
00400   otv_ExtensionSubst_validate( FT_Bytes       table,
00401                                OTV_Validator  valid )
00402   {
00403     FT_Bytes  p = table;
00404     FT_UInt   SubstFormat;
00405 
00406 
00407     OTV_NAME_ENTER( "ExtensionSubst" );
00408 
00409     OTV_LIMIT_CHECK( 2 );
00410     SubstFormat = FT_NEXT_USHORT( p );
00411 
00412     OTV_TRACE(( " (format %d)\n", SubstFormat ));
00413 
00414     switch ( SubstFormat )
00415     {
00416     case 1:     /* ExtensionSubstFormat1 */
00417       {
00418         FT_UInt            ExtensionLookupType;
00419         FT_ULong           ExtensionOffset;
00420         OTV_Validate_Func  validate;
00421 
00422 
00423         OTV_LIMIT_CHECK( 6 );
00424         ExtensionLookupType = FT_NEXT_USHORT( p );
00425         ExtensionOffset     = FT_NEXT_ULONG( p );
00426 
00427         if ( ExtensionLookupType == 0 ||
00428              ExtensionLookupType == 7 ||
00429              ExtensionLookupType > 8  )
00430           FT_INVALID_DATA;
00431 
00432         validate = valid->type_funcs[ExtensionLookupType - 1];
00433         validate( table + ExtensionOffset, valid );
00434       }
00435       break;
00436 
00437     default:
00438       FT_INVALID_FORMAT;
00439     }
00440 
00441     OTV_EXIT;
00442   }
00443 
00444 
00445   /*************************************************************************/
00446   /*************************************************************************/
00447   /*****                                                               *****/
00448   /*****                    GSUB LOOKUP TYPE 8                         *****/
00449   /*****                                                               *****/
00450   /*************************************************************************/
00451   /*************************************************************************/
00452 
00453   /* uses valid->glyph_count */
00454 
00455   static void
00456   otv_ReverseChainSingleSubst_validate( FT_Bytes       table,
00457                                         OTV_Validator  valid )
00458   {
00459     FT_Bytes  p = table, Coverage;
00460     FT_UInt   SubstFormat;
00461     FT_UInt   BacktrackGlyphCount, LookaheadGlyphCount, GlyphCount;
00462 
00463 
00464     OTV_NAME_ENTER( "ReverseChainSingleSubst" );
00465 
00466     OTV_LIMIT_CHECK( 2 );
00467     SubstFormat = FT_NEXT_USHORT( p );
00468 
00469     OTV_TRACE(( " (format %d)\n", SubstFormat ));
00470 
00471     switch ( SubstFormat )
00472     {
00473     case 1:     /* ReverseChainSingleSubstFormat1 */
00474       OTV_LIMIT_CHECK( 4 );
00475       Coverage            = table + FT_NEXT_USHORT( p );
00476       BacktrackGlyphCount = FT_NEXT_USHORT( p );
00477 
00478       OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
00479 
00480       otv_Coverage_validate( Coverage, valid, -1 );
00481 
00482       OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
00483 
00484       for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
00485         otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
00486 
00487       LookaheadGlyphCount = FT_NEXT_USHORT( p );
00488 
00489       OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
00490 
00491       OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
00492 
00493       for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
00494         otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
00495 
00496       GlyphCount = FT_NEXT_USHORT( p );
00497 
00498       OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
00499 
00500       if ( GlyphCount != otv_Coverage_get_count( Coverage ) )
00501         FT_INVALID_DATA;
00502 
00503       OTV_LIMIT_CHECK( GlyphCount * 2 );
00504 
00505       /* Substitute */
00506       for ( ; GlyphCount > 0; GlyphCount-- )
00507         if ( FT_NEXT_USHORT( p ) >= valid->glyph_count )
00508           FT_INVALID_DATA;
00509 
00510       break;
00511 
00512     default:
00513       FT_INVALID_FORMAT;
00514     }
00515 
00516     OTV_EXIT;
00517   }
00518 
00519 
00520   static const OTV_Validate_Func  otv_gsub_validate_funcs[8] =
00521   {
00522     otv_SingleSubst_validate,
00523     otv_MultipleSubst_validate,
00524     otv_AlternateSubst_validate,
00525     otv_LigatureSubst_validate,
00526     otv_ContextSubst_validate,
00527     otv_ChainContextSubst_validate,
00528     otv_ExtensionSubst_validate,
00529     otv_ReverseChainSingleSubst_validate
00530   };
00531 
00532 
00533   /*************************************************************************/
00534   /*************************************************************************/
00535   /*****                                                               *****/
00536   /*****                          GSUB TABLE                           *****/
00537   /*****                                                               *****/
00538   /*************************************************************************/
00539   /*************************************************************************/
00540 
00541   /* sets valid->type_count  */
00542   /* sets valid->type_funcs  */
00543   /* sets valid->glyph_count */
00544 
00545   FT_LOCAL_DEF( void )
00546   otv_GSUB_validate( FT_Bytes      table,
00547                      FT_UInt       glyph_count,
00548                      FT_Validator  ftvalid )
00549   {
00550     OTV_ValidatorRec  validrec;
00551     OTV_Validator     valid = &validrec;
00552     FT_Bytes          p     = table;
00553     FT_UInt           ScriptList, FeatureList, LookupList;
00554 
00555 
00556     valid->root = ftvalid;
00557 
00558     FT_TRACE3(( "validating GSUB table\n" ));
00559     OTV_INIT;
00560 
00561     OTV_LIMIT_CHECK( 10 );
00562 
00563     if ( FT_NEXT_ULONG( p ) != 0x10000UL )      /* Version */
00564       FT_INVALID_FORMAT;
00565 
00566     ScriptList  = FT_NEXT_USHORT( p );
00567     FeatureList = FT_NEXT_USHORT( p );
00568     LookupList  = FT_NEXT_USHORT( p );
00569 
00570     valid->type_count  = 8;
00571     valid->type_funcs  = (OTV_Validate_Func*)otv_gsub_validate_funcs;
00572     valid->glyph_count = glyph_count;
00573 
00574     otv_LookupList_validate( table + LookupList,
00575                              valid );
00576     otv_FeatureList_validate( table + FeatureList, table + LookupList,
00577                               valid );
00578     otv_ScriptList_validate( table + ScriptList, table + FeatureList,
00579                              valid );
00580 
00581     FT_TRACE4(( "\n" ));
00582   }
00583 
00584 
00585 /* END */

Generated on Tue Jul 5 14:13:48 2011 for ROOT_528-00b_version by  doxygen 1.5.1