Subversion Repositories Kolibri OS

Rev

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

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  otvgsub.c                                                              */
  4. /*                                                                         */
  5. /*    OpenType GSUB table validation (body).                               */
  6. /*                                                                         */
  7. /*  Copyright 2004, 2005, 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 "otvalid.h"
  20. #include "otvcommn.h"
  21.  
  22.  
  23.   /*************************************************************************/
  24.   /*                                                                       */
  25.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  26.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  27.   /* messages during execution.                                            */
  28.   /*                                                                       */
  29. #undef  FT_COMPONENT
  30. #define FT_COMPONENT  trace_otvgsub
  31.  
  32.  
  33.   /*************************************************************************/
  34.   /*************************************************************************/
  35.   /*****                                                               *****/
  36.   /*****                  GSUB LOOKUP TYPE 1                           *****/
  37.   /*****                                                               *****/
  38.   /*************************************************************************/
  39.   /*************************************************************************/
  40.  
  41.   /* uses valid->glyph_count */
  42.  
  43.   static void
  44.   otv_SingleSubst_validate( FT_Bytes       table,
  45.                             OTV_Validator  valid )
  46.   {
  47.     FT_Bytes  p = table;
  48.     FT_UInt   SubstFormat;
  49.  
  50.  
  51.     OTV_NAME_ENTER( "SingleSubst" );
  52.  
  53.     OTV_LIMIT_CHECK( 2 );
  54.     SubstFormat = FT_NEXT_USHORT( p );
  55.  
  56.     OTV_TRACE(( " (format %d)\n", SubstFormat ));
  57.  
  58.     switch ( SubstFormat )
  59.     {
  60.     case 1:     /* SingleSubstFormat1 */
  61.       {
  62.         FT_Bytes  Coverage;
  63.         FT_Int    DeltaGlyphID;
  64.         FT_Long   idx;
  65.  
  66.  
  67.         OTV_LIMIT_CHECK( 4 );
  68.         Coverage     = table + FT_NEXT_USHORT( p );
  69.         DeltaGlyphID = FT_NEXT_SHORT( p );
  70.  
  71.         otv_Coverage_validate( Coverage, valid, -1 );
  72.  
  73.         idx = otv_Coverage_get_first( Coverage ) + DeltaGlyphID;
  74.         if ( idx < 0 )
  75.           FT_INVALID_DATA;
  76.  
  77.         idx = otv_Coverage_get_last( Coverage ) + DeltaGlyphID;
  78.         if ( (FT_UInt)idx >= valid->glyph_count )
  79.           FT_INVALID_DATA;
  80.       }
  81.       break;
  82.  
  83.     case 2:     /* SingleSubstFormat2 */
  84.       {
  85.         FT_UInt  Coverage, GlyphCount;
  86.  
  87.  
  88.         OTV_LIMIT_CHECK( 4 );
  89.         Coverage   = FT_NEXT_USHORT( p );
  90.         GlyphCount = FT_NEXT_USHORT( p );
  91.  
  92.         OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
  93.  
  94.         otv_Coverage_validate( table + Coverage, valid, GlyphCount );
  95.  
  96.         OTV_LIMIT_CHECK( GlyphCount * 2 );
  97.  
  98.         /* Substitute */
  99.         for ( ; GlyphCount > 0; GlyphCount-- )
  100.           if ( FT_NEXT_USHORT( p ) >= valid->glyph_count )
  101.             FT_INVALID_GLYPH_ID;
  102.       }
  103.       break;
  104.  
  105.     default:
  106.       FT_INVALID_FORMAT;
  107.     }
  108.  
  109.     OTV_EXIT;
  110.   }
  111.  
  112.  
  113.   /*************************************************************************/
  114.   /*************************************************************************/
  115.   /*****                                                               *****/
  116.   /*****                  GSUB LOOKUP TYPE 2                           *****/
  117.   /*****                                                               *****/
  118.   /*************************************************************************/
  119.   /*************************************************************************/
  120.  
  121.   /* sets valid->extra1 (glyph count) */
  122.  
  123.   static void
  124.   otv_MultipleSubst_validate( FT_Bytes       table,
  125.                               OTV_Validator  valid )
  126.   {
  127.     FT_Bytes  p = table;
  128.     FT_UInt   SubstFormat;
  129.  
  130.  
  131.     OTV_NAME_ENTER( "MultipleSubst" );
  132.  
  133.     OTV_LIMIT_CHECK( 2 );
  134.     SubstFormat = FT_NEXT_USHORT( p );
  135.  
  136.     OTV_TRACE(( " (format %d)\n", SubstFormat ));
  137.  
  138.     switch ( SubstFormat )
  139.     {
  140.     case 1:
  141.       valid->extra1 = valid->glyph_count;
  142.       OTV_NEST2( MultipleSubstFormat1, Sequence );
  143.       OTV_RUN( table, valid );
  144.       break;
  145.  
  146.     default:
  147.       FT_INVALID_FORMAT;
  148.     }
  149.  
  150.     OTV_EXIT;
  151.   }
  152.  
  153.  
  154.   /*************************************************************************/
  155.   /*************************************************************************/
  156.   /*****                                                               *****/
  157.   /*****                    GSUB LOOKUP TYPE 3                         *****/
  158.   /*****                                                               *****/
  159.   /*************************************************************************/
  160.   /*************************************************************************/
  161.  
  162.   /* sets valid->extra1 (glyph count) */
  163.  
  164.   static void
  165.   otv_AlternateSubst_validate( FT_Bytes       table,
  166.                                OTV_Validator  valid )
  167.   {
  168.     FT_Bytes  p = table;
  169.     FT_UInt   SubstFormat;
  170.  
  171.  
  172.     OTV_NAME_ENTER( "AlternateSubst" );
  173.  
  174.     OTV_LIMIT_CHECK( 2 );
  175.     SubstFormat = FT_NEXT_USHORT( p );
  176.  
  177.     OTV_TRACE(( " (format %d)\n", SubstFormat ));
  178.  
  179.     switch ( SubstFormat )
  180.     {
  181.     case 1:
  182.       valid->extra1 = valid->glyph_count;
  183.       OTV_NEST2( AlternateSubstFormat1, AlternateSet );
  184.       OTV_RUN( table, valid );
  185.       break;
  186.  
  187.     default:
  188.       FT_INVALID_FORMAT;
  189.     }
  190.  
  191.     OTV_EXIT;
  192.   }
  193.  
  194.  
  195.   /*************************************************************************/
  196.   /*************************************************************************/
  197.   /*****                                                               *****/
  198.   /*****                    GSUB LOOKUP TYPE 4                         *****/
  199.   /*****                                                               *****/
  200.   /*************************************************************************/
  201.   /*************************************************************************/
  202.  
  203. #define LigatureFunc  otv_Ligature_validate
  204.  
  205.   /* uses valid->glyph_count */
  206.  
  207.   static void
  208.   otv_Ligature_validate( FT_Bytes       table,
  209.                          OTV_Validator  valid )
  210.   {
  211.     FT_Bytes  p = table;
  212.     FT_UInt   LigatureGlyph, CompCount;
  213.  
  214.  
  215.     OTV_ENTER;
  216.  
  217.     OTV_LIMIT_CHECK( 4 );
  218.     LigatureGlyph = FT_NEXT_USHORT( p );
  219.     if ( LigatureGlyph >= valid->glyph_count )
  220.       FT_INVALID_DATA;
  221.  
  222.     CompCount = FT_NEXT_USHORT( p );
  223.  
  224.     OTV_TRACE(( " (CompCount = %d)\n", CompCount ));
  225.  
  226.     if ( CompCount == 0 )
  227.       FT_INVALID_DATA;
  228.  
  229.     CompCount--;
  230.  
  231.     OTV_LIMIT_CHECK( CompCount * 2 );     /* Component */
  232.  
  233.     /* no need to check the Component glyph indices */
  234.  
  235.     OTV_EXIT;
  236.   }
  237.  
  238.  
  239.   static void
  240.   otv_LigatureSubst_validate( FT_Bytes       table,
  241.                               OTV_Validator  valid )
  242.   {
  243.     FT_Bytes  p = table;
  244.     FT_UInt   SubstFormat;
  245.  
  246.  
  247.     OTV_NAME_ENTER( "LigatureSubst" );
  248.  
  249.     OTV_LIMIT_CHECK( 2 );
  250.     SubstFormat = FT_NEXT_USHORT( p );
  251.  
  252.     OTV_TRACE(( " (format %d)\n", SubstFormat ));
  253.  
  254.     switch ( SubstFormat )
  255.     {
  256.     case 1:
  257.       OTV_NEST3( LigatureSubstFormat1, LigatureSet, Ligature );
  258.       OTV_RUN( table, valid );
  259.       break;
  260.  
  261.     default:
  262.       FT_INVALID_FORMAT;
  263.     }
  264.  
  265.     OTV_EXIT;
  266.   }
  267.  
  268.  
  269.   /*************************************************************************/
  270.   /*************************************************************************/
  271.   /*****                                                               *****/
  272.   /*****                  GSUB LOOKUP TYPE 5                           *****/
  273.   /*****                                                               *****/
  274.   /*************************************************************************/
  275.   /*************************************************************************/
  276.  
  277.   /* sets valid->extra1 (lookup count) */
  278.  
  279.   static void
  280.   otv_ContextSubst_validate( FT_Bytes       table,
  281.                              OTV_Validator  valid )
  282.   {
  283.     FT_Bytes  p = table;
  284.     FT_UInt   SubstFormat;
  285.  
  286.  
  287.     OTV_NAME_ENTER( "ContextSubst" );
  288.  
  289.     OTV_LIMIT_CHECK( 2 );
  290.     SubstFormat = FT_NEXT_USHORT( p );
  291.  
  292.     OTV_TRACE(( " (format %d)\n", SubstFormat ));
  293.  
  294.     switch ( SubstFormat )
  295.     {
  296.     case 1:
  297.       /* no need to check glyph indices/classes used as input for these */
  298.       /* context rules since even invalid glyph indices/classes return  */
  299.       /* meaningful results                                             */
  300.  
  301.       valid->extra1 = valid->lookup_count;
  302.       OTV_NEST3( ContextSubstFormat1, SubRuleSet, SubRule );
  303.       OTV_RUN( table, valid );
  304.       break;
  305.  
  306.     case 2:
  307.       /* no need to check glyph indices/classes used as input for these */
  308.       /* context rules since even invalid glyph indices/classes return  */
  309.       /* meaningful results                                             */
  310.  
  311.       OTV_NEST3( ContextSubstFormat2, SubClassSet, SubClassRule );
  312.       OTV_RUN( table, valid );
  313.       break;
  314.  
  315.     case 3:
  316.       OTV_NEST1( ContextSubstFormat3 );
  317.       OTV_RUN( table, valid );
  318.       break;
  319.  
  320.     default:
  321.       FT_INVALID_FORMAT;
  322.     }
  323.  
  324.     OTV_EXIT;
  325.   }
  326.  
  327.  
  328.   /*************************************************************************/
  329.   /*************************************************************************/
  330.   /*****                                                               *****/
  331.   /*****                    GSUB LOOKUP TYPE 6                         *****/
  332.   /*****                                                               *****/
  333.   /*************************************************************************/
  334.   /*************************************************************************/
  335.  
  336.   /* sets valid->extra1 (lookup count)            */
  337.  
  338.   static void
  339.   otv_ChainContextSubst_validate( FT_Bytes       table,
  340.                                   OTV_Validator  valid )
  341.   {
  342.     FT_Bytes  p = table;
  343.     FT_UInt   SubstFormat;
  344.  
  345.  
  346.     OTV_NAME_ENTER( "ChainContextSubst" );
  347.  
  348.     OTV_LIMIT_CHECK( 2 );
  349.     SubstFormat = FT_NEXT_USHORT( p );
  350.  
  351.     OTV_TRACE(( " (format %d)\n", SubstFormat ));
  352.  
  353.     switch ( SubstFormat )
  354.     {
  355.     case 1:
  356.       /* no need to check glyph indices/classes used as input for these */
  357.       /* context rules since even invalid glyph indices/classes return  */
  358.       /* meaningful results                                             */
  359.  
  360.       valid->extra1 = valid->lookup_count;
  361.       OTV_NEST3( ChainContextSubstFormat1,
  362.                  ChainSubRuleSet, ChainSubRule );
  363.       OTV_RUN( table, valid );
  364.       break;
  365.  
  366.     case 2:
  367.       /* no need to check glyph indices/classes used as input for these */
  368.       /* context rules since even invalid glyph indices/classes return  */
  369.       /* meaningful results                                             */
  370.  
  371.       OTV_NEST3( ChainContextSubstFormat2,
  372.                  ChainSubClassSet, ChainSubClassRule );
  373.       OTV_RUN( table, valid );
  374.       break;
  375.  
  376.     case 3:
  377.       OTV_NEST1( ChainContextSubstFormat3 );
  378.       OTV_RUN( table, valid );
  379.       break;
  380.  
  381.     default:
  382.       FT_INVALID_FORMAT;
  383.     }
  384.  
  385.     OTV_EXIT;
  386.   }
  387.  
  388.  
  389.   /*************************************************************************/
  390.   /*************************************************************************/
  391.   /*****                                                               *****/
  392.   /*****                    GSUB LOOKUP TYPE 7                         *****/
  393.   /*****                                                               *****/
  394.   /*************************************************************************/
  395.   /*************************************************************************/
  396.  
  397.   /* uses valid->type_funcs */
  398.  
  399.   static void
  400.   otv_ExtensionSubst_validate( FT_Bytes       table,
  401.                                OTV_Validator  valid )
  402.   {
  403.     FT_Bytes  p = table;
  404.     FT_UInt   SubstFormat;
  405.  
  406.  
  407.     OTV_NAME_ENTER( "ExtensionSubst" );
  408.  
  409.     OTV_LIMIT_CHECK( 2 );
  410.     SubstFormat = FT_NEXT_USHORT( p );
  411.  
  412.     OTV_TRACE(( " (format %d)\n", SubstFormat ));
  413.  
  414.     switch ( SubstFormat )
  415.     {
  416.     case 1:     /* ExtensionSubstFormat1 */
  417.       {
  418.         FT_UInt            ExtensionLookupType;
  419.         FT_ULong           ExtensionOffset;
  420.         OTV_Validate_Func  validate;
  421.  
  422.  
  423.         OTV_LIMIT_CHECK( 6 );
  424.         ExtensionLookupType = FT_NEXT_USHORT( p );
  425.         ExtensionOffset     = FT_NEXT_ULONG( p );
  426.  
  427.         if ( ExtensionLookupType == 0 ||
  428.              ExtensionLookupType == 7 ||
  429.              ExtensionLookupType > 8  )
  430.           FT_INVALID_DATA;
  431.  
  432.         validate = valid->type_funcs[ExtensionLookupType - 1];
  433.         validate( table + ExtensionOffset, valid );
  434.       }
  435.       break;
  436.  
  437.     default:
  438.       FT_INVALID_FORMAT;
  439.     }
  440.  
  441.     OTV_EXIT;
  442.   }
  443.  
  444.  
  445.   /*************************************************************************/
  446.   /*************************************************************************/
  447.   /*****                                                               *****/
  448.   /*****                    GSUB LOOKUP TYPE 8                         *****/
  449.   /*****                                                               *****/
  450.   /*************************************************************************/
  451.   /*************************************************************************/
  452.  
  453.   /* uses valid->glyph_count */
  454.  
  455.   static void
  456.   otv_ReverseChainSingleSubst_validate( FT_Bytes       table,
  457.                                         OTV_Validator  valid )
  458.   {
  459.     FT_Bytes  p = table, Coverage;
  460.     FT_UInt   SubstFormat;
  461.     FT_UInt   BacktrackGlyphCount, LookaheadGlyphCount, GlyphCount;
  462.  
  463.  
  464.     OTV_NAME_ENTER( "ReverseChainSingleSubst" );
  465.  
  466.     OTV_LIMIT_CHECK( 2 );
  467.     SubstFormat = FT_NEXT_USHORT( p );
  468.  
  469.     OTV_TRACE(( " (format %d)\n", SubstFormat ));
  470.  
  471.     switch ( SubstFormat )
  472.     {
  473.     case 1:     /* ReverseChainSingleSubstFormat1 */
  474.       OTV_LIMIT_CHECK( 4 );
  475.       Coverage            = table + FT_NEXT_USHORT( p );
  476.       BacktrackGlyphCount = FT_NEXT_USHORT( p );
  477.  
  478.       OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
  479.  
  480.       otv_Coverage_validate( Coverage, valid, -1 );
  481.  
  482.       OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
  483.  
  484.       for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
  485.         otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
  486.  
  487.       LookaheadGlyphCount = FT_NEXT_USHORT( p );
  488.  
  489.       OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
  490.  
  491.       OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
  492.  
  493.       for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
  494.         otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
  495.  
  496.       GlyphCount = FT_NEXT_USHORT( p );
  497.  
  498.       OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
  499.  
  500.       if ( GlyphCount != otv_Coverage_get_count( Coverage ) )
  501.         FT_INVALID_DATA;
  502.  
  503.       OTV_LIMIT_CHECK( GlyphCount * 2 );
  504.  
  505.       /* Substitute */
  506.       for ( ; GlyphCount > 0; GlyphCount-- )
  507.         if ( FT_NEXT_USHORT( p ) >= valid->glyph_count )
  508.           FT_INVALID_DATA;
  509.  
  510.       break;
  511.  
  512.     default:
  513.       FT_INVALID_FORMAT;
  514.     }
  515.  
  516.     OTV_EXIT;
  517.   }
  518.  
  519.  
  520.   static const OTV_Validate_Func  otv_gsub_validate_funcs[8] =
  521.   {
  522.     otv_SingleSubst_validate,
  523.     otv_MultipleSubst_validate,
  524.     otv_AlternateSubst_validate,
  525.     otv_LigatureSubst_validate,
  526.     otv_ContextSubst_validate,
  527.     otv_ChainContextSubst_validate,
  528.     otv_ExtensionSubst_validate,
  529.     otv_ReverseChainSingleSubst_validate
  530.   };
  531.  
  532.  
  533.   /*************************************************************************/
  534.   /*************************************************************************/
  535.   /*****                                                               *****/
  536.   /*****                          GSUB TABLE                           *****/
  537.   /*****                                                               *****/
  538.   /*************************************************************************/
  539.   /*************************************************************************/
  540.  
  541.   /* sets valid->type_count  */
  542.   /* sets valid->type_funcs  */
  543.   /* sets valid->glyph_count */
  544.  
  545.   FT_LOCAL_DEF( void )
  546.   otv_GSUB_validate( FT_Bytes      table,
  547.                      FT_UInt       glyph_count,
  548.                      FT_Validator  ftvalid )
  549.   {
  550.     OTV_ValidatorRec  validrec;
  551.     OTV_Validator     valid = &validrec;
  552.     FT_Bytes          p     = table;
  553.     FT_UInt           ScriptList, FeatureList, LookupList;
  554.  
  555.  
  556.     valid->root = ftvalid;
  557.  
  558.     FT_TRACE3(( "validating GSUB table\n" ));
  559.     OTV_INIT;
  560.  
  561.     OTV_LIMIT_CHECK( 10 );
  562.  
  563.     if ( FT_NEXT_ULONG( p ) != 0x10000UL )      /* Version */
  564.       FT_INVALID_FORMAT;
  565.  
  566.     ScriptList  = FT_NEXT_USHORT( p );
  567.     FeatureList = FT_NEXT_USHORT( p );
  568.     LookupList  = FT_NEXT_USHORT( p );
  569.  
  570.     valid->type_count  = 8;
  571.     valid->type_funcs  = (OTV_Validate_Func*)otv_gsub_validate_funcs;
  572.     valid->glyph_count = glyph_count;
  573.  
  574.     otv_LookupList_validate( table + LookupList,
  575.                              valid );
  576.     otv_FeatureList_validate( table + FeatureList, table + LookupList,
  577.                               valid );
  578.     otv_ScriptList_validate( table + ScriptList, table + FeatureList,
  579.                              valid );
  580.  
  581.     FT_TRACE4(( "\n" ));
  582.   }
  583.  
  584.  
  585. /* END */
  586.