misc/libfreetype/src/gxvalid/gxvmort.c
changeset 9431 0f5961910e27
parent 9357 a501f5ec7b34
parent 9429 7a97a554ac80
child 9433 f0a8ac191839
equal deleted inserted replaced
9357:a501f5ec7b34 9431:0f5961910e27
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  gxvmort.c                                                              */
       
     4 /*                                                                         */
       
     5 /*    TrueTypeGX/AAT mort table validation (body).                         */
       
     6 /*                                                                         */
       
     7 /*  Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K.,       */
       
     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 /*                                                                         */
       
    20 /* gxvalid is derived from both gxlayout module and otvalid module.        */
       
    21 /* Development of gxlayout is supported by the Information-technology      */
       
    22 /* Promotion Agency(IPA), Japan.                                           */
       
    23 /*                                                                         */
       
    24 /***************************************************************************/
       
    25 
       
    26 
       
    27 #include "gxvmort.h"
       
    28 #include "gxvfeat.h"
       
    29 
       
    30 
       
    31   /*************************************************************************/
       
    32   /*                                                                       */
       
    33   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
       
    34   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
       
    35   /* messages during execution.                                            */
       
    36   /*                                                                       */
       
    37 #undef  FT_COMPONENT
       
    38 #define FT_COMPONENT  trace_gxvmort
       
    39 
       
    40 
       
    41   static void
       
    42   gxv_mort_feature_validate( GXV_mort_feature  f,
       
    43                              GXV_Validator     valid )
       
    44   {
       
    45     if ( f->featureType >= gxv_feat_registry_length )
       
    46     {
       
    47       GXV_TRACE(( "featureType %d is out of registered range, "
       
    48                   "setting %d is unchecked\n",
       
    49                   f->featureType, f->featureSetting ));
       
    50       if ( valid->root->level >= FT_VALIDATE_PARANOID )
       
    51         FT_INVALID_DATA;
       
    52     }
       
    53     else if ( !gxv_feat_registry[f->featureType].existence )
       
    54     {
       
    55       GXV_TRACE(( "featureType %d is within registered area "
       
    56                   "but undefined, setting %d is unchecked\n",
       
    57                   f->featureType, f->featureSetting ));
       
    58       if ( valid->root->level >= FT_VALIDATE_PARANOID )
       
    59         FT_INVALID_DATA;
       
    60     }
       
    61     else
       
    62     {
       
    63       FT_Byte  nSettings_max;
       
    64 
       
    65 
       
    66       /* nSettings in gxvfeat.c is halved for exclusive on/off settings */
       
    67       nSettings_max = gxv_feat_registry[f->featureType].nSettings;
       
    68       if ( gxv_feat_registry[f->featureType].exclusive )
       
    69         nSettings_max = (FT_Byte)( 2 * nSettings_max );
       
    70 
       
    71       GXV_TRACE(( "featureType %d is registered", f->featureType ));
       
    72       GXV_TRACE(( "setting %d", f->featureSetting ));
       
    73 
       
    74       if ( f->featureSetting > nSettings_max )
       
    75       {
       
    76         GXV_TRACE(( "out of defined range %d", nSettings_max ));
       
    77         if ( valid->root->level >= FT_VALIDATE_PARANOID )
       
    78           FT_INVALID_DATA;
       
    79       }
       
    80       GXV_TRACE(( "\n" ));
       
    81     }
       
    82 
       
    83     /* TODO: enableFlags must be unique value in specified chain?  */
       
    84   }
       
    85 
       
    86 
       
    87   /*
       
    88    * nFeatureFlags is typed to FT_ULong to accept that in
       
    89    * mort (typed FT_UShort) and morx (typed FT_ULong).
       
    90    */
       
    91   FT_LOCAL_DEF( void )
       
    92   gxv_mort_featurearray_validate( FT_Bytes       table,
       
    93                                   FT_Bytes       limit,
       
    94                                   FT_ULong       nFeatureFlags,
       
    95                                   GXV_Validator  valid )
       
    96   {
       
    97     FT_Bytes  p = table;
       
    98     FT_ULong  i;
       
    99 
       
   100     GXV_mort_featureRec  f = GXV_MORT_FEATURE_OFF;
       
   101 
       
   102 
       
   103     GXV_NAME_ENTER( "mort feature list" );
       
   104     for ( i = 0; i < nFeatureFlags; i++ )
       
   105     {
       
   106       GXV_LIMIT_CHECK( 2 + 2 + 4 + 4 );
       
   107       f.featureType    = FT_NEXT_USHORT( p );
       
   108       f.featureSetting = FT_NEXT_USHORT( p );
       
   109       f.enableFlags    = FT_NEXT_ULONG( p );
       
   110       f.disableFlags   = FT_NEXT_ULONG( p );
       
   111 
       
   112       gxv_mort_feature_validate( &f, valid );
       
   113     }
       
   114 
       
   115     if ( !IS_GXV_MORT_FEATURE_OFF( f ) )
       
   116       FT_INVALID_DATA;
       
   117 
       
   118     valid->subtable_length = p - table;
       
   119     GXV_EXIT;
       
   120   }
       
   121 
       
   122 
       
   123   FT_LOCAL_DEF( void )
       
   124   gxv_mort_coverage_validate( FT_UShort      coverage,
       
   125                               GXV_Validator  valid )
       
   126   {
       
   127     FT_UNUSED( valid );
       
   128 
       
   129     if ( coverage & 0x8000U )
       
   130       GXV_TRACE(( " this subtable is for vertical text only\n" ));
       
   131     else
       
   132       GXV_TRACE(( " this subtable is for horizontal text only\n" ));
       
   133 
       
   134     if ( coverage & 0x4000 )
       
   135       GXV_TRACE(( " this subtable is applied to glyph array "
       
   136                   "in descending order\n" ));
       
   137     else
       
   138       GXV_TRACE(( " this subtable is applied to glyph array "
       
   139                   "in ascending order\n" ));
       
   140 
       
   141     if ( coverage & 0x2000 )
       
   142       GXV_TRACE(( " this subtable is forcibly applied to "
       
   143                   "vertical/horizontal text\n" ));
       
   144 
       
   145     if ( coverage & 0x1FF8 )
       
   146       GXV_TRACE(( " coverage has non-zero bits in reserved area\n" ));
       
   147   }
       
   148 
       
   149 
       
   150   static void
       
   151   gxv_mort_subtables_validate( FT_Bytes       table,
       
   152                                FT_Bytes       limit,
       
   153                                FT_UShort      nSubtables,
       
   154                                GXV_Validator  valid )
       
   155   {
       
   156     FT_Bytes  p = table;
       
   157 
       
   158     GXV_Validate_Func fmt_funcs_table[] =
       
   159     {
       
   160       gxv_mort_subtable_type0_validate, /* 0 */
       
   161       gxv_mort_subtable_type1_validate, /* 1 */
       
   162       gxv_mort_subtable_type2_validate, /* 2 */
       
   163       NULL,                             /* 3 */
       
   164       gxv_mort_subtable_type4_validate, /* 4 */
       
   165       gxv_mort_subtable_type5_validate, /* 5 */
       
   166 
       
   167     };
       
   168 
       
   169     GXV_Validate_Func  func;
       
   170     FT_UShort          i;
       
   171 
       
   172 
       
   173     GXV_NAME_ENTER( "subtables in a chain" );
       
   174 
       
   175     for ( i = 0; i < nSubtables; i++ )
       
   176     {
       
   177       FT_UShort  length;
       
   178       FT_UShort  coverage;
       
   179       FT_ULong   subFeatureFlags;
       
   180       FT_UInt    type;
       
   181       FT_UInt    rest;
       
   182 
       
   183 
       
   184       GXV_LIMIT_CHECK( 2 + 2 + 4 );
       
   185       length          = FT_NEXT_USHORT( p );
       
   186       coverage        = FT_NEXT_USHORT( p );
       
   187       subFeatureFlags = FT_NEXT_ULONG( p );
       
   188 
       
   189       GXV_TRACE(( "validating chain subtable %d/%d (%d bytes)\n",
       
   190                   i + 1, nSubtables, length ));
       
   191       type = coverage & 0x0007;
       
   192       rest = length - ( 2 + 2 + 4 );
       
   193 
       
   194       GXV_LIMIT_CHECK( rest );
       
   195       gxv_mort_coverage_validate( coverage, valid );
       
   196 
       
   197       if ( type > 5 )
       
   198         FT_INVALID_FORMAT;
       
   199 
       
   200       func = fmt_funcs_table[type];
       
   201       if ( func == NULL )
       
   202         GXV_TRACE(( "morx type %d is reserved\n", type ));
       
   203 
       
   204       func( p, p + rest, valid );
       
   205 
       
   206       p += rest;
       
   207     }
       
   208 
       
   209     valid->subtable_length = p - table;
       
   210 
       
   211     GXV_EXIT;
       
   212   }
       
   213 
       
   214 
       
   215   static void
       
   216   gxv_mort_chain_validate( FT_Bytes       table,
       
   217                            FT_Bytes       limit,
       
   218                            GXV_Validator  valid )
       
   219   {
       
   220     FT_Bytes   p = table;
       
   221     FT_ULong   defaultFlags;
       
   222     FT_ULong   chainLength;
       
   223     FT_UShort  nFeatureFlags;
       
   224     FT_UShort  nSubtables;
       
   225 
       
   226 
       
   227     GXV_NAME_ENTER( "mort chain header" );
       
   228 
       
   229     GXV_LIMIT_CHECK( 4 + 4 + 2 + 2 );
       
   230     defaultFlags  = FT_NEXT_ULONG( p );
       
   231     chainLength   = FT_NEXT_ULONG( p );
       
   232     nFeatureFlags = FT_NEXT_USHORT( p );
       
   233     nSubtables    = FT_NEXT_USHORT( p );
       
   234 
       
   235     gxv_mort_featurearray_validate( p, table + chainLength,
       
   236                                     nFeatureFlags, valid );
       
   237     p += valid->subtable_length;
       
   238     gxv_mort_subtables_validate( p, table + chainLength, nSubtables, valid );
       
   239     valid->subtable_length = chainLength;
       
   240 
       
   241     GXV_EXIT;
       
   242   }
       
   243 
       
   244 
       
   245   FT_LOCAL_DEF( void )
       
   246   gxv_mort_validate( FT_Bytes      table,
       
   247                      FT_Face       face,
       
   248                      FT_Validator  ftvalid )
       
   249   {
       
   250     GXV_ValidatorRec  validrec;
       
   251     GXV_Validator     valid = &validrec;
       
   252     FT_Bytes          p     = table;
       
   253     FT_Bytes          limit = 0;
       
   254     FT_ULong          version;
       
   255     FT_ULong          nChains;
       
   256     FT_ULong          i;
       
   257 
       
   258 
       
   259     valid->root = ftvalid;
       
   260     valid->face = face;
       
   261     limit       = valid->root->limit;
       
   262 
       
   263     FT_TRACE3(( "validating `mort' table\n" ));
       
   264     GXV_INIT;
       
   265 
       
   266     GXV_LIMIT_CHECK( 4 + 4 );
       
   267     version = FT_NEXT_ULONG( p );
       
   268     nChains = FT_NEXT_ULONG( p );
       
   269 
       
   270     if (version != 0x00010000UL)
       
   271       FT_INVALID_FORMAT;
       
   272 
       
   273     for ( i = 0; i < nChains; i++ )
       
   274     {
       
   275       GXV_TRACE(( "validating chain %d/%d\n", i + 1, nChains ));
       
   276       GXV_32BIT_ALIGNMENT_VALIDATE( p - table );
       
   277       gxv_mort_chain_validate( p, limit, valid );
       
   278       p += valid->subtable_length;
       
   279     }
       
   280 
       
   281     FT_TRACE4(( "\n" ));
       
   282   }
       
   283 
       
   284 
       
   285 /* END */