gxvmort.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  gxvmort.c                                                              */
00004 /*                                                                         */
00005 /*    TrueTypeGX/AAT mort table validation (body).                         */
00006 /*                                                                         */
00007 /*  Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K.,       */
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 /*                                                                         */
00020 /* gxvalid is derived from both gxlayout module and otvalid module.        */
00021 /* Development of gxlayout is supported by the Information-technology      */
00022 /* Promotion Agency(IPA), Japan.                                           */
00023 /*                                                                         */
00024 /***************************************************************************/
00025 
00026 
00027 #include "gxvmort.h"
00028 #include "gxvfeat.h"
00029 
00030 
00031   /*************************************************************************/
00032   /*                                                                       */
00033   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00034   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00035   /* messages during execution.                                            */
00036   /*                                                                       */
00037 #undef  FT_COMPONENT
00038 #define FT_COMPONENT  trace_gxvmort
00039 
00040 
00041   static void
00042   gxv_mort_feature_validate( GXV_mort_feature  f,
00043                              GXV_Validator     valid )
00044   {
00045     if ( f->featureType >= gxv_feat_registry_length )
00046     {
00047       GXV_TRACE(( "featureType %d is out of registered range, "
00048                   "setting %d is unchecked\n",
00049                   f->featureType, f->featureSetting ));
00050       if ( valid->root->level >= FT_VALIDATE_PARANOID )
00051         FT_INVALID_DATA;
00052     }
00053     else if ( !gxv_feat_registry[f->featureType].existence )
00054     {
00055       GXV_TRACE(( "featureType %d is within registered area "
00056                   "but undefined, setting %d is unchecked\n",
00057                   f->featureType, f->featureSetting ));
00058       if ( valid->root->level >= FT_VALIDATE_PARANOID )
00059         FT_INVALID_DATA;
00060     }
00061     else
00062     {
00063       FT_Byte  nSettings_max;
00064 
00065 
00066       /* nSettings in gxvfeat.c is halved for exclusive on/off settings */
00067       nSettings_max = gxv_feat_registry[f->featureType].nSettings;
00068       if ( gxv_feat_registry[f->featureType].exclusive )
00069         nSettings_max = (FT_Byte)( 2 * nSettings_max );
00070 
00071       GXV_TRACE(( "featureType %d is registered", f->featureType ));
00072       GXV_TRACE(( "setting %d", f->featureSetting ));
00073 
00074       if ( f->featureSetting > nSettings_max )
00075       {
00076         GXV_TRACE(( "out of defined range %d", nSettings_max ));
00077         if ( valid->root->level >= FT_VALIDATE_PARANOID )
00078           FT_INVALID_DATA;
00079       }
00080       GXV_TRACE(( "\n" ));
00081     }
00082 
00083     /* TODO: enableFlags must be unique value in specified chain?  */
00084   }
00085 
00086 
00087   /*
00088    * nFeatureFlags is typed to FT_ULong to accept that in
00089    * mort (typed FT_UShort) and morx (typed FT_ULong).
00090    */
00091   FT_LOCAL_DEF( void )
00092   gxv_mort_featurearray_validate( FT_Bytes       table,
00093                                   FT_Bytes       limit,
00094                                   FT_ULong       nFeatureFlags,
00095                                   GXV_Validator  valid )
00096   {
00097     FT_Bytes  p = table;
00098     FT_ULong  i;
00099 
00100     GXV_mort_featureRec  f = GXV_MORT_FEATURE_OFF;
00101 
00102 
00103     GXV_NAME_ENTER( "mort feature list" );
00104     for ( i = 0; i < nFeatureFlags; i++ )
00105     {
00106       GXV_LIMIT_CHECK( 2 + 2 + 4 + 4 );
00107       f.featureType    = FT_NEXT_USHORT( p );
00108       f.featureSetting = FT_NEXT_USHORT( p );
00109       f.enableFlags    = FT_NEXT_ULONG( p );
00110       f.disableFlags   = FT_NEXT_ULONG( p );
00111 
00112       gxv_mort_feature_validate( &f, valid );
00113     }
00114 
00115     if ( !IS_GXV_MORT_FEATURE_OFF( f ) )
00116       FT_INVALID_DATA;
00117 
00118     valid->subtable_length = p - table;
00119     GXV_EXIT;
00120   }
00121 
00122 
00123   FT_LOCAL_DEF( void )
00124   gxv_mort_coverage_validate( FT_UShort      coverage,
00125                               GXV_Validator  valid )
00126   {
00127     FT_UNUSED( valid );
00128 
00129     if ( coverage & 0x8000U )
00130       GXV_TRACE(( " this subtable is for vertical text only\n" ));
00131     else
00132       GXV_TRACE(( " this subtable is for horizontal text only\n" ));
00133 
00134     if ( coverage & 0x4000 )
00135       GXV_TRACE(( " this subtable is applied to glyph array "
00136                   "in descending order\n" ));
00137     else
00138       GXV_TRACE(( " this subtable is applied to glyph array "
00139                   "in ascending order\n" ));
00140 
00141     if ( coverage & 0x2000 )
00142       GXV_TRACE(( " this subtable is forcibly applied to "
00143                   "vertical/horizontal text\n" ));
00144 
00145     if ( coverage & 0x1FF8 )
00146       GXV_TRACE(( " coverage has non-zero bits in reserved area\n" ));
00147   }
00148 
00149 
00150   static void
00151   gxv_mort_subtables_validate( FT_Bytes       table,
00152                                FT_Bytes       limit,
00153                                FT_UShort      nSubtables,
00154                                GXV_Validator  valid )
00155   {
00156     FT_Bytes  p = table;
00157 
00158     GXV_Validate_Func fmt_funcs_table[] =
00159     {
00160       gxv_mort_subtable_type0_validate, /* 0 */
00161       gxv_mort_subtable_type1_validate, /* 1 */
00162       gxv_mort_subtable_type2_validate, /* 2 */
00163       NULL,                             /* 3 */
00164       gxv_mort_subtable_type4_validate, /* 4 */
00165       gxv_mort_subtable_type5_validate, /* 5 */
00166 
00167     };
00168 
00169     GXV_Validate_Func  func;
00170     FT_UShort          i;
00171 
00172 
00173     GXV_NAME_ENTER( "subtables in a chain" );
00174 
00175     for ( i = 0; i < nSubtables; i++ )
00176     {
00177       FT_UShort  length;
00178       FT_UShort  coverage;
00179       FT_ULong   subFeatureFlags;
00180       FT_UInt    type;
00181       FT_UInt    rest;
00182 
00183 
00184       GXV_LIMIT_CHECK( 2 + 2 + 4 );
00185       length          = FT_NEXT_USHORT( p );
00186       coverage        = FT_NEXT_USHORT( p );
00187       subFeatureFlags = FT_NEXT_ULONG( p );
00188 
00189       GXV_TRACE(( "validating chain subtable %d/%d (%d bytes)\n",
00190                   i + 1, nSubtables, length ));
00191       type = coverage & 0x0007;
00192       rest = length - ( 2 + 2 + 4 );
00193 
00194       GXV_LIMIT_CHECK( rest );
00195       gxv_mort_coverage_validate( coverage, valid );
00196 
00197       if ( type > 5 )
00198         FT_INVALID_FORMAT;
00199 
00200       func = fmt_funcs_table[type];
00201       if ( func == NULL )
00202         GXV_TRACE(( "morx type %d is reserved\n", type ));
00203 
00204       func( p, p + rest, valid );
00205 
00206       p += rest;
00207     }
00208 
00209     valid->subtable_length = p - table;
00210 
00211     GXV_EXIT;
00212   }
00213 
00214 
00215   static void
00216   gxv_mort_chain_validate( FT_Bytes       table,
00217                            FT_Bytes       limit,
00218                            GXV_Validator  valid )
00219   {
00220     FT_Bytes   p = table;
00221     FT_ULong   defaultFlags;
00222     FT_ULong   chainLength;
00223     FT_UShort  nFeatureFlags;
00224     FT_UShort  nSubtables;
00225 
00226 
00227     GXV_NAME_ENTER( "mort chain header" );
00228 
00229     GXV_LIMIT_CHECK( 4 + 4 + 2 + 2 );
00230     defaultFlags  = FT_NEXT_ULONG( p );
00231     chainLength   = FT_NEXT_ULONG( p );
00232     nFeatureFlags = FT_NEXT_USHORT( p );
00233     nSubtables    = FT_NEXT_USHORT( p );
00234 
00235     gxv_mort_featurearray_validate( p, table + chainLength,
00236                                     nFeatureFlags, valid );
00237     p += valid->subtable_length;
00238     gxv_mort_subtables_validate( p, table + chainLength, nSubtables, valid );
00239     valid->subtable_length = chainLength;
00240 
00241     GXV_EXIT;
00242   }
00243 
00244 
00245   FT_LOCAL_DEF( void )
00246   gxv_mort_validate( FT_Bytes      table,
00247                      FT_Face       face,
00248                      FT_Validator  ftvalid )
00249   {
00250     GXV_ValidatorRec  validrec;
00251     GXV_Validator     valid = &validrec;
00252     FT_Bytes          p     = table;
00253     FT_Bytes          limit = 0;
00254     FT_ULong          version;
00255     FT_ULong          nChains;
00256     FT_ULong          i;
00257 
00258 
00259     valid->root = ftvalid;
00260     valid->face = face;
00261     limit       = valid->root->limit;
00262 
00263     FT_TRACE3(( "validating `mort' table\n" ));
00264     GXV_INIT;
00265 
00266     GXV_LIMIT_CHECK( 4 + 4 );
00267     version = FT_NEXT_ULONG( p );
00268     nChains = FT_NEXT_ULONG( p );
00269 
00270     if (version != 0x00010000UL)
00271       FT_INVALID_FORMAT;
00272 
00273     for ( i = 0; i < nChains; i++ )
00274     {
00275       GXV_TRACE(( "validating chain %d/%d\n", i + 1, nChains ));
00276       GXV_32BIT_ALIGNMENT_VALIDATE( p - table );
00277       gxv_mort_chain_validate( p, limit, valid );
00278       p += valid->subtable_length;
00279     }
00280 
00281     FT_TRACE4(( "\n" ));
00282   }
00283 
00284 
00285 /* END */

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