otvgpos.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  otvgpos.c                                                              */
00004 /*                                                                         */
00005 /*    OpenType GPOS table validation (body).                               */
00006 /*                                                                         */
00007 /*  Copyright 2002, 2004, 2005, 2006, 2007, 2008 by                        */
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 #include "otvalid.h"
00020 #include "otvcommn.h"
00021 #include "otvgpos.h"
00022 
00023 
00024   /*************************************************************************/
00025   /*                                                                       */
00026   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00027   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00028   /* messages during execution.                                            */
00029   /*                                                                       */
00030 #undef  FT_COMPONENT
00031 #define FT_COMPONENT  trace_otvgpos
00032 
00033 
00034   static void
00035   otv_Anchor_validate( FT_Bytes       table,
00036                        OTV_Validator  valid );
00037 
00038   static void
00039   otv_MarkArray_validate( FT_Bytes       table,
00040                           OTV_Validator  valid );
00041 
00042 
00043   /*************************************************************************/
00044   /*************************************************************************/
00045   /*****                                                               *****/
00046   /*****                      UTILITY FUNCTIONS                        *****/
00047   /*****                                                               *****/
00048   /*************************************************************************/
00049   /*************************************************************************/
00050 
00051 #define BaseArrayFunc       otv_x_sxy
00052 #define LigatureAttachFunc  otv_x_sxy
00053 #define Mark2ArrayFunc      otv_x_sxy
00054 
00055   /* uses valid->extra1 (counter)                             */
00056   /* uses valid->extra2 (boolean to handle NULL anchor field) */
00057 
00058   static void
00059   otv_x_sxy( FT_Bytes       table,
00060              OTV_Validator  valid )
00061   {
00062     FT_Bytes  p = table;
00063     FT_UInt   Count, count1, table_size;
00064 
00065 
00066     OTV_ENTER;
00067 
00068     OTV_LIMIT_CHECK( 2 );
00069 
00070     Count = FT_NEXT_USHORT( p );
00071 
00072     OTV_TRACE(( " (Count = %d)\n", Count ));
00073 
00074     OTV_LIMIT_CHECK( Count * valid->extra1 * 2 );
00075 
00076     table_size = Count * valid->extra1 * 2 + 2;
00077 
00078     for ( ; Count > 0; Count-- )
00079       for ( count1 = valid->extra1; count1 > 0; count1-- )
00080       {
00081         OTV_OPTIONAL_TABLE( anchor_offset );
00082 
00083 
00084         OTV_OPTIONAL_OFFSET( anchor_offset );
00085 
00086         if ( valid->extra2 )
00087         {
00088           OTV_SIZE_CHECK( anchor_offset );
00089           if ( anchor_offset )
00090             otv_Anchor_validate( table + anchor_offset, valid );
00091         }
00092         else
00093           otv_Anchor_validate( table + anchor_offset, valid );
00094       }
00095 
00096     OTV_EXIT;
00097   }
00098 
00099 
00100 #define MarkBasePosFormat1Func  otv_u_O_O_u_O_O
00101 #define MarkLigPosFormat1Func   otv_u_O_O_u_O_O
00102 #define MarkMarkPosFormat1Func  otv_u_O_O_u_O_O
00103 
00104   /* sets valid->extra1 (class count) */
00105 
00106   static void
00107   otv_u_O_O_u_O_O( FT_Bytes       table,
00108                    OTV_Validator  valid )
00109   {
00110     FT_Bytes           p = table;
00111     FT_UInt            Coverage1, Coverage2, ClassCount;
00112     FT_UInt            Array1, Array2;
00113     OTV_Validate_Func  func;
00114 
00115 
00116     OTV_ENTER;
00117 
00118     p += 2;     /* skip PosFormat */
00119 
00120     OTV_LIMIT_CHECK( 10 );
00121     Coverage1  = FT_NEXT_USHORT( p );
00122     Coverage2  = FT_NEXT_USHORT( p );
00123     ClassCount = FT_NEXT_USHORT( p );
00124     Array1     = FT_NEXT_USHORT( p );
00125     Array2     = FT_NEXT_USHORT( p );
00126 
00127     otv_Coverage_validate( table + Coverage1, valid, -1 );
00128     otv_Coverage_validate( table + Coverage2, valid, -1 );
00129 
00130     otv_MarkArray_validate( table + Array1, valid );
00131 
00132     valid->nesting_level++;
00133     func          = valid->func[valid->nesting_level];
00134     valid->extra1 = ClassCount;
00135 
00136     func( table + Array2, valid );
00137 
00138     valid->nesting_level--;
00139 
00140     OTV_EXIT;
00141   }
00142 
00143 
00144   /*************************************************************************/
00145   /*************************************************************************/
00146   /*****                                                               *****/
00147   /*****                        VALUE RECORDS                          *****/
00148   /*****                                                               *****/
00149   /*************************************************************************/
00150   /*************************************************************************/
00151 
00152   static FT_UInt
00153   otv_value_length( FT_UInt  format )
00154   {
00155     FT_UInt  count;
00156 
00157 
00158     count = ( ( format & 0xAA ) >> 1 ) + ( format & 0x55 );
00159     count = ( ( count  & 0xCC ) >> 2 ) + ( count  & 0x33 );
00160     count = ( ( count  & 0xF0 ) >> 4 ) + ( count  & 0x0F );
00161 
00162     return count * 2;
00163   }
00164 
00165 
00166   /* uses valid->extra3 (pointer to base table) */
00167 
00168   static void
00169   otv_ValueRecord_validate( FT_Bytes       table,
00170                             FT_UInt        format,
00171                             OTV_Validator  valid )
00172   {
00173     FT_Bytes  p = table;
00174     FT_UInt   count;
00175 
00176 #ifdef FT_DEBUG_LEVEL_TRACE
00177     FT_Int    loop;
00178     FT_ULong  res = 0;
00179 
00180 
00181     OTV_NAME_ENTER( "ValueRecord" );
00182 
00183     /* display `format' in dual representation */
00184     for ( loop = 7; loop >= 0; loop-- )
00185     {
00186       res <<= 4;
00187       res  += ( format >> loop ) & 1;
00188     }
00189 
00190     OTV_TRACE(( " (format 0b%08lx)\n", res ));
00191 #endif
00192 
00193     if ( format >= 0x100 )
00194       FT_INVALID_FORMAT;
00195 
00196     for ( count = 4; count > 0; count-- )
00197     {
00198       if ( format & 1 )
00199       {
00200         /* XPlacement, YPlacement, XAdvance, YAdvance */
00201         OTV_LIMIT_CHECK( 2 );
00202         p += 2;
00203       }
00204 
00205       format >>= 1;
00206     }
00207 
00208     for ( count = 4; count > 0; count-- )
00209     {
00210       if ( format & 1 )
00211       {
00212         FT_PtrDist  table_size;
00213 
00214         OTV_OPTIONAL_TABLE( device );
00215 
00216 
00217         /* XPlaDevice, YPlaDevice, XAdvDevice, YAdvDevice */
00218         OTV_LIMIT_CHECK( 2 );
00219         OTV_OPTIONAL_OFFSET( device );
00220 
00221         /* XXX: this value is usually too small, especially if the current */
00222         /* ValueRecord is part of an array -- getting the correct table    */
00223         /* size is probably not worth the trouble                          */
00224 
00225         table_size = p - valid->extra3;
00226 
00227         OTV_SIZE_CHECK( device );
00228         if ( device )
00229           otv_Device_validate( valid->extra3 + device, valid );
00230       }
00231       format >>= 1;
00232     }
00233 
00234     OTV_EXIT;
00235   }
00236 
00237 
00238   /*************************************************************************/
00239   /*************************************************************************/
00240   /*****                                                               *****/
00241   /*****                           ANCHORS                             *****/
00242   /*****                                                               *****/
00243   /*************************************************************************/
00244   /*************************************************************************/
00245 
00246   static void
00247   otv_Anchor_validate( FT_Bytes       table,
00248                        OTV_Validator  valid )
00249   {
00250     FT_Bytes  p = table;
00251     FT_UInt   AnchorFormat;
00252 
00253 
00254     OTV_NAME_ENTER( "Anchor");
00255 
00256     OTV_LIMIT_CHECK( 6 );
00257     AnchorFormat = FT_NEXT_USHORT( p );
00258 
00259     OTV_TRACE(( " (format %d)\n", AnchorFormat ));
00260 
00261     p += 4;     /* skip XCoordinate and YCoordinate */
00262 
00263     switch ( AnchorFormat )
00264     {
00265     case 1:
00266       break;
00267 
00268     case 2:
00269       OTV_LIMIT_CHECK( 2 );  /* AnchorPoint */
00270       break;
00271 
00272     case 3:
00273       {
00274         FT_UInt   table_size;
00275 
00276         OTV_OPTIONAL_TABLE( XDeviceTable );
00277         OTV_OPTIONAL_TABLE( YDeviceTable );
00278 
00279 
00280         OTV_LIMIT_CHECK( 4 );
00281         OTV_OPTIONAL_OFFSET( XDeviceTable );
00282         OTV_OPTIONAL_OFFSET( YDeviceTable );
00283 
00284         table_size = 6 + 4;
00285 
00286         OTV_SIZE_CHECK( XDeviceTable );
00287         if ( XDeviceTable )
00288           otv_Device_validate( table + XDeviceTable, valid );
00289 
00290         OTV_SIZE_CHECK( YDeviceTable );
00291         if ( YDeviceTable )
00292           otv_Device_validate( table + YDeviceTable, valid );
00293       }
00294       break;
00295 
00296     default:
00297       FT_INVALID_FORMAT;
00298     }
00299 
00300     OTV_EXIT;
00301   }
00302 
00303 
00304   /*************************************************************************/
00305   /*************************************************************************/
00306   /*****                                                               *****/
00307   /*****                         MARK ARRAYS                           *****/
00308   /*****                                                               *****/
00309   /*************************************************************************/
00310   /*************************************************************************/
00311 
00312   static void
00313   otv_MarkArray_validate( FT_Bytes       table,
00314                           OTV_Validator  valid )
00315   {
00316     FT_Bytes  p = table;
00317     FT_UInt   MarkCount;
00318 
00319 
00320     OTV_NAME_ENTER( "MarkArray" );
00321 
00322     OTV_LIMIT_CHECK( 2 );
00323     MarkCount = FT_NEXT_USHORT( p );
00324 
00325     OTV_TRACE(( " (MarkCount = %d)\n", MarkCount ));
00326 
00327     OTV_LIMIT_CHECK( MarkCount * 4 );
00328 
00329     /* MarkRecord */
00330     for ( ; MarkCount > 0; MarkCount-- )
00331     {
00332       p += 2;   /* skip Class */
00333       /* MarkAnchor */
00334       otv_Anchor_validate( table + FT_NEXT_USHORT( p ), valid );
00335     }
00336 
00337     OTV_EXIT;
00338   }
00339 
00340 
00341   /*************************************************************************/
00342   /*************************************************************************/
00343   /*****                                                               *****/
00344   /*****                     GPOS LOOKUP TYPE 1                        *****/
00345   /*****                                                               *****/
00346   /*************************************************************************/
00347   /*************************************************************************/
00348 
00349   /* sets valid->extra3 (pointer to base table) */
00350 
00351   static void
00352   otv_SinglePos_validate( FT_Bytes       table,
00353                           OTV_Validator  valid )
00354   {
00355     FT_Bytes  p = table;
00356     FT_UInt   PosFormat;
00357 
00358 
00359     OTV_NAME_ENTER( "SinglePos" );
00360 
00361     OTV_LIMIT_CHECK( 2 );
00362     PosFormat = FT_NEXT_USHORT( p );
00363 
00364     OTV_TRACE(( " (format %d)\n", PosFormat ));
00365 
00366     valid->extra3 = table;
00367 
00368     switch ( PosFormat )
00369     {
00370     case 1:     /* SinglePosFormat1 */
00371       {
00372         FT_UInt  Coverage, ValueFormat;
00373 
00374 
00375         OTV_LIMIT_CHECK( 4 );
00376         Coverage    = FT_NEXT_USHORT( p );
00377         ValueFormat = FT_NEXT_USHORT( p );
00378 
00379         otv_Coverage_validate( table + Coverage, valid, -1 );
00380         otv_ValueRecord_validate( p, ValueFormat, valid ); /* Value */
00381       }
00382       break;
00383 
00384     case 2:     /* SinglePosFormat2 */
00385       {
00386         FT_UInt  Coverage, ValueFormat, ValueCount, len_value;
00387 
00388 
00389         OTV_LIMIT_CHECK( 6 );
00390         Coverage    = FT_NEXT_USHORT( p );
00391         ValueFormat = FT_NEXT_USHORT( p );
00392         ValueCount  = FT_NEXT_USHORT( p );
00393 
00394         OTV_TRACE(( " (ValueCount = %d)\n", ValueCount ));
00395 
00396         len_value = otv_value_length( ValueFormat );
00397 
00398         otv_Coverage_validate( table + Coverage, valid, ValueCount );
00399 
00400         OTV_LIMIT_CHECK( ValueCount * len_value );
00401 
00402         /* Value */
00403         for ( ; ValueCount > 0; ValueCount-- )
00404         {
00405           otv_ValueRecord_validate( p, ValueFormat, valid );
00406           p += len_value;
00407         }
00408       }
00409       break;
00410 
00411     default:
00412       FT_INVALID_FORMAT;
00413     }
00414 
00415     OTV_EXIT;
00416   }
00417 
00418 
00419   /*************************************************************************/
00420   /*************************************************************************/
00421   /*****                                                               *****/
00422   /*****                     GPOS LOOKUP TYPE 2                        *****/
00423   /*****                                                               *****/
00424   /*************************************************************************/
00425   /*************************************************************************/
00426 
00427   static void
00428   otv_PairSet_validate( FT_Bytes       table,
00429                         FT_UInt        format1,
00430                         FT_UInt        format2,
00431                         OTV_Validator  valid )
00432   {
00433     FT_Bytes  p = table;
00434     FT_UInt   value_len1, value_len2, PairValueCount;
00435 
00436 
00437     OTV_NAME_ENTER( "PairSet" );
00438 
00439     OTV_LIMIT_CHECK( 2 );
00440     PairValueCount = FT_NEXT_USHORT( p );
00441 
00442     OTV_TRACE(( " (PairValueCount = %d)\n", PairValueCount ));
00443 
00444     value_len1 = otv_value_length( format1 );
00445     value_len2 = otv_value_length( format2 );
00446 
00447     OTV_LIMIT_CHECK( PairValueCount * ( value_len1 + value_len2 + 2 ) );
00448 
00449     /* PairValueRecord */
00450     for ( ; PairValueCount > 0; PairValueCount-- )
00451     {
00452       p += 2;       /* skip SecondGlyph */
00453 
00454       if ( format1 )
00455         otv_ValueRecord_validate( p, format1, valid ); /* Value1 */
00456       p += value_len1;
00457 
00458       if ( format2 )
00459         otv_ValueRecord_validate( p, format2, valid ); /* Value2 */
00460       p += value_len2;
00461     }
00462 
00463     OTV_EXIT;
00464   }
00465 
00466 
00467   /* sets valid->extra3 (pointer to base table) */
00468 
00469   static void
00470   otv_PairPos_validate( FT_Bytes       table,
00471                         OTV_Validator  valid )
00472   {
00473     FT_Bytes  p = table;
00474     FT_UInt   PosFormat;
00475 
00476 
00477     OTV_NAME_ENTER( "PairPos" );
00478 
00479     OTV_LIMIT_CHECK( 2 );
00480     PosFormat = FT_NEXT_USHORT( p );
00481 
00482     OTV_TRACE(( " (format %d)\n", PosFormat ));
00483 
00484     valid->extra3 = table;
00485 
00486     switch ( PosFormat )
00487     {
00488     case 1:     /* PairPosFormat1 */
00489       {
00490         FT_UInt  Coverage, ValueFormat1, ValueFormat2, PairSetCount;
00491 
00492 
00493         OTV_LIMIT_CHECK( 8 );
00494         Coverage     = FT_NEXT_USHORT( p );
00495         ValueFormat1 = FT_NEXT_USHORT( p );
00496         ValueFormat2 = FT_NEXT_USHORT( p );
00497         PairSetCount = FT_NEXT_USHORT( p );
00498 
00499         OTV_TRACE(( " (PairSetCount = %d)\n", PairSetCount ));
00500 
00501         otv_Coverage_validate( table + Coverage, valid, -1 );
00502 
00503         OTV_LIMIT_CHECK( PairSetCount * 2 );
00504 
00505         /* PairSetOffset */
00506         for ( ; PairSetCount > 0; PairSetCount-- )
00507           otv_PairSet_validate( table + FT_NEXT_USHORT( p ),
00508                                 ValueFormat1, ValueFormat2, valid );
00509       }
00510       break;
00511 
00512     case 2:     /* PairPosFormat2 */
00513       {
00514         FT_UInt  Coverage, ValueFormat1, ValueFormat2, ClassDef1, ClassDef2;
00515         FT_UInt  ClassCount1, ClassCount2, len_value1, len_value2, count;
00516 
00517 
00518         OTV_LIMIT_CHECK( 14 );
00519         Coverage     = FT_NEXT_USHORT( p );
00520         ValueFormat1 = FT_NEXT_USHORT( p );
00521         ValueFormat2 = FT_NEXT_USHORT( p );
00522         ClassDef1    = FT_NEXT_USHORT( p );
00523         ClassDef2    = FT_NEXT_USHORT( p );
00524         ClassCount1  = FT_NEXT_USHORT( p );
00525         ClassCount2  = FT_NEXT_USHORT( p );
00526 
00527         OTV_TRACE(( " (ClassCount1 = %d)\n", ClassCount1 ));
00528         OTV_TRACE(( " (ClassCount2 = %d)\n", ClassCount2 ));
00529 
00530         len_value1 = otv_value_length( ValueFormat1 );
00531         len_value2 = otv_value_length( ValueFormat2 );
00532 
00533         otv_Coverage_validate( table + Coverage, valid, -1 );
00534         otv_ClassDef_validate( table + ClassDef1, valid );
00535         otv_ClassDef_validate( table + ClassDef2, valid );
00536 
00537         OTV_LIMIT_CHECK( ClassCount1 * ClassCount2 *
00538                      ( len_value1 + len_value2 ) );
00539 
00540         /* Class1Record */
00541         for ( ; ClassCount1 > 0; ClassCount1-- )
00542         {
00543           /* Class2Record */
00544           for ( count = ClassCount2; count > 0; count-- )
00545           {
00546             if ( ValueFormat1 )
00547               /* Value1 */
00548               otv_ValueRecord_validate( p, ValueFormat1, valid );
00549             p += len_value1;
00550 
00551             if ( ValueFormat2 )
00552               /* Value2 */
00553               otv_ValueRecord_validate( p, ValueFormat2, valid );
00554             p += len_value2;
00555           }
00556         }
00557       }
00558       break;
00559 
00560     default:
00561       FT_INVALID_FORMAT;
00562     }
00563 
00564     OTV_EXIT;
00565   }
00566 
00567 
00568   /*************************************************************************/
00569   /*************************************************************************/
00570   /*****                                                               *****/
00571   /*****                     GPOS LOOKUP TYPE 3                        *****/
00572   /*****                                                               *****/
00573   /*************************************************************************/
00574   /*************************************************************************/
00575 
00576   static void
00577   otv_CursivePos_validate( FT_Bytes       table,
00578                            OTV_Validator  valid )
00579   {
00580     FT_Bytes  p = table;
00581     FT_UInt   PosFormat;
00582 
00583 
00584     OTV_NAME_ENTER( "CursivePos" );
00585 
00586     OTV_LIMIT_CHECK( 2 );
00587     PosFormat = FT_NEXT_USHORT( p );
00588 
00589     OTV_TRACE(( " (format %d)\n", PosFormat ));
00590 
00591     switch ( PosFormat )
00592     {
00593     case 1:     /* CursivePosFormat1 */
00594       {
00595         FT_UInt   table_size;
00596         FT_UInt   Coverage, EntryExitCount;
00597 
00598         OTV_OPTIONAL_TABLE( EntryAnchor );
00599         OTV_OPTIONAL_TABLE( ExitAnchor  );
00600 
00601 
00602         OTV_LIMIT_CHECK( 4 );
00603         Coverage       = FT_NEXT_USHORT( p );
00604         EntryExitCount = FT_NEXT_USHORT( p );
00605 
00606         OTV_TRACE(( " (EntryExitCount = %d)\n", EntryExitCount ));
00607 
00608         otv_Coverage_validate( table + Coverage, valid, EntryExitCount );
00609 
00610         OTV_LIMIT_CHECK( EntryExitCount * 4 );
00611 
00612         table_size = EntryExitCount * 4 + 4;
00613 
00614         /* EntryExitRecord */
00615         for ( ; EntryExitCount > 0; EntryExitCount-- )
00616         {
00617           OTV_OPTIONAL_OFFSET( EntryAnchor );
00618           OTV_OPTIONAL_OFFSET( ExitAnchor  );
00619 
00620           OTV_SIZE_CHECK( EntryAnchor );
00621           if ( EntryAnchor )
00622             otv_Anchor_validate( table + EntryAnchor, valid );
00623 
00624           OTV_SIZE_CHECK( ExitAnchor );
00625           if ( ExitAnchor )
00626             otv_Anchor_validate( table + ExitAnchor, valid );
00627         }
00628       }
00629       break;
00630 
00631     default:
00632       FT_INVALID_FORMAT;
00633     }
00634 
00635     OTV_EXIT;
00636   }
00637 
00638 
00639   /*************************************************************************/
00640   /*************************************************************************/
00641   /*****                                                               *****/
00642   /*****                     GPOS LOOKUP TYPE 4                        *****/
00643   /*****                                                               *****/
00644   /*************************************************************************/
00645   /*************************************************************************/
00646 
00647   /* UNDOCUMENTED (in OpenType 1.5):              */
00648   /* BaseRecord tables can contain NULL pointers. */
00649 
00650   /* sets valid->extra2 (1) */
00651 
00652   static void
00653   otv_MarkBasePos_validate( FT_Bytes       table,
00654                             OTV_Validator  valid )
00655   {
00656     FT_Bytes  p = table;
00657     FT_UInt   PosFormat;
00658 
00659 
00660     OTV_NAME_ENTER( "MarkBasePos" );
00661 
00662     OTV_LIMIT_CHECK( 2 );
00663     PosFormat = FT_NEXT_USHORT( p );
00664 
00665     OTV_TRACE(( " (format %d)\n", PosFormat ));
00666 
00667     switch ( PosFormat )
00668     {
00669     case 1:
00670       valid->extra2 = 1;
00671       OTV_NEST2( MarkBasePosFormat1, BaseArray );
00672       OTV_RUN( table, valid );
00673       break;
00674 
00675     default:
00676       FT_INVALID_FORMAT;
00677     }
00678 
00679     OTV_EXIT;
00680   }
00681 
00682 
00683   /*************************************************************************/
00684   /*************************************************************************/
00685   /*****                                                               *****/
00686   /*****                     GPOS LOOKUP TYPE 5                        *****/
00687   /*****                                                               *****/
00688   /*************************************************************************/
00689   /*************************************************************************/
00690 
00691   /* sets valid->extra2 (1) */
00692 
00693   static void
00694   otv_MarkLigPos_validate( FT_Bytes       table,
00695                            OTV_Validator  valid )
00696   {
00697     FT_Bytes  p = table;
00698     FT_UInt   PosFormat;
00699 
00700 
00701     OTV_NAME_ENTER( "MarkLigPos" );
00702 
00703     OTV_LIMIT_CHECK( 2 );
00704     PosFormat = FT_NEXT_USHORT( p );
00705 
00706     OTV_TRACE(( " (format %d)\n", PosFormat ));
00707 
00708     switch ( PosFormat )
00709     {
00710     case 1:
00711       valid->extra2 = 1;
00712       OTV_NEST3( MarkLigPosFormat1, LigatureArray, LigatureAttach );
00713       OTV_RUN( table, valid );
00714       break;
00715 
00716     default:
00717       FT_INVALID_FORMAT;
00718     }
00719 
00720     OTV_EXIT;
00721   }
00722 
00723 
00724   /*************************************************************************/
00725   /*************************************************************************/
00726   /*****                                                               *****/
00727   /*****                     GPOS LOOKUP TYPE 6                        *****/
00728   /*****                                                               *****/
00729   /*************************************************************************/
00730   /*************************************************************************/
00731 
00732   /* sets valid->extra2 (0) */
00733 
00734   static void
00735   otv_MarkMarkPos_validate( FT_Bytes       table,
00736                             OTV_Validator  valid )
00737   {
00738     FT_Bytes  p = table;
00739     FT_UInt   PosFormat;
00740 
00741 
00742     OTV_NAME_ENTER( "MarkMarkPos" );
00743 
00744     OTV_LIMIT_CHECK( 2 );
00745     PosFormat = FT_NEXT_USHORT( p );
00746 
00747     OTV_TRACE(( " (format %d)\n", PosFormat ));
00748 
00749     switch ( PosFormat )
00750     {
00751     case 1:
00752       valid->extra2 = 0;
00753       OTV_NEST2( MarkMarkPosFormat1, Mark2Array );
00754       OTV_RUN( table, valid );
00755       break;
00756 
00757     default:
00758       FT_INVALID_FORMAT;
00759     }
00760 
00761     OTV_EXIT;
00762   }
00763 
00764 
00765   /*************************************************************************/
00766   /*************************************************************************/
00767   /*****                                                               *****/
00768   /*****                     GPOS LOOKUP TYPE 7                        *****/
00769   /*****                                                               *****/
00770   /*************************************************************************/
00771   /*************************************************************************/
00772 
00773   /* sets valid->extra1 (lookup count) */
00774 
00775   static void
00776   otv_ContextPos_validate( FT_Bytes       table,
00777                            OTV_Validator  valid )
00778   {
00779     FT_Bytes  p = table;
00780     FT_UInt   PosFormat;
00781 
00782 
00783     OTV_NAME_ENTER( "ContextPos" );
00784 
00785     OTV_LIMIT_CHECK( 2 );
00786     PosFormat = FT_NEXT_USHORT( p );
00787 
00788     OTV_TRACE(( " (format %d)\n", PosFormat ));
00789 
00790     switch ( PosFormat )
00791     {
00792     case 1:
00793       /* no need to check glyph indices/classes used as input for these */
00794       /* context rules since even invalid glyph indices/classes return  */
00795       /* meaningful results                                             */
00796 
00797       valid->extra1 = valid->lookup_count;
00798       OTV_NEST3( ContextPosFormat1, PosRuleSet, PosRule );
00799       OTV_RUN( table, valid );
00800       break;
00801 
00802     case 2:
00803       /* no need to check glyph indices/classes used as input for these */
00804       /* context rules since even invalid glyph indices/classes return  */
00805       /* meaningful results                                             */
00806 
00807       OTV_NEST3( ContextPosFormat2, PosClassSet, PosClassRule );
00808       OTV_RUN( table, valid );
00809       break;
00810 
00811     case 3:
00812       OTV_NEST1( ContextPosFormat3 );
00813       OTV_RUN( table, valid );
00814       break;
00815 
00816     default:
00817       FT_INVALID_FORMAT;
00818     }
00819 
00820     OTV_EXIT;
00821   }
00822 
00823 
00824   /*************************************************************************/
00825   /*************************************************************************/
00826   /*****                                                               *****/
00827   /*****                     GPOS LOOKUP TYPE 8                        *****/
00828   /*****                                                               *****/
00829   /*************************************************************************/
00830   /*************************************************************************/
00831 
00832   /* sets valid->extra1 (lookup count) */
00833 
00834   static void
00835   otv_ChainContextPos_validate( FT_Bytes       table,
00836                                 OTV_Validator  valid )
00837   {
00838     FT_Bytes  p = table;
00839     FT_UInt   PosFormat;
00840 
00841 
00842     OTV_NAME_ENTER( "ChainContextPos" );
00843 
00844     OTV_LIMIT_CHECK( 2 );
00845     PosFormat = FT_NEXT_USHORT( p );
00846 
00847     OTV_TRACE(( " (format %d)\n", PosFormat ));
00848 
00849     switch ( PosFormat )
00850     {
00851     case 1:
00852       /* no need to check glyph indices/classes used as input for these */
00853       /* context rules since even invalid glyph indices/classes return  */
00854       /* meaningful results                                             */
00855 
00856       valid->extra1 = valid->lookup_count;
00857       OTV_NEST3( ChainContextPosFormat1,
00858                  ChainPosRuleSet, ChainPosRule );
00859       OTV_RUN( table, valid );
00860       break;
00861 
00862     case 2:
00863       /* no need to check glyph indices/classes used as input for these */
00864       /* context rules since even invalid glyph indices/classes return  */
00865       /* meaningful results                                             */
00866 
00867       OTV_NEST3( ChainContextPosFormat2,
00868                  ChainPosClassSet, ChainPosClassRule );
00869       OTV_RUN( table, valid );
00870       break;
00871 
00872     case 3:
00873       OTV_NEST1( ChainContextPosFormat3 );
00874       OTV_RUN( table, valid );
00875       break;
00876 
00877     default:
00878       FT_INVALID_FORMAT;
00879     }
00880 
00881     OTV_EXIT;
00882   }
00883 
00884 
00885   /*************************************************************************/
00886   /*************************************************************************/
00887   /*****                                                               *****/
00888   /*****                     GPOS LOOKUP TYPE 9                        *****/
00889   /*****                                                               *****/
00890   /*************************************************************************/
00891   /*************************************************************************/
00892 
00893   /* uses valid->type_funcs */
00894 
00895   static void
00896   otv_ExtensionPos_validate( FT_Bytes       table,
00897                              OTV_Validator  valid )
00898   {
00899     FT_Bytes  p = table;
00900     FT_UInt   PosFormat;
00901 
00902 
00903     OTV_NAME_ENTER( "ExtensionPos" );
00904 
00905     OTV_LIMIT_CHECK( 2 );
00906     PosFormat = FT_NEXT_USHORT( p );
00907 
00908     OTV_TRACE(( " (format %d)\n", PosFormat ));
00909 
00910     switch ( PosFormat )
00911     {
00912     case 1:     /* ExtensionPosFormat1 */
00913       {
00914         FT_UInt            ExtensionLookupType;
00915         FT_ULong           ExtensionOffset;
00916         OTV_Validate_Func  validate;
00917 
00918 
00919         OTV_LIMIT_CHECK( 6 );
00920         ExtensionLookupType = FT_NEXT_USHORT( p );
00921         ExtensionOffset     = FT_NEXT_ULONG( p );
00922 
00923         if ( ExtensionLookupType == 0 || ExtensionLookupType >= 9 )
00924           FT_INVALID_DATA;
00925 
00926         validate = valid->type_funcs[ExtensionLookupType - 1];
00927         validate( table + ExtensionOffset, valid );
00928       }
00929       break;
00930 
00931     default:
00932       FT_INVALID_FORMAT;
00933     }
00934 
00935     OTV_EXIT;
00936   }
00937 
00938 
00939   static const OTV_Validate_Func  otv_gpos_validate_funcs[9] =
00940   {
00941     otv_SinglePos_validate,
00942     otv_PairPos_validate,
00943     otv_CursivePos_validate,
00944     otv_MarkBasePos_validate,
00945     otv_MarkLigPos_validate,
00946     otv_MarkMarkPos_validate,
00947     otv_ContextPos_validate,
00948     otv_ChainContextPos_validate,
00949     otv_ExtensionPos_validate
00950   };
00951 
00952 
00953   /* sets valid->type_count */
00954   /* sets valid->type_funcs */
00955 
00956   FT_LOCAL_DEF( void )
00957   otv_GPOS_subtable_validate( FT_Bytes       table,
00958                               OTV_Validator  valid )
00959   {
00960     valid->type_count = 9;
00961     valid->type_funcs = (OTV_Validate_Func*)otv_gpos_validate_funcs;
00962 
00963     otv_Lookup_validate( table, valid );
00964   }
00965 
00966 
00967   /*************************************************************************/
00968   /*************************************************************************/
00969   /*****                                                               *****/
00970   /*****                          GPOS TABLE                           *****/
00971   /*****                                                               *****/
00972   /*************************************************************************/
00973   /*************************************************************************/
00974 
00975   /* sets valid->glyph_count */
00976 
00977   FT_LOCAL_DEF( void )
00978   otv_GPOS_validate( FT_Bytes      table,
00979                      FT_UInt       glyph_count,
00980                      FT_Validator  ftvalid )
00981   {
00982     OTV_ValidatorRec  validrec;
00983     OTV_Validator     valid = &validrec;
00984     FT_Bytes          p     = table;
00985     FT_UInt           ScriptList, FeatureList, LookupList;
00986 
00987 
00988     valid->root = ftvalid;
00989 
00990     FT_TRACE3(( "validating GPOS table\n" ));
00991     OTV_INIT;
00992 
00993     OTV_LIMIT_CHECK( 10 );
00994 
00995     if ( FT_NEXT_ULONG( p ) != 0x10000UL )      /* Version */
00996       FT_INVALID_FORMAT;
00997 
00998     ScriptList  = FT_NEXT_USHORT( p );
00999     FeatureList = FT_NEXT_USHORT( p );
01000     LookupList  = FT_NEXT_USHORT( p );
01001 
01002     valid->type_count  = 9;
01003     valid->type_funcs  = (OTV_Validate_Func*)otv_gpos_validate_funcs;
01004     valid->glyph_count = glyph_count;
01005 
01006     otv_LookupList_validate( table + LookupList,
01007                              valid );
01008     otv_FeatureList_validate( table + FeatureList, table + LookupList,
01009                               valid );
01010     otv_ScriptList_validate( table + ScriptList, table + FeatureList,
01011                              valid );
01012 
01013     FT_TRACE4(( "\n" ));
01014   }
01015 
01016 
01017 /* END */

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