Subversion Repositories Kolibri OS

Rev

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

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  gxvmort2.c                                                             */
  4. /*                                                                         */
  5. /*    TrueTypeGX/AAT mort table validation                                 */
  6. /*    body for type2 (Ligature Substitution) subtable.                     */
  7. /*                                                                         */
  8. /*  Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K.,       */
  9. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  10. /*                                                                         */
  11. /*  This file is part of the FreeType project, and may only be used,       */
  12. /*  modified, and distributed under the terms of the FreeType project      */
  13. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  14. /*  this file you indicate that you have read the license and              */
  15. /*  understand and accept it fully.                                        */
  16. /*                                                                         */
  17. /***************************************************************************/
  18.  
  19. /***************************************************************************/
  20. /*                                                                         */
  21. /* gxvalid is derived from both gxlayout module and otvalid module.        */
  22. /* Development of gxlayout is supported by the Information-technology      */
  23. /* Promotion Agency(IPA), Japan.                                           */
  24. /*                                                                         */
  25. /***************************************************************************/
  26.  
  27.  
  28. #include "gxvmort.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.   typedef struct  GXV_mort_subtable_type2_StateOptRec_
  42.   {
  43.     FT_UShort  ligActionTable;
  44.     FT_UShort  componentTable;
  45.     FT_UShort  ligatureTable;
  46.     FT_UShort  ligActionTable_length;
  47.     FT_UShort  componentTable_length;
  48.     FT_UShort  ligatureTable_length;
  49.  
  50.   }  GXV_mort_subtable_type2_StateOptRec,
  51.     *GXV_mort_subtable_type2_StateOptRecData;
  52.  
  53. #define GXV_MORT_SUBTABLE_TYPE2_HEADER_SIZE \
  54.           ( GXV_STATETABLE_HEADER_SIZE + 2 + 2 + 2 )
  55.  
  56.  
  57.   static void
  58.   gxv_mort_subtable_type2_opttable_load( FT_Bytes       table,
  59.                                          FT_Bytes       limit,
  60.                                          GXV_Validator  valid )
  61.   {
  62.     FT_Bytes p = table;
  63.     GXV_mort_subtable_type2_StateOptRecData  optdata =
  64.       (GXV_mort_subtable_type2_StateOptRecData)valid->statetable.optdata;
  65.  
  66.  
  67.     GXV_LIMIT_CHECK( 2 + 2 + 2 );
  68.     optdata->ligActionTable = FT_NEXT_USHORT( p );
  69.     optdata->componentTable = FT_NEXT_USHORT( p );
  70.     optdata->ligatureTable  = FT_NEXT_USHORT( p );
  71.  
  72.     GXV_TRACE(( "offset to ligActionTable=0x%04x\n",
  73.                 optdata->ligActionTable ));
  74.     GXV_TRACE(( "offset to componentTable=0x%04x\n",
  75.                 optdata->componentTable ));
  76.     GXV_TRACE(( "offset to ligatureTable=0x%04x\n",
  77.                 optdata->ligatureTable ));
  78.   }
  79.  
  80.  
  81.   static void
  82.   gxv_mort_subtable_type2_subtable_setup( FT_UShort      table_size,
  83.                                           FT_UShort      classTable,
  84.                                           FT_UShort      stateArray,
  85.                                           FT_UShort      entryTable,
  86.                                           FT_UShort      *classTable_length_p,
  87.                                           FT_UShort      *stateArray_length_p,
  88.                                           FT_UShort      *entryTable_length_p,
  89.                                           GXV_Validator  valid )
  90.   {
  91.     FT_UShort  o[6];
  92.     FT_UShort  *l[6];
  93.     FT_UShort  buff[7];
  94.  
  95.     GXV_mort_subtable_type2_StateOptRecData  optdata =
  96.       (GXV_mort_subtable_type2_StateOptRecData)valid->statetable.optdata;
  97.  
  98.  
  99.     GXV_NAME_ENTER( "subtable boundaries setup" );
  100.  
  101.     o[0] = classTable;
  102.     o[1] = stateArray;
  103.     o[2] = entryTable;
  104.     o[3] = optdata->ligActionTable;
  105.     o[4] = optdata->componentTable;
  106.     o[5] = optdata->ligatureTable;
  107.     l[0] = classTable_length_p;
  108.     l[1] = stateArray_length_p;
  109.     l[2] = entryTable_length_p;
  110.     l[3] = &(optdata->ligActionTable_length);
  111.     l[4] = &(optdata->componentTable_length);
  112.     l[5] = &(optdata->ligatureTable_length);
  113.  
  114.     gxv_set_length_by_ushort_offset( o, l, buff, 6, table_size, valid );
  115.  
  116.     GXV_TRACE(( "classTable: offset=0x%04x length=0x%04x\n",
  117.                 classTable, *classTable_length_p ));
  118.     GXV_TRACE(( "stateArray: offset=0x%04x length=0x%04x\n",
  119.                 stateArray, *stateArray_length_p ));
  120.     GXV_TRACE(( "entryTable: offset=0x%04x length=0x%04x\n",
  121.                 entryTable, *entryTable_length_p ));
  122.     GXV_TRACE(( "ligActionTable: offset=0x%04x length=0x%04x\n",
  123.                 optdata->ligActionTable,
  124.                 optdata->ligActionTable_length ));
  125.     GXV_TRACE(( "componentTable: offset=0x%04x length=0x%04x\n",
  126.                 optdata->componentTable,
  127.                 optdata->componentTable_length ));
  128.     GXV_TRACE(( "ligatureTable:  offset=0x%04x length=0x%04x\n",
  129.                 optdata->ligatureTable,
  130.                 optdata->ligatureTable_length ));
  131.  
  132.     GXV_EXIT;
  133.   }
  134.  
  135.  
  136.   static void
  137.   gxv_mort_subtable_type2_ligActionOffset_validate(
  138.     FT_Bytes       table,
  139.     FT_UShort      ligActionOffset,
  140.     GXV_Validator  valid )
  141.   {
  142.     /* access ligActionTable */
  143.     GXV_mort_subtable_type2_StateOptRecData  optdata =
  144.       (GXV_mort_subtable_type2_StateOptRecData)valid->statetable.optdata;
  145.  
  146.     FT_Bytes lat_base  = table + optdata->ligActionTable;
  147.     FT_Bytes p         = table + ligActionOffset;
  148.     FT_Bytes lat_limit = lat_base + optdata->ligActionTable;
  149.  
  150.  
  151.     GXV_32BIT_ALIGNMENT_VALIDATE( ligActionOffset );
  152.     if ( p < lat_base )
  153.     {
  154.       GXV_TRACE(( "too short offset 0x%04x: p < lat_base (%d byte rewind)\n",
  155.                   ligActionOffset, lat_base - p ));
  156.  
  157.       /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */
  158.       GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
  159.     }
  160.     else if ( lat_limit < p )
  161.     {
  162.       GXV_TRACE(( "too large offset 0x%04x: lat_limit < p (%d byte overrun)\n",
  163.                   ligActionOffset, p - lat_limit ));
  164.  
  165.       /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */
  166.       GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
  167.     }
  168.     else
  169.     {
  170.       /* validate entry in ligActionTable */
  171.       FT_ULong   lig_action;
  172. #ifdef GXV_LOAD_UNUSED_VARS
  173.       FT_UShort  last;
  174.       FT_UShort  store;
  175. #endif
  176.       FT_ULong   offset;
  177.  
  178.  
  179.       lig_action = FT_NEXT_ULONG( p );
  180. #ifdef GXV_LOAD_UNUSED_VARS
  181.       last   = (FT_UShort)( ( lig_action >> 31 ) & 1 );
  182.       store  = (FT_UShort)( ( lig_action >> 30 ) & 1 );
  183. #endif
  184.  
  185.       /* Apple spec defines this offset as a word offset */
  186.       offset = lig_action & 0x3FFFFFFFUL;
  187.       if ( offset * 2 < optdata->ligatureTable )
  188.       {
  189.         GXV_TRACE(( "too short offset 0x%08x:"
  190.                     " 2 x offset < ligatureTable (%d byte rewind)\n",
  191.                      offset, optdata->ligatureTable - offset * 2 ));
  192.  
  193.         GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
  194.       } else if ( offset * 2 >
  195.                   optdata->ligatureTable + optdata->ligatureTable_length )
  196.       {
  197.         GXV_TRACE(( "too long offset 0x%08x:"
  198.                     " 2 x offset > ligatureTable + ligatureTable_length"
  199.                     " (%d byte overrun)\n",
  200.                      offset,
  201.                      optdata->ligatureTable + optdata->ligatureTable_length
  202.                      - offset * 2 ));
  203.  
  204.         GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
  205.       }
  206.     }
  207.   }
  208.  
  209.  
  210.   static void
  211.   gxv_mort_subtable_type2_entry_validate(
  212.     FT_Byte                         state,
  213.     FT_UShort                       flags,
  214.     GXV_StateTable_GlyphOffsetCPtr  glyphOffset_p,
  215.     FT_Bytes                        table,
  216.     FT_Bytes                        limit,
  217.     GXV_Validator                   valid )
  218.   {
  219. #ifdef GXV_LOAD_UNUSED_VARS
  220.     FT_UShort setComponent;
  221.     FT_UShort dontAdvance;
  222. #endif
  223.     FT_UShort offset;
  224.  
  225.     FT_UNUSED( state );
  226.     FT_UNUSED( glyphOffset_p );
  227.     FT_UNUSED( limit );
  228.  
  229.  
  230. #ifdef GXV_LOAD_UNUSED_VARS
  231.     setComponent = (FT_UShort)( ( flags >> 15 ) & 1 );
  232.     dontAdvance  = (FT_UShort)( ( flags >> 14 ) & 1 );
  233. #endif
  234.  
  235.     offset = (FT_UShort)( flags & 0x3FFFU );
  236.  
  237.     if ( 0 < offset )
  238.       gxv_mort_subtable_type2_ligActionOffset_validate( table, offset,
  239.                                                         valid );
  240.   }
  241.  
  242.  
  243.   static void
  244.   gxv_mort_subtable_type2_ligatureTable_validate( FT_Bytes       table,
  245.                                                   GXV_Validator  valid )
  246.   {
  247.     GXV_mort_subtable_type2_StateOptRecData  optdata =
  248.       (GXV_mort_subtable_type2_StateOptRecData)valid->statetable.optdata;
  249.  
  250.     FT_Bytes p     = table + optdata->ligatureTable;
  251.     FT_Bytes limit = table + optdata->ligatureTable
  252.                            + optdata->ligatureTable_length;
  253.  
  254.  
  255.     GXV_NAME_ENTER( "mort chain subtable type2 - substitutionTable" );
  256.     if ( 0 != optdata->ligatureTable )
  257.     {
  258.       /* Apple does not give specification of ligatureTable format */
  259.       while ( p < limit )
  260.       {
  261.         FT_UShort  lig_gid;
  262.  
  263.  
  264.         GXV_LIMIT_CHECK( 2 );
  265.         lig_gid = FT_NEXT_USHORT( p );
  266.  
  267.         if ( valid->face->num_glyphs < lig_gid )
  268.           GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
  269.       }
  270.     }
  271.     GXV_EXIT;
  272.   }
  273.  
  274.  
  275.   FT_LOCAL_DEF( void )
  276.   gxv_mort_subtable_type2_validate( FT_Bytes       table,
  277.                                     FT_Bytes       limit,
  278.                                     GXV_Validator  valid )
  279.   {
  280.     FT_Bytes  p = table;
  281.  
  282.     GXV_mort_subtable_type2_StateOptRec  lig_rec;
  283.  
  284.  
  285.     GXV_NAME_ENTER( "mort chain subtable type2 (Ligature Substitution)" );
  286.  
  287.     GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE2_HEADER_SIZE );
  288.  
  289.     valid->statetable.optdata =
  290.       &lig_rec;
  291.     valid->statetable.optdata_load_func =
  292.       gxv_mort_subtable_type2_opttable_load;
  293.     valid->statetable.subtable_setup_func =
  294.       gxv_mort_subtable_type2_subtable_setup;
  295.     valid->statetable.entry_glyphoffset_fmt =
  296.       GXV_GLYPHOFFSET_NONE;
  297.     valid->statetable.entry_validate_func =
  298.       gxv_mort_subtable_type2_entry_validate;
  299.  
  300.     gxv_StateTable_validate( p, limit, valid );
  301.  
  302.     p += valid->subtable_length;
  303.     gxv_mort_subtable_type2_ligatureTable_validate( table, valid );
  304.  
  305.     valid->subtable_length = p - table;
  306.  
  307.     GXV_EXIT;
  308.   }
  309.  
  310.  
  311. /* END */
  312.