Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  otvcommn.c                                                             */
  4. /*                                                                         */
  5. /*    OpenType common tables validation (body).                            */
  6. /*                                                                         */
  7. /*  Copyright 2004, 2005, 2006, 2007 by                                    */
  8. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  9. /*                                                                         */
  10. /*  This file is part of the FreeType project, and may only be used,       */
  11. /*  modified, and distributed under the terms of the FreeType project      */
  12. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13. /*  this file you indicate that you have read the license and              */
  14. /*  understand and accept it fully.                                        */
  15. /*                                                                         */
  16. /***************************************************************************/
  17.  
  18.  
  19. #include "otvcommn.h"
  20.  
  21.  
  22.   /*************************************************************************/
  23.   /*                                                                       */
  24.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  25.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  26.   /* messages during execution.                                            */
  27.   /*                                                                       */
  28. #undef  FT_COMPONENT
  29. #define FT_COMPONENT  trace_otvcommon
  30.  
  31.  
  32.   /*************************************************************************/
  33.   /*************************************************************************/
  34.   /*****                                                               *****/
  35.   /*****                       COVERAGE TABLE                          *****/
  36.   /*****                                                               *****/
  37.   /*************************************************************************/
  38.   /*************************************************************************/
  39.  
  40.   FT_LOCAL_DEF( void )
  41.   otv_Coverage_validate( FT_Bytes       table,
  42.                          OTV_Validator  valid,
  43.                          FT_Int         expected_count )
  44.   {
  45.     FT_Bytes  p = table;
  46.     FT_UInt   CoverageFormat;
  47.     FT_UInt   total = 0;
  48.  
  49.  
  50.     OTV_NAME_ENTER( "Coverage" );
  51.  
  52.     OTV_LIMIT_CHECK( 4 );
  53.     CoverageFormat = FT_NEXT_USHORT( p );
  54.  
  55.     OTV_TRACE(( " (format %d)\n", CoverageFormat ));
  56.  
  57.     switch ( CoverageFormat )
  58.     {
  59.     case 1:     /* CoverageFormat1 */
  60.       {
  61.         FT_UInt  GlyphCount;
  62.         FT_UInt  i;
  63.  
  64.  
  65.         GlyphCount = FT_NEXT_USHORT( p );
  66.  
  67.         OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
  68.  
  69.         OTV_LIMIT_CHECK( GlyphCount * 2 );        /* GlyphArray */
  70.  
  71.         for ( i = 0; i < GlyphCount; ++i )
  72.         {
  73.           FT_UInt  gid;
  74.  
  75.  
  76.           gid = FT_NEXT_USHORT( p );
  77.           if ( gid >= valid->glyph_count )
  78.             FT_INVALID_GLYPH_ID;
  79.         }
  80.  
  81.         total = GlyphCount;
  82.       }
  83.       break;
  84.  
  85.     case 2:     /* CoverageFormat2 */
  86.       {
  87.         FT_UInt  n, RangeCount;
  88.         FT_UInt  Start, End, StartCoverageIndex, last = 0;
  89.  
  90.  
  91.         RangeCount = FT_NEXT_USHORT( p );
  92.  
  93.         OTV_TRACE(( " (RangeCount = %d)\n", RangeCount ));
  94.  
  95.         OTV_LIMIT_CHECK( RangeCount * 6 );
  96.  
  97.         /* RangeRecord */
  98.         for ( n = 0; n < RangeCount; n++ )
  99.         {
  100.           Start              = FT_NEXT_USHORT( p );
  101.           End                = FT_NEXT_USHORT( p );
  102.           StartCoverageIndex = FT_NEXT_USHORT( p );
  103.  
  104.           if ( Start > End || StartCoverageIndex != total )
  105.             FT_INVALID_DATA;
  106.  
  107.           if ( End >= valid->glyph_count )
  108.             FT_INVALID_GLYPH_ID;
  109.  
  110.           if ( n > 0 && Start <= last )
  111.             FT_INVALID_DATA;
  112.  
  113.           total += End - Start + 1;
  114.           last   = End;
  115.         }
  116.       }
  117.       break;
  118.  
  119.     default:
  120.       FT_INVALID_FORMAT;
  121.     }
  122.  
  123.     /* Generally, a coverage table offset has an associated count field.  */
  124.     /* The number of glyphs in the table should match this field.  If     */
  125.     /* there is no associated count, a value of -1 tells us not to check. */
  126.     if ( expected_count != -1 && (FT_UInt)expected_count != total )
  127.       FT_INVALID_DATA;
  128.  
  129.     OTV_EXIT;
  130.   }
  131.  
  132.  
  133.   FT_LOCAL_DEF( FT_UInt )
  134.   otv_Coverage_get_first( FT_Bytes  table )
  135.   {
  136.     FT_Bytes  p = table;
  137.  
  138.  
  139.     p += 4;     /* skip CoverageFormat and Glyph/RangeCount */
  140.  
  141.     return FT_NEXT_USHORT( p );
  142.   }
  143.  
  144.  
  145.   FT_LOCAL_DEF( FT_UInt )
  146.   otv_Coverage_get_last( FT_Bytes  table )
  147.   {
  148.     FT_Bytes  p = table;
  149.     FT_UInt   CoverageFormat = FT_NEXT_USHORT( p );
  150.     FT_UInt   count          = FT_NEXT_USHORT( p );     /* Glyph/RangeCount */
  151.     FT_UInt   result = 0;
  152.  
  153.  
  154.     switch ( CoverageFormat )
  155.     {
  156.     case 1:
  157.       p += ( count - 1 ) * 2;
  158.       result = FT_NEXT_USHORT( p );
  159.       break;
  160.  
  161.     case 2:
  162.       p += ( count - 1 ) * 6 + 2;
  163.       result = FT_NEXT_USHORT( p );
  164.       break;
  165.  
  166.     default:
  167.       ;
  168.     }
  169.  
  170.     return result;
  171.   }
  172.  
  173.  
  174.   FT_LOCAL_DEF( FT_UInt )
  175.   otv_Coverage_get_count( FT_Bytes  table )
  176.   {
  177.     FT_Bytes  p              = table;
  178.     FT_UInt   CoverageFormat = FT_NEXT_USHORT( p );
  179.     FT_UInt   count          = FT_NEXT_USHORT( p );     /* Glyph/RangeCount */
  180.     FT_UInt   result         = 0;
  181.  
  182.  
  183.     switch ( CoverageFormat )
  184.     {
  185.     case 1:
  186.       return count;
  187.  
  188.     case 2:
  189.       {
  190.         FT_UInt  Start, End;
  191.  
  192.  
  193.         for ( ; count > 0; count-- )
  194.         {
  195.           Start = FT_NEXT_USHORT( p );
  196.           End   = FT_NEXT_USHORT( p );
  197.           p    += 2;                    /* skip StartCoverageIndex */
  198.  
  199.           result += End - Start + 1;
  200.         }
  201.       }
  202.       break;
  203.  
  204.     default:
  205.       ;
  206.     }
  207.  
  208.     return result;
  209.   }
  210.  
  211.  
  212.   /*************************************************************************/
  213.   /*************************************************************************/
  214.   /*****                                                               *****/
  215.   /*****                   CLASS DEFINITION TABLE                      *****/
  216.   /*****                                                               *****/
  217.   /*************************************************************************/
  218.   /*************************************************************************/
  219.  
  220.   FT_LOCAL_DEF( void )
  221.   otv_ClassDef_validate( FT_Bytes       table,
  222.                          OTV_Validator  valid )
  223.   {
  224.     FT_Bytes  p = table;
  225.     FT_UInt   ClassFormat;
  226.  
  227.  
  228.     OTV_NAME_ENTER( "ClassDef" );
  229.  
  230.     OTV_LIMIT_CHECK( 4 );
  231.     ClassFormat = FT_NEXT_USHORT( p );
  232.  
  233.     OTV_TRACE(( " (format %d)\n", ClassFormat ));
  234.  
  235.     switch ( ClassFormat )
  236.     {
  237.     case 1:     /* ClassDefFormat1 */
  238.       {
  239.         FT_UInt  StartGlyph;
  240.         FT_UInt  GlyphCount;
  241.  
  242.  
  243.         OTV_LIMIT_CHECK( 4 );
  244.  
  245.         StartGlyph = FT_NEXT_USHORT( p );
  246.         GlyphCount = FT_NEXT_USHORT( p );
  247.  
  248.         OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
  249.  
  250.         OTV_LIMIT_CHECK( GlyphCount * 2 );    /* ClassValueArray */
  251.  
  252.         if ( StartGlyph + GlyphCount - 1 >= valid->glyph_count )
  253.           FT_INVALID_GLYPH_ID;
  254.       }
  255.       break;
  256.  
  257.     case 2:     /* ClassDefFormat2 */
  258.       {
  259.         FT_UInt  n, ClassRangeCount;
  260.         FT_UInt  Start, End, last = 0;
  261.  
  262.  
  263.         ClassRangeCount = FT_NEXT_USHORT( p );
  264.  
  265.         OTV_TRACE(( " (ClassRangeCount = %d)\n", ClassRangeCount ));
  266.  
  267.         OTV_LIMIT_CHECK( ClassRangeCount * 6 );
  268.  
  269.         /* ClassRangeRecord */
  270.         for ( n = 0; n < ClassRangeCount; n++ )
  271.         {
  272.           Start = FT_NEXT_USHORT( p );
  273.           End   = FT_NEXT_USHORT( p );
  274.           p    += 2;                        /* skip Class */
  275.  
  276.           if ( Start > End || ( n > 0 && Start <= last ) )
  277.             FT_INVALID_DATA;
  278.  
  279.           if ( End >= valid->glyph_count )
  280.             FT_INVALID_GLYPH_ID;
  281.  
  282.           last = End;
  283.         }
  284.       }
  285.       break;
  286.  
  287.     default:
  288.       FT_INVALID_FORMAT;
  289.     }
  290.  
  291.     /* no need to check glyph indices used as input to class definition   */
  292.     /* tables since even invalid glyph indices return a meaningful result */
  293.  
  294.     OTV_EXIT;
  295.   }
  296.  
  297.  
  298.   /*************************************************************************/
  299.   /*************************************************************************/
  300.   /*****                                                               *****/
  301.   /*****                      DEVICE TABLE                             *****/
  302.   /*****                                                               *****/
  303.   /*************************************************************************/
  304.   /*************************************************************************/
  305.  
  306.   FT_LOCAL_DEF( void )
  307.   otv_Device_validate( FT_Bytes       table,
  308.                        OTV_Validator  valid )
  309.   {
  310.     FT_Bytes  p = table;
  311.     FT_UInt   StartSize, EndSize, DeltaFormat, count;
  312.  
  313.  
  314.     OTV_NAME_ENTER( "Device" );
  315.  
  316.     OTV_LIMIT_CHECK( 8 );
  317.     StartSize   = FT_NEXT_USHORT( p );
  318.     EndSize     = FT_NEXT_USHORT( p );
  319.     DeltaFormat = FT_NEXT_USHORT( p );
  320.  
  321.     if ( DeltaFormat < 1 || DeltaFormat > 3 )
  322.       FT_INVALID_FORMAT;
  323.  
  324.     if ( EndSize < StartSize )
  325.       FT_INVALID_DATA;
  326.  
  327.     count = EndSize - StartSize + 1;
  328.     OTV_LIMIT_CHECK( ( 1 << DeltaFormat ) * count / 8 );  /* DeltaValue */
  329.  
  330.     OTV_EXIT;
  331.   }
  332.  
  333.  
  334.   /*************************************************************************/
  335.   /*************************************************************************/
  336.   /*****                                                               *****/
  337.   /*****                         LOOKUPS                               *****/
  338.   /*****                                                               *****/
  339.   /*************************************************************************/
  340.   /*************************************************************************/
  341.  
  342.   /* uses valid->type_count */
  343.   /* uses valid->type_funcs */
  344.  
  345.   FT_LOCAL_DEF( void )
  346.   otv_Lookup_validate( FT_Bytes       table,
  347.                        OTV_Validator  valid )
  348.   {
  349.     FT_Bytes           p = table;
  350.     FT_UInt            LookupType, SubTableCount;
  351.     OTV_Validate_Func  validate;
  352.  
  353.  
  354.     OTV_NAME_ENTER( "Lookup" );
  355.  
  356.     OTV_LIMIT_CHECK( 6 );
  357.     LookupType    = FT_NEXT_USHORT( p );
  358.     p            += 2;                      /* skip LookupFlag */
  359.     SubTableCount = FT_NEXT_USHORT( p );
  360.  
  361.     OTV_TRACE(( " (type %d)\n", LookupType ));
  362.  
  363.     if ( LookupType == 0 || LookupType > valid->type_count )
  364.       FT_INVALID_DATA;
  365.  
  366.     validate = valid->type_funcs[LookupType - 1];
  367.  
  368.     OTV_TRACE(( " (SubTableCount = %d)\n", SubTableCount ));
  369.  
  370.     OTV_LIMIT_CHECK( SubTableCount * 2 );
  371.  
  372.     /* SubTable */
  373.     for ( ; SubTableCount > 0; SubTableCount-- )
  374.       validate( table + FT_NEXT_USHORT( p ), valid );
  375.  
  376.     OTV_EXIT;
  377.   }
  378.  
  379.  
  380.   /* uses valid->lookup_count */
  381.  
  382.   FT_LOCAL_DEF( void )
  383.   otv_LookupList_validate( FT_Bytes       table,
  384.                            OTV_Validator  valid )
  385.   {
  386.     FT_Bytes  p = table;
  387.     FT_UInt   LookupCount;
  388.  
  389.  
  390.     OTV_NAME_ENTER( "LookupList" );
  391.  
  392.     OTV_LIMIT_CHECK( 2 );
  393.     LookupCount = FT_NEXT_USHORT( p );
  394.  
  395.     OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
  396.  
  397.     OTV_LIMIT_CHECK( LookupCount * 2 );
  398.  
  399.     valid->lookup_count = LookupCount;
  400.  
  401.     /* Lookup */
  402.     for ( ; LookupCount > 0; LookupCount-- )
  403.       otv_Lookup_validate( table + FT_NEXT_USHORT( p ), valid );
  404.  
  405.     OTV_EXIT;
  406.   }
  407.  
  408.  
  409.   static FT_UInt
  410.   otv_LookupList_get_count( FT_Bytes  table )
  411.   {
  412.     return FT_NEXT_USHORT( table );
  413.   }
  414.  
  415.  
  416.   /*************************************************************************/
  417.   /*************************************************************************/
  418.   /*****                                                               *****/
  419.   /*****                        FEATURES                               *****/
  420.   /*****                                                               *****/
  421.   /*************************************************************************/
  422.   /*************************************************************************/
  423.  
  424.   /* uses valid->lookup_count */
  425.  
  426.   FT_LOCAL_DEF( void )
  427.   otv_Feature_validate( FT_Bytes       table,
  428.                         OTV_Validator  valid )
  429.   {
  430.     FT_Bytes  p = table;
  431.     FT_UInt   LookupCount;
  432.  
  433.  
  434.     OTV_NAME_ENTER( "Feature" );
  435.  
  436.     OTV_LIMIT_CHECK( 4 );
  437.     p           += 2;                   /* skip FeatureParams (unused) */
  438.     LookupCount  = FT_NEXT_USHORT( p );
  439.  
  440.     OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
  441.  
  442.     OTV_LIMIT_CHECK( LookupCount * 2 );
  443.  
  444.     /* LookupListIndex */
  445.     for ( ; LookupCount > 0; LookupCount-- )
  446.       if ( FT_NEXT_USHORT( p ) >= valid->lookup_count )
  447.         FT_INVALID_DATA;
  448.  
  449.     OTV_EXIT;
  450.   }
  451.  
  452.  
  453.   static FT_UInt
  454.   otv_Feature_get_count( FT_Bytes  table )
  455.   {
  456.     return FT_NEXT_USHORT( table );
  457.   }
  458.  
  459.  
  460.   /* sets valid->lookup_count */
  461.  
  462.   FT_LOCAL_DEF( void )
  463.   otv_FeatureList_validate( FT_Bytes       table,
  464.                             FT_Bytes       lookups,
  465.                             OTV_Validator  valid )
  466.   {
  467.     FT_Bytes  p = table;
  468.     FT_UInt   FeatureCount;
  469.  
  470.  
  471.     OTV_NAME_ENTER( "FeatureList" );
  472.  
  473.     OTV_LIMIT_CHECK( 2 );
  474.     FeatureCount = FT_NEXT_USHORT( p );
  475.  
  476.     OTV_TRACE(( " (FeatureCount = %d)\n", FeatureCount ));
  477.  
  478.     OTV_LIMIT_CHECK( FeatureCount * 2 );
  479.  
  480.     valid->lookup_count = otv_LookupList_get_count( lookups );
  481.  
  482.     /* FeatureRecord */
  483.     for ( ; FeatureCount > 0; FeatureCount-- )
  484.     {
  485.       p += 4;       /* skip FeatureTag */
  486.  
  487.       /* Feature */
  488.       otv_Feature_validate( table + FT_NEXT_USHORT( p ), valid );
  489.     }
  490.  
  491.     OTV_EXIT;
  492.   }
  493.  
  494.  
  495.   /*************************************************************************/
  496.   /*************************************************************************/
  497.   /*****                                                               *****/
  498.   /*****                       LANGUAGE SYSTEM                         *****/
  499.   /*****                                                               *****/
  500.   /*************************************************************************/
  501.   /*************************************************************************/
  502.  
  503.  
  504.   /* uses valid->extra1 (number of features) */
  505.  
  506.   FT_LOCAL_DEF( void )
  507.   otv_LangSys_validate( FT_Bytes       table,
  508.                         OTV_Validator  valid )
  509.   {
  510.     FT_Bytes  p = table;
  511.     FT_UInt   ReqFeatureIndex;
  512.     FT_UInt   FeatureCount;
  513.  
  514.  
  515.     OTV_NAME_ENTER( "LangSys" );
  516.  
  517.     OTV_LIMIT_CHECK( 6 );
  518.     p              += 2;                    /* skip LookupOrder (unused) */
  519.     ReqFeatureIndex = FT_NEXT_USHORT( p );
  520.     FeatureCount    = FT_NEXT_USHORT( p );
  521.  
  522.     OTV_TRACE(( " (ReqFeatureIndex = %d)\n", ReqFeatureIndex ));
  523.     OTV_TRACE(( " (FeatureCount = %d)\n",    FeatureCount    ));
  524.  
  525.     if ( ReqFeatureIndex != 0xFFFFU && ReqFeatureIndex >= valid->extra1 )
  526.       FT_INVALID_DATA;
  527.  
  528.     OTV_LIMIT_CHECK( FeatureCount * 2 );
  529.  
  530.     /* FeatureIndex */
  531.     for ( ; FeatureCount > 0; FeatureCount-- )
  532.       if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
  533.         FT_INVALID_DATA;
  534.  
  535.     OTV_EXIT;
  536.   }
  537.  
  538.  
  539.   /*************************************************************************/
  540.   /*************************************************************************/
  541.   /*****                                                               *****/
  542.   /*****                           SCRIPTS                             *****/
  543.   /*****                                                               *****/
  544.   /*************************************************************************/
  545.   /*************************************************************************/
  546.  
  547.   FT_LOCAL_DEF( void )
  548.   otv_Script_validate( FT_Bytes       table,
  549.                        OTV_Validator  valid )
  550.   {
  551.     FT_UInt   DefaultLangSys, LangSysCount;
  552.     FT_Bytes  p = table;
  553.  
  554.  
  555.     OTV_NAME_ENTER( "Script" );
  556.  
  557.     OTV_LIMIT_CHECK( 4 );
  558.     DefaultLangSys = FT_NEXT_USHORT( p );
  559.     LangSysCount   = FT_NEXT_USHORT( p );
  560.  
  561.     OTV_TRACE(( " (LangSysCount = %d)\n", LangSysCount ));
  562.  
  563.     if ( DefaultLangSys != 0 )
  564.       otv_LangSys_validate( table + DefaultLangSys, valid );
  565.  
  566.     OTV_LIMIT_CHECK( LangSysCount * 6 );
  567.  
  568.     /* LangSysRecord */
  569.     for ( ; LangSysCount > 0; LangSysCount-- )
  570.     {
  571.       p += 4;       /* skip LangSysTag */
  572.  
  573.       /* LangSys */
  574.       otv_LangSys_validate( table + FT_NEXT_USHORT( p ), valid );
  575.     }
  576.  
  577.     OTV_EXIT;
  578.   }
  579.  
  580.  
  581.   /* sets valid->extra1 (number of features) */
  582.  
  583.   FT_LOCAL_DEF( void )
  584.   otv_ScriptList_validate( FT_Bytes       table,
  585.                            FT_Bytes       features,
  586.                            OTV_Validator  valid )
  587.   {
  588.     FT_UInt   ScriptCount;
  589.     FT_Bytes  p = table;
  590.  
  591.  
  592.     OTV_NAME_ENTER( "ScriptList" );
  593.  
  594.     OTV_LIMIT_CHECK( 2 );
  595.     ScriptCount = FT_NEXT_USHORT( p );
  596.  
  597.     OTV_TRACE(( " (ScriptCount = %d)\n", ScriptCount ));
  598.  
  599.     OTV_LIMIT_CHECK( ScriptCount * 6 );
  600.  
  601.     valid->extra1 = otv_Feature_get_count( features );
  602.  
  603.     /* ScriptRecord */
  604.     for ( ; ScriptCount > 0; ScriptCount-- )
  605.     {
  606.       p += 4;       /* skip ScriptTag */
  607.  
  608.       otv_Script_validate( table + FT_NEXT_USHORT( p ), valid ); /* Script */
  609.     }
  610.  
  611.     OTV_EXIT;
  612.   }
  613.  
  614.  
  615.   /*************************************************************************/
  616.   /*************************************************************************/
  617.   /*****                                                               *****/
  618.   /*****                      UTILITY FUNCTIONS                        *****/
  619.   /*****                                                               *****/
  620.   /*************************************************************************/
  621.   /*************************************************************************/
  622.  
  623.   /*
  624.      u:   uint16
  625.      ux:  unit16 [x]
  626.  
  627.      s:   struct
  628.      sx:  struct [x]
  629.      sxy: struct [x], using external y count
  630.  
  631.      x:   uint16 x
  632.  
  633.      C:   Coverage
  634.  
  635.      O:   Offset
  636.      On:  Offset (NULL)
  637.      Ox:  Offset [x]
  638.      Onx: Offset (NULL) [x]
  639.   */
  640.  
  641.   FT_LOCAL_DEF( void )
  642.   otv_x_Ox( FT_Bytes       table,
  643.             OTV_Validator  valid )
  644.   {
  645.     FT_Bytes           p = table;
  646.     FT_UInt            Count;
  647.     OTV_Validate_Func  func;
  648.  
  649.  
  650.     OTV_ENTER;
  651.  
  652.     OTV_LIMIT_CHECK( 2 );
  653.     Count = FT_NEXT_USHORT( p );
  654.  
  655.     OTV_TRACE(( " (Count = %d)\n", Count ));
  656.  
  657.     OTV_LIMIT_CHECK( Count * 2 );
  658.  
  659.     valid->nesting_level++;
  660.     func = valid->func[valid->nesting_level];
  661.  
  662.     for ( ; Count > 0; Count-- )
  663.       func( table + FT_NEXT_USHORT( p ), valid );
  664.  
  665.     valid->nesting_level--;
  666.  
  667.     OTV_EXIT;
  668.   }
  669.  
  670.  
  671.   FT_LOCAL_DEF( void )
  672.   otv_u_C_x_Ox( FT_Bytes       table,
  673.                 OTV_Validator  valid )
  674.   {
  675.     FT_Bytes           p = table;
  676.     FT_UInt            Count, Coverage;
  677.     OTV_Validate_Func  func;
  678.  
  679.  
  680.     OTV_ENTER;
  681.  
  682.     p += 2;     /* skip Format */
  683.  
  684.     OTV_LIMIT_CHECK( 4 );
  685.     Coverage = FT_NEXT_USHORT( p );
  686.     Count    = FT_NEXT_USHORT( p );
  687.  
  688.     OTV_TRACE(( " (Count = %d)\n", Count ));
  689.  
  690.     otv_Coverage_validate( table + Coverage, valid, Count );
  691.  
  692.     OTV_LIMIT_CHECK( Count * 2 );
  693.  
  694.     valid->nesting_level++;
  695.     func = valid->func[valid->nesting_level];
  696.  
  697.     for ( ; Count > 0; Count-- )
  698.       func( table + FT_NEXT_USHORT( p ), valid );
  699.  
  700.     valid->nesting_level--;
  701.  
  702.     OTV_EXIT;
  703.   }
  704.  
  705.  
  706.   /* uses valid->extra1 (if > 0: array value limit) */
  707.  
  708.   FT_LOCAL_DEF( void )
  709.   otv_x_ux( FT_Bytes       table,
  710.             OTV_Validator  valid )
  711.   {
  712.     FT_Bytes  p = table;
  713.     FT_UInt   Count;
  714.  
  715.  
  716.     OTV_ENTER;
  717.  
  718.     OTV_LIMIT_CHECK( 2 );
  719.     Count = FT_NEXT_USHORT( p );
  720.  
  721.     OTV_TRACE(( " (Count = %d)\n", Count ));
  722.  
  723.     OTV_LIMIT_CHECK( Count * 2 );
  724.  
  725.     if ( valid->extra1 )
  726.     {
  727.       for ( ; Count > 0; Count-- )
  728.         if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
  729.           FT_INVALID_DATA;
  730.     }
  731.  
  732.     OTV_EXIT;
  733.   }
  734.  
  735.  
  736.   /* `ux' in the function's name is not really correct since only x-1 */
  737.   /* elements are tested                                              */
  738.  
  739.   /* uses valid->extra1 (array value limit) */
  740.  
  741.   FT_LOCAL_DEF( void )
  742.   otv_x_y_ux_sy( FT_Bytes       table,
  743.                  OTV_Validator  valid )
  744.   {
  745.     FT_Bytes  p = table;
  746.     FT_UInt   Count1, Count2;
  747.  
  748.  
  749.     OTV_ENTER;
  750.  
  751.     OTV_LIMIT_CHECK( 4 );
  752.     Count1 = FT_NEXT_USHORT( p );
  753.     Count2 = FT_NEXT_USHORT( p );
  754.  
  755.     OTV_TRACE(( " (Count1 = %d)\n", Count1 ));
  756.     OTV_TRACE(( " (Count2 = %d)\n", Count2 ));
  757.  
  758.     if ( Count1 == 0 )
  759.       FT_INVALID_DATA;
  760.  
  761.     OTV_LIMIT_CHECK( ( Count1 - 1 ) * 2 + Count2 * 4 );
  762.     p += ( Count1 - 1 ) * 2;
  763.  
  764.     for ( ; Count2 > 0; Count2-- )
  765.     {
  766.       if ( FT_NEXT_USHORT( p ) >= Count1 )
  767.         FT_INVALID_DATA;
  768.  
  769.       if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
  770.         FT_INVALID_DATA;
  771.     }
  772.  
  773.     OTV_EXIT;
  774.   }
  775.  
  776.  
  777.   /* `uy' in the function's name is not really correct since only y-1 */
  778.   /* elements are tested                                              */
  779.  
  780.   /* uses valid->extra1 (array value limit) */
  781.  
  782.   FT_LOCAL_DEF( void )
  783.   otv_x_ux_y_uy_z_uz_p_sp( FT_Bytes       table,
  784.                            OTV_Validator  valid )
  785.   {
  786.     FT_Bytes  p = table;
  787.     FT_UInt   BacktrackCount, InputCount, LookaheadCount;
  788.     FT_UInt   Count;
  789.  
  790.  
  791.     OTV_ENTER;
  792.  
  793.     OTV_LIMIT_CHECK( 2 );
  794.     BacktrackCount = FT_NEXT_USHORT( p );
  795.  
  796.     OTV_TRACE(( " (BacktrackCount = %d)\n", BacktrackCount ));
  797.  
  798.     OTV_LIMIT_CHECK( BacktrackCount * 2 + 2 );
  799.     p += BacktrackCount * 2;
  800.  
  801.     InputCount = FT_NEXT_USHORT( p );
  802.     if ( InputCount == 0 )
  803.       FT_INVALID_DATA;
  804.  
  805.     OTV_TRACE(( " (InputCount = %d)\n", InputCount ));
  806.  
  807.     OTV_LIMIT_CHECK( InputCount * 2 );
  808.     p += ( InputCount - 1 ) * 2;
  809.  
  810.     LookaheadCount = FT_NEXT_USHORT( p );
  811.  
  812.     OTV_TRACE(( " (LookaheadCount = %d)\n", LookaheadCount ));
  813.  
  814.     OTV_LIMIT_CHECK( LookaheadCount * 2 + 2 );
  815.     p += LookaheadCount * 2;
  816.  
  817.     Count = FT_NEXT_USHORT( p );
  818.  
  819.     OTV_TRACE(( " (Count = %d)\n", Count ));
  820.  
  821.     OTV_LIMIT_CHECK( Count * 4 );
  822.  
  823.     for ( ; Count > 0; Count-- )
  824.     {
  825.       if ( FT_NEXT_USHORT( p ) >= InputCount )
  826.         FT_INVALID_DATA;
  827.  
  828.       if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
  829.         FT_INVALID_DATA;
  830.     }
  831.  
  832.     OTV_EXIT;
  833.   }
  834.  
  835.  
  836.   /* sets valid->extra1 (valid->lookup_count) */
  837.  
  838.   FT_LOCAL_DEF( void )
  839.   otv_u_O_O_x_Onx( FT_Bytes       table,
  840.                    OTV_Validator  valid )
  841.   {
  842.     FT_Bytes           p = table;
  843.     FT_UInt            Coverage, ClassDef, ClassSetCount;
  844.     OTV_Validate_Func  func;
  845.  
  846.  
  847.     OTV_ENTER;
  848.  
  849.     p += 2;     /* skip Format */
  850.  
  851.     OTV_LIMIT_CHECK( 6 );
  852.     Coverage      = FT_NEXT_USHORT( p );
  853.     ClassDef      = FT_NEXT_USHORT( p );
  854.     ClassSetCount = FT_NEXT_USHORT( p );
  855.  
  856.     OTV_TRACE(( " (ClassSetCount = %d)\n", ClassSetCount ));
  857.  
  858.     otv_Coverage_validate( table + Coverage, valid, -1 );
  859.     otv_ClassDef_validate( table + ClassDef, valid );
  860.  
  861.     OTV_LIMIT_CHECK( ClassSetCount * 2 );
  862.  
  863.     valid->nesting_level++;
  864.     func          = valid->func[valid->nesting_level];
  865.     valid->extra1 = valid->lookup_count;
  866.  
  867.     for ( ; ClassSetCount > 0; ClassSetCount-- )
  868.     {
  869.       FT_UInt  offset = FT_NEXT_USHORT( p );
  870.  
  871.  
  872.       if ( offset )
  873.         func( table + offset, valid );
  874.     }
  875.  
  876.     valid->nesting_level--;
  877.  
  878.     OTV_EXIT;
  879.   }
  880.  
  881.  
  882.   /* uses valid->lookup_count */
  883.  
  884.   FT_LOCAL_DEF( void )
  885.   otv_u_x_y_Ox_sy( FT_Bytes       table,
  886.                    OTV_Validator  valid )
  887.   {
  888.     FT_Bytes  p = table;
  889.     FT_UInt   GlyphCount, Count, count1;
  890.  
  891.  
  892.     OTV_ENTER;
  893.  
  894.     p += 2;     /* skip Format */
  895.  
  896.     OTV_LIMIT_CHECK( 4 );
  897.     GlyphCount = FT_NEXT_USHORT( p );
  898.     Count      = FT_NEXT_USHORT( p );
  899.  
  900.     OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
  901.     OTV_TRACE(( " (Count = %d)\n",      Count      ));
  902.  
  903.     OTV_LIMIT_CHECK( GlyphCount * 2 + Count * 4 );
  904.  
  905.     for ( count1 = GlyphCount; count1 > 0; count1-- )
  906.       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
  907.  
  908.     for ( ; Count > 0; Count-- )
  909.     {
  910.       if ( FT_NEXT_USHORT( p ) >= GlyphCount )
  911.         FT_INVALID_DATA;
  912.  
  913.       if ( FT_NEXT_USHORT( p ) >= valid->lookup_count )
  914.         FT_INVALID_DATA;
  915.     }
  916.  
  917.     OTV_EXIT;
  918.   }
  919.  
  920.  
  921.   /* sets valid->extra1 (valid->lookup_count)    */
  922.  
  923.   FT_LOCAL_DEF( void )
  924.   otv_u_O_O_O_O_x_Onx( FT_Bytes       table,
  925.                        OTV_Validator  valid )
  926.   {
  927.     FT_Bytes           p = table;
  928.     FT_UInt            Coverage;
  929.     FT_UInt            BacktrackClassDef, InputClassDef, LookaheadClassDef;
  930.     FT_UInt            ChainClassSetCount;
  931.     OTV_Validate_Func  func;
  932.  
  933.  
  934.     OTV_ENTER;
  935.  
  936.     p += 2;     /* skip Format */
  937.  
  938.     OTV_LIMIT_CHECK( 10 );
  939.     Coverage           = FT_NEXT_USHORT( p );
  940.     BacktrackClassDef  = FT_NEXT_USHORT( p );
  941.     InputClassDef      = FT_NEXT_USHORT( p );
  942.     LookaheadClassDef  = FT_NEXT_USHORT( p );
  943.     ChainClassSetCount = FT_NEXT_USHORT( p );
  944.  
  945.     OTV_TRACE(( " (ChainClassSetCount = %d)\n", ChainClassSetCount ));
  946.  
  947.     otv_Coverage_validate( table + Coverage, valid, -1 );
  948.  
  949.     otv_ClassDef_validate( table + BacktrackClassDef,  valid );
  950.     otv_ClassDef_validate( table + InputClassDef, valid );
  951.     otv_ClassDef_validate( table + LookaheadClassDef, valid );
  952.  
  953.     OTV_LIMIT_CHECK( ChainClassSetCount * 2 );
  954.  
  955.     valid->nesting_level++;
  956.     func          = valid->func[valid->nesting_level];
  957.     valid->extra1 = valid->lookup_count;
  958.  
  959.     for ( ; ChainClassSetCount > 0; ChainClassSetCount-- )
  960.     {
  961.       FT_UInt  offset = FT_NEXT_USHORT( p );
  962.  
  963.  
  964.       if ( offset )
  965.         func( table + offset, valid );
  966.     }
  967.  
  968.     valid->nesting_level--;
  969.  
  970.     OTV_EXIT;
  971.   }
  972.  
  973.  
  974.   /* uses valid->lookup_count */
  975.  
  976.   FT_LOCAL_DEF( void )
  977.   otv_u_x_Ox_y_Oy_z_Oz_p_sp( FT_Bytes       table,
  978.                              OTV_Validator  valid )
  979.   {
  980.     FT_Bytes  p = table;
  981.     FT_UInt   BacktrackGlyphCount, InputGlyphCount, LookaheadGlyphCount;
  982.     FT_UInt   count1, count2;
  983.  
  984.  
  985.     OTV_ENTER;
  986.  
  987.     p += 2;     /* skip Format */
  988.  
  989.     OTV_LIMIT_CHECK( 2 );
  990.     BacktrackGlyphCount = FT_NEXT_USHORT( p );
  991.  
  992.     OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
  993.  
  994.     OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
  995.  
  996.     for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
  997.       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
  998.  
  999.     InputGlyphCount = FT_NEXT_USHORT( p );
  1000.  
  1001.     OTV_TRACE(( " (InputGlyphCount = %d)\n", InputGlyphCount ));
  1002.  
  1003.     OTV_LIMIT_CHECK( InputGlyphCount * 2 + 2 );
  1004.  
  1005.     for ( count1 = InputGlyphCount; count1 > 0; count1-- )
  1006.       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
  1007.  
  1008.     LookaheadGlyphCount = FT_NEXT_USHORT( p );
  1009.  
  1010.     OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
  1011.  
  1012.     OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
  1013.  
  1014.     for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
  1015.       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
  1016.  
  1017.     count2 = FT_NEXT_USHORT( p );
  1018.  
  1019.     OTV_TRACE(( " (Count = %d)\n", count2 ));
  1020.  
  1021.     OTV_LIMIT_CHECK( count2 * 4 );
  1022.  
  1023.     for ( ; count2 > 0; count2-- )
  1024.     {
  1025.       if ( FT_NEXT_USHORT( p ) >= InputGlyphCount )
  1026.         FT_INVALID_DATA;
  1027.  
  1028.       if ( FT_NEXT_USHORT( p ) >= valid->lookup_count )
  1029.         FT_INVALID_DATA;
  1030.     }
  1031.  
  1032.     OTV_EXIT;
  1033.   }
  1034.  
  1035.  
  1036.   FT_LOCAL_DEF( FT_UInt )
  1037.   otv_GSUBGPOS_get_Lookup_count( FT_Bytes  table )
  1038.   {
  1039.     FT_Bytes  p = table + 8;
  1040.  
  1041.  
  1042.     return otv_LookupList_get_count( table + FT_NEXT_USHORT( p ) );
  1043.   }
  1044.  
  1045.  
  1046.   FT_LOCAL_DEF( FT_UInt )
  1047.   otv_GSUBGPOS_have_MarkAttachmentType_flag( FT_Bytes  table )
  1048.   {
  1049.     FT_Bytes  p, lookup;
  1050.     FT_UInt   count;
  1051.  
  1052.  
  1053.     if ( !table )
  1054.       return 0;
  1055.  
  1056.     /* LookupList */
  1057.     p      = table + 8;
  1058.     table += FT_NEXT_USHORT( p );
  1059.  
  1060.     /* LookupCount */
  1061.     p     = table;
  1062.     count = FT_NEXT_USHORT( p );
  1063.  
  1064.     for ( ; count > 0; count-- )
  1065.     {
  1066.       FT_Bytes  oldp;
  1067.  
  1068.  
  1069.       /* Lookup */
  1070.       lookup = table + FT_NEXT_USHORT( p );
  1071.  
  1072.       oldp = p;
  1073.  
  1074.       /* LookupFlag */
  1075.       p = lookup + 2;
  1076.       if ( FT_NEXT_USHORT( p ) & 0xFF00U )
  1077.         return 1;
  1078.  
  1079.       p = oldp;
  1080.     }
  1081.  
  1082.     return 0;
  1083.   }
  1084.  
  1085.  
  1086. /* END */
  1087.