gxvkern.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  gxvkern.c                                                              */
00004 /*                                                                         */
00005 /*    TrueTypeGX/AAT kern table validation (body).                         */
00006 /*                                                                         */
00007 /*  Copyright 2004, 2005, 2006, 2007                                       */
00008 /*  by suzuki toshiya, Masatake YAMATO, Red Hat K.K.,                      */
00009 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00010 /*                                                                         */
00011 /*  This file is part of the FreeType project, and may only be used,       */
00012 /*  modified, and distributed under the terms of the FreeType project      */
00013 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00014 /*  this file you indicate that you have read the license and              */
00015 /*  understand and accept it fully.                                        */
00016 /*                                                                         */
00017 /***************************************************************************/
00018 
00019 /***************************************************************************/
00020 /*                                                                         */
00021 /* gxvalid is derived from both gxlayout module and otvalid module.        */
00022 /* Development of gxlayout is supported by the Information-technology      */
00023 /* Promotion Agency(IPA), Japan.                                           */
00024 /*                                                                         */
00025 /***************************************************************************/
00026 
00027 
00028 #include "gxvalid.h"
00029 #include "gxvcommn.h"
00030 
00031 #include FT_SFNT_NAMES_H
00032 #include FT_SERVICE_GX_VALIDATE_H
00033 
00034 
00035   /*************************************************************************/
00036   /*                                                                       */
00037   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00038   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00039   /* messages during execution.                                            */
00040   /*                                                                       */
00041 #undef  FT_COMPONENT
00042 #define FT_COMPONENT  trace_gxvkern
00043 
00044 
00045   /*************************************************************************/
00046   /*************************************************************************/
00047   /*****                                                               *****/
00048   /*****                      Data and Types                           *****/
00049   /*****                                                               *****/
00050   /*************************************************************************/
00051   /*************************************************************************/
00052 
00053   typedef enum  GXV_kern_Version_
00054   {
00055     KERN_VERSION_CLASSIC = 0x0000,
00056     KERN_VERSION_NEW     = 0x0001
00057 
00058   } GXV_kern_Version;
00059 
00060 
00061   typedef enum GXV_kern_Dialect_
00062   {
00063     KERN_DIALECT_UNKNOWN = 0,
00064     KERN_DIALECT_MS      = FT_VALIDATE_MS,
00065     KERN_DIALECT_APPLE   = FT_VALIDATE_APPLE,
00066     KERN_DIALECT_ANY     = FT_VALIDATE_CKERN
00067 
00068   } GXV_kern_Dialect;
00069 
00070 
00071   typedef struct  GXV_kern_DataRec_
00072   {
00073     GXV_kern_Version  version;
00074     void             *subtable_data;
00075     GXV_kern_Dialect  dialect_request;
00076 
00077   } GXV_kern_DataRec, *GXV_kern_Data;
00078 
00079 
00080 #define GXV_KERN_DATA( field )  GXV_TABLE_DATA( kern, field )
00081 
00082 #define KERN_IS_CLASSIC( valid )                               \
00083           ( KERN_VERSION_CLASSIC == GXV_KERN_DATA( version ) )
00084 #define KERN_IS_NEW( valid )                                   \
00085           ( KERN_VERSION_NEW     == GXV_KERN_DATA( version ) )
00086 
00087 #define KERN_DIALECT( valid )              \
00088           GXV_KERN_DATA( dialect_request )
00089 #define KERN_ALLOWS_MS( valid )                       \
00090           ( KERN_DIALECT( valid ) & KERN_DIALECT_MS )
00091 #define KERN_ALLOWS_APPLE( valid )                       \
00092           ( KERN_DIALECT( valid ) & KERN_DIALECT_APPLE )
00093 
00094 #define GXV_KERN_HEADER_SIZE           ( KERN_IS_NEW( valid ) ? 8 : 4 )
00095 #define GXV_KERN_SUBTABLE_HEADER_SIZE  ( KERN_IS_NEW( valid ) ? 8 : 6 )
00096 
00097 
00098   /*************************************************************************/
00099   /*************************************************************************/
00100   /*****                                                               *****/
00101   /*****                      SUBTABLE VALIDATORS                      *****/
00102   /*****                                                               *****/
00103   /*************************************************************************/
00104   /*************************************************************************/
00105 
00106 
00107   /* ============================= format 0 ============================== */
00108 
00109   static void
00110   gxv_kern_subtable_fmt0_pairs_validate( FT_Bytes       table,
00111                                          FT_Bytes       limit,
00112                                          FT_UShort      nPairs,
00113                                          GXV_Validator  valid )
00114   {
00115     FT_Bytes   p = table;
00116     FT_UShort  i;
00117 
00118     FT_UShort  last_gid_left  = 0;
00119     FT_UShort  last_gid_right = 0;
00120 
00121     FT_UNUSED( limit );
00122 
00123 
00124     GXV_NAME_ENTER( "kern format 0 pairs" );
00125 
00126     for ( i = 0; i < nPairs; i++ )
00127     {
00128       FT_UShort  gid_left;
00129       FT_UShort  gid_right;
00130       FT_Short   kernValue;
00131 
00132 
00133       /* left */
00134       gid_left  = FT_NEXT_USHORT( p );
00135       gxv_glyphid_validate( gid_left, valid );
00136 
00137       /* right */
00138       gid_right = FT_NEXT_USHORT( p );
00139       gxv_glyphid_validate( gid_right, valid );
00140 
00141       /* Pairs of left and right GIDs must be unique and sorted. */
00142       GXV_TRACE(( "left gid = %u, right gid = %u\n", gid_left, gid_right ));
00143       if ( gid_left == last_gid_left )
00144       {
00145         if ( last_gid_right < gid_right )
00146           last_gid_right = gid_right;
00147         else
00148           FT_INVALID_DATA;
00149       }
00150       else if ( last_gid_left < gid_left )
00151       {
00152         last_gid_left  = gid_left;
00153         last_gid_right = gid_right;
00154       }
00155       else
00156         FT_INVALID_DATA;
00157 
00158       /* skip the kern value */
00159       kernValue = FT_NEXT_SHORT( p );
00160     }
00161 
00162     GXV_EXIT;
00163   }
00164 
00165   static void
00166   gxv_kern_subtable_fmt0_validate( FT_Bytes       table,
00167                                    FT_Bytes       limit,
00168                                    GXV_Validator  valid )
00169   {
00170     FT_Bytes   p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
00171 
00172     FT_UShort  nPairs;
00173     FT_UShort  unitSize;
00174 
00175 
00176     GXV_NAME_ENTER( "kern subtable format 0" );
00177 
00178     unitSize = 2 + 2 + 2;
00179     nPairs   = 0;
00180 
00181     /* nPairs, searchRange, entrySelector, rangeShift */
00182     GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 );
00183     gxv_BinSrchHeader_validate( p, limit, &unitSize, &nPairs, valid );
00184     p += 2 + 2 + 2 + 2;
00185 
00186     gxv_kern_subtable_fmt0_pairs_validate( p, limit, nPairs, valid );
00187 
00188     GXV_EXIT;
00189   }
00190 
00191 
00192   /* ============================= format 1 ============================== */
00193 
00194 
00195   typedef struct  GXV_kern_fmt1_StateOptRec_
00196   {
00197     FT_UShort  valueTable;
00198     FT_UShort  valueTable_length;
00199 
00200   } GXV_kern_fmt1_StateOptRec, *GXV_kern_fmt1_StateOptRecData;
00201 
00202 
00203   static void
00204   gxv_kern_subtable_fmt1_valueTable_load( FT_Bytes       table,
00205                                           FT_Bytes       limit,
00206                                           GXV_Validator  valid )
00207   {
00208     FT_Bytes                       p = table;
00209     GXV_kern_fmt1_StateOptRecData  optdata =
00210       (GXV_kern_fmt1_StateOptRecData)valid->statetable.optdata;
00211 
00212 
00213     GXV_LIMIT_CHECK( 2 );
00214     optdata->valueTable = FT_NEXT_USHORT( p );
00215   }
00216 
00217 
00218   /*
00219    * passed tables_size covers whole StateTable, including kern fmt1 header
00220    */
00221   static void
00222   gxv_kern_subtable_fmt1_subtable_setup( FT_UShort      table_size,
00223                                          FT_UShort      classTable,
00224                                          FT_UShort      stateArray,
00225                                          FT_UShort      entryTable,
00226                                          FT_UShort*     classTable_length_p,
00227                                          FT_UShort*     stateArray_length_p,
00228                                          FT_UShort*     entryTable_length_p,
00229                                          GXV_Validator  valid )
00230   {
00231     FT_UShort  o[4];
00232     FT_UShort  *l[4];
00233     FT_UShort  buff[5];
00234 
00235     GXV_kern_fmt1_StateOptRecData  optdata =
00236       (GXV_kern_fmt1_StateOptRecData)valid->statetable.optdata;
00237 
00238 
00239     o[0] = classTable;
00240     o[1] = stateArray;
00241     o[2] = entryTable;
00242     o[3] = optdata->valueTable;
00243     l[0] = classTable_length_p;
00244     l[1] = stateArray_length_p;
00245     l[2] = entryTable_length_p;
00246     l[3] = &(optdata->valueTable_length);
00247 
00248     gxv_set_length_by_ushort_offset( o, l, buff, 4, table_size, valid );
00249   }
00250 
00251 
00252   /*
00253    * passed table & limit are of whole StateTable, not including subtables
00254    */
00255   static void
00256   gxv_kern_subtable_fmt1_entry_validate(
00257     FT_Byte                         state,
00258     FT_UShort                       flags,
00259     GXV_StateTable_GlyphOffsetCPtr  glyphOffset_p,
00260     FT_Bytes                        table,
00261     FT_Bytes                        limit,
00262     GXV_Validator                   valid )
00263   {
00264     FT_UShort  push;
00265     FT_UShort  dontAdvance;
00266     FT_UShort  valueOffset;
00267     FT_UShort  kernAction;
00268     FT_UShort  kernValue;
00269 
00270     FT_UNUSED( state );
00271     FT_UNUSED( glyphOffset_p );
00272 
00273 
00274     push        = (FT_UShort)( ( flags >> 15 ) & 1      );
00275     dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1      );
00276     valueOffset = (FT_UShort)(   flags         & 0x3FFF );
00277 
00278     {
00279       GXV_kern_fmt1_StateOptRecData  vt_rec =
00280         (GXV_kern_fmt1_StateOptRecData)valid->statetable.optdata;
00281       FT_Bytes  p;
00282 
00283 
00284       if ( valueOffset < vt_rec->valueTable )
00285         FT_INVALID_OFFSET;
00286 
00287       p     = table + valueOffset;
00288       limit = table + vt_rec->valueTable + vt_rec->valueTable_length;
00289 
00290       GXV_LIMIT_CHECK( 2 + 2 );
00291       kernAction = FT_NEXT_USHORT( p );
00292       kernValue  = FT_NEXT_USHORT( p );
00293     }
00294   }
00295 
00296 
00297   static void
00298   gxv_kern_subtable_fmt1_validate( FT_Bytes       table,
00299                                    FT_Bytes       limit,
00300                                    GXV_Validator  valid )
00301   {
00302     FT_Bytes                   p = table;
00303     GXV_kern_fmt1_StateOptRec  vt_rec;
00304 
00305 
00306     GXV_NAME_ENTER( "kern subtable format 1" );
00307 
00308     valid->statetable.optdata =
00309       &vt_rec;
00310     valid->statetable.optdata_load_func =
00311       gxv_kern_subtable_fmt1_valueTable_load;
00312     valid->statetable.subtable_setup_func =
00313       gxv_kern_subtable_fmt1_subtable_setup;
00314     valid->statetable.entry_glyphoffset_fmt =
00315       GXV_GLYPHOFFSET_NONE;
00316     valid->statetable.entry_validate_func =
00317       gxv_kern_subtable_fmt1_entry_validate;
00318 
00319     gxv_StateTable_validate( p, limit, valid );
00320 
00321     GXV_EXIT;
00322   }
00323 
00324 
00325   /* ================ Data for Class-Based Subtables 2, 3 ================ */
00326 
00327   typedef enum  GXV_kern_ClassSpec_
00328   {
00329     GXV_KERN_CLS_L = 0,
00330     GXV_KERN_CLS_R
00331 
00332   } GXV_kern_ClassSpec;
00333 
00334 
00335   /* ============================= format 2 ============================== */
00336 
00337   /* ---------------------- format 2 specific data ----------------------- */
00338 
00339   typedef struct  GXV_kern_subtable_fmt2_DataRec_
00340   {
00341     FT_UShort         rowWidth;
00342     FT_UShort         array;
00343     FT_UShort         offset_min[2];
00344     FT_UShort         offset_max[2];
00345     const FT_String*  class_tag[2];
00346     GXV_odtect_Range  odtect;
00347 
00348   } GXV_kern_subtable_fmt2_DataRec, *GXV_kern_subtable_fmt2_Data;
00349 
00350 
00351 #define GXV_KERN_FMT2_DATA( field )                         \
00352         ( ( (GXV_kern_subtable_fmt2_DataRec *)              \
00353               ( GXV_KERN_DATA( subtable_data ) ) )->field )
00354 
00355 
00356   /* -------------------------- utility functions ----------------------- */
00357 
00358   static void
00359   gxv_kern_subtable_fmt2_clstbl_validate( FT_Bytes            table,
00360                                           FT_Bytes            limit,
00361                                           GXV_kern_ClassSpec  spec,
00362                                           GXV_Validator       valid )
00363   {
00364     const FT_String*  tag    = GXV_KERN_FMT2_DATA( class_tag[spec] );
00365     GXV_odtect_Range  odtect = GXV_KERN_FMT2_DATA( odtect );
00366 
00367     FT_Bytes   p = table;
00368     FT_UShort  firstGlyph;
00369     FT_UShort  nGlyphs;
00370 
00371 
00372     GXV_NAME_ENTER( "kern format 2 classTable" );
00373 
00374     GXV_LIMIT_CHECK( 2 + 2 );
00375     firstGlyph = FT_NEXT_USHORT( p );
00376     nGlyphs    = FT_NEXT_USHORT( p );
00377     GXV_TRACE(( " %s firstGlyph=%d, nGlyphs=%d\n",
00378                 tag, firstGlyph, nGlyphs ));
00379 
00380     gxv_glyphid_validate( firstGlyph, valid );
00381     gxv_glyphid_validate( (FT_UShort)( firstGlyph + nGlyphs - 1 ), valid );
00382 
00383     gxv_array_getlimits_ushort( p, p + ( 2 * nGlyphs ),
00384                                 &( GXV_KERN_FMT2_DATA( offset_min[spec] ) ),
00385                                 &( GXV_KERN_FMT2_DATA( offset_max[spec] ) ),
00386                                 valid );
00387 
00388     gxv_odtect_add_range( table, 2 * nGlyphs, tag, odtect );
00389 
00390     GXV_EXIT;
00391   }
00392 
00393 
00394   static void
00395   gxv_kern_subtable_fmt2_validate( FT_Bytes       table,
00396                                    FT_Bytes       limit,
00397                                    GXV_Validator  valid )
00398   {
00399     GXV_ODTECT( 3, odtect );
00400     GXV_kern_subtable_fmt2_DataRec  fmt2_rec =
00401       { 0, 0, { 0, 0 }, { 0, 0 }, { "leftClass", "rightClass" }, NULL };
00402 
00403     FT_Bytes   p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
00404     FT_UShort  leftOffsetTable;
00405     FT_UShort  rightOffsetTable;
00406 
00407 
00408     GXV_NAME_ENTER( "kern subtable format 2" );
00409 
00410     GXV_ODTECT_INIT( odtect );
00411     fmt2_rec.odtect = odtect;
00412     GXV_KERN_DATA( subtable_data ) = &fmt2_rec;
00413 
00414     GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 );
00415     GXV_KERN_FMT2_DATA( rowWidth ) = FT_NEXT_USHORT( p );
00416     leftOffsetTable                = FT_NEXT_USHORT( p );
00417     rightOffsetTable               = FT_NEXT_USHORT( p );
00418     GXV_KERN_FMT2_DATA( array )    = FT_NEXT_USHORT( p );
00419 
00420     GXV_TRACE(( "rowWidth = %d\n", GXV_KERN_FMT2_DATA( rowWidth ) ));
00421 
00422 
00423     GXV_LIMIT_CHECK( leftOffsetTable );
00424     GXV_LIMIT_CHECK( rightOffsetTable );
00425     GXV_LIMIT_CHECK( GXV_KERN_FMT2_DATA( array ) );
00426 
00427     gxv_kern_subtable_fmt2_clstbl_validate( table + leftOffsetTable, limit,
00428                                             GXV_KERN_CLS_L, valid );
00429 
00430     gxv_kern_subtable_fmt2_clstbl_validate( table + rightOffsetTable, limit,
00431                                             GXV_KERN_CLS_R, valid );
00432 
00433     if ( GXV_KERN_FMT2_DATA( offset_min[GXV_KERN_CLS_L] ) +
00434            GXV_KERN_FMT2_DATA( offset_min[GXV_KERN_CLS_R] )
00435          < GXV_KERN_FMT2_DATA( array )                      )
00436       FT_INVALID_OFFSET;
00437 
00438     gxv_odtect_add_range( table + GXV_KERN_FMT2_DATA( array ),
00439                           GXV_KERN_FMT2_DATA( offset_max[GXV_KERN_CLS_L] )
00440                             + GXV_KERN_FMT2_DATA( offset_max[GXV_KERN_CLS_R] )
00441                             - GXV_KERN_FMT2_DATA( array ),
00442                           "array", odtect );
00443 
00444     gxv_odtect_validate( odtect, valid );
00445 
00446     GXV_EXIT;
00447   }
00448 
00449 
00450   /* ============================= format 3 ============================== */
00451 
00452   static void
00453   gxv_kern_subtable_fmt3_validate( FT_Bytes       table,
00454                                    FT_Bytes       limit,
00455                                    GXV_Validator  valid )
00456   {
00457     FT_Bytes   p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
00458     FT_UShort  glyphCount;
00459     FT_Byte    kernValueCount;
00460     FT_Byte    leftClassCount;
00461     FT_Byte    rightClassCount;
00462     FT_Byte    flags;
00463 
00464 
00465     GXV_NAME_ENTER( "kern subtable format 3" );
00466 
00467     GXV_LIMIT_CHECK( 2 + 1 + 1 + 1 + 1 );
00468     glyphCount      = FT_NEXT_USHORT( p );
00469     kernValueCount  = FT_NEXT_BYTE( p );
00470     leftClassCount  = FT_NEXT_BYTE( p );
00471     rightClassCount = FT_NEXT_BYTE( p );
00472     flags           = FT_NEXT_BYTE( p );
00473 
00474     if ( valid->face->num_glyphs != glyphCount )
00475     {
00476       GXV_TRACE(( "maxGID=%d, but glyphCount=%d\n",
00477                   valid->face->num_glyphs, glyphCount ));
00478       if ( valid->root->level >= FT_VALIDATE_PARANOID )
00479         FT_INVALID_GLYPH_ID;
00480     }
00481 
00482     /*
00483      * just skip kernValue[kernValueCount]
00484      */
00485     GXV_LIMIT_CHECK( 2 * kernValueCount );
00486     p += 2 * kernValueCount;
00487 
00488     /*
00489      * check leftClass[gid] < leftClassCount
00490      */
00491     {
00492       FT_Byte  min, max;
00493 
00494 
00495       GXV_LIMIT_CHECK( glyphCount );
00496       gxv_array_getlimits_byte( p, p + glyphCount, &min, &max, valid );
00497       p += valid->subtable_length;
00498 
00499       if ( leftClassCount < max )
00500         FT_INVALID_DATA;
00501     }
00502 
00503     /*
00504      * check rightClass[gid] < rightClassCount
00505      */
00506     {
00507       FT_Byte  min, max;
00508 
00509 
00510       GXV_LIMIT_CHECK( glyphCount );
00511       gxv_array_getlimits_byte( p, p + glyphCount, &min, &max, valid );
00512       p += valid->subtable_length;
00513 
00514       if ( rightClassCount < max )
00515         FT_INVALID_DATA;
00516     }
00517 
00518     /*
00519      * check kernIndex[i, j] < kernValueCount
00520      */
00521     {
00522       FT_UShort  i, j;
00523 
00524 
00525       for ( i = 0; i < leftClassCount; i++ )
00526       {
00527         for ( j = 0; j < rightClassCount; j++ )
00528         {
00529           GXV_LIMIT_CHECK( 1 );
00530           if ( kernValueCount < FT_NEXT_BYTE( p ) )
00531             FT_INVALID_OFFSET;
00532         }
00533       }
00534     }
00535 
00536     valid->subtable_length = p - table;
00537 
00538     GXV_EXIT;
00539   }
00540 
00541 
00542   static FT_Bool
00543   gxv_kern_coverage_new_apple_validate( FT_UShort      coverage,
00544                                         FT_UShort*     format,
00545                                         GXV_Validator  valid )
00546   {
00547     /* new Apple-dialect */
00548     FT_Bool  kernVertical;
00549     FT_Bool  kernCrossStream;
00550     FT_Bool  kernVariation;
00551 
00552     FT_UNUSED( valid );
00553 
00554 
00555     /* reserved bits = 0 */
00556     if ( coverage & 0x1FFC )
00557       return 0;
00558 
00559     kernVertical    = FT_BOOL( ( coverage >> 15 ) & 1 );
00560     kernCrossStream = FT_BOOL( ( coverage >> 14 ) & 1 );
00561     kernVariation   = FT_BOOL( ( coverage >> 13 ) & 1 );
00562 
00563     *format = (FT_UShort)( coverage & 0x0003 );
00564 
00565     GXV_TRACE(( "new Apple-dialect: "
00566                 "horizontal=%d, cross-stream=%d, variation=%d, format=%d\n",
00567                  !kernVertical, kernCrossStream, kernVariation, *format ));
00568 
00569     GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" ));
00570 
00571     return 1;
00572   }
00573 
00574 
00575   static FT_Bool
00576   gxv_kern_coverage_classic_apple_validate( FT_UShort      coverage,
00577                                             FT_UShort*     format,
00578                                             GXV_Validator  valid )
00579   {
00580     /* classic Apple-dialect */
00581     FT_Bool  horizontal;
00582     FT_Bool  cross_stream;
00583 
00584 
00585     /* check expected flags, but don't check if MS-dialect is impossible */
00586     if ( !( coverage & 0xFD00 ) && KERN_ALLOWS_MS( valid ) )
00587       return 0;
00588 
00589     /* reserved bits = 0 */
00590     if ( coverage & 0x02FC )
00591       return 0;
00592 
00593     horizontal   = FT_BOOL( ( coverage >> 15 ) & 1 );
00594     cross_stream = FT_BOOL( ( coverage >> 13 ) & 1 );
00595 
00596     *format = (FT_UShort)( coverage & 0x0003 );
00597 
00598     GXV_TRACE(( "classic Apple-dialect: "
00599                 "horizontal=%d, cross-stream=%d, format=%d\n",
00600                  horizontal, cross_stream, *format ));
00601 
00602     /* format 1 requires GX State Machine, too new for classic */
00603     if ( *format == 1 )
00604       return 0;
00605 
00606     GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" ));
00607 
00608     return 1;
00609   }
00610 
00611 
00612   static FT_Bool
00613   gxv_kern_coverage_classic_microsoft_validate( FT_UShort      coverage,
00614                                                 FT_UShort*     format,
00615                                                 GXV_Validator  valid )
00616   {
00617     /* classic Microsoft-dialect */
00618     FT_Bool  horizontal;
00619     FT_Bool  minimum;
00620     FT_Bool  cross_stream;
00621     FT_Bool  override;
00622 
00623     FT_UNUSED( valid );
00624 
00625 
00626     /* reserved bits = 0 */
00627     if ( coverage & 0xFDF0 )
00628       return 0;
00629 
00630     horizontal   = FT_BOOL(   coverage        & 1 );
00631     minimum      = FT_BOOL( ( coverage >> 1 ) & 1 );
00632     cross_stream = FT_BOOL( ( coverage >> 2 ) & 1 );
00633     override     = FT_BOOL( ( coverage >> 3 ) & 1 );
00634 
00635     *format = (FT_UShort)( ( coverage >> 8 ) & 0x0003 );
00636 
00637     GXV_TRACE(( "classic Microsoft-dialect: "
00638                 "horizontal=%d, minimum=%d, cross-stream=%d, "
00639                 "override=%d, format=%d\n",
00640                 horizontal, minimum, cross_stream, override, *format ));
00641 
00642     if ( *format == 2 )
00643       GXV_TRACE((
00644         "kerning values in Microsoft format 2 subtable are ignored\n" ));
00645 
00646     return 1;
00647   }
00648 
00649 
00650   /*************************************************************************/
00651   /*************************************************************************/
00652   /*****                                                               *****/
00653   /*****                            MAIN                               *****/
00654   /*****                                                               *****/
00655   /*************************************************************************/
00656   /*************************************************************************/
00657 
00658   static GXV_kern_Dialect
00659   gxv_kern_coverage_validate( FT_UShort      coverage,
00660                               FT_UShort*     format,
00661                               GXV_Validator  valid )
00662   {
00663     GXV_kern_Dialect  result = KERN_DIALECT_UNKNOWN;
00664 
00665 
00666     GXV_NAME_ENTER( "validating coverage" );
00667 
00668     GXV_TRACE(( "interprete coverage 0x%04x by Apple style\n", coverage ));
00669 
00670     if ( KERN_IS_NEW( valid ) )
00671     {
00672       if ( gxv_kern_coverage_new_apple_validate( coverage,
00673                                                  format,
00674                                                  valid ) )
00675       {
00676         result = KERN_DIALECT_APPLE;
00677         goto Exit;
00678       }
00679     }
00680 
00681     if ( KERN_IS_CLASSIC( valid ) && KERN_ALLOWS_APPLE( valid ) )
00682     {
00683       if ( gxv_kern_coverage_classic_apple_validate( coverage,
00684                                                      format,
00685                                                      valid ) )
00686       {
00687         result = KERN_DIALECT_APPLE;
00688         goto Exit;
00689       }
00690     }
00691 
00692     if ( KERN_IS_CLASSIC( valid ) && KERN_ALLOWS_MS( valid ) )
00693     {
00694       if ( gxv_kern_coverage_classic_microsoft_validate( coverage,
00695                                                          format,
00696                                                          valid ) )
00697       {
00698         result = KERN_DIALECT_MS;
00699         goto Exit;
00700       }
00701     }
00702 
00703     GXV_TRACE(( "cannot interprete coverage, broken kern subtable\n" ));
00704 
00705   Exit:
00706     GXV_EXIT;
00707     return result;
00708   }
00709 
00710 
00711   static void
00712   gxv_kern_subtable_validate( FT_Bytes       table,
00713                               FT_Bytes       limit,
00714                               GXV_Validator  valid )
00715   {
00716     FT_Bytes   p = table;
00717     FT_UShort  version = 0;    /* MS only: subtable version, unused */
00718     FT_ULong   length;         /* MS: 16bit, Apple: 32bit*/
00719     FT_UShort  coverage;
00720     FT_UShort  tupleIndex = 0; /* Apple only */
00721     FT_UShort  u16[2];
00722     FT_UShort  format = 255;   /* subtable format */
00723 
00724 
00725     GXV_NAME_ENTER( "kern subtable" );
00726 
00727     GXV_LIMIT_CHECK( 2 + 2 + 2 );
00728     u16[0]   = FT_NEXT_USHORT( p ); /* Apple: length_hi MS: version */
00729     u16[1]   = FT_NEXT_USHORT( p ); /* Apple: length_lo MS: length */
00730     coverage = FT_NEXT_USHORT( p );
00731 
00732     switch ( gxv_kern_coverage_validate( coverage, &format, valid ) )
00733     {
00734     case KERN_DIALECT_MS:
00735       version    = u16[0];
00736       length     = u16[1];
00737       tupleIndex = 0;
00738       GXV_TRACE(( "Subtable version = %d\n", version ));
00739       GXV_TRACE(( "Subtable length = %d\n", length ));
00740       break;
00741 
00742     case KERN_DIALECT_APPLE:
00743       version    = 0;
00744       length     = ( u16[0] << 16 ) + u16[1];
00745       tupleIndex = 0;
00746       GXV_TRACE(( "Subtable length = %d\n", length ));
00747 
00748       if ( KERN_IS_NEW( valid ) )
00749       {
00750         GXV_LIMIT_CHECK( 2 );
00751         tupleIndex = FT_NEXT_USHORT( p );
00752         GXV_TRACE(( "Subtable tupleIndex = %d\n", tupleIndex ));
00753       }
00754       break;
00755 
00756     default:
00757       length = u16[1];
00758       GXV_TRACE(( "cannot detect subtable dialect, "
00759                   "just skip %d byte\n", length ));
00760       goto Exit;
00761     }
00762 
00763     /* formats 1, 2, 3 require the position of the start of this subtable */
00764     if ( format == 0 )
00765       gxv_kern_subtable_fmt0_validate( table, table + length, valid );
00766     else if ( format == 1 )
00767       gxv_kern_subtable_fmt1_validate( table, table + length, valid );
00768     else if ( format == 2 )
00769       gxv_kern_subtable_fmt2_validate( table, table + length, valid );
00770     else if ( format == 3 )
00771       gxv_kern_subtable_fmt3_validate( table, table + length, valid );
00772     else
00773       FT_INVALID_DATA;
00774 
00775   Exit:
00776     valid->subtable_length = length;
00777     GXV_EXIT;
00778   }
00779 
00780 
00781   /*************************************************************************/
00782   /*************************************************************************/
00783   /*****                                                               *****/
00784   /*****                         kern TABLE                            *****/
00785   /*****                                                               *****/
00786   /*************************************************************************/
00787   /*************************************************************************/
00788 
00789   static void
00790   gxv_kern_validate_generic( FT_Bytes          table,
00791                              FT_Face           face,
00792                              FT_Bool           classic_only,
00793                              GXV_kern_Dialect  dialect_request,
00794                              FT_Validator      ftvalid )
00795   {
00796     GXV_ValidatorRec   validrec;
00797     GXV_Validator      valid = &validrec;
00798 
00799     GXV_kern_DataRec   kernrec;
00800     GXV_kern_Data      kern = &kernrec;
00801 
00802     FT_Bytes           p     = table;
00803     FT_Bytes           limit = 0;
00804 
00805     FT_ULong           nTables = 0;
00806     FT_UInt            i;
00807 
00808 
00809     valid->root       = ftvalid;
00810     valid->table_data = kern;
00811     valid->face       = face;
00812 
00813     FT_TRACE3(( "validating `kern' table\n" ));
00814     GXV_INIT;
00815     KERN_DIALECT( valid ) = dialect_request;
00816 
00817     GXV_LIMIT_CHECK( 2 );
00818     GXV_KERN_DATA( version ) = (GXV_kern_Version)FT_NEXT_USHORT( p );
00819     GXV_TRACE(( "version 0x%04x (higher 16bit)\n",
00820                 GXV_KERN_DATA( version ) ));
00821 
00822     if ( 0x0001 < GXV_KERN_DATA( version ) )
00823       FT_INVALID_FORMAT;
00824     else if ( KERN_IS_CLASSIC( valid ) )
00825     {
00826       GXV_LIMIT_CHECK( 2 );
00827       nTables = FT_NEXT_USHORT( p );
00828     }
00829     else if ( KERN_IS_NEW( valid ) )
00830     {
00831       if ( classic_only )
00832         FT_INVALID_FORMAT;
00833 
00834       if ( 0x0000 != FT_NEXT_USHORT( p ) )
00835         FT_INVALID_FORMAT;
00836 
00837       GXV_LIMIT_CHECK( 4 );
00838       nTables = FT_NEXT_ULONG( p );
00839     }
00840 
00841     for ( i = 0; i < nTables; i++ )
00842     {
00843       GXV_TRACE(( "validating subtable %d/%d\n", i, nTables ));
00844       /* p should be 32bit-aligned? */
00845       gxv_kern_subtable_validate( p, 0, valid );
00846       p += valid->subtable_length;
00847     }
00848 
00849     FT_TRACE4(( "\n" ));
00850   }
00851 
00852 
00853   FT_LOCAL_DEF( void )
00854   gxv_kern_validate( FT_Bytes      table,
00855                      FT_Face       face,
00856                      FT_Validator  ftvalid )
00857   {
00858     gxv_kern_validate_generic( table, face, 0, KERN_DIALECT_ANY, ftvalid );
00859   }
00860 
00861 
00862   FT_LOCAL_DEF( void )
00863   gxv_kern_validate_classic( FT_Bytes      table,
00864                              FT_Face       face,
00865                              FT_Int        dialect_flags,
00866                              FT_Validator  ftvalid )
00867   {
00868     GXV_kern_Dialect  dialect_request;
00869 
00870 
00871     dialect_request = (GXV_kern_Dialect)dialect_flags;
00872     gxv_kern_validate_generic( table, face, 1, dialect_request, ftvalid );
00873   }
00874 
00875 
00876 /* END */

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