ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

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 Sat May 26 2012 04:32:44 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.