Subversion Repositories Kolibri OS

Rev

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

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  gxvmort.c                                                              */
  4. /*                                                                         */
  5. /*    TrueTypeGX/AAT mort table validation (body).                         */
  6. /*                                                                         */
  7. /*  Copyright 2005, 2013 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
  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. /*                                                                         */
  20. /* gxvalid is derived from both gxlayout module and otvalid module.        */
  21. /* Development of gxlayout is supported by the Information-technology      */
  22. /* Promotion Agency(IPA), Japan.                                           */
  23. /*                                                                         */
  24. /***************************************************************************/
  25.  
  26.  
  27. #include "gxvmort.h"
  28. #include "gxvfeat.h"
  29.  
  30.  
  31.   /*************************************************************************/
  32.   /*                                                                       */
  33.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  34.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  35.   /* messages during execution.                                            */
  36.   /*                                                                       */
  37. #undef  FT_COMPONENT
  38. #define FT_COMPONENT  trace_gxvmort
  39.  
  40.  
  41.   static void
  42.   gxv_mort_feature_validate( GXV_mort_feature  f,
  43.                              GXV_Validator     valid )
  44.   {
  45.     if ( f->featureType >= gxv_feat_registry_length )
  46.     {
  47.       GXV_TRACE(( "featureType %d is out of registered range, "
  48.                   "setting %d is unchecked\n",
  49.                   f->featureType, f->featureSetting ));
  50.       GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
  51.     }
  52.     else if ( !gxv_feat_registry[f->featureType].existence )
  53.     {
  54.       GXV_TRACE(( "featureType %d is within registered area "
  55.                   "but undefined, setting %d is unchecked\n",
  56.                   f->featureType, f->featureSetting ));
  57.       GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
  58.     }
  59.     else
  60.     {
  61.       FT_Byte  nSettings_max;
  62.  
  63.  
  64.       /* nSettings in gxvfeat.c is halved for exclusive on/off settings */
  65.       nSettings_max = gxv_feat_registry[f->featureType].nSettings;
  66.       if ( gxv_feat_registry[f->featureType].exclusive )
  67.         nSettings_max = (FT_Byte)( 2 * nSettings_max );
  68.  
  69.       GXV_TRACE(( "featureType %d is registered", f->featureType ));
  70.       GXV_TRACE(( "setting %d", f->featureSetting ));
  71.  
  72.       if ( f->featureSetting > nSettings_max )
  73.       {
  74.         GXV_TRACE(( "out of defined range %d", nSettings_max ));
  75.         GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
  76.       }
  77.       GXV_TRACE(( "\n" ));
  78.     }
  79.  
  80.     /* TODO: enableFlags must be unique value in specified chain?  */
  81.   }
  82.  
  83.  
  84.   /*
  85.    * nFeatureFlags is typed to FT_ULong to accept that in
  86.    * mort (typed FT_UShort) and morx (typed FT_ULong).
  87.    */
  88.   FT_LOCAL_DEF( void )
  89.   gxv_mort_featurearray_validate( FT_Bytes       table,
  90.                                   FT_Bytes       limit,
  91.                                   FT_ULong       nFeatureFlags,
  92.                                   GXV_Validator  valid )
  93.   {
  94.     FT_Bytes  p = table;
  95.     FT_ULong  i;
  96.  
  97.     GXV_mort_featureRec  f = GXV_MORT_FEATURE_OFF;
  98.  
  99.  
  100.     GXV_NAME_ENTER( "mort feature list" );
  101.     for ( i = 0; i < nFeatureFlags; i++ )
  102.     {
  103.       GXV_LIMIT_CHECK( 2 + 2 + 4 + 4 );
  104.       f.featureType    = FT_NEXT_USHORT( p );
  105.       f.featureSetting = FT_NEXT_USHORT( p );
  106.       f.enableFlags    = FT_NEXT_ULONG( p );
  107.       f.disableFlags   = FT_NEXT_ULONG( p );
  108.  
  109.       gxv_mort_feature_validate( &f, valid );
  110.     }
  111.  
  112.     if ( !IS_GXV_MORT_FEATURE_OFF( f ) )
  113.       FT_INVALID_DATA;
  114.  
  115.     valid->subtable_length = p - table;
  116.     GXV_EXIT;
  117.   }
  118.  
  119.  
  120.   FT_LOCAL_DEF( void )
  121.   gxv_mort_coverage_validate( FT_UShort      coverage,
  122.                               GXV_Validator  valid )
  123.   {
  124.     FT_UNUSED( valid );
  125.  
  126.     if ( coverage & 0x8000U )
  127.       GXV_TRACE(( " this subtable is for vertical text only\n" ));
  128.     else
  129.       GXV_TRACE(( " this subtable is for horizontal text only\n" ));
  130.  
  131.     if ( coverage & 0x4000 )
  132.       GXV_TRACE(( " this subtable is applied to glyph array "
  133.                   "in descending order\n" ));
  134.     else
  135.       GXV_TRACE(( " this subtable is applied to glyph array "
  136.                   "in ascending order\n" ));
  137.  
  138.     if ( coverage & 0x2000 )
  139.       GXV_TRACE(( " this subtable is forcibly applied to "
  140.                   "vertical/horizontal text\n" ));
  141.  
  142.     if ( coverage & 0x1FF8 )
  143.       GXV_TRACE(( " coverage has non-zero bits in reserved area\n" ));
  144.   }
  145.  
  146.  
  147.   static void
  148.   gxv_mort_subtables_validate( FT_Bytes       table,
  149.                                FT_Bytes       limit,
  150.                                FT_UShort      nSubtables,
  151.                                GXV_Validator  valid )
  152.   {
  153.     FT_Bytes  p = table;
  154.  
  155.     GXV_Validate_Func fmt_funcs_table[] =
  156.     {
  157.       gxv_mort_subtable_type0_validate, /* 0 */
  158.       gxv_mort_subtable_type1_validate, /* 1 */
  159.       gxv_mort_subtable_type2_validate, /* 2 */
  160.       NULL,                             /* 3 */
  161.       gxv_mort_subtable_type4_validate, /* 4 */
  162.       gxv_mort_subtable_type5_validate, /* 5 */
  163.  
  164.     };
  165.  
  166.     FT_UShort  i;
  167.  
  168.  
  169.     GXV_NAME_ENTER( "subtables in a chain" );
  170.  
  171.     for ( i = 0; i < nSubtables; i++ )
  172.     {
  173.       GXV_Validate_Func  func;
  174.  
  175.       FT_UShort  length;
  176.       FT_UShort  coverage;
  177. #ifdef GXV_LOAD_UNUSED_VARS
  178.       FT_ULong   subFeatureFlags;
  179. #endif
  180.       FT_UInt    type;
  181.       FT_UInt    rest;
  182.  
  183.  
  184.       GXV_LIMIT_CHECK( 2 + 2 + 4 );
  185.       length          = FT_NEXT_USHORT( p );
  186.       coverage        = FT_NEXT_USHORT( p );
  187. #ifdef GXV_LOAD_UNUSED_VARS
  188.       subFeatureFlags = FT_NEXT_ULONG( p );
  189. #else
  190.       p += 4;
  191. #endif
  192.  
  193.       GXV_TRACE(( "validating chain subtable %d/%d (%d bytes)\n",
  194.                   i + 1, nSubtables, length ));
  195.       type = coverage & 0x0007;
  196.       rest = length - ( 2 + 2 + 4 );
  197.  
  198.       GXV_LIMIT_CHECK( rest );
  199.       gxv_mort_coverage_validate( coverage, valid );
  200.  
  201.       if ( type > 5 )
  202.         FT_INVALID_FORMAT;
  203.  
  204.       func = fmt_funcs_table[type];
  205.       if ( func == NULL )
  206.         GXV_TRACE(( "morx type %d is reserved\n", type ));
  207.  
  208.       func( p, p + rest, valid );
  209.  
  210.       p += rest;
  211.       /* TODO: validate subFeatureFlags */
  212.     }
  213.  
  214.     valid->subtable_length = p - table;
  215.  
  216.     GXV_EXIT;
  217.   }
  218.  
  219.  
  220.   static void
  221.   gxv_mort_chain_validate( FT_Bytes       table,
  222.                            FT_Bytes       limit,
  223.                            GXV_Validator  valid )
  224.   {
  225.     FT_Bytes   p = table;
  226. #ifdef GXV_LOAD_UNUSED_VARS
  227.     FT_ULong   defaultFlags;
  228. #endif
  229.     FT_ULong   chainLength;
  230.     FT_UShort  nFeatureFlags;
  231.     FT_UShort  nSubtables;
  232.  
  233.  
  234.     GXV_NAME_ENTER( "mort chain header" );
  235.  
  236.     GXV_LIMIT_CHECK( 4 + 4 + 2 + 2 );
  237. #ifdef GXV_LOAD_UNUSED_VARS
  238.     defaultFlags  = FT_NEXT_ULONG( p );
  239. #else
  240.     p += 4;
  241. #endif
  242.     chainLength   = FT_NEXT_ULONG( p );
  243.     nFeatureFlags = FT_NEXT_USHORT( p );
  244.     nSubtables    = FT_NEXT_USHORT( p );
  245.  
  246.     gxv_mort_featurearray_validate( p, table + chainLength,
  247.                                     nFeatureFlags, valid );
  248.     p += valid->subtable_length;
  249.     gxv_mort_subtables_validate( p, table + chainLength, nSubtables, valid );
  250.     valid->subtable_length = chainLength;
  251.  
  252.     /* TODO: validate defaultFlags */
  253.     GXV_EXIT;
  254.   }
  255.  
  256.  
  257.   FT_LOCAL_DEF( void )
  258.   gxv_mort_validate( FT_Bytes      table,
  259.                      FT_Face       face,
  260.                      FT_Validator  ftvalid )
  261.   {
  262.     GXV_ValidatorRec  validrec;
  263.     GXV_Validator     valid = &validrec;
  264.     FT_Bytes          p     = table;
  265.     FT_Bytes          limit = 0;
  266.     FT_ULong          version;
  267.     FT_ULong          nChains;
  268.     FT_ULong          i;
  269.  
  270.  
  271.     valid->root = ftvalid;
  272.     valid->face = face;
  273.     limit       = valid->root->limit;
  274.  
  275.     FT_TRACE3(( "validating `mort' table\n" ));
  276.     GXV_INIT;
  277.  
  278.     GXV_LIMIT_CHECK( 4 + 4 );
  279.     version = FT_NEXT_ULONG( p );
  280.     nChains = FT_NEXT_ULONG( p );
  281.  
  282.     if (version != 0x00010000UL)
  283.       FT_INVALID_FORMAT;
  284.  
  285.     for ( i = 0; i < nChains; i++ )
  286.     {
  287.       GXV_TRACE(( "validating chain %d/%d\n", i + 1, nChains ));
  288.       GXV_32BIT_ALIGNMENT_VALIDATE( p - table );
  289.       gxv_mort_chain_validate( p, limit, valid );
  290.       p += valid->subtable_length;
  291.     }
  292.  
  293.     FT_TRACE4(( "\n" ));
  294.   }
  295.  
  296.  
  297. /* END */
  298.