gxvjust.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  gxvjust.c                                                              */
00004 /*                                                                         */
00005 /*    TrueTypeGX/AAT just table validation (body).                         */
00006 /*                                                                         */
00007 /*  Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K.,       */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 /***************************************************************************/
00019 /*                                                                         */
00020 /* gxvalid is derived from both gxlayout module and otvalid module.        */
00021 /* Development of gxlayout is supported by the Information-technology      */
00022 /* Promotion Agency(IPA), Japan.                                           */
00023 /*                                                                         */
00024 /***************************************************************************/
00025 
00026 
00027 #include "gxvalid.h"
00028 #include "gxvcommn.h"
00029 
00030 #include FT_SFNT_NAMES_H
00031 
00032 
00033   /*************************************************************************/
00034   /*                                                                       */
00035   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00036   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00037   /* messages during execution.                                            */
00038   /*                                                                       */
00039 #undef  FT_COMPONENT
00040 #define FT_COMPONENT  trace_gxvjust
00041 
00042   /*
00043    * referred `just' table format specification:
00044    * http://developer.apple.com/fonts/TTRefMan/RM06/Chap6just.html
00045    * last updated 2000.
00046    * ----------------------------------------------
00047    * [JUST HEADER]: GXV_JUST_HEADER_SIZE
00048    * version     (fixed:  32bit) = 0x00010000
00049    * format      (uint16: 16bit) = 0 is only defined (2000)
00050    * horizOffset (uint16: 16bit)
00051    * vertOffset  (uint16: 16bit)
00052    * ----------------------------------------------
00053    */
00054 
00055   typedef struct  GXV_just_DataRec_
00056   {
00057     FT_UShort  wdc_offset_max;
00058     FT_UShort  wdc_offset_min;
00059     FT_UShort  pc_offset_max;
00060     FT_UShort  pc_offset_min;
00061 
00062   } GXV_just_DataRec, *GXV_just_Data;
00063 
00064 
00065 #define  GXV_JUST_DATA( a )  GXV_TABLE_DATA( just, a )
00066 
00067 
00068   static void
00069   gxv_just_wdp_entry_validate( FT_Bytes       table,
00070                                FT_Bytes       limit,
00071                                GXV_Validator  valid )
00072   {
00073     FT_Bytes   p = table;
00074     FT_ULong   justClass;
00075     FT_Fixed   beforeGrowLimit;
00076     FT_Fixed   beforeShrinkGrowLimit;
00077     FT_Fixed   afterGrowLimit;
00078     FT_Fixed   afterShrinkGrowLimit;
00079     FT_UShort  growFlags;
00080     FT_UShort  shrinkFlags;
00081 
00082 
00083     GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 + 4 + 2 + 2 );
00084     justClass             = FT_NEXT_ULONG( p );
00085     beforeGrowLimit       = FT_NEXT_ULONG( p );
00086     beforeShrinkGrowLimit = FT_NEXT_ULONG( p );
00087     afterGrowLimit        = FT_NEXT_ULONG( p );
00088     afterShrinkGrowLimit  = FT_NEXT_ULONG( p );
00089     growFlags             = FT_NEXT_USHORT( p );
00090     shrinkFlags           = FT_NEXT_USHORT( p );
00091 
00092     /* TODO: decode flags for human readability */
00093 
00094     valid->subtable_length = p - table;
00095   }
00096 
00097 
00098   static void
00099   gxv_just_wdc_entry_validate( FT_Bytes       table,
00100                                FT_Bytes       limit,
00101                                GXV_Validator  valid )
00102   {
00103     FT_Bytes  p = table;
00104     FT_ULong  count, i;
00105 
00106 
00107     GXV_LIMIT_CHECK( 4 );
00108     count = FT_NEXT_ULONG( p );
00109     for ( i = 0; i < count; i++ )
00110     {
00111       GXV_TRACE(( "validating wdc pair %d/%d\n", i + 1, count ));
00112       gxv_just_wdp_entry_validate( p, limit, valid );
00113       p += valid->subtable_length;
00114     }
00115 
00116     valid->subtable_length = p - table;
00117   }
00118 
00119 
00120   static void
00121   gxv_just_widthDeltaClusters_validate( FT_Bytes       table,
00122                                         FT_Bytes       limit,
00123                                         GXV_Validator  valid )
00124   {
00125     FT_Bytes  p         = table ;
00126     FT_Bytes  wdc_end   = table + GXV_JUST_DATA( wdc_offset_max );
00127     FT_UInt   i;
00128 
00129 
00130     GXV_NAME_ENTER( "just justDeltaClusters" );
00131 
00132     if ( limit <= wdc_end )
00133       FT_INVALID_OFFSET;
00134 
00135     for ( i = 0; p <= wdc_end; i++ )
00136     {
00137       gxv_just_wdc_entry_validate( p, limit, valid );
00138       p += valid->subtable_length;
00139     }
00140 
00141     valid->subtable_length = p - table;
00142 
00143     GXV_EXIT;
00144   }
00145 
00146 
00147   static void
00148   gxv_just_actSubrecord_type0_validate( FT_Bytes       table,
00149                                         FT_Bytes       limit,
00150                                         GXV_Validator  valid )
00151   {
00152     FT_Bytes   p = table;
00153 
00154     FT_Fixed   lowerLimit;
00155     FT_Fixed   upperLimit;
00156 
00157     FT_UShort  order;
00158     FT_UShort  decomposedCount;
00159 
00160     FT_UInt    i;
00161 
00162 
00163     GXV_LIMIT_CHECK( 4 + 4 + 2 + 2 );
00164     lowerLimit      = FT_NEXT_ULONG( p );
00165     upperLimit      = FT_NEXT_ULONG( p );
00166     order           = FT_NEXT_USHORT( p );
00167     decomposedCount = FT_NEXT_USHORT( p );
00168 
00169     for ( i = 0; i < decomposedCount; i++ )
00170     {
00171       FT_UShort glyphs;
00172 
00173 
00174       GXV_LIMIT_CHECK( 2 );
00175       glyphs = FT_NEXT_USHORT( p );
00176     }
00177 
00178     valid->subtable_length = p - table;
00179   }
00180 
00181 
00182   static void
00183   gxv_just_actSubrecord_type1_validate( FT_Bytes       table,
00184                                         FT_Bytes       limit,
00185                                         GXV_Validator  valid )
00186   {
00187     FT_Bytes   p = table;
00188     FT_UShort  addGlyph;
00189 
00190 
00191     GXV_LIMIT_CHECK( 2 );
00192     addGlyph = FT_NEXT_USHORT( p );
00193 
00194     valid->subtable_length = p - table;
00195   }
00196 
00197 
00198   static void
00199   gxv_just_actSubrecord_type2_validate( FT_Bytes       table,
00200                                         FT_Bytes       limit,
00201                                         GXV_Validator  valid )
00202   {
00203     FT_Bytes   p = table;
00204     FT_Fixed   substThreshhold; /* Apple misspelled "Threshhold" */
00205     FT_UShort  addGlyph;
00206     FT_UShort  substGlyph;
00207 
00208 
00209     GXV_LIMIT_CHECK( 4 + 2 + 2 );
00210     substThreshhold = FT_NEXT_ULONG( p );
00211     addGlyph        = FT_NEXT_USHORT( p );
00212     substGlyph      = FT_NEXT_USHORT( p );
00213 
00214     valid->subtable_length = p - table;
00215   }
00216 
00217 
00218   static void
00219   gxv_just_actSubrecord_type4_validate( FT_Bytes       table,
00220                                         FT_Bytes       limit,
00221                                         GXV_Validator  valid )
00222   {
00223     FT_Bytes  p = table;
00224     FT_ULong  variantsAxis;
00225     FT_Fixed  minimumLimit;
00226     FT_Fixed  noStretchValue;
00227     FT_Fixed  maximumLimit;
00228 
00229 
00230     GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
00231     variantsAxis   = FT_NEXT_ULONG( p );
00232     minimumLimit   = FT_NEXT_ULONG( p );
00233     noStretchValue = FT_NEXT_ULONG( p );
00234     maximumLimit   = FT_NEXT_ULONG( p );
00235 
00236     valid->subtable_length = p - table;
00237   }
00238 
00239 
00240   static void
00241   gxv_just_actSubrecord_type5_validate( FT_Bytes       table,
00242                                         FT_Bytes       limit,
00243                                         GXV_Validator  valid )
00244   {
00245     FT_Bytes   p = table;
00246     FT_UShort  flags;
00247     FT_UShort  glyph;
00248 
00249 
00250     GXV_LIMIT_CHECK( 2 + 2 );
00251     flags = FT_NEXT_USHORT( p );
00252     glyph = FT_NEXT_USHORT( p );
00253 
00254     valid->subtable_length = p - table;
00255   }
00256 
00257 
00258   /* parse single actSubrecord */
00259   static void
00260   gxv_just_actSubrecord_validate( FT_Bytes       table,
00261                                   FT_Bytes       limit,
00262                                   GXV_Validator  valid )
00263   {
00264     FT_Bytes   p = table;
00265     FT_UShort  actionClass;
00266     FT_UShort  actionType;
00267     FT_ULong   actionLength;
00268 
00269 
00270     GXV_NAME_ENTER( "just actSubrecord" );
00271 
00272     GXV_LIMIT_CHECK( 2 + 2 + 4 );
00273     actionClass  = FT_NEXT_USHORT( p );
00274     actionType   = FT_NEXT_USHORT( p );
00275     actionLength = FT_NEXT_ULONG( p );
00276 
00277     if ( actionType == 0 )
00278       gxv_just_actSubrecord_type0_validate( p, limit, valid );
00279     else if ( actionType == 1 )
00280       gxv_just_actSubrecord_type1_validate( p, limit, valid );
00281     else if ( actionType == 2 )
00282       gxv_just_actSubrecord_type2_validate( p, limit, valid );
00283     else if ( actionType == 3 )
00284       ;                         /* Stretch glyph action: no actionData */
00285     else if ( actionType == 4 )
00286       gxv_just_actSubrecord_type4_validate( p, limit, valid );
00287     else if ( actionType == 5 )
00288       gxv_just_actSubrecord_type5_validate( p, limit, valid );
00289     else
00290       FT_INVALID_DATA;
00291 
00292     valid->subtable_length = actionLength;
00293 
00294     GXV_EXIT;
00295   }
00296 
00297 
00298   static void
00299   gxv_just_pcActionRecord_validate( FT_Bytes       table,
00300                                     FT_Bytes       limit,
00301                                     GXV_Validator  valid )
00302   {
00303     FT_Bytes  p = table;
00304     FT_ULong  actionCount;
00305     FT_ULong  i;
00306 
00307 
00308     GXV_LIMIT_CHECK( 4 );
00309     actionCount = FT_NEXT_ULONG( p );
00310     GXV_TRACE(( "actionCount = %d\n", actionCount ));
00311 
00312     for ( i = 0; i < actionCount; i++ )
00313     {
00314       gxv_just_actSubrecord_validate( p, limit, valid );
00315       p += valid->subtable_length;
00316     }
00317 
00318     valid->subtable_length = p - table;
00319 
00320     GXV_EXIT;
00321   }
00322 
00323 
00324   static void
00325   gxv_just_pcTable_LookupValue_entry_validate( FT_UShort            glyph,
00326                                                GXV_LookupValueCPtr  value_p,
00327                                                GXV_Validator        valid )
00328   {
00329     FT_UNUSED( glyph );
00330 
00331     if ( value_p->u > GXV_JUST_DATA( pc_offset_max ) )
00332       GXV_JUST_DATA( pc_offset_max ) = value_p->u;
00333     if ( value_p->u < GXV_JUST_DATA( pc_offset_max ) )
00334       GXV_JUST_DATA( pc_offset_min ) = value_p->u;
00335   }
00336 
00337 
00338   static void
00339   gxv_just_pcLookupTable_validate( FT_Bytes       table,
00340                                    FT_Bytes       limit,
00341                                    GXV_Validator  valid )
00342   {
00343     FT_Bytes p = table;
00344 
00345 
00346     GXV_NAME_ENTER( "just pcLookupTable" );
00347     GXV_JUST_DATA( pc_offset_max ) = 0x0000;
00348     GXV_JUST_DATA( pc_offset_min ) = 0xFFFFU;
00349 
00350     valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
00351     valid->lookupval_func = gxv_just_pcTable_LookupValue_entry_validate;
00352 
00353     gxv_LookupTable_validate( p, limit, valid );
00354 
00355     /* subtable_length is set by gxv_LookupTable_validate() */
00356 
00357     GXV_EXIT;
00358   }
00359 
00360 
00361   static void
00362   gxv_just_postcompTable_validate( FT_Bytes       table,
00363                                    FT_Bytes       limit,
00364                                    GXV_Validator  valid )
00365   {
00366     FT_Bytes  p = table;
00367 
00368 
00369     GXV_NAME_ENTER( "just postcompTable" );
00370 
00371     gxv_just_pcLookupTable_validate( p, limit, valid );
00372     p += valid->subtable_length;
00373 
00374     gxv_just_pcActionRecord_validate( p, limit, valid );
00375     p += valid->subtable_length;
00376 
00377     valid->subtable_length = p - table;
00378 
00379     GXV_EXIT;
00380   }
00381 
00382 
00383   static void
00384   gxv_just_classTable_entry_validate(
00385     FT_Byte                         state,
00386     FT_UShort                       flags,
00387     GXV_StateTable_GlyphOffsetCPtr  glyphOffset_p,
00388     FT_Bytes                        table,
00389     FT_Bytes                        limit,
00390     GXV_Validator                   valid )
00391   {
00392     FT_UShort  setMark;
00393     FT_UShort  dontAdvance;
00394     FT_UShort  markClass;
00395     FT_UShort  currentClass;
00396 
00397     FT_UNUSED( state );
00398     FT_UNUSED( glyphOffset_p );
00399     FT_UNUSED( table );
00400     FT_UNUSED( limit );
00401     FT_UNUSED( valid );
00402 
00403 
00404     setMark      = (FT_UShort)( ( flags >> 15 ) & 1    );
00405     dontAdvance  = (FT_UShort)( ( flags >> 14 ) & 1    );
00406     markClass    = (FT_UShort)( ( flags >> 7  ) & 0x7F );
00407     currentClass = (FT_UShort)(   flags         & 0x7F );
00408 
00409     /* TODO: validate markClass & currentClass */
00410   }
00411 
00412 
00413   static void
00414   gxv_just_justClassTable_validate ( FT_Bytes       table,
00415                                      FT_Bytes       limit,
00416                                      GXV_Validator  valid )
00417   {
00418     FT_Bytes   p = table;
00419     FT_UShort  length;
00420     FT_UShort  coverage;
00421     FT_ULong   subFeatureFlags;
00422 
00423 
00424     GXV_NAME_ENTER( "just justClassTable" );
00425 
00426     GXV_LIMIT_CHECK( 2 + 2 + 4 );
00427     length          = FT_NEXT_USHORT( p );
00428     coverage        = FT_NEXT_USHORT( p );
00429     subFeatureFlags = FT_NEXT_ULONG( p );
00430 
00431     GXV_TRACE(( "  justClassTable: coverage = 0x%04x (%s)",
00432                 coverage,
00433                 ( 0x4000 & coverage ) == 0 ? "ascending" : "descending" ));
00434 
00435     valid->statetable.optdata               = NULL;
00436     valid->statetable.optdata_load_func     = NULL;
00437     valid->statetable.subtable_setup_func   = NULL;
00438     valid->statetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_NONE;
00439     valid->statetable.entry_validate_func   =
00440       gxv_just_classTable_entry_validate;
00441 
00442     gxv_StateTable_validate( p, table + length, valid );
00443 
00444     /* subtable_length is set by gxv_LookupTable_validate() */
00445 
00446     GXV_EXIT;
00447   }
00448 
00449 
00450   static void
00451   gxv_just_wdcTable_LookupValue_validate( FT_UShort            glyph,
00452                                           GXV_LookupValueCPtr  value_p,
00453                                           GXV_Validator        valid )
00454   {
00455     FT_UNUSED( glyph );
00456 
00457     if ( value_p->u > GXV_JUST_DATA( wdc_offset_max ) )
00458       GXV_JUST_DATA( wdc_offset_max ) = value_p->u;
00459     if ( value_p->u < GXV_JUST_DATA( wdc_offset_min ) )
00460       GXV_JUST_DATA( wdc_offset_min ) = value_p->u;
00461   }
00462 
00463 
00464   static void
00465   gxv_just_justData_lookuptable_validate( FT_Bytes       table,
00466                                           FT_Bytes       limit,
00467                                           GXV_Validator  valid )
00468   {
00469     FT_Bytes  p = table;
00470 
00471 
00472     GXV_JUST_DATA( wdc_offset_max ) = 0x0000;
00473     GXV_JUST_DATA( wdc_offset_min ) = 0xFFFFU;
00474 
00475     valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
00476     valid->lookupval_func = gxv_just_wdcTable_LookupValue_validate;
00477 
00478     gxv_LookupTable_validate( p, limit, valid );
00479 
00480     /* subtable_length is set by gxv_LookupTable_validate() */
00481 
00482     GXV_EXIT;
00483   }
00484 
00485 
00486   /*
00487    * gxv_just_justData_validate() parses and validates horizData, vertData.
00488    */
00489   static void
00490   gxv_just_justData_validate( FT_Bytes       table,
00491                               FT_Bytes       limit,
00492                               GXV_Validator  valid )
00493   {
00494     /*
00495      * following 3 offsets are measured from the start of `just'
00496      * (which table points to), not justData
00497      */
00498     FT_UShort  justClassTableOffset;
00499     FT_UShort  wdcTableOffset;
00500     FT_UShort  pcTableOffset;
00501     FT_Bytes   p = table;
00502 
00503     GXV_ODTECT( 4, odtect );
00504 
00505 
00506     GXV_NAME_ENTER( "just justData" );
00507 
00508     GXV_ODTECT_INIT( odtect );
00509     GXV_LIMIT_CHECK( 2 + 2 + 2 );
00510     justClassTableOffset = FT_NEXT_USHORT( p );
00511     wdcTableOffset       = FT_NEXT_USHORT( p );
00512     pcTableOffset        = FT_NEXT_USHORT( p );
00513 
00514     GXV_TRACE(( " (justClassTableOffset = 0x%04x)\n", justClassTableOffset ));
00515     GXV_TRACE(( " (wdcTableOffset = 0x%04x)\n", wdcTableOffset ));
00516     GXV_TRACE(( " (pcTableOffset = 0x%04x)\n", pcTableOffset ));
00517 
00518     gxv_just_justData_lookuptable_validate( p, limit, valid );
00519     gxv_odtect_add_range( p, valid->subtable_length,
00520                           "just_LookupTable", odtect );
00521 
00522     if ( wdcTableOffset )
00523     {
00524       gxv_just_widthDeltaClusters_validate(
00525         valid->root->base + wdcTableOffset, limit, valid );
00526       gxv_odtect_add_range( valid->root->base + wdcTableOffset,
00527                             valid->subtable_length, "just_wdcTable", odtect );
00528     }
00529 
00530     if ( pcTableOffset )
00531     {
00532       gxv_just_postcompTable_validate( valid->root->base + pcTableOffset,
00533                                        limit, valid );
00534       gxv_odtect_add_range( valid->root->base + pcTableOffset,
00535                             valid->subtable_length, "just_pcTable", odtect );
00536     }
00537 
00538     if ( justClassTableOffset )
00539     {
00540       gxv_just_justClassTable_validate(
00541         valid->root->base + justClassTableOffset, limit, valid );
00542       gxv_odtect_add_range( valid->root->base + justClassTableOffset,
00543                             valid->subtable_length, "just_justClassTable",
00544                             odtect );
00545     }
00546 
00547     gxv_odtect_validate( odtect, valid );
00548 
00549     GXV_EXIT;
00550   }
00551 
00552 
00553   FT_LOCAL_DEF( void )
00554   gxv_just_validate( FT_Bytes      table,
00555                      FT_Face       face,
00556                      FT_Validator  ftvalid )
00557   {
00558     FT_Bytes           p     = table;
00559     FT_Bytes           limit = 0;
00560     FT_Offset          table_size;
00561 
00562     GXV_ValidatorRec   validrec;
00563     GXV_Validator      valid = &validrec;
00564     GXV_just_DataRec   justrec;
00565     GXV_just_Data      just = &justrec;
00566 
00567     FT_ULong           version;
00568     FT_UShort          format;
00569     FT_UShort          horizOffset;
00570     FT_UShort          vertOffset;
00571 
00572     GXV_ODTECT( 3, odtect );
00573 
00574 
00575     GXV_ODTECT_INIT( odtect );
00576 
00577     valid->root       = ftvalid;
00578     valid->table_data = just;
00579     valid->face       = face;
00580 
00581     FT_TRACE3(( "validating `just' table\n" ));
00582     GXV_INIT;
00583 
00584     limit      = valid->root->limit;
00585     table_size = limit - table;
00586 
00587     GXV_LIMIT_CHECK( 4 + 2 + 2 + 2 );
00588     version     = FT_NEXT_ULONG( p );
00589     format      = FT_NEXT_USHORT( p );
00590     horizOffset = FT_NEXT_USHORT( p );
00591     vertOffset  = FT_NEXT_USHORT( p );
00592     gxv_odtect_add_range( table, p - table, "just header", odtect );
00593 
00594 
00595     /* Version 1.0 (always:2000) */
00596     GXV_TRACE(( " (version = 0x%08x)\n", version ));
00597     if ( version != 0x00010000UL )
00598       FT_INVALID_FORMAT;
00599 
00600     /* format 0 (always:2000) */
00601     GXV_TRACE(( " (format = 0x%04x)\n", format ));
00602     if ( format != 0x0000 )
00603         FT_INVALID_FORMAT;
00604 
00605     GXV_TRACE(( " (horizOffset = %d)\n", horizOffset  ));
00606     GXV_TRACE(( " (vertOffset = %d)\n", vertOffset  ));
00607 
00608 
00609     /* validate justData */
00610     if ( 0 < horizOffset )
00611     {
00612       gxv_just_justData_validate( table + horizOffset, limit, valid );
00613       gxv_odtect_add_range( table + horizOffset, valid->subtable_length,
00614                             "horizJustData", odtect );
00615     }
00616 
00617     if ( 0 < vertOffset )
00618     {
00619       gxv_just_justData_validate( table + vertOffset, limit, valid );
00620       gxv_odtect_add_range( table + vertOffset, valid->subtable_length,
00621                             "vertJustData", odtect );
00622     }
00623 
00624     gxv_odtect_validate( odtect, valid );
00625 
00626     FT_TRACE4(( "\n" ));
00627   }
00628 
00629 
00630 /* END */

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