misc/libfreetype/src/gxvalid/gxvmort1.c
changeset 9372 915436ff64ab
parent 9371 f3840de881bd
child 9373 b769a8e38cbd
equal deleted inserted replaced
9371:f3840de881bd 9372:915436ff64ab
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  gxvmort1.c                                                             */
       
     4 /*                                                                         */
       
     5 /*    TrueTypeGX/AAT mort table validation                                 */
       
     6 /*    body for type1 (Contextual Substitution) subtable.                   */
       
     7 /*                                                                         */
       
     8 /*  Copyright 2005, 2007 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
       
     9 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
       
    10 /*                                                                         */
       
    11 /*  This file is part of the FreeType project, and may only be used,       */
       
    12 /*  modified, and distributed under the terms of the FreeType project      */
       
    13 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
       
    14 /*  this file you indicate that you have read the license and              */
       
    15 /*  understand and accept it fully.                                        */
       
    16 /*                                                                         */
       
    17 /***************************************************************************/
       
    18 
       
    19 /***************************************************************************/
       
    20 /*                                                                         */
       
    21 /* gxvalid is derived from both gxlayout module and otvalid module.        */
       
    22 /* Development of gxlayout is supported by the Information-technology      */
       
    23 /* Promotion Agency(IPA), Japan.                                           */
       
    24 /*                                                                         */
       
    25 /***************************************************************************/
       
    26 
       
    27 
       
    28 #include "gxvmort.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   typedef struct  GXV_mort_subtable_type1_StateOptRec_
       
    42   {
       
    43     FT_UShort  substitutionTable;
       
    44     FT_UShort  substitutionTable_length;
       
    45 
       
    46   }  GXV_mort_subtable_type1_StateOptRec,
       
    47     *GXV_mort_subtable_type1_StateOptRecData;
       
    48 
       
    49 #define GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE \
       
    50           ( GXV_STATETABLE_HEADER_SIZE + 2 )
       
    51 
       
    52 
       
    53   static void
       
    54   gxv_mort_subtable_type1_substitutionTable_load( FT_Bytes       table,
       
    55                                                   FT_Bytes       limit,
       
    56                                                   GXV_Validator  valid )
       
    57   {
       
    58     FT_Bytes  p = table;
       
    59 
       
    60     GXV_mort_subtable_type1_StateOptRecData  optdata =
       
    61       (GXV_mort_subtable_type1_StateOptRecData)valid->statetable.optdata;
       
    62 
       
    63 
       
    64     GXV_LIMIT_CHECK( 2 );
       
    65     optdata->substitutionTable = FT_NEXT_USHORT( p );
       
    66   }
       
    67 
       
    68 
       
    69   static void
       
    70   gxv_mort_subtable_type1_subtable_setup( FT_UShort      table_size,
       
    71                                           FT_UShort      classTable,
       
    72                                           FT_UShort      stateArray,
       
    73                                           FT_UShort      entryTable,
       
    74                                           FT_UShort*     classTable_length_p,
       
    75                                           FT_UShort*     stateArray_length_p,
       
    76                                           FT_UShort*     entryTable_length_p,
       
    77                                           GXV_Validator  valid )
       
    78   {
       
    79     FT_UShort  o[4];
       
    80     FT_UShort  *l[4];
       
    81     FT_UShort  buff[5];
       
    82 
       
    83     GXV_mort_subtable_type1_StateOptRecData  optdata =
       
    84       (GXV_mort_subtable_type1_StateOptRecData)valid->statetable.optdata;
       
    85 
       
    86 
       
    87     o[0] = classTable;
       
    88     o[1] = stateArray;
       
    89     o[2] = entryTable;
       
    90     o[3] = optdata->substitutionTable;
       
    91     l[0] = classTable_length_p;
       
    92     l[1] = stateArray_length_p;
       
    93     l[2] = entryTable_length_p;
       
    94     l[3] = &( optdata->substitutionTable_length );
       
    95 
       
    96     gxv_set_length_by_ushort_offset( o, l, buff, 4, table_size, valid );
       
    97   }
       
    98 
       
    99 
       
   100   static void
       
   101   gxv_mort_subtable_type1_offset_to_subst_validate(
       
   102     FT_Short          wordOffset,
       
   103     const FT_String*  tag,
       
   104     FT_Byte           state,
       
   105     GXV_Validator     valid )
       
   106   {
       
   107     FT_UShort  substTable;
       
   108     FT_UShort  substTable_limit;
       
   109     FT_UShort  min_gid;
       
   110     FT_UShort  max_gid;
       
   111 
       
   112     FT_UNUSED( tag );
       
   113     FT_UNUSED( state );
       
   114 
       
   115 
       
   116     substTable =
       
   117       ((GXV_mort_subtable_type1_StateOptRec *)
       
   118        (valid->statetable.optdata))->substitutionTable;
       
   119     substTable_limit =
       
   120       (FT_UShort)( substTable +
       
   121                    ((GXV_mort_subtable_type1_StateOptRec *)
       
   122                     (valid->statetable.optdata))->substitutionTable_length );
       
   123 
       
   124     min_gid = (FT_UShort)( ( substTable       - wordOffset * 2 ) / 2 );
       
   125     max_gid = (FT_UShort)( ( substTable_limit - wordOffset * 2 ) / 2 );
       
   126     max_gid = (FT_UShort)( FT_MAX( max_gid, valid->face->num_glyphs ) );
       
   127 
       
   128     /* XXX: check range? */
       
   129 
       
   130     /* TODO: min_gid & max_gid comparison with ClassTable contents */
       
   131   }
       
   132 
       
   133 
       
   134   static void
       
   135   gxv_mort_subtable_type1_entry_validate(
       
   136     FT_Byte                         state,
       
   137     FT_UShort                       flags,
       
   138     GXV_StateTable_GlyphOffsetCPtr  glyphOffset_p,
       
   139     FT_Bytes                        table,
       
   140     FT_Bytes                        limit,
       
   141     GXV_Validator                   valid )
       
   142   {
       
   143     FT_UShort  setMark;
       
   144     FT_UShort  dontAdvance;
       
   145     FT_UShort  reserved;
       
   146     FT_Short   markOffset;
       
   147     FT_Short   currentOffset;
       
   148 
       
   149     FT_UNUSED( table );
       
   150     FT_UNUSED( limit );
       
   151 
       
   152 
       
   153     setMark       = (FT_UShort)(   flags >> 15            );
       
   154     dontAdvance   = (FT_UShort)( ( flags >> 14 ) & 1      );
       
   155     reserved      = (FT_Short)(    flags         & 0x3FFF );
       
   156 
       
   157     markOffset    = (FT_Short)( glyphOffset_p->ul >> 16 );
       
   158     currentOffset = (FT_Short)( glyphOffset_p->ul       );
       
   159 
       
   160     if ( 0 < reserved )
       
   161     {
       
   162       GXV_TRACE(( " non-zero bits found in reserved range\n" ));
       
   163       if ( valid->root->level >= FT_VALIDATE_PARANOID )
       
   164         FT_INVALID_DATA;
       
   165     }
       
   166 
       
   167     gxv_mort_subtable_type1_offset_to_subst_validate( markOffset,
       
   168                                                       "markOffset",
       
   169                                                       state,
       
   170                                                       valid );
       
   171 
       
   172     gxv_mort_subtable_type1_offset_to_subst_validate( currentOffset,
       
   173                                                       "currentOffset",
       
   174                                                       state,
       
   175                                                       valid );
       
   176   }
       
   177 
       
   178 
       
   179   static void
       
   180   gxv_mort_subtable_type1_substTable_validate( FT_Bytes       table,
       
   181                                                FT_Bytes       limit,
       
   182                                                GXV_Validator  valid )
       
   183   {
       
   184     FT_Bytes   p = table;
       
   185     FT_UShort  num_gids = (FT_UShort)(
       
   186                  ((GXV_mort_subtable_type1_StateOptRec *)
       
   187                   (valid->statetable.optdata))->substitutionTable_length / 2 );
       
   188     FT_UShort  i;
       
   189 
       
   190 
       
   191     GXV_NAME_ENTER( "validating contents of substitutionTable" );
       
   192     for ( i = 0; i < num_gids ; i ++ )
       
   193     {
       
   194       FT_UShort  dst_gid;
       
   195 
       
   196 
       
   197       GXV_LIMIT_CHECK( 2 );
       
   198       dst_gid = FT_NEXT_USHORT( p );
       
   199 
       
   200       if ( dst_gid >= 0xFFFFU )
       
   201         continue;
       
   202 
       
   203       if ( dst_gid > valid->face->num_glyphs )
       
   204       {
       
   205         GXV_TRACE(( "substTable include too large gid[%d]=%d >"
       
   206                     " max defined gid #%d\n",
       
   207                     i, dst_gid, valid->face->num_glyphs ));
       
   208         if ( valid->root->level >= FT_VALIDATE_PARANOID )
       
   209           FT_INVALID_GLYPH_ID;
       
   210       }
       
   211     }
       
   212 
       
   213     GXV_EXIT;
       
   214   }
       
   215 
       
   216 
       
   217   /*
       
   218    * subtable for Contextual glyph substitution is a modified StateTable.
       
   219    * In addition to classTable, stateArray, and entryTable, the field
       
   220    * `substitutionTable' is added.
       
   221    */
       
   222   FT_LOCAL_DEF( void )
       
   223   gxv_mort_subtable_type1_validate( FT_Bytes       table,
       
   224                                     FT_Bytes       limit,
       
   225                                     GXV_Validator  valid )
       
   226   {
       
   227     FT_Bytes  p = table;
       
   228 
       
   229     GXV_mort_subtable_type1_StateOptRec  st_rec;
       
   230 
       
   231 
       
   232     GXV_NAME_ENTER( "mort chain subtable type1 (Contextual Glyph Subst)" );
       
   233 
       
   234     GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE );
       
   235 
       
   236     valid->statetable.optdata =
       
   237       &st_rec;
       
   238     valid->statetable.optdata_load_func =
       
   239       gxv_mort_subtable_type1_substitutionTable_load;
       
   240     valid->statetable.subtable_setup_func =
       
   241       gxv_mort_subtable_type1_subtable_setup;
       
   242     valid->statetable.entry_glyphoffset_fmt =
       
   243       GXV_GLYPHOFFSET_ULONG;
       
   244     valid->statetable.entry_validate_func =
       
   245 
       
   246       gxv_mort_subtable_type1_entry_validate;
       
   247     gxv_StateTable_validate( p, limit, valid );
       
   248 
       
   249     gxv_mort_subtable_type1_substTable_validate(
       
   250       table + st_rec.substitutionTable,
       
   251       table + st_rec.substitutionTable + st_rec.substitutionTable_length,
       
   252       valid );
       
   253 
       
   254     GXV_EXIT;
       
   255   }
       
   256 
       
   257 
       
   258 /* END */