Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ttcmap.c                                                               */
  4. /*                                                                         */
  5. /*    TrueType character mapping table (cmap) support (body).              */
  6. /*                                                                         */
  7. /*  Copyright 2002-2010, 2012, 2013 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 <ft2build.h>
  20. #include FT_INTERNAL_DEBUG_H
  21.  
  22. #include "sferrors.h"           /* must come before FT_INTERNAL_VALIDATE_H */
  23.  
  24. #include FT_INTERNAL_VALIDATE_H
  25. #include FT_INTERNAL_STREAM_H
  26. #include "ttload.h"
  27. #include "ttcmap.h"
  28. #include "sfntpic.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_ttcmap
  39.  
  40.  
  41. #define TT_PEEK_SHORT   FT_PEEK_SHORT
  42. #define TT_PEEK_USHORT  FT_PEEK_USHORT
  43. #define TT_PEEK_UINT24  FT_PEEK_UOFF3
  44. #define TT_PEEK_LONG    FT_PEEK_LONG
  45. #define TT_PEEK_ULONG   FT_PEEK_ULONG
  46.  
  47. #define TT_NEXT_SHORT   FT_NEXT_SHORT
  48. #define TT_NEXT_USHORT  FT_NEXT_USHORT
  49. #define TT_NEXT_UINT24  FT_NEXT_UOFF3
  50. #define TT_NEXT_LONG    FT_NEXT_LONG
  51. #define TT_NEXT_ULONG   FT_NEXT_ULONG
  52.  
  53.  
  54.   FT_CALLBACK_DEF( FT_Error )
  55.   tt_cmap_init( TT_CMap   cmap,
  56.                 FT_Byte*  table )
  57.   {
  58.     cmap->data = table;
  59.     return FT_Err_Ok;
  60.   }
  61.  
  62.  
  63.   /*************************************************************************/
  64.   /*************************************************************************/
  65.   /*****                                                               *****/
  66.   /*****                           FORMAT 0                            *****/
  67.   /*****                                                               *****/
  68.   /*************************************************************************/
  69.   /*************************************************************************/
  70.  
  71.   /*************************************************************************/
  72.   /*                                                                       */
  73.   /* TABLE OVERVIEW                                                        */
  74.   /* --------------                                                        */
  75.   /*                                                                       */
  76.   /*   NAME        OFFSET         TYPE          DESCRIPTION                */
  77.   /*                                                                       */
  78.   /*   format      0              USHORT        must be 0                  */
  79.   /*   length      2              USHORT        table length in bytes      */
  80.   /*   language    4              USHORT        Mac language code          */
  81.   /*   glyph_ids   6              BYTE[256]     array of glyph indices     */
  82.   /*               262                                                     */
  83.   /*                                                                       */
  84.  
  85. #ifdef TT_CONFIG_CMAP_FORMAT_0
  86.  
  87.   FT_CALLBACK_DEF( FT_Error )
  88.   tt_cmap0_validate( FT_Byte*      table,
  89.                      FT_Validator  valid )
  90.   {
  91.     FT_Byte*  p      = table + 2;
  92.     FT_UInt   length = TT_NEXT_USHORT( p );
  93.  
  94.  
  95.     if ( table + length > valid->limit || length < 262 )
  96.       FT_INVALID_TOO_SHORT;
  97.  
  98.     /* check glyph indices whenever necessary */
  99.     if ( valid->level >= FT_VALIDATE_TIGHT )
  100.     {
  101.       FT_UInt  n, idx;
  102.  
  103.  
  104.       p = table + 6;
  105.       for ( n = 0; n < 256; n++ )
  106.       {
  107.         idx = *p++;
  108.         if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
  109.           FT_INVALID_GLYPH_ID;
  110.       }
  111.     }
  112.  
  113.     return FT_Err_Ok;
  114.   }
  115.  
  116.  
  117.   FT_CALLBACK_DEF( FT_UInt )
  118.   tt_cmap0_char_index( TT_CMap    cmap,
  119.                        FT_UInt32  char_code )
  120.   {
  121.     FT_Byte*  table = cmap->data;
  122.  
  123.  
  124.     return char_code < 256 ? table[6 + char_code] : 0;
  125.   }
  126.  
  127.  
  128.   FT_CALLBACK_DEF( FT_UInt32 )
  129.   tt_cmap0_char_next( TT_CMap     cmap,
  130.                       FT_UInt32  *pchar_code )
  131.   {
  132.     FT_Byte*   table    = cmap->data;
  133.     FT_UInt32  charcode = *pchar_code;
  134.     FT_UInt32  result   = 0;
  135.     FT_UInt    gindex   = 0;
  136.  
  137.  
  138.     table += 6;  /* go to glyph IDs */
  139.     while ( ++charcode < 256 )
  140.     {
  141.       gindex = table[charcode];
  142.       if ( gindex != 0 )
  143.       {
  144.         result = charcode;
  145.         break;
  146.       }
  147.     }
  148.  
  149.     *pchar_code = result;
  150.     return gindex;
  151.   }
  152.  
  153.  
  154.   FT_CALLBACK_DEF( FT_Error )
  155.   tt_cmap0_get_info( TT_CMap       cmap,
  156.                      TT_CMapInfo  *cmap_info )
  157.   {
  158.     FT_Byte*  p = cmap->data + 4;
  159.  
  160.  
  161.     cmap_info->format   = 0;
  162.     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
  163.  
  164.     return FT_Err_Ok;
  165.   }
  166.  
  167.  
  168.   FT_DEFINE_TT_CMAP(
  169.     tt_cmap0_class_rec,
  170.     sizeof ( TT_CMapRec ),
  171.  
  172.     (FT_CMap_InitFunc)     tt_cmap_init,
  173.     (FT_CMap_DoneFunc)     NULL,
  174.     (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
  175.     (FT_CMap_CharNextFunc) tt_cmap0_char_next,
  176.  
  177.     NULL,
  178.     NULL,
  179.     NULL,
  180.     NULL,
  181.     NULL,
  182.  
  183.     0,
  184.     (TT_CMap_ValidateFunc)tt_cmap0_validate,
  185.     (TT_CMap_Info_GetFunc)tt_cmap0_get_info )
  186.  
  187. #endif /* TT_CONFIG_CMAP_FORMAT_0 */
  188.  
  189.  
  190.   /*************************************************************************/
  191.   /*************************************************************************/
  192.   /*****                                                               *****/
  193.   /*****                          FORMAT 2                             *****/
  194.   /*****                                                               *****/
  195.   /***** This is used for certain CJK encodings that encode text in a  *****/
  196.   /***** mixed 8/16 bits encoding along the following lines:           *****/
  197.   /*****                                                               *****/
  198.   /***** * Certain byte values correspond to an 8-bit character code   *****/
  199.   /*****   (typically in the range 0..127 for ASCII compatibility).    *****/
  200.   /*****                                                               *****/
  201.   /***** * Certain byte values signal the first byte of a 2-byte       *****/
  202.   /*****   character code (but these values are also valid as the      *****/
  203.   /*****   second byte of a 2-byte character).                         *****/
  204.   /*****                                                               *****/
  205.   /***** The following charmap lookup and iteration functions all      *****/
  206.   /***** assume that the value "charcode" correspond to following:     *****/
  207.   /*****                                                               *****/
  208.   /*****   - For one byte characters, "charcode" is simply the         *****/
  209.   /*****     character code.                                           *****/
  210.   /*****                                                               *****/
  211.   /*****   - For two byte characters, "charcode" is the 2-byte         *****/
  212.   /*****     character code in big endian format.  More exactly:       *****/
  213.   /*****                                                               *****/
  214.   /*****       (charcode >> 8)    is the first byte value              *****/
  215.   /*****       (charcode & 0xFF)  is the second byte value             *****/
  216.   /*****                                                               *****/
  217.   /***** Note that not all values of "charcode" are valid according    *****/
  218.   /***** to these rules, and the function moderately check the         *****/
  219.   /***** arguments.                                                    *****/
  220.   /*****                                                               *****/
  221.   /*************************************************************************/
  222.   /*************************************************************************/
  223.  
  224.   /*************************************************************************/
  225.   /*                                                                       */
  226.   /* TABLE OVERVIEW                                                        */
  227.   /* --------------                                                        */
  228.   /*                                                                       */
  229.   /*   NAME        OFFSET         TYPE            DESCRIPTION              */
  230.   /*                                                                       */
  231.   /*   format      0              USHORT          must be 2                */
  232.   /*   length      2              USHORT          table length in bytes    */
  233.   /*   language    4              USHORT          Mac language code        */
  234.   /*   keys        6              USHORT[256]     sub-header keys          */
  235.   /*   subs        518            SUBHEAD[NSUBS]  sub-headers array        */
  236.   /*   glyph_ids   518+NSUB*8     USHORT[]        glyph ID array           */
  237.   /*                                                                       */
  238.   /* The `keys' table is used to map charcode high-bytes to sub-headers.   */
  239.   /* The value of `NSUBS' is the number of sub-headers defined in the      */
  240.   /* table and is computed by finding the maximum of the `keys' table.     */
  241.   /*                                                                       */
  242.   /* Note that for any n, `keys[n]' is a byte offset within the `subs'     */
  243.   /* table, i.e., it is the corresponding sub-header index multiplied      */
  244.   /* by 8.                                                                 */
  245.   /*                                                                       */
  246.   /* Each sub-header has the following format:                             */
  247.   /*                                                                       */
  248.   /*   NAME        OFFSET      TYPE            DESCRIPTION                 */
  249.   /*                                                                       */
  250.   /*   first       0           USHORT          first valid low-byte        */
  251.   /*   count       2           USHORT          number of valid low-bytes   */
  252.   /*   delta       4           SHORT           see below                   */
  253.   /*   offset      6           USHORT          see below                   */
  254.   /*                                                                       */
  255.   /* A sub-header defines, for each high-byte, the range of valid          */
  256.   /* low-bytes within the charmap.  Note that the range defined by `first' */
  257.   /* and `count' must be completely included in the interval [0..255]      */
  258.   /* according to the specification.                                       */
  259.   /*                                                                       */
  260.   /* If a character code is contained within a given sub-header, then      */
  261.   /* mapping it to a glyph index is done as follows:                       */
  262.   /*                                                                       */
  263.   /* * The value of `offset' is read.  This is a _byte_ distance from the  */
  264.   /*   location of the `offset' field itself into a slice of the           */
  265.   /*   `glyph_ids' table.  Let's call it `slice' (it is a USHORT[] too).   */
  266.   /*                                                                       */
  267.   /* * The value `slice[char.lo - first]' is read.  If it is 0, there is   */
  268.   /*   no glyph for the charcode.  Otherwise, the value of `delta' is      */
  269.   /*   added to it (modulo 65536) to form a new glyph index.               */
  270.   /*                                                                       */
  271.   /* It is up to the validation routine to check that all offsets fall     */
  272.   /* within the glyph IDs table (and not within the `subs' table itself or */
  273.   /* outside of the CMap).                                                 */
  274.   /*                                                                       */
  275.  
  276. #ifdef TT_CONFIG_CMAP_FORMAT_2
  277.  
  278.   FT_CALLBACK_DEF( FT_Error )
  279.   tt_cmap2_validate( FT_Byte*      table,
  280.                      FT_Validator  valid )
  281.   {
  282.     FT_Byte*  p      = table + 2;           /* skip format */
  283.     FT_UInt   length = TT_PEEK_USHORT( p );
  284.     FT_UInt   n, max_subs;
  285.     FT_Byte*  keys;                         /* keys table */
  286.     FT_Byte*  subs;                         /* sub-headers */
  287.     FT_Byte*  glyph_ids;                    /* glyph ID array */
  288.  
  289.  
  290.     if ( table + length > valid->limit || length < 6 + 512 )
  291.       FT_INVALID_TOO_SHORT;
  292.  
  293.     keys = table + 6;
  294.  
  295.     /* parse keys to compute sub-headers count */
  296.     p        = keys;
  297.     max_subs = 0;
  298.     for ( n = 0; n < 256; n++ )
  299.     {
  300.       FT_UInt  idx = TT_NEXT_USHORT( p );
  301.  
  302.  
  303.       /* value must be multiple of 8 */
  304.       if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
  305.         FT_INVALID_DATA;
  306.  
  307.       idx >>= 3;
  308.  
  309.       if ( idx > max_subs )
  310.         max_subs = idx;
  311.     }
  312.  
  313.     FT_ASSERT( p == table + 518 );
  314.  
  315.     subs      = p;
  316.     glyph_ids = subs + (max_subs + 1) * 8;
  317.     if ( glyph_ids > valid->limit )
  318.       FT_INVALID_TOO_SHORT;
  319.  
  320.     /* parse sub-headers */
  321.     for ( n = 0; n <= max_subs; n++ )
  322.     {
  323.       FT_UInt   first_code, code_count, offset;
  324.       FT_Int    delta;
  325.       FT_Byte*  ids;
  326.  
  327.  
  328.       first_code = TT_NEXT_USHORT( p );
  329.       code_count = TT_NEXT_USHORT( p );
  330.       delta      = TT_NEXT_SHORT( p );
  331.       offset     = TT_NEXT_USHORT( p );
  332.  
  333.       /* many Dynalab fonts have empty sub-headers */
  334.       if ( code_count == 0 )
  335.         continue;
  336.  
  337.       /* check range within 0..255 */
  338.       if ( valid->level >= FT_VALIDATE_PARANOID )
  339.       {
  340.         if ( first_code >= 256 || first_code + code_count > 256 )
  341.           FT_INVALID_DATA;
  342.       }
  343.  
  344.       /* check offset */
  345.       if ( offset != 0 )
  346.       {
  347.         ids = p - 2 + offset;
  348.         if ( ids < glyph_ids || ids + code_count*2 > table + length )
  349.           FT_INVALID_OFFSET;
  350.  
  351.         /* check glyph IDs */
  352.         if ( valid->level >= FT_VALIDATE_TIGHT )
  353.         {
  354.           FT_Byte*  limit = p + code_count * 2;
  355.           FT_UInt   idx;
  356.  
  357.  
  358.           for ( ; p < limit; )
  359.           {
  360.             idx = TT_NEXT_USHORT( p );
  361.             if ( idx != 0 )
  362.             {
  363.               idx = ( idx + delta ) & 0xFFFFU;
  364.               if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
  365.                 FT_INVALID_GLYPH_ID;
  366.             }
  367.           }
  368.         }
  369.       }
  370.     }
  371.  
  372.     return FT_Err_Ok;
  373.   }
  374.  
  375.  
  376.   /* return sub header corresponding to a given character code */
  377.   /* NULL on invalid charcode                                  */
  378.   static FT_Byte*
  379.   tt_cmap2_get_subheader( FT_Byte*   table,
  380.                           FT_UInt32  char_code )
  381.   {
  382.     FT_Byte*  result = NULL;
  383.  
  384.  
  385.     if ( char_code < 0x10000UL )
  386.     {
  387.       FT_UInt   char_lo = (FT_UInt)( char_code & 0xFF );
  388.       FT_UInt   char_hi = (FT_UInt)( char_code >> 8 );
  389.       FT_Byte*  p       = table + 6;    /* keys table */
  390.       FT_Byte*  subs    = table + 518;  /* subheaders table */
  391.       FT_Byte*  sub;
  392.  
  393.  
  394.       if ( char_hi == 0 )
  395.       {
  396.         /* an 8-bit character code -- we use subHeader 0 in this case */
  397.         /* to test whether the character code is in the charmap       */
  398.         /*                                                            */
  399.         sub = subs;  /* jump to first sub-header */
  400.  
  401.         /* check that the sub-header for this byte is 0, which */
  402.         /* indicates that it is really a valid one-byte value  */
  403.         /* Otherwise, return 0                                 */
  404.         /*                                                     */
  405.         p += char_lo * 2;
  406.         if ( TT_PEEK_USHORT( p ) != 0 )
  407.           goto Exit;
  408.       }
  409.       else
  410.       {
  411.         /* a 16-bit character code */
  412.  
  413.         /* jump to key entry  */
  414.         p  += char_hi * 2;
  415.         /* jump to sub-header */
  416.         sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) );
  417.  
  418.         /* check that the high byte isn't a valid one-byte value */
  419.         if ( sub == subs )
  420.           goto Exit;
  421.       }
  422.       result = sub;
  423.     }
  424.   Exit:
  425.     return result;
  426.   }
  427.  
  428.  
  429.   FT_CALLBACK_DEF( FT_UInt )
  430.   tt_cmap2_char_index( TT_CMap    cmap,
  431.                        FT_UInt32  char_code )
  432.   {
  433.     FT_Byte*  table   = cmap->data;
  434.     FT_UInt   result  = 0;
  435.     FT_Byte*  subheader;
  436.  
  437.  
  438.     subheader = tt_cmap2_get_subheader( table, char_code );
  439.     if ( subheader )
  440.     {
  441.       FT_Byte*  p   = subheader;
  442.       FT_UInt   idx = (FT_UInt)(char_code & 0xFF);
  443.       FT_UInt   start, count;
  444.       FT_Int    delta;
  445.       FT_UInt   offset;
  446.  
  447.  
  448.       start  = TT_NEXT_USHORT( p );
  449.       count  = TT_NEXT_USHORT( p );
  450.       delta  = TT_NEXT_SHORT ( p );
  451.       offset = TT_PEEK_USHORT( p );
  452.  
  453.       idx -= start;
  454.       if ( idx < count && offset != 0 )
  455.       {
  456.         p  += offset + 2 * idx;
  457.         idx = TT_PEEK_USHORT( p );
  458.  
  459.         if ( idx != 0 )
  460.           result = (FT_UInt)( idx + delta ) & 0xFFFFU;
  461.       }
  462.     }
  463.     return result;
  464.   }
  465.  
  466.  
  467.   FT_CALLBACK_DEF( FT_UInt32 )
  468.   tt_cmap2_char_next( TT_CMap     cmap,
  469.                       FT_UInt32  *pcharcode )
  470.   {
  471.     FT_Byte*   table    = cmap->data;
  472.     FT_UInt    gindex   = 0;
  473.     FT_UInt32  result   = 0;
  474.     FT_UInt32  charcode = *pcharcode + 1;
  475.     FT_Byte*   subheader;
  476.  
  477.  
  478.     while ( charcode < 0x10000UL )
  479.     {
  480.       subheader = tt_cmap2_get_subheader( table, charcode );
  481.       if ( subheader )
  482.       {
  483.         FT_Byte*  p       = subheader;
  484.         FT_UInt   start   = TT_NEXT_USHORT( p );
  485.         FT_UInt   count   = TT_NEXT_USHORT( p );
  486.         FT_Int    delta   = TT_NEXT_SHORT ( p );
  487.         FT_UInt   offset  = TT_PEEK_USHORT( p );
  488.         FT_UInt   char_lo = (FT_UInt)( charcode & 0xFF );
  489.         FT_UInt   pos, idx;
  490.  
  491.  
  492.         if ( offset == 0 )
  493.           goto Next_SubHeader;
  494.  
  495.         if ( char_lo < start )
  496.         {
  497.           char_lo = start;
  498.           pos     = 0;
  499.         }
  500.         else
  501.           pos = (FT_UInt)( char_lo - start );
  502.  
  503.         p       += offset + pos * 2;
  504.         charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo;
  505.  
  506.         for ( ; pos < count; pos++, charcode++ )
  507.         {
  508.           idx = TT_NEXT_USHORT( p );
  509.  
  510.           if ( idx != 0 )
  511.           {
  512.             gindex = ( idx + delta ) & 0xFFFFU;
  513.             if ( gindex != 0 )
  514.             {
  515.               result = charcode;
  516.               goto Exit;
  517.             }
  518.           }
  519.         }
  520.       }
  521.  
  522.       /* jump to next sub-header, i.e. higher byte value */
  523.     Next_SubHeader:
  524.       charcode = FT_PAD_FLOOR( charcode, 256 ) + 256;
  525.     }
  526.  
  527.   Exit:
  528.     *pcharcode = result;
  529.  
  530.     return gindex;
  531.   }
  532.  
  533.  
  534.   FT_CALLBACK_DEF( FT_Error )
  535.   tt_cmap2_get_info( TT_CMap       cmap,
  536.                      TT_CMapInfo  *cmap_info )
  537.   {
  538.     FT_Byte*  p = cmap->data + 4;
  539.  
  540.  
  541.     cmap_info->format   = 2;
  542.     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
  543.  
  544.     return FT_Err_Ok;
  545.   }
  546.  
  547.  
  548.   FT_DEFINE_TT_CMAP(
  549.     tt_cmap2_class_rec,
  550.     sizeof ( TT_CMapRec ),
  551.  
  552.     (FT_CMap_InitFunc)     tt_cmap_init,
  553.     (FT_CMap_DoneFunc)     NULL,
  554.     (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
  555.     (FT_CMap_CharNextFunc) tt_cmap2_char_next,
  556.  
  557.     NULL,
  558.     NULL,
  559.     NULL,
  560.     NULL,
  561.     NULL,
  562.  
  563.     2,
  564.     (TT_CMap_ValidateFunc)tt_cmap2_validate,
  565.     (TT_CMap_Info_GetFunc)tt_cmap2_get_info )
  566.  
  567. #endif /* TT_CONFIG_CMAP_FORMAT_2 */
  568.  
  569.  
  570.   /*************************************************************************/
  571.   /*************************************************************************/
  572.   /*****                                                               *****/
  573.   /*****                           FORMAT 4                            *****/
  574.   /*****                                                               *****/
  575.   /*************************************************************************/
  576.   /*************************************************************************/
  577.  
  578.   /*************************************************************************/
  579.   /*                                                                       */
  580.   /* TABLE OVERVIEW                                                        */
  581.   /* --------------                                                        */
  582.   /*                                                                       */
  583.   /*   NAME          OFFSET         TYPE              DESCRIPTION          */
  584.   /*                                                                       */
  585.   /*   format        0              USHORT            must be 4            */
  586.   /*   length        2              USHORT            table length         */
  587.   /*                                                  in bytes             */
  588.   /*   language      4              USHORT            Mac language code    */
  589.   /*                                                                       */
  590.   /*   segCountX2    6              USHORT            2*NUM_SEGS           */
  591.   /*   searchRange   8              USHORT            2*(1 << LOG_SEGS)    */
  592.   /*   entrySelector 10             USHORT            LOG_SEGS             */
  593.   /*   rangeShift    12             USHORT            segCountX2 -         */
  594.   /*                                                    searchRange        */
  595.   /*                                                                       */
  596.   /*   endCount      14             USHORT[NUM_SEGS]  end charcode for     */
  597.   /*                                                  each segment; last   */
  598.   /*                                                  is 0xFFFF            */
  599.   /*                                                                       */
  600.   /*   pad           14+NUM_SEGS*2  USHORT            padding              */
  601.   /*                                                                       */
  602.   /*   startCount    16+NUM_SEGS*2  USHORT[NUM_SEGS]  first charcode for   */
  603.   /*                                                  each segment         */
  604.   /*                                                                       */
  605.   /*   idDelta       16+NUM_SEGS*4  SHORT[NUM_SEGS]   delta for each       */
  606.   /*                                                  segment              */
  607.   /*   idOffset      16+NUM_SEGS*6  SHORT[NUM_SEGS]   range offset for     */
  608.   /*                                                  each segment; can be */
  609.   /*                                                  zero                 */
  610.   /*                                                                       */
  611.   /*   glyphIds      16+NUM_SEGS*8  USHORT[]          array of glyph ID    */
  612.   /*                                                  ranges               */
  613.   /*                                                                       */
  614.   /* Character codes are modelled by a series of ordered (increasing)      */
  615.   /* intervals called segments.  Each segment has start and end codes,     */
  616.   /* provided by the `startCount' and `endCount' arrays.  Segments must    */
  617.   /* not overlap, and the last segment should always contain the value     */
  618.   /* 0xFFFF for `endCount'.                                                */
  619.   /*                                                                       */
  620.   /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
  621.   /* ignored (they are traces of over-engineering in the TrueType          */
  622.   /* specification).                                                       */
  623.   /*                                                                       */
  624.   /* Each segment also has a signed `delta', as well as an optional offset */
  625.   /* within the `glyphIds' table.                                          */
  626.   /*                                                                       */
  627.   /* If a segment's idOffset is 0, the glyph index corresponding to any    */
  628.   /* charcode within the segment is obtained by adding the value of        */
  629.   /* `idDelta' directly to the charcode, modulo 65536.                     */
  630.   /*                                                                       */
  631.   /* Otherwise, a glyph index is taken from the glyph IDs sub-array for    */
  632.   /* the segment, and the value of `idDelta' is added to it.               */
  633.   /*                                                                       */
  634.   /*                                                                       */
  635.   /* Finally, note that a lot of fonts contain an invalid last segment,    */
  636.   /* where `start' and `end' are correctly set to 0xFFFF but both `delta'  */
  637.   /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with     */
  638.   /* OpenOffice.org).  We need special code to deal with them correctly.   */
  639.   /*                                                                       */
  640.  
  641. #ifdef TT_CONFIG_CMAP_FORMAT_4
  642.  
  643.   typedef struct  TT_CMap4Rec_
  644.   {
  645.     TT_CMapRec  cmap;
  646.     FT_UInt32   cur_charcode;   /* current charcode */
  647.     FT_UInt     cur_gindex;     /* current glyph index */
  648.  
  649.     FT_UInt     num_ranges;
  650.     FT_UInt     cur_range;
  651.     FT_UInt     cur_start;
  652.     FT_UInt     cur_end;
  653.     FT_Int      cur_delta;
  654.     FT_Byte*    cur_values;
  655.  
  656.   } TT_CMap4Rec, *TT_CMap4;
  657.  
  658.  
  659.   FT_CALLBACK_DEF( FT_Error )
  660.   tt_cmap4_init( TT_CMap4  cmap,
  661.                  FT_Byte*  table )
  662.   {
  663.     FT_Byte*  p;
  664.  
  665.  
  666.     cmap->cmap.data    = table;
  667.  
  668.     p                  = table + 6;
  669.     cmap->num_ranges   = FT_PEEK_USHORT( p ) >> 1;
  670.     cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
  671.     cmap->cur_gindex   = 0;
  672.  
  673.     return FT_Err_Ok;
  674.   }
  675.  
  676.  
  677.   static FT_Int
  678.   tt_cmap4_set_range( TT_CMap4  cmap,
  679.                       FT_UInt   range_index )
  680.   {
  681.     FT_Byte*  table = cmap->cmap.data;
  682.     FT_Byte*  p;
  683.     FT_UInt   num_ranges = cmap->num_ranges;
  684.  
  685.  
  686.     while ( range_index < num_ranges )
  687.     {
  688.       FT_UInt  offset;
  689.  
  690.  
  691.       p             = table + 14 + range_index * 2;
  692.       cmap->cur_end = FT_PEEK_USHORT( p );
  693.  
  694.       p              += 2 + num_ranges * 2;
  695.       cmap->cur_start = FT_PEEK_USHORT( p );
  696.  
  697.       p              += num_ranges * 2;
  698.       cmap->cur_delta = FT_PEEK_SHORT( p );
  699.  
  700.       p     += num_ranges * 2;
  701.       offset = FT_PEEK_USHORT( p );
  702.  
  703.       /* some fonts have an incorrect last segment; */
  704.       /* we have to catch it                        */
  705.       if ( range_index     >= num_ranges - 1 &&
  706.            cmap->cur_start == 0xFFFFU        &&
  707.            cmap->cur_end   == 0xFFFFU        )
  708.       {
  709.         TT_Face   face  = (TT_Face)cmap->cmap.cmap.charmap.face;
  710.         FT_Byte*  limit = face->cmap_table + face->cmap_size;
  711.  
  712.  
  713.         if ( offset && p + offset + 2 > limit )
  714.         {
  715.           cmap->cur_delta = 1;
  716.           offset          = 0;
  717.         }
  718.       }
  719.  
  720.       if ( offset != 0xFFFFU )
  721.       {
  722.         cmap->cur_values = offset ? p + offset : NULL;
  723.         cmap->cur_range  = range_index;
  724.         return 0;
  725.       }
  726.  
  727.       /* we skip empty segments */
  728.       range_index++;
  729.     }
  730.  
  731.     return -1;
  732.   }
  733.  
  734.  
  735.   /* search the index of the charcode next to cmap->cur_charcode; */
  736.   /* caller should call tt_cmap4_set_range with proper range      */
  737.   /* before calling this function                                 */
  738.   /*                                                              */
  739.   static void
  740.   tt_cmap4_next( TT_CMap4  cmap )
  741.   {
  742.     FT_UInt  charcode;
  743.  
  744.  
  745.     if ( cmap->cur_charcode >= 0xFFFFUL )
  746.       goto Fail;
  747.  
  748.     charcode = (FT_UInt)cmap->cur_charcode + 1;
  749.  
  750.     if ( charcode < cmap->cur_start )
  751.       charcode = cmap->cur_start;
  752.  
  753.     for ( ;; )
  754.     {
  755.       FT_Byte*  values = cmap->cur_values;
  756.       FT_UInt   end    = cmap->cur_end;
  757.       FT_Int    delta  = cmap->cur_delta;
  758.  
  759.  
  760.       if ( charcode <= end )
  761.       {
  762.         if ( values )
  763.         {
  764.           FT_Byte*  p = values + 2 * ( charcode - cmap->cur_start );
  765.  
  766.  
  767.           do
  768.           {
  769.             FT_UInt  gindex = FT_NEXT_USHORT( p );
  770.  
  771.  
  772.             if ( gindex != 0 )
  773.             {
  774.               gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU );
  775.               if ( gindex != 0 )
  776.               {
  777.                 cmap->cur_charcode = charcode;
  778.                 cmap->cur_gindex   = gindex;
  779.                 return;
  780.               }
  781.             }
  782.           } while ( ++charcode <= end );
  783.         }
  784.         else
  785.         {
  786.           do
  787.           {
  788.             FT_UInt  gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU );
  789.  
  790.  
  791.             if ( gindex != 0 )
  792.             {
  793.               cmap->cur_charcode = charcode;
  794.               cmap->cur_gindex   = gindex;
  795.               return;
  796.             }
  797.           } while ( ++charcode <= end );
  798.         }
  799.       }
  800.  
  801.       /* we need to find another range */
  802.       if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )
  803.         break;
  804.  
  805.       if ( charcode < cmap->cur_start )
  806.         charcode = cmap->cur_start;
  807.     }
  808.  
  809.   Fail:
  810.     cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
  811.     cmap->cur_gindex   = 0;
  812.   }
  813.  
  814.  
  815.   FT_CALLBACK_DEF( FT_Error )
  816.   tt_cmap4_validate( FT_Byte*      table,
  817.                      FT_Validator  valid )
  818.   {
  819.     FT_Byte*  p      = table + 2;               /* skip format */
  820.     FT_UInt   length = TT_NEXT_USHORT( p );
  821.     FT_Byte   *ends, *starts, *offsets, *deltas, *glyph_ids;
  822.     FT_UInt   num_segs;
  823.     FT_Error  error = FT_Err_Ok;
  824.  
  825.  
  826.     if ( length < 16 )
  827.       FT_INVALID_TOO_SHORT;
  828.  
  829.     /* in certain fonts, the `length' field is invalid and goes */
  830.     /* out of bound.  We try to correct this here...            */
  831.     if ( table + length > valid->limit )
  832.     {
  833.       if ( valid->level >= FT_VALIDATE_TIGHT )
  834.         FT_INVALID_TOO_SHORT;
  835.  
  836.       length = (FT_UInt)( valid->limit - table );
  837.     }
  838.  
  839.     p        = table + 6;
  840.     num_segs = TT_NEXT_USHORT( p );   /* read segCountX2 */
  841.  
  842.     if ( valid->level >= FT_VALIDATE_PARANOID )
  843.     {
  844.       /* check that we have an even value here */
  845.       if ( num_segs & 1 )
  846.         FT_INVALID_DATA;
  847.     }
  848.  
  849.     num_segs /= 2;
  850.  
  851.     if ( length < 16 + num_segs * 2 * 4 )
  852.       FT_INVALID_TOO_SHORT;
  853.  
  854.     /* check the search parameters - even though we never use them */
  855.     /*                                                             */
  856.     if ( valid->level >= FT_VALIDATE_PARANOID )
  857.     {
  858.       /* check the values of `searchRange', `entrySelector', `rangeShift' */
  859.       FT_UInt  search_range   = TT_NEXT_USHORT( p );
  860.       FT_UInt  entry_selector = TT_NEXT_USHORT( p );
  861.       FT_UInt  range_shift    = TT_NEXT_USHORT( p );
  862.  
  863.  
  864.       if ( ( search_range | range_shift ) & 1 )  /* must be even values */
  865.         FT_INVALID_DATA;
  866.  
  867.       search_range /= 2;
  868.       range_shift  /= 2;
  869.  
  870.       /* `search range' is the greatest power of 2 that is <= num_segs */
  871.  
  872.       if ( search_range                > num_segs                 ||
  873.            search_range * 2            < num_segs                 ||
  874.            search_range + range_shift != num_segs                 ||
  875.            search_range               != ( 1U << entry_selector ) )
  876.         FT_INVALID_DATA;
  877.     }
  878.  
  879.     ends      = table   + 14;
  880.     starts    = table   + 16 + num_segs * 2;
  881.     deltas    = starts  + num_segs * 2;
  882.     offsets   = deltas  + num_segs * 2;
  883.     glyph_ids = offsets + num_segs * 2;
  884.  
  885.     /* check last segment; its end count value must be 0xFFFF */
  886.     if ( valid->level >= FT_VALIDATE_PARANOID )
  887.     {
  888.       p = ends + ( num_segs - 1 ) * 2;
  889.       if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
  890.         FT_INVALID_DATA;
  891.     }
  892.  
  893.     {
  894.       FT_UInt   start, end, offset, n;
  895.       FT_UInt   last_start = 0, last_end = 0;
  896.       FT_Int    delta;
  897.       FT_Byte*  p_start   = starts;
  898.       FT_Byte*  p_end     = ends;
  899.       FT_Byte*  p_delta   = deltas;
  900.       FT_Byte*  p_offset  = offsets;
  901.  
  902.  
  903.       for ( n = 0; n < num_segs; n++ )
  904.       {
  905.         p      = p_offset;
  906.         start  = TT_NEXT_USHORT( p_start );
  907.         end    = TT_NEXT_USHORT( p_end );
  908.         delta  = TT_NEXT_SHORT( p_delta );
  909.         offset = TT_NEXT_USHORT( p_offset );
  910.  
  911.         if ( start > end )
  912.           FT_INVALID_DATA;
  913.  
  914.         /* this test should be performed at default validation level; */
  915.         /* unfortunately, some popular Asian fonts have overlapping   */
  916.         /* ranges in their charmaps                                   */
  917.         /*                                                            */
  918.         if ( start <= last_end && n > 0 )
  919.         {
  920.           if ( valid->level >= FT_VALIDATE_TIGHT )
  921.             FT_INVALID_DATA;
  922.           else
  923.           {
  924.             /* allow overlapping segments, provided their start points */
  925.             /* and end points, respectively, are in ascending order    */
  926.             /*                                                         */
  927.             if ( last_start > start || last_end > end )
  928.               error |= TT_CMAP_FLAG_UNSORTED;
  929.             else
  930.               error |= TT_CMAP_FLAG_OVERLAPPING;
  931.           }
  932.         }
  933.  
  934.         if ( offset && offset != 0xFFFFU )
  935.         {
  936.           p += offset;  /* start of glyph ID array */
  937.  
  938.           /* check that we point within the glyph IDs table only */
  939.           if ( valid->level >= FT_VALIDATE_TIGHT )
  940.           {
  941.             if ( p < glyph_ids                                ||
  942.                  p + ( end - start + 1 ) * 2 > table + length )
  943.               FT_INVALID_DATA;
  944.           }
  945.           /* Some fonts handle the last segment incorrectly.  In */
  946.           /* theory, 0xFFFF might point to an ordinary glyph --  */
  947.           /* a cmap 4 is versatile and could be used for any     */
  948.           /* encoding, not only Unicode.  However, reality shows */
  949.           /* that far too many fonts are sloppy and incorrectly  */
  950.           /* set all fields but `start' and `end' for the last   */
  951.           /* segment if it contains only a single character.     */
  952.           /*                                                     */
  953.           /* We thus omit the test here, delaying it to the      */
  954.           /* routines which actually access the cmap.            */
  955.           else if ( n != num_segs - 1                       ||
  956.                     !( start == 0xFFFFU && end == 0xFFFFU ) )
  957.           {
  958.             if ( p < glyph_ids                              ||
  959.                  p + ( end - start + 1 ) * 2 > valid->limit )
  960.               FT_INVALID_DATA;
  961.           }
  962.  
  963.           /* check glyph indices within the segment range */
  964.           if ( valid->level >= FT_VALIDATE_TIGHT )
  965.           {
  966.             FT_UInt  i, idx;
  967.  
  968.  
  969.             for ( i = start; i < end; i++ )
  970.             {
  971.               idx = FT_NEXT_USHORT( p );
  972.               if ( idx != 0 )
  973.               {
  974.                 idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
  975.  
  976.                 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
  977.                   FT_INVALID_GLYPH_ID;
  978.               }
  979.             }
  980.           }
  981.         }
  982.         else if ( offset == 0xFFFFU )
  983.         {
  984.           /* some fonts (erroneously?) use a range offset of 0xFFFF */
  985.           /* to mean missing glyph in cmap table                    */
  986.           /*                                                        */
  987.           if ( valid->level >= FT_VALIDATE_PARANOID    ||
  988.                n != num_segs - 1                       ||
  989.                !( start == 0xFFFFU && end == 0xFFFFU ) )
  990.             FT_INVALID_DATA;
  991.         }
  992.  
  993.         last_start = start;
  994.         last_end   = end;
  995.       }
  996.     }
  997.  
  998.     return error;
  999.   }
  1000.  
  1001.  
  1002.   static FT_UInt
  1003.   tt_cmap4_char_map_linear( TT_CMap     cmap,
  1004.                             FT_UInt32*  pcharcode,
  1005.                             FT_Bool     next )
  1006.   {
  1007.     FT_UInt    num_segs2, start, end, offset;
  1008.     FT_Int     delta;
  1009.     FT_UInt    i, num_segs;
  1010.     FT_UInt32  charcode = *pcharcode;
  1011.     FT_UInt    gindex   = 0;
  1012.     FT_Byte*   p;
  1013.  
  1014.  
  1015.     p = cmap->data + 6;
  1016.     num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
  1017.  
  1018.     num_segs = num_segs2 >> 1;
  1019.  
  1020.     if ( !num_segs )
  1021.       return 0;
  1022.  
  1023.     if ( next )
  1024.       charcode++;
  1025.  
  1026.     /* linear search */
  1027.     for ( ; charcode <= 0xFFFFU; charcode++ )
  1028.     {
  1029.       FT_Byte*  q;
  1030.  
  1031.  
  1032.       p = cmap->data + 14;               /* ends table   */
  1033.       q = cmap->data + 16 + num_segs2;   /* starts table */
  1034.  
  1035.       for ( i = 0; i < num_segs; i++ )
  1036.       {
  1037.         end   = TT_NEXT_USHORT( p );
  1038.         start = TT_NEXT_USHORT( q );
  1039.  
  1040.         if ( charcode >= start && charcode <= end )
  1041.         {
  1042.           p       = q - 2 + num_segs2;
  1043.           delta   = TT_PEEK_SHORT( p );
  1044.           p      += num_segs2;
  1045.           offset  = TT_PEEK_USHORT( p );
  1046.  
  1047.           /* some fonts have an incorrect last segment; */
  1048.           /* we have to catch it                        */
  1049.           if ( i >= num_segs - 1                  &&
  1050.                start == 0xFFFFU && end == 0xFFFFU )
  1051.           {
  1052.             TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
  1053.             FT_Byte*  limit = face->cmap_table + face->cmap_size;
  1054.  
  1055.  
  1056.             if ( offset && p + offset + 2 > limit )
  1057.             {
  1058.               delta  = 1;
  1059.               offset = 0;
  1060.             }
  1061.           }
  1062.  
  1063.           if ( offset == 0xFFFFU )
  1064.             continue;
  1065.  
  1066.           if ( offset )
  1067.           {
  1068.             p += offset + ( charcode - start ) * 2;
  1069.             gindex = TT_PEEK_USHORT( p );
  1070.             if ( gindex != 0 )
  1071.               gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
  1072.           }
  1073.           else
  1074.             gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
  1075.  
  1076.           break;
  1077.         }
  1078.       }
  1079.  
  1080.       if ( !next || gindex )
  1081.         break;
  1082.     }
  1083.  
  1084.     if ( next && gindex )
  1085.       *pcharcode = charcode;
  1086.  
  1087.     return gindex;
  1088.   }
  1089.  
  1090.  
  1091.   static FT_UInt
  1092.   tt_cmap4_char_map_binary( TT_CMap     cmap,
  1093.                             FT_UInt32*  pcharcode,
  1094.                             FT_Bool     next )
  1095.   {
  1096.     FT_UInt   num_segs2, start, end, offset;
  1097.     FT_Int    delta;
  1098.     FT_UInt   max, min, mid, num_segs;
  1099.     FT_UInt   charcode = (FT_UInt)*pcharcode;
  1100.     FT_UInt   gindex   = 0;
  1101.     FT_Byte*  p;
  1102.  
  1103.  
  1104.     p = cmap->data + 6;
  1105.     num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
  1106.  
  1107.     if ( !num_segs2 )
  1108.       return 0;
  1109.  
  1110.     num_segs = num_segs2 >> 1;
  1111.  
  1112.     /* make compiler happy */
  1113.     mid = num_segs;
  1114.     end = 0xFFFFU;
  1115.  
  1116.     if ( next )
  1117.       charcode++;
  1118.  
  1119.     min = 0;
  1120.     max = num_segs;
  1121.  
  1122.     /* binary search */
  1123.     while ( min < max )
  1124.     {
  1125.       mid    = ( min + max ) >> 1;
  1126.       p      = cmap->data + 14 + mid * 2;
  1127.       end    = TT_PEEK_USHORT( p );
  1128.       p     += 2 + num_segs2;
  1129.       start  = TT_PEEK_USHORT( p );
  1130.  
  1131.       if ( charcode < start )
  1132.         max = mid;
  1133.       else if ( charcode > end )
  1134.         min = mid + 1;
  1135.       else
  1136.       {
  1137.         p     += num_segs2;
  1138.         delta  = TT_PEEK_SHORT( p );
  1139.         p     += num_segs2;
  1140.         offset = TT_PEEK_USHORT( p );
  1141.  
  1142.         /* some fonts have an incorrect last segment; */
  1143.         /* we have to catch it                        */
  1144.         if ( mid >= num_segs - 1                &&
  1145.              start == 0xFFFFU && end == 0xFFFFU )
  1146.         {
  1147.           TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
  1148.           FT_Byte*  limit = face->cmap_table + face->cmap_size;
  1149.  
  1150.  
  1151.           if ( offset && p + offset + 2 > limit )
  1152.           {
  1153.             delta  = 1;
  1154.             offset = 0;
  1155.           }
  1156.         }
  1157.  
  1158.         /* search the first segment containing `charcode' */
  1159.         if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING )
  1160.         {
  1161.           FT_UInt  i;
  1162.  
  1163.  
  1164.           /* call the current segment `max' */
  1165.           max = mid;
  1166.  
  1167.           if ( offset == 0xFFFFU )
  1168.             mid = max + 1;
  1169.  
  1170.           /* search in segments before the current segment */
  1171.           for ( i = max ; i > 0; i-- )
  1172.           {
  1173.             FT_UInt   prev_end;
  1174.             FT_Byte*  old_p;
  1175.  
  1176.  
  1177.             old_p    = p;
  1178.             p        = cmap->data + 14 + ( i - 1 ) * 2;
  1179.             prev_end = TT_PEEK_USHORT( p );
  1180.  
  1181.             if ( charcode > prev_end )
  1182.             {
  1183.               p = old_p;
  1184.               break;
  1185.             }
  1186.  
  1187.             end    = prev_end;
  1188.             p     += 2 + num_segs2;
  1189.             start  = TT_PEEK_USHORT( p );
  1190.             p     += num_segs2;
  1191.             delta  = TT_PEEK_SHORT( p );
  1192.             p     += num_segs2;
  1193.             offset = TT_PEEK_USHORT( p );
  1194.  
  1195.             if ( offset != 0xFFFFU )
  1196.               mid = i - 1;
  1197.           }
  1198.  
  1199.           /* no luck */
  1200.           if ( mid == max + 1 )
  1201.           {
  1202.             if ( i != max )
  1203.             {
  1204.               p      = cmap->data + 14 + max * 2;
  1205.               end    = TT_PEEK_USHORT( p );
  1206.               p     += 2 + num_segs2;
  1207.               start  = TT_PEEK_USHORT( p );
  1208.               p     += num_segs2;
  1209.               delta  = TT_PEEK_SHORT( p );
  1210.               p     += num_segs2;
  1211.               offset = TT_PEEK_USHORT( p );
  1212.             }
  1213.  
  1214.             mid = max;
  1215.  
  1216.             /* search in segments after the current segment */
  1217.             for ( i = max + 1; i < num_segs; i++ )
  1218.             {
  1219.               FT_UInt  next_end, next_start;
  1220.  
  1221.  
  1222.               p          = cmap->data + 14 + i * 2;
  1223.               next_end   = TT_PEEK_USHORT( p );
  1224.               p         += 2 + num_segs2;
  1225.               next_start = TT_PEEK_USHORT( p );
  1226.  
  1227.               if ( charcode < next_start )
  1228.                 break;
  1229.  
  1230.               end    = next_end;
  1231.               start  = next_start;
  1232.               p     += num_segs2;
  1233.               delta  = TT_PEEK_SHORT( p );
  1234.               p     += num_segs2;
  1235.               offset = TT_PEEK_USHORT( p );
  1236.  
  1237.               if ( offset != 0xFFFFU )
  1238.                 mid = i;
  1239.             }
  1240.             i--;
  1241.  
  1242.             /* still no luck */
  1243.             if ( mid == max )
  1244.             {
  1245.               mid = i;
  1246.  
  1247.               break;
  1248.             }
  1249.           }
  1250.  
  1251.           /* end, start, delta, and offset are for the i'th segment */
  1252.           if ( mid != i )
  1253.           {
  1254.             p      = cmap->data + 14 + mid * 2;
  1255.             end    = TT_PEEK_USHORT( p );
  1256.             p     += 2 + num_segs2;
  1257.             start  = TT_PEEK_USHORT( p );
  1258.             p     += num_segs2;
  1259.             delta  = TT_PEEK_SHORT( p );
  1260.             p     += num_segs2;
  1261.             offset = TT_PEEK_USHORT( p );
  1262.           }
  1263.         }
  1264.         else
  1265.         {
  1266.           if ( offset == 0xFFFFU )
  1267.             break;
  1268.         }
  1269.  
  1270.         if ( offset )
  1271.         {
  1272.           p += offset + ( charcode - start ) * 2;
  1273.           gindex = TT_PEEK_USHORT( p );
  1274.           if ( gindex != 0 )
  1275.             gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
  1276.         }
  1277.         else
  1278.           gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
  1279.  
  1280.         break;
  1281.       }
  1282.     }
  1283.  
  1284.     if ( next )
  1285.     {
  1286.       TT_CMap4  cmap4 = (TT_CMap4)cmap;
  1287.  
  1288.  
  1289.       /* if `charcode' is not in any segment, then `mid' is */
  1290.       /* the segment nearest to `charcode'                  */
  1291.       /*                                                    */
  1292.  
  1293.       if ( charcode > end )
  1294.       {
  1295.         mid++;
  1296.         if ( mid == num_segs )
  1297.           return 0;
  1298.       }
  1299.  
  1300.       if ( tt_cmap4_set_range( cmap4, mid ) )
  1301.       {
  1302.         if ( gindex )
  1303.           *pcharcode = charcode;
  1304.       }
  1305.       else
  1306.       {
  1307.         cmap4->cur_charcode = charcode;
  1308.  
  1309.         if ( gindex )
  1310.           cmap4->cur_gindex = gindex;
  1311.         else
  1312.         {
  1313.           cmap4->cur_charcode = charcode;
  1314.           tt_cmap4_next( cmap4 );
  1315.           gindex = cmap4->cur_gindex;
  1316.         }
  1317.  
  1318.         if ( gindex )
  1319.           *pcharcode = cmap4->cur_charcode;
  1320.       }
  1321.     }
  1322.  
  1323.     return gindex;
  1324.   }
  1325.  
  1326.  
  1327.   FT_CALLBACK_DEF( FT_UInt )
  1328.   tt_cmap4_char_index( TT_CMap    cmap,
  1329.                        FT_UInt32  char_code )
  1330.   {
  1331.     if ( char_code >= 0x10000UL )
  1332.       return 0;
  1333.  
  1334.     if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
  1335.       return tt_cmap4_char_map_linear( cmap, &char_code, 0 );
  1336.     else
  1337.       return tt_cmap4_char_map_binary( cmap, &char_code, 0 );
  1338.   }
  1339.  
  1340.  
  1341.   FT_CALLBACK_DEF( FT_UInt32 )
  1342.   tt_cmap4_char_next( TT_CMap     cmap,
  1343.                       FT_UInt32  *pchar_code )
  1344.   {
  1345.     FT_UInt  gindex;
  1346.  
  1347.  
  1348.     if ( *pchar_code >= 0xFFFFU )
  1349.       return 0;
  1350.  
  1351.     if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
  1352.       gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 );
  1353.     else
  1354.     {
  1355.       TT_CMap4  cmap4 = (TT_CMap4)cmap;
  1356.  
  1357.  
  1358.       /* no need to search */
  1359.       if ( *pchar_code == cmap4->cur_charcode )
  1360.       {
  1361.         tt_cmap4_next( cmap4 );
  1362.         gindex = cmap4->cur_gindex;
  1363.         if ( gindex )
  1364.           *pchar_code = cmap4->cur_charcode;
  1365.       }
  1366.       else
  1367.         gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 );
  1368.     }
  1369.  
  1370.     return gindex;
  1371.   }
  1372.  
  1373.  
  1374.   FT_CALLBACK_DEF( FT_Error )
  1375.   tt_cmap4_get_info( TT_CMap       cmap,
  1376.                      TT_CMapInfo  *cmap_info )
  1377.   {
  1378.     FT_Byte*  p = cmap->data + 4;
  1379.  
  1380.  
  1381.     cmap_info->format   = 4;
  1382.     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
  1383.  
  1384.     return FT_Err_Ok;
  1385.   }
  1386.  
  1387.  
  1388.   FT_DEFINE_TT_CMAP(
  1389.     tt_cmap4_class_rec,
  1390.     sizeof ( TT_CMap4Rec ),
  1391.     (FT_CMap_InitFunc)     tt_cmap4_init,
  1392.     (FT_CMap_DoneFunc)     NULL,
  1393.     (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
  1394.     (FT_CMap_CharNextFunc) tt_cmap4_char_next,
  1395.  
  1396.     NULL,
  1397.     NULL,
  1398.     NULL,
  1399.     NULL,
  1400.     NULL,
  1401.  
  1402.     4,
  1403.     (TT_CMap_ValidateFunc)tt_cmap4_validate,
  1404.     (TT_CMap_Info_GetFunc)tt_cmap4_get_info )
  1405.  
  1406. #endif /* TT_CONFIG_CMAP_FORMAT_4 */
  1407.  
  1408.  
  1409.   /*************************************************************************/
  1410.   /*************************************************************************/
  1411.   /*****                                                               *****/
  1412.   /*****                          FORMAT 6                             *****/
  1413.   /*****                                                               *****/
  1414.   /*************************************************************************/
  1415.   /*************************************************************************/
  1416.  
  1417.   /*************************************************************************/
  1418.   /*                                                                       */
  1419.   /* TABLE OVERVIEW                                                        */
  1420.   /* --------------                                                        */
  1421.   /*                                                                       */
  1422.   /*   NAME        OFFSET          TYPE             DESCRIPTION            */
  1423.   /*                                                                       */
  1424.   /*   format       0              USHORT           must be 4              */
  1425.   /*   length       2              USHORT           table length in bytes  */
  1426.   /*   language     4              USHORT           Mac language code      */
  1427.   /*                                                                       */
  1428.   /*   first        6              USHORT           first segment code     */
  1429.   /*   count        8              USHORT           segment size in chars  */
  1430.   /*   glyphIds     10             USHORT[count]    glyph IDs              */
  1431.   /*                                                                       */
  1432.   /* A very simplified segment mapping.                                    */
  1433.   /*                                                                       */
  1434.  
  1435. #ifdef TT_CONFIG_CMAP_FORMAT_6
  1436.  
  1437.   FT_CALLBACK_DEF( FT_Error )
  1438.   tt_cmap6_validate( FT_Byte*      table,
  1439.                      FT_Validator  valid )
  1440.   {
  1441.     FT_Byte*  p;
  1442.     FT_UInt   length, count;
  1443.  
  1444.  
  1445.     if ( table + 10 > valid->limit )
  1446.       FT_INVALID_TOO_SHORT;
  1447.  
  1448.     p      = table + 2;
  1449.     length = TT_NEXT_USHORT( p );
  1450.  
  1451.     p      = table + 8;             /* skip language and start index */
  1452.     count  = TT_NEXT_USHORT( p );
  1453.  
  1454.     if ( table + length > valid->limit || length < 10 + count * 2 )
  1455.       FT_INVALID_TOO_SHORT;
  1456.  
  1457.     /* check glyph indices */
  1458.     if ( valid->level >= FT_VALIDATE_TIGHT )
  1459.     {
  1460.       FT_UInt  gindex;
  1461.  
  1462.  
  1463.       for ( ; count > 0; count-- )
  1464.       {
  1465.         gindex = TT_NEXT_USHORT( p );
  1466.         if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
  1467.           FT_INVALID_GLYPH_ID;
  1468.       }
  1469.     }
  1470.  
  1471.     return FT_Err_Ok;
  1472.   }
  1473.  
  1474.  
  1475.   FT_CALLBACK_DEF( FT_UInt )
  1476.   tt_cmap6_char_index( TT_CMap    cmap,
  1477.                        FT_UInt32  char_code )
  1478.   {
  1479.     FT_Byte*  table  = cmap->data;
  1480.     FT_UInt   result = 0;
  1481.     FT_Byte*  p      = table + 6;
  1482.     FT_UInt   start  = TT_NEXT_USHORT( p );
  1483.     FT_UInt   count  = TT_NEXT_USHORT( p );
  1484.     FT_UInt   idx    = (FT_UInt)( char_code - start );
  1485.  
  1486.  
  1487.     if ( idx < count )
  1488.     {
  1489.       p += 2 * idx;
  1490.       result = TT_PEEK_USHORT( p );
  1491.     }
  1492.     return result;
  1493.   }
  1494.  
  1495.  
  1496.   FT_CALLBACK_DEF( FT_UInt32 )
  1497.   tt_cmap6_char_next( TT_CMap     cmap,
  1498.                       FT_UInt32  *pchar_code )
  1499.   {
  1500.     FT_Byte*   table     = cmap->data;
  1501.     FT_UInt32  result    = 0;
  1502.     FT_UInt32  char_code = *pchar_code + 1;
  1503.     FT_UInt    gindex    = 0;
  1504.  
  1505.     FT_Byte*   p         = table + 6;
  1506.     FT_UInt    start     = TT_NEXT_USHORT( p );
  1507.     FT_UInt    count     = TT_NEXT_USHORT( p );
  1508.     FT_UInt    idx;
  1509.  
  1510.  
  1511.     if ( char_code >= 0x10000UL )
  1512.       goto Exit;
  1513.  
  1514.     if ( char_code < start )
  1515.       char_code = start;
  1516.  
  1517.     idx = (FT_UInt)( char_code - start );
  1518.     p  += 2 * idx;
  1519.  
  1520.     for ( ; idx < count; idx++ )
  1521.     {
  1522.       gindex = TT_NEXT_USHORT( p );
  1523.       if ( gindex != 0 )
  1524.       {
  1525.         result = char_code;
  1526.         break;
  1527.       }
  1528.       char_code++;
  1529.     }
  1530.  
  1531.   Exit:
  1532.     *pchar_code = result;
  1533.     return gindex;
  1534.   }
  1535.  
  1536.  
  1537.   FT_CALLBACK_DEF( FT_Error )
  1538.   tt_cmap6_get_info( TT_CMap       cmap,
  1539.                      TT_CMapInfo  *cmap_info )
  1540.   {
  1541.     FT_Byte*  p = cmap->data + 4;
  1542.  
  1543.  
  1544.     cmap_info->format   = 6;
  1545.     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
  1546.  
  1547.     return FT_Err_Ok;
  1548.   }
  1549.  
  1550.  
  1551.   FT_DEFINE_TT_CMAP(
  1552.     tt_cmap6_class_rec,
  1553.     sizeof ( TT_CMapRec ),
  1554.  
  1555.     (FT_CMap_InitFunc)     tt_cmap_init,
  1556.     (FT_CMap_DoneFunc)     NULL,
  1557.     (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
  1558.     (FT_CMap_CharNextFunc) tt_cmap6_char_next,
  1559.  
  1560.     NULL,
  1561.     NULL,
  1562.     NULL,
  1563.     NULL,
  1564.     NULL,
  1565.  
  1566.     6,
  1567.     (TT_CMap_ValidateFunc)tt_cmap6_validate,
  1568.     (TT_CMap_Info_GetFunc)tt_cmap6_get_info )
  1569.  
  1570. #endif /* TT_CONFIG_CMAP_FORMAT_6 */
  1571.  
  1572.  
  1573.   /*************************************************************************/
  1574.   /*************************************************************************/
  1575.   /*****                                                               *****/
  1576.   /*****                          FORMAT 8                             *****/
  1577.   /*****                                                               *****/
  1578.   /***** It is hard to completely understand what the OpenType spec    *****/
  1579.   /***** says about this format, but here is my conclusion.            *****/
  1580.   /*****                                                               *****/
  1581.   /***** The purpose of this format is to easily map UTF-16 text to    *****/
  1582.   /***** glyph indices.  Basically, the `char_code' must be in one of  *****/
  1583.   /***** the following formats:                                        *****/
  1584.   /*****                                                               *****/
  1585.   /*****   - A 16-bit value that isn't part of the Unicode Surrogates  *****/
  1586.   /*****     Area (i.e. U+D800-U+DFFF).                                *****/
  1587.   /*****                                                               *****/
  1588.   /*****   - A 32-bit value, made of two surrogate values, i.e.. if    *****/
  1589.   /*****     `char_code = (char_hi << 16) | char_lo', then both        *****/
  1590.   /*****     `char_hi' and `char_lo' must be in the Surrogates Area.   *****/
  1591.   /*****      Area.                                                    *****/
  1592.   /*****                                                               *****/
  1593.   /***** The `is32' table embedded in the charmap indicates whether a  *****/
  1594.   /***** given 16-bit value is in the surrogates area or not.          *****/
  1595.   /*****                                                               *****/
  1596.   /***** So, for any given `char_code', we can assert the following:   *****/
  1597.   /*****                                                               *****/
  1598.   /*****   If `char_hi == 0' then we must have `is32[char_lo] == 0'.   *****/
  1599.   /*****                                                               *****/
  1600.   /*****   If `char_hi != 0' then we must have both                    *****/
  1601.   /*****   `is32[char_hi] != 0' and `is32[char_lo] != 0'.              *****/
  1602.   /*****                                                               *****/
  1603.   /*************************************************************************/
  1604.   /*************************************************************************/
  1605.  
  1606.   /*************************************************************************/
  1607.   /*                                                                       */
  1608.   /* TABLE OVERVIEW                                                        */
  1609.   /* --------------                                                        */
  1610.   /*                                                                       */
  1611.   /*   NAME        OFFSET         TYPE        DESCRIPTION                  */
  1612.   /*                                                                       */
  1613.   /*   format      0              USHORT      must be 8                    */
  1614.   /*   reserved    2              USHORT      reserved                     */
  1615.   /*   length      4              ULONG       length in bytes              */
  1616.   /*   language    8              ULONG       Mac language code            */
  1617.   /*   is32        12             BYTE[8192]  32-bitness bitmap            */
  1618.   /*   count       8204           ULONG       number of groups             */
  1619.   /*                                                                       */
  1620.   /* This header is followed by `count' groups of the following format:    */
  1621.   /*                                                                       */
  1622.   /*   start       0              ULONG       first charcode               */
  1623.   /*   end         4              ULONG       last charcode                */
  1624.   /*   startId     8              ULONG       start glyph ID for the group */
  1625.   /*                                                                       */
  1626.  
  1627. #ifdef TT_CONFIG_CMAP_FORMAT_8
  1628.  
  1629.   FT_CALLBACK_DEF( FT_Error )
  1630.   tt_cmap8_validate( FT_Byte*      table,
  1631.                      FT_Validator  valid )
  1632.   {
  1633.     FT_Byte*   p = table + 4;
  1634.     FT_Byte*   is32;
  1635.     FT_UInt32  length;
  1636.     FT_UInt32  num_groups;
  1637.  
  1638.  
  1639.     if ( table + 16 + 8192 > valid->limit )
  1640.       FT_INVALID_TOO_SHORT;
  1641.  
  1642.     length = TT_NEXT_ULONG( p );
  1643.     if ( length > (FT_UInt32)( valid->limit - table ) || length < 8192 + 16 )
  1644.       FT_INVALID_TOO_SHORT;
  1645.  
  1646.     is32       = table + 12;
  1647.     p          = is32  + 8192;          /* skip `is32' array */
  1648.     num_groups = TT_NEXT_ULONG( p );
  1649.  
  1650.     if ( p + num_groups * 12 > valid->limit )
  1651.       FT_INVALID_TOO_SHORT;
  1652.  
  1653.     /* check groups, they must be in increasing order */
  1654.     {
  1655.       FT_UInt32  n, start, end, start_id, count, last = 0;
  1656.  
  1657.  
  1658.       for ( n = 0; n < num_groups; n++ )
  1659.       {
  1660.         FT_UInt   hi, lo;
  1661.  
  1662.  
  1663.         start    = TT_NEXT_ULONG( p );
  1664.         end      = TT_NEXT_ULONG( p );
  1665.         start_id = TT_NEXT_ULONG( p );
  1666.  
  1667.         if ( start > end )
  1668.           FT_INVALID_DATA;
  1669.  
  1670.         if ( n > 0 && start <= last )
  1671.           FT_INVALID_DATA;
  1672.  
  1673.         if ( valid->level >= FT_VALIDATE_TIGHT )
  1674.         {
  1675.           if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
  1676.             FT_INVALID_GLYPH_ID;
  1677.  
  1678.           count = (FT_UInt32)( end - start + 1 );
  1679.  
  1680.           if ( start & ~0xFFFFU )
  1681.           {
  1682.             /* start_hi != 0; check that is32[i] is 1 for each i in */
  1683.             /* the `hi' and `lo' of the range [start..end]          */
  1684.             for ( ; count > 0; count--, start++ )
  1685.             {
  1686.               hi = (FT_UInt)( start >> 16 );
  1687.               lo = (FT_UInt)( start & 0xFFFFU );
  1688.  
  1689.               if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
  1690.                 FT_INVALID_DATA;
  1691.  
  1692.               if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
  1693.                 FT_INVALID_DATA;
  1694.             }
  1695.           }
  1696.           else
  1697.           {
  1698.             /* start_hi == 0; check that is32[i] is 0 for each i in */
  1699.             /* the range [start..end]                               */
  1700.  
  1701.             /* end_hi cannot be != 0! */
  1702.             if ( end & ~0xFFFFU )
  1703.               FT_INVALID_DATA;
  1704.  
  1705.             for ( ; count > 0; count--, start++ )
  1706.             {
  1707.               lo = (FT_UInt)( start & 0xFFFFU );
  1708.  
  1709.               if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
  1710.                 FT_INVALID_DATA;
  1711.             }
  1712.           }
  1713.         }
  1714.  
  1715.         last = end;
  1716.       }
  1717.     }
  1718.  
  1719.     return FT_Err_Ok;
  1720.   }
  1721.  
  1722.  
  1723.   FT_CALLBACK_DEF( FT_UInt )
  1724.   tt_cmap8_char_index( TT_CMap    cmap,
  1725.                        FT_UInt32  char_code )
  1726.   {
  1727.     FT_Byte*   table      = cmap->data;
  1728.     FT_UInt    result     = 0;
  1729.     FT_Byte*   p          = table + 8204;
  1730.     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
  1731.     FT_UInt32  start, end, start_id;
  1732.  
  1733.  
  1734.     for ( ; num_groups > 0; num_groups-- )
  1735.     {
  1736.       start    = TT_NEXT_ULONG( p );
  1737.       end      = TT_NEXT_ULONG( p );
  1738.       start_id = TT_NEXT_ULONG( p );
  1739.  
  1740.       if ( char_code < start )
  1741.         break;
  1742.  
  1743.       if ( char_code <= end )
  1744.       {
  1745.         result = (FT_UInt)( start_id + char_code - start );
  1746.         break;
  1747.       }
  1748.     }
  1749.     return result;
  1750.   }
  1751.  
  1752.  
  1753.   FT_CALLBACK_DEF( FT_UInt32 )
  1754.   tt_cmap8_char_next( TT_CMap     cmap,
  1755.                       FT_UInt32  *pchar_code )
  1756.   {
  1757.     FT_UInt32  result     = 0;
  1758.     FT_UInt32  char_code  = *pchar_code + 1;
  1759.     FT_UInt    gindex     = 0;
  1760.     FT_Byte*   table      = cmap->data;
  1761.     FT_Byte*   p          = table + 8204;
  1762.     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
  1763.     FT_UInt32  start, end, start_id;
  1764.  
  1765.  
  1766.     p = table + 8208;
  1767.  
  1768.     for ( ; num_groups > 0; num_groups-- )
  1769.     {
  1770.       start    = TT_NEXT_ULONG( p );
  1771.       end      = TT_NEXT_ULONG( p );
  1772.       start_id = TT_NEXT_ULONG( p );
  1773.  
  1774.       if ( char_code < start )
  1775.         char_code = start;
  1776.  
  1777.       if ( char_code <= end )
  1778.       {
  1779.         gindex = (FT_UInt)( char_code - start + start_id );
  1780.         if ( gindex != 0 )
  1781.         {
  1782.           result = char_code;
  1783.           goto Exit;
  1784.         }
  1785.       }
  1786.     }
  1787.  
  1788.   Exit:
  1789.     *pchar_code = result;
  1790.     return gindex;
  1791.   }
  1792.  
  1793.  
  1794.   FT_CALLBACK_DEF( FT_Error )
  1795.   tt_cmap8_get_info( TT_CMap       cmap,
  1796.                      TT_CMapInfo  *cmap_info )
  1797.   {
  1798.     FT_Byte*  p = cmap->data + 8;
  1799.  
  1800.  
  1801.     cmap_info->format   = 8;
  1802.     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
  1803.  
  1804.     return FT_Err_Ok;
  1805.   }
  1806.  
  1807.  
  1808.   FT_DEFINE_TT_CMAP(
  1809.     tt_cmap8_class_rec,
  1810.     sizeof ( TT_CMapRec ),
  1811.  
  1812.     (FT_CMap_InitFunc)     tt_cmap_init,
  1813.     (FT_CMap_DoneFunc)     NULL,
  1814.     (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
  1815.     (FT_CMap_CharNextFunc) tt_cmap8_char_next,
  1816.  
  1817.     NULL,
  1818.     NULL,
  1819.     NULL,
  1820.     NULL,
  1821.     NULL,
  1822.  
  1823.     8,
  1824.     (TT_CMap_ValidateFunc)tt_cmap8_validate,
  1825.     (TT_CMap_Info_GetFunc)tt_cmap8_get_info )
  1826.  
  1827. #endif /* TT_CONFIG_CMAP_FORMAT_8 */
  1828.  
  1829.  
  1830.   /*************************************************************************/
  1831.   /*************************************************************************/
  1832.   /*****                                                               *****/
  1833.   /*****                          FORMAT 10                            *****/
  1834.   /*****                                                               *****/
  1835.   /*************************************************************************/
  1836.   /*************************************************************************/
  1837.  
  1838.   /*************************************************************************/
  1839.   /*                                                                       */
  1840.   /* TABLE OVERVIEW                                                        */
  1841.   /* --------------                                                        */
  1842.   /*                                                                       */
  1843.   /*   NAME      OFFSET  TYPE               DESCRIPTION                    */
  1844.   /*                                                                       */
  1845.   /*   format     0      USHORT             must be 10                     */
  1846.   /*   reserved   2      USHORT             reserved                       */
  1847.   /*   length     4      ULONG              length in bytes                */
  1848.   /*   language   8      ULONG              Mac language code              */
  1849.   /*                                                                       */
  1850.   /*   start     12      ULONG              first char in range            */
  1851.   /*   count     16      ULONG              number of chars in range       */
  1852.   /*   glyphIds  20      USHORT[count]      glyph indices covered          */
  1853.   /*                                                                       */
  1854.  
  1855. #ifdef TT_CONFIG_CMAP_FORMAT_10
  1856.  
  1857.   FT_CALLBACK_DEF( FT_Error )
  1858.   tt_cmap10_validate( FT_Byte*      table,
  1859.                       FT_Validator  valid )
  1860.   {
  1861.     FT_Byte*  p = table + 4;
  1862.     FT_ULong  length, count;
  1863.  
  1864.  
  1865.     if ( table + 20 > valid->limit )
  1866.       FT_INVALID_TOO_SHORT;
  1867.  
  1868.     length = TT_NEXT_ULONG( p );
  1869.     p      = table + 16;
  1870.     count  = TT_NEXT_ULONG( p );
  1871.  
  1872.     if ( length > (FT_ULong)( valid->limit - table ) ||
  1873.          length < 20 + count * 2                     )
  1874.       FT_INVALID_TOO_SHORT;
  1875.  
  1876.     /* check glyph indices */
  1877.     if ( valid->level >= FT_VALIDATE_TIGHT )
  1878.     {
  1879.       FT_UInt  gindex;
  1880.  
  1881.  
  1882.       for ( ; count > 0; count-- )
  1883.       {
  1884.         gindex = TT_NEXT_USHORT( p );
  1885.         if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
  1886.           FT_INVALID_GLYPH_ID;
  1887.       }
  1888.     }
  1889.  
  1890.     return FT_Err_Ok;
  1891.   }
  1892.  
  1893.  
  1894.   FT_CALLBACK_DEF( FT_UInt )
  1895.   tt_cmap10_char_index( TT_CMap    cmap,
  1896.                         FT_UInt32  char_code )
  1897.   {
  1898.     FT_Byte*   table  = cmap->data;
  1899.     FT_UInt    result = 0;
  1900.     FT_Byte*   p      = table + 12;
  1901.     FT_UInt32  start  = TT_NEXT_ULONG( p );
  1902.     FT_UInt32  count  = TT_NEXT_ULONG( p );
  1903.     FT_UInt32  idx    = (FT_ULong)( char_code - start );
  1904.  
  1905.  
  1906.     if ( idx < count )
  1907.     {
  1908.       p     += 2 * idx;
  1909.       result = TT_PEEK_USHORT( p );
  1910.     }
  1911.     return result;
  1912.   }
  1913.  
  1914.  
  1915.   FT_CALLBACK_DEF( FT_UInt32 )
  1916.   tt_cmap10_char_next( TT_CMap     cmap,
  1917.                        FT_UInt32  *pchar_code )
  1918.   {
  1919.     FT_Byte*   table     = cmap->data;
  1920.     FT_UInt32  char_code = *pchar_code + 1;
  1921.     FT_UInt    gindex    = 0;
  1922.     FT_Byte*   p         = table + 12;
  1923.     FT_UInt32  start     = TT_NEXT_ULONG( p );
  1924.     FT_UInt32  count     = TT_NEXT_ULONG( p );
  1925.     FT_UInt32  idx;
  1926.  
  1927.  
  1928.     if ( char_code < start )
  1929.       char_code = start;
  1930.  
  1931.     idx = (FT_UInt32)( char_code - start );
  1932.     p  += 2 * idx;
  1933.  
  1934.     for ( ; idx < count; idx++ )
  1935.     {
  1936.       gindex = TT_NEXT_USHORT( p );
  1937.       if ( gindex != 0 )
  1938.         break;
  1939.       char_code++;
  1940.     }
  1941.  
  1942.     *pchar_code = char_code;
  1943.     return gindex;
  1944.   }
  1945.  
  1946.  
  1947.   FT_CALLBACK_DEF( FT_Error )
  1948.   tt_cmap10_get_info( TT_CMap       cmap,
  1949.                       TT_CMapInfo  *cmap_info )
  1950.   {
  1951.     FT_Byte*  p = cmap->data + 8;
  1952.  
  1953.  
  1954.     cmap_info->format   = 10;
  1955.     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
  1956.  
  1957.     return FT_Err_Ok;
  1958.   }
  1959.  
  1960.  
  1961.   FT_DEFINE_TT_CMAP(
  1962.     tt_cmap10_class_rec,
  1963.     sizeof ( TT_CMapRec ),
  1964.  
  1965.     (FT_CMap_InitFunc)     tt_cmap_init,
  1966.     (FT_CMap_DoneFunc)     NULL,
  1967.     (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
  1968.     (FT_CMap_CharNextFunc) tt_cmap10_char_next,
  1969.  
  1970.     NULL,
  1971.     NULL,
  1972.     NULL,
  1973.     NULL,
  1974.     NULL,
  1975.  
  1976.     10,
  1977.     (TT_CMap_ValidateFunc)tt_cmap10_validate,
  1978.     (TT_CMap_Info_GetFunc)tt_cmap10_get_info )
  1979.  
  1980. #endif /* TT_CONFIG_CMAP_FORMAT_10 */
  1981.  
  1982.  
  1983.   /*************************************************************************/
  1984.   /*************************************************************************/
  1985.   /*****                                                               *****/
  1986.   /*****                          FORMAT 12                            *****/
  1987.   /*****                                                               *****/
  1988.   /*************************************************************************/
  1989.   /*************************************************************************/
  1990.  
  1991.   /*************************************************************************/
  1992.   /*                                                                       */
  1993.   /* TABLE OVERVIEW                                                        */
  1994.   /* --------------                                                        */
  1995.   /*                                                                       */
  1996.   /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
  1997.   /*                                                                       */
  1998.   /*   format      0          USHORT     must be 12                        */
  1999.   /*   reserved    2          USHORT     reserved                          */
  2000.   /*   length      4          ULONG      length in bytes                   */
  2001.   /*   language    8          ULONG      Mac language code                 */
  2002.   /*   count       12         ULONG      number of groups                  */
  2003.   /*               16                                                      */
  2004.   /*                                                                       */
  2005.   /* This header is followed by `count' groups of the following format:    */
  2006.   /*                                                                       */
  2007.   /*   start       0          ULONG      first charcode                    */
  2008.   /*   end         4          ULONG      last charcode                     */
  2009.   /*   startId     8          ULONG      start glyph ID for the group      */
  2010.   /*                                                                       */
  2011.  
  2012. #ifdef TT_CONFIG_CMAP_FORMAT_12
  2013.  
  2014.   typedef struct  TT_CMap12Rec_
  2015.   {
  2016.     TT_CMapRec  cmap;
  2017.     FT_Bool     valid;
  2018.     FT_ULong    cur_charcode;
  2019.     FT_UInt     cur_gindex;
  2020.     FT_ULong    cur_group;
  2021.     FT_ULong    num_groups;
  2022.  
  2023.   } TT_CMap12Rec, *TT_CMap12;
  2024.  
  2025.  
  2026.   FT_CALLBACK_DEF( FT_Error )
  2027.   tt_cmap12_init( TT_CMap12  cmap,
  2028.                   FT_Byte*   table )
  2029.   {
  2030.     cmap->cmap.data  = table;
  2031.  
  2032.     table           += 12;
  2033.     cmap->num_groups = FT_PEEK_ULONG( table );
  2034.  
  2035.     cmap->valid      = 0;
  2036.  
  2037.     return FT_Err_Ok;
  2038.   }
  2039.  
  2040.  
  2041.   FT_CALLBACK_DEF( FT_Error )
  2042.   tt_cmap12_validate( FT_Byte*      table,
  2043.                       FT_Validator  valid )
  2044.   {
  2045.     FT_Byte*   p;
  2046.     FT_ULong   length;
  2047.     FT_ULong   num_groups;
  2048.  
  2049.  
  2050.     if ( table + 16 > valid->limit )
  2051.       FT_INVALID_TOO_SHORT;
  2052.  
  2053.     p      = table + 4;
  2054.     length = TT_NEXT_ULONG( p );
  2055.  
  2056.     p          = table + 12;
  2057.     num_groups = TT_NEXT_ULONG( p );
  2058.  
  2059.     if ( length > (FT_ULong)( valid->limit - table ) ||
  2060.          length < 16 + 12 * num_groups               )
  2061.       FT_INVALID_TOO_SHORT;
  2062.  
  2063.     /* check groups, they must be in increasing order */
  2064.     {
  2065.       FT_ULong  n, start, end, start_id, last = 0;
  2066.  
  2067.  
  2068.       for ( n = 0; n < num_groups; n++ )
  2069.       {
  2070.         start    = TT_NEXT_ULONG( p );
  2071.         end      = TT_NEXT_ULONG( p );
  2072.         start_id = TT_NEXT_ULONG( p );
  2073.  
  2074.         if ( start > end )
  2075.           FT_INVALID_DATA;
  2076.  
  2077.         if ( n > 0 && start <= last )
  2078.           FT_INVALID_DATA;
  2079.  
  2080.         if ( valid->level >= FT_VALIDATE_TIGHT )
  2081.         {
  2082.           if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
  2083.             FT_INVALID_GLYPH_ID;
  2084.         }
  2085.  
  2086.         last = end;
  2087.       }
  2088.     }
  2089.  
  2090.     return FT_Err_Ok;
  2091.   }
  2092.  
  2093.  
  2094.   /* search the index of the charcode next to cmap->cur_charcode */
  2095.   /* cmap->cur_group should be set up properly by caller         */
  2096.   /*                                                             */
  2097.   static void
  2098.   tt_cmap12_next( TT_CMap12  cmap )
  2099.   {
  2100.     FT_Byte*  p;
  2101.     FT_ULong  start, end, start_id, char_code;
  2102.     FT_ULong  n;
  2103.     FT_UInt   gindex;
  2104.  
  2105.  
  2106.     if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
  2107.       goto Fail;
  2108.  
  2109.     char_code = cmap->cur_charcode + 1;
  2110.  
  2111.     n = cmap->cur_group;
  2112.  
  2113.     for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
  2114.     {
  2115.       p        = cmap->cmap.data + 16 + 12 * n;
  2116.       start    = TT_NEXT_ULONG( p );
  2117.       end      = TT_NEXT_ULONG( p );
  2118.       start_id = TT_PEEK_ULONG( p );
  2119.  
  2120.       if ( char_code < start )
  2121.         char_code = start;
  2122.  
  2123.       for ( ; char_code <= end; char_code++ )
  2124.       {
  2125.         gindex = (FT_UInt)( start_id + char_code - start );
  2126.  
  2127.         if ( gindex )
  2128.         {
  2129.           cmap->cur_charcode = char_code;;
  2130.           cmap->cur_gindex   = gindex;
  2131.           cmap->cur_group    = n;
  2132.  
  2133.           return;
  2134.         }
  2135.       }
  2136.     }
  2137.  
  2138.   Fail:
  2139.     cmap->valid = 0;
  2140.   }
  2141.  
  2142.  
  2143.   static FT_UInt
  2144.   tt_cmap12_char_map_binary( TT_CMap     cmap,
  2145.                              FT_UInt32*  pchar_code,
  2146.                              FT_Bool     next )
  2147.   {
  2148.     FT_UInt    gindex     = 0;
  2149.     FT_Byte*   p          = cmap->data + 12;
  2150.     FT_UInt32  num_groups = TT_PEEK_ULONG( p );
  2151.     FT_UInt32  char_code  = *pchar_code;
  2152.     FT_UInt32  start, end, start_id;
  2153.     FT_UInt32  max, min, mid;
  2154.  
  2155.  
  2156.     if ( !num_groups )
  2157.       return 0;
  2158.  
  2159.     /* make compiler happy */
  2160.     mid = num_groups;
  2161.     end = 0xFFFFFFFFUL;
  2162.  
  2163.     if ( next )
  2164.       char_code++;
  2165.  
  2166.     min = 0;
  2167.     max = num_groups;
  2168.  
  2169.     /* binary search */
  2170.     while ( min < max )
  2171.     {
  2172.       mid = ( min + max ) >> 1;
  2173.       p   = cmap->data + 16 + 12 * mid;
  2174.  
  2175.       start = TT_NEXT_ULONG( p );
  2176.       end   = TT_NEXT_ULONG( p );
  2177.  
  2178.       if ( char_code < start )
  2179.         max = mid;
  2180.       else if ( char_code > end )
  2181.         min = mid + 1;
  2182.       else
  2183.       {
  2184.         start_id = TT_PEEK_ULONG( p );
  2185.         gindex = (FT_UInt)( start_id + char_code - start );
  2186.  
  2187.         break;
  2188.       }
  2189.     }
  2190.  
  2191.     if ( next )
  2192.     {
  2193.       TT_CMap12  cmap12 = (TT_CMap12)cmap;
  2194.  
  2195.  
  2196.       /* if `char_code' is not in any group, then `mid' is */
  2197.       /* the group nearest to `char_code'                  */
  2198.       /*                                                   */
  2199.  
  2200.       if ( char_code > end )
  2201.       {
  2202.         mid++;
  2203.         if ( mid == num_groups )
  2204.           return 0;
  2205.       }
  2206.  
  2207.       cmap12->valid        = 1;
  2208.       cmap12->cur_charcode = char_code;
  2209.       cmap12->cur_group    = mid;
  2210.  
  2211.       if ( !gindex )
  2212.       {
  2213.         tt_cmap12_next( cmap12 );
  2214.  
  2215.         if ( cmap12->valid )
  2216.           gindex = cmap12->cur_gindex;
  2217.       }
  2218.       else
  2219.         cmap12->cur_gindex = gindex;
  2220.  
  2221.       if ( gindex )
  2222.         *pchar_code = cmap12->cur_charcode;
  2223.     }
  2224.  
  2225.     return gindex;
  2226.   }
  2227.  
  2228.  
  2229.   FT_CALLBACK_DEF( FT_UInt )
  2230.   tt_cmap12_char_index( TT_CMap    cmap,
  2231.                         FT_UInt32  char_code )
  2232.   {
  2233.     return tt_cmap12_char_map_binary( cmap, &char_code, 0 );
  2234.   }
  2235.  
  2236.  
  2237.   FT_CALLBACK_DEF( FT_UInt32 )
  2238.   tt_cmap12_char_next( TT_CMap     cmap,
  2239.                        FT_UInt32  *pchar_code )
  2240.   {
  2241.     TT_CMap12  cmap12 = (TT_CMap12)cmap;
  2242.     FT_ULong   gindex;
  2243.  
  2244.  
  2245.     if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )
  2246.       return 0;
  2247.  
  2248.     /* no need to search */
  2249.     if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
  2250.     {
  2251.       tt_cmap12_next( cmap12 );
  2252.       if ( cmap12->valid )
  2253.       {
  2254.         gindex = cmap12->cur_gindex;
  2255.  
  2256.         /* XXX: check cur_charcode overflow is expected */
  2257.         if ( gindex )
  2258.           *pchar_code = (FT_UInt32)cmap12->cur_charcode;
  2259.       }
  2260.       else
  2261.         gindex = 0;
  2262.     }
  2263.     else
  2264.       gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
  2265.  
  2266.     /* XXX: check gindex overflow is expected */
  2267.     return (FT_UInt32)gindex;
  2268.   }
  2269.  
  2270.  
  2271.   FT_CALLBACK_DEF( FT_Error )
  2272.   tt_cmap12_get_info( TT_CMap       cmap,
  2273.                       TT_CMapInfo  *cmap_info )
  2274.   {
  2275.     FT_Byte*  p = cmap->data + 8;
  2276.  
  2277.  
  2278.     cmap_info->format   = 12;
  2279.     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
  2280.  
  2281.     return FT_Err_Ok;
  2282.   }
  2283.  
  2284.  
  2285.   FT_DEFINE_TT_CMAP(
  2286.     tt_cmap12_class_rec,
  2287.     sizeof ( TT_CMap12Rec ),
  2288.  
  2289.     (FT_CMap_InitFunc)     tt_cmap12_init,
  2290.     (FT_CMap_DoneFunc)     NULL,
  2291.     (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
  2292.     (FT_CMap_CharNextFunc) tt_cmap12_char_next,
  2293.  
  2294.     NULL,
  2295.     NULL,
  2296.     NULL,
  2297.     NULL,
  2298.     NULL,
  2299.  
  2300.     12,
  2301.     (TT_CMap_ValidateFunc)tt_cmap12_validate,
  2302.     (TT_CMap_Info_GetFunc)tt_cmap12_get_info )
  2303.  
  2304. #endif /* TT_CONFIG_CMAP_FORMAT_12 */
  2305.  
  2306.  
  2307.   /*************************************************************************/
  2308.   /*************************************************************************/
  2309.   /*****                                                               *****/
  2310.   /*****                          FORMAT 13                            *****/
  2311.   /*****                                                               *****/
  2312.   /*************************************************************************/
  2313.   /*************************************************************************/
  2314.  
  2315.   /*************************************************************************/
  2316.   /*                                                                       */
  2317.   /* TABLE OVERVIEW                                                        */
  2318.   /* --------------                                                        */
  2319.   /*                                                                       */
  2320.   /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
  2321.   /*                                                                       */
  2322.   /*   format      0          USHORT     must be 13                        */
  2323.   /*   reserved    2          USHORT     reserved                          */
  2324.   /*   length      4          ULONG      length in bytes                   */
  2325.   /*   language    8          ULONG      Mac language code                 */
  2326.   /*   count       12         ULONG      number of groups                  */
  2327.   /*               16                                                      */
  2328.   /*                                                                       */
  2329.   /* This header is followed by `count' groups of the following format:    */
  2330.   /*                                                                       */
  2331.   /*   start       0          ULONG      first charcode                    */
  2332.   /*   end         4          ULONG      last charcode                     */
  2333.   /*   glyphId     8          ULONG      glyph ID for the whole group      */
  2334.   /*                                                                       */
  2335.  
  2336. #ifdef TT_CONFIG_CMAP_FORMAT_13
  2337.  
  2338.   typedef struct  TT_CMap13Rec_
  2339.   {
  2340.     TT_CMapRec  cmap;
  2341.     FT_Bool     valid;
  2342.     FT_ULong    cur_charcode;
  2343.     FT_UInt     cur_gindex;
  2344.     FT_ULong    cur_group;
  2345.     FT_ULong    num_groups;
  2346.  
  2347.   } TT_CMap13Rec, *TT_CMap13;
  2348.  
  2349.  
  2350.   FT_CALLBACK_DEF( FT_Error )
  2351.   tt_cmap13_init( TT_CMap13  cmap,
  2352.                   FT_Byte*   table )
  2353.   {
  2354.     cmap->cmap.data  = table;
  2355.  
  2356.     table           += 12;
  2357.     cmap->num_groups = FT_PEEK_ULONG( table );
  2358.  
  2359.     cmap->valid      = 0;
  2360.  
  2361.     return FT_Err_Ok;
  2362.   }
  2363.  
  2364.  
  2365.   FT_CALLBACK_DEF( FT_Error )
  2366.   tt_cmap13_validate( FT_Byte*      table,
  2367.                       FT_Validator  valid )
  2368.   {
  2369.     FT_Byte*  p;
  2370.     FT_ULong  length;
  2371.     FT_ULong  num_groups;
  2372.  
  2373.  
  2374.     if ( table + 16 > valid->limit )
  2375.       FT_INVALID_TOO_SHORT;
  2376.  
  2377.     p      = table + 4;
  2378.     length = TT_NEXT_ULONG( p );
  2379.  
  2380.     p          = table + 12;
  2381.     num_groups = TT_NEXT_ULONG( p );
  2382.  
  2383.     if ( length > (FT_ULong)( valid->limit - table ) ||
  2384.          length < 16 + 12 * num_groups               )
  2385.       FT_INVALID_TOO_SHORT;
  2386.  
  2387.     /* check groups, they must be in increasing order */
  2388.     {
  2389.       FT_ULong  n, start, end, glyph_id, last = 0;
  2390.  
  2391.  
  2392.       for ( n = 0; n < num_groups; n++ )
  2393.       {
  2394.         start    = TT_NEXT_ULONG( p );
  2395.         end      = TT_NEXT_ULONG( p );
  2396.         glyph_id = TT_NEXT_ULONG( p );
  2397.  
  2398.         if ( start > end )
  2399.           FT_INVALID_DATA;
  2400.  
  2401.         if ( n > 0 && start <= last )
  2402.           FT_INVALID_DATA;
  2403.  
  2404.         if ( valid->level >= FT_VALIDATE_TIGHT )
  2405.         {
  2406.           if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) )
  2407.             FT_INVALID_GLYPH_ID;
  2408.         }
  2409.  
  2410.         last = end;
  2411.       }
  2412.     }
  2413.  
  2414.     return FT_Err_Ok;
  2415.   }
  2416.  
  2417.  
  2418.   /* search the index of the charcode next to cmap->cur_charcode */
  2419.   /* cmap->cur_group should be set up properly by caller         */
  2420.   /*                                                             */
  2421.   static void
  2422.   tt_cmap13_next( TT_CMap13  cmap )
  2423.   {
  2424.     FT_Byte*  p;
  2425.     FT_ULong  start, end, glyph_id, char_code;
  2426.     FT_ULong  n;
  2427.     FT_UInt   gindex;
  2428.  
  2429.  
  2430.     if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
  2431.       goto Fail;
  2432.  
  2433.     char_code = cmap->cur_charcode + 1;
  2434.  
  2435.     n = cmap->cur_group;
  2436.  
  2437.     for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
  2438.     {
  2439.       p        = cmap->cmap.data + 16 + 12 * n;
  2440.       start    = TT_NEXT_ULONG( p );
  2441.       end      = TT_NEXT_ULONG( p );
  2442.       glyph_id = TT_PEEK_ULONG( p );
  2443.  
  2444.       if ( char_code < start )
  2445.         char_code = start;
  2446.  
  2447.       if ( char_code <= end )
  2448.       {
  2449.         gindex = (FT_UInt)glyph_id;
  2450.  
  2451.         if ( gindex )
  2452.         {
  2453.           cmap->cur_charcode = char_code;;
  2454.           cmap->cur_gindex   = gindex;
  2455.           cmap->cur_group    = n;
  2456.  
  2457.           return;
  2458.         }
  2459.       }
  2460.     }
  2461.  
  2462.   Fail:
  2463.     cmap->valid = 0;
  2464.   }
  2465.  
  2466.  
  2467.   static FT_UInt
  2468.   tt_cmap13_char_map_binary( TT_CMap     cmap,
  2469.                              FT_UInt32*  pchar_code,
  2470.                              FT_Bool     next )
  2471.   {
  2472.     FT_UInt    gindex     = 0;
  2473.     FT_Byte*   p          = cmap->data + 12;
  2474.     FT_UInt32  num_groups = TT_PEEK_ULONG( p );
  2475.     FT_UInt32  char_code  = *pchar_code;
  2476.     FT_UInt32  start, end;
  2477.     FT_UInt32  max, min, mid;
  2478.  
  2479.  
  2480.     if ( !num_groups )
  2481.       return 0;
  2482.  
  2483.     /* make compiler happy */
  2484.     mid = num_groups;
  2485.     end = 0xFFFFFFFFUL;
  2486.  
  2487.     if ( next )
  2488.       char_code++;
  2489.  
  2490.     min = 0;
  2491.     max = num_groups;
  2492.  
  2493.     /* binary search */
  2494.     while ( min < max )
  2495.     {
  2496.       mid = ( min + max ) >> 1;
  2497.       p   = cmap->data + 16 + 12 * mid;
  2498.  
  2499.       start = TT_NEXT_ULONG( p );
  2500.       end   = TT_NEXT_ULONG( p );
  2501.  
  2502.       if ( char_code < start )
  2503.         max = mid;
  2504.       else if ( char_code > end )
  2505.         min = mid + 1;
  2506.       else
  2507.       {
  2508.         gindex = (FT_UInt)TT_PEEK_ULONG( p );
  2509.  
  2510.         break;
  2511.       }
  2512.     }
  2513.  
  2514.     if ( next )
  2515.     {
  2516.       TT_CMap13  cmap13 = (TT_CMap13)cmap;
  2517.  
  2518.  
  2519.       /* if `char_code' is not in any group, then `mid' is */
  2520.       /* the group nearest to `char_code'                  */
  2521.  
  2522.       if ( char_code > end )
  2523.       {
  2524.         mid++;
  2525.         if ( mid == num_groups )
  2526.           return 0;
  2527.       }
  2528.  
  2529.       cmap13->valid        = 1;
  2530.       cmap13->cur_charcode = char_code;
  2531.       cmap13->cur_group    = mid;
  2532.  
  2533.       if ( !gindex )
  2534.       {
  2535.         tt_cmap13_next( cmap13 );
  2536.  
  2537.         if ( cmap13->valid )
  2538.           gindex = cmap13->cur_gindex;
  2539.       }
  2540.       else
  2541.         cmap13->cur_gindex = gindex;
  2542.  
  2543.       if ( gindex )
  2544.         *pchar_code = cmap13->cur_charcode;
  2545.     }
  2546.  
  2547.     return gindex;
  2548.   }
  2549.  
  2550.  
  2551.   FT_CALLBACK_DEF( FT_UInt )
  2552.   tt_cmap13_char_index( TT_CMap    cmap,
  2553.                         FT_UInt32  char_code )
  2554.   {
  2555.     return tt_cmap13_char_map_binary( cmap, &char_code, 0 );
  2556.   }
  2557.  
  2558.  
  2559.   FT_CALLBACK_DEF( FT_UInt32 )
  2560.   tt_cmap13_char_next( TT_CMap     cmap,
  2561.                        FT_UInt32  *pchar_code )
  2562.   {
  2563.     TT_CMap13  cmap13 = (TT_CMap13)cmap;
  2564.     FT_UInt    gindex;
  2565.  
  2566.  
  2567.     if ( cmap13->cur_charcode >= 0xFFFFFFFFUL )
  2568.       return 0;
  2569.  
  2570.     /* no need to search */
  2571.     if ( cmap13->valid && cmap13->cur_charcode == *pchar_code )
  2572.     {
  2573.       tt_cmap13_next( cmap13 );
  2574.       if ( cmap13->valid )
  2575.       {
  2576.         gindex = cmap13->cur_gindex;
  2577.         if ( gindex )
  2578.           *pchar_code = cmap13->cur_charcode;
  2579.       }
  2580.       else
  2581.         gindex = 0;
  2582.     }
  2583.     else
  2584.       gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 );
  2585.  
  2586.     return gindex;
  2587.   }
  2588.  
  2589.  
  2590.   FT_CALLBACK_DEF( FT_Error )
  2591.   tt_cmap13_get_info( TT_CMap       cmap,
  2592.                       TT_CMapInfo  *cmap_info )
  2593.   {
  2594.     FT_Byte*  p = cmap->data + 8;
  2595.  
  2596.  
  2597.     cmap_info->format   = 13;
  2598.     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
  2599.  
  2600.     return FT_Err_Ok;
  2601.   }
  2602.  
  2603.  
  2604.   FT_DEFINE_TT_CMAP(
  2605.     tt_cmap13_class_rec,
  2606.     sizeof ( TT_CMap13Rec ),
  2607.  
  2608.     (FT_CMap_InitFunc)     tt_cmap13_init,
  2609.     (FT_CMap_DoneFunc)     NULL,
  2610.     (FT_CMap_CharIndexFunc)tt_cmap13_char_index,
  2611.     (FT_CMap_CharNextFunc) tt_cmap13_char_next,
  2612.  
  2613.     NULL,
  2614.     NULL,
  2615.     NULL,
  2616.     NULL,
  2617.     NULL,
  2618.  
  2619.     13,
  2620.     (TT_CMap_ValidateFunc)tt_cmap13_validate,
  2621.     (TT_CMap_Info_GetFunc)tt_cmap13_get_info )
  2622.  
  2623. #endif /* TT_CONFIG_CMAP_FORMAT_13 */
  2624.  
  2625.  
  2626.   /*************************************************************************/
  2627.   /*************************************************************************/
  2628.   /*****                                                               *****/
  2629.   /*****                           FORMAT 14                           *****/
  2630.   /*****                                                               *****/
  2631.   /*************************************************************************/
  2632.   /*************************************************************************/
  2633.  
  2634.   /*************************************************************************/
  2635.   /*                                                                       */
  2636.   /* TABLE OVERVIEW                                                        */
  2637.   /* --------------                                                        */
  2638.   /*                                                                       */
  2639.   /*   NAME         OFFSET  TYPE    DESCRIPTION                            */
  2640.   /*                                                                       */
  2641.   /*   format         0     USHORT  must be 14                             */
  2642.   /*   length         2     ULONG   table length in bytes                  */
  2643.   /*   numSelector    6     ULONG   number of variation sel. records       */
  2644.   /*                                                                       */
  2645.   /* Followed by numSelector records, each of which looks like             */
  2646.   /*                                                                       */
  2647.   /*   varSelector    0     UINT24  Unicode codepoint of sel.              */
  2648.   /*   defaultOff     3     ULONG   offset to a default UVS table          */
  2649.   /*                                describing any variants to be found in */
  2650.   /*                                the normal Unicode subtable.           */
  2651.   /*   nonDefOff      7     ULONG   offset to a non-default UVS table      */
  2652.   /*                                describing any variants not in the     */
  2653.   /*                                standard cmap, with GIDs here          */
  2654.   /* (either offset may be 0 NULL)                                         */
  2655.   /*                                                                       */
  2656.   /* Selectors are sorted by code point.                                   */
  2657.   /*                                                                       */
  2658.   /* A default Unicode Variation Selector (UVS) subtable is just a list of */
  2659.   /* ranges of code points which are to be found in the standard cmap.  No */
  2660.   /* glyph IDs (GIDs) here.                                                */
  2661.   /*                                                                       */
  2662.   /*   numRanges      0     ULONG   number of ranges following             */
  2663.   /*                                                                       */
  2664.   /* A range looks like                                                    */
  2665.   /*                                                                       */
  2666.   /*   uniStart       0     UINT24  code point of the first character in   */
  2667.   /*                                this range                             */
  2668.   /*   additionalCnt  3     UBYTE   count of additional characters in this */
  2669.   /*                                range (zero means a range of a single  */
  2670.   /*                                character)                             */
  2671.   /*                                                                       */
  2672.   /* Ranges are sorted by `uniStart'.                                      */
  2673.   /*                                                                       */
  2674.   /* A non-default Unicode Variation Selector (UVS) subtable is a list of  */
  2675.   /* mappings from codepoint to GID.                                       */
  2676.   /*                                                                       */
  2677.   /*   numMappings    0     ULONG   number of mappings                     */
  2678.   /*                                                                       */
  2679.   /* A range looks like                                                    */
  2680.   /*                                                                       */
  2681.   /*   uniStart       0     UINT24  code point of the first character in   */
  2682.   /*                                this range                             */
  2683.   /*   GID            3     USHORT  and its GID                            */
  2684.   /*                                                                       */
  2685.   /* Ranges are sorted by `uniStart'.                                      */
  2686.  
  2687. #ifdef TT_CONFIG_CMAP_FORMAT_14
  2688.  
  2689.   typedef struct  TT_CMap14Rec_
  2690.   {
  2691.     TT_CMapRec  cmap;
  2692.     FT_ULong    num_selectors;
  2693.  
  2694.     /* This array is used to store the results of various
  2695.      * cmap 14 query functions.  The data is overwritten
  2696.      * on each call to these functions.
  2697.      */
  2698.     FT_UInt32   max_results;
  2699.     FT_UInt32*  results;
  2700.     FT_Memory   memory;
  2701.  
  2702.   } TT_CMap14Rec, *TT_CMap14;
  2703.  
  2704.  
  2705.   FT_CALLBACK_DEF( void )
  2706.   tt_cmap14_done( TT_CMap14  cmap )
  2707.   {
  2708.     FT_Memory  memory = cmap->memory;
  2709.  
  2710.  
  2711.     cmap->max_results = 0;
  2712.     if ( memory != NULL && cmap->results != NULL )
  2713.       FT_FREE( cmap->results );
  2714.   }
  2715.  
  2716.  
  2717.   static FT_Error
  2718.   tt_cmap14_ensure( TT_CMap14  cmap,
  2719.                     FT_UInt32  num_results,
  2720.                     FT_Memory  memory )
  2721.   {
  2722.     FT_UInt32  old_max = cmap->max_results;
  2723.     FT_Error   error   = FT_Err_Ok;
  2724.  
  2725.  
  2726.     if ( num_results > cmap->max_results )
  2727.     {
  2728.        cmap->memory = memory;
  2729.  
  2730.        if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) )
  2731.          return error;
  2732.  
  2733.        cmap->max_results = num_results;
  2734.     }
  2735.  
  2736.     return error;
  2737.   }
  2738.  
  2739.  
  2740.   FT_CALLBACK_DEF( FT_Error )
  2741.   tt_cmap14_init( TT_CMap14  cmap,
  2742.                   FT_Byte*   table )
  2743.   {
  2744.     cmap->cmap.data = table;
  2745.  
  2746.     table               += 6;
  2747.     cmap->num_selectors  = FT_PEEK_ULONG( table );
  2748.     cmap->max_results    = 0;
  2749.     cmap->results        = NULL;
  2750.  
  2751.     return FT_Err_Ok;
  2752.   }
  2753.  
  2754.  
  2755.   FT_CALLBACK_DEF( FT_Error )
  2756.   tt_cmap14_validate( FT_Byte*      table,
  2757.                       FT_Validator  valid )
  2758.   {
  2759.     FT_Byte*  p             = table + 2;
  2760.     FT_ULong  length        = TT_NEXT_ULONG( p );
  2761.     FT_ULong  num_selectors = TT_NEXT_ULONG( p );
  2762.  
  2763.  
  2764.     if ( length > (FT_ULong)( valid->limit - table ) ||
  2765.          length < 10 + 11 * num_selectors            )
  2766.       FT_INVALID_TOO_SHORT;
  2767.  
  2768.     /* check selectors, they must be in increasing order */
  2769.     {
  2770.       /* we start lastVarSel at 1 because a variant selector value of 0
  2771.        * isn't valid.
  2772.        */
  2773.       FT_ULong  n, lastVarSel = 1;
  2774.  
  2775.  
  2776.       for ( n = 0; n < num_selectors; n++ )
  2777.       {
  2778.         FT_ULong  varSel    = TT_NEXT_UINT24( p );
  2779.         FT_ULong  defOff    = TT_NEXT_ULONG( p );
  2780.         FT_ULong  nondefOff = TT_NEXT_ULONG( p );
  2781.  
  2782.  
  2783.         if ( defOff >= length || nondefOff >= length )
  2784.           FT_INVALID_TOO_SHORT;
  2785.  
  2786.         if ( varSel < lastVarSel )
  2787.           FT_INVALID_DATA;
  2788.  
  2789.         lastVarSel = varSel + 1;
  2790.  
  2791.         /* check the default table (these glyphs should be reached     */
  2792.         /* through the normal Unicode cmap, no GIDs, just check order) */
  2793.         if ( defOff != 0 )
  2794.         {
  2795.           FT_Byte*  defp      = table + defOff;
  2796.           FT_ULong  numRanges = TT_NEXT_ULONG( defp );
  2797.           FT_ULong  i;
  2798.           FT_ULong  lastBase  = 0;
  2799.  
  2800.  
  2801.           if ( defp + numRanges * 4 > valid->limit )
  2802.             FT_INVALID_TOO_SHORT;
  2803.  
  2804.           for ( i = 0; i < numRanges; ++i )
  2805.           {
  2806.             FT_ULong  base = TT_NEXT_UINT24( defp );
  2807.             FT_ULong  cnt  = FT_NEXT_BYTE( defp );
  2808.  
  2809.  
  2810.             if ( base + cnt >= 0x110000UL )              /* end of Unicode */
  2811.               FT_INVALID_DATA;
  2812.  
  2813.             if ( base < lastBase )
  2814.               FT_INVALID_DATA;
  2815.  
  2816.             lastBase = base + cnt + 1U;
  2817.           }
  2818.         }
  2819.  
  2820.         /* and the non-default table (these glyphs are specified here) */
  2821.         if ( nondefOff != 0 )
  2822.         {
  2823.           FT_Byte*  ndp         = table + nondefOff;
  2824.           FT_ULong  numMappings = TT_NEXT_ULONG( ndp );
  2825.           FT_ULong  i, lastUni  = 0;
  2826.  
  2827.  
  2828.           if ( numMappings * 4 > (FT_ULong)( valid->limit - ndp ) )
  2829.             FT_INVALID_TOO_SHORT;
  2830.  
  2831.           for ( i = 0; i < numMappings; ++i )
  2832.           {
  2833.             FT_ULong  uni = TT_NEXT_UINT24( ndp );
  2834.             FT_ULong  gid = TT_NEXT_USHORT( ndp );
  2835.  
  2836.  
  2837.             if ( uni >= 0x110000UL )                     /* end of Unicode */
  2838.               FT_INVALID_DATA;
  2839.  
  2840.             if ( uni < lastUni )
  2841.               FT_INVALID_DATA;
  2842.  
  2843.             lastUni = uni + 1U;
  2844.  
  2845.             if ( valid->level >= FT_VALIDATE_TIGHT    &&
  2846.                  gid >= TT_VALID_GLYPH_COUNT( valid ) )
  2847.               FT_INVALID_GLYPH_ID;
  2848.           }
  2849.         }
  2850.       }
  2851.     }
  2852.  
  2853.     return FT_Err_Ok;
  2854.   }
  2855.  
  2856.  
  2857.   FT_CALLBACK_DEF( FT_UInt )
  2858.   tt_cmap14_char_index( TT_CMap    cmap,
  2859.                         FT_UInt32  char_code )
  2860.   {
  2861.     FT_UNUSED( cmap );
  2862.     FT_UNUSED( char_code );
  2863.  
  2864.     /* This can't happen */
  2865.     return 0;
  2866.   }
  2867.  
  2868.  
  2869.   FT_CALLBACK_DEF( FT_UInt32 )
  2870.   tt_cmap14_char_next( TT_CMap     cmap,
  2871.                        FT_UInt32  *pchar_code )
  2872.   {
  2873.     FT_UNUSED( cmap );
  2874.  
  2875.     /* This can't happen */
  2876.     *pchar_code = 0;
  2877.     return 0;
  2878.   }
  2879.  
  2880.  
  2881.   FT_CALLBACK_DEF( FT_Error )
  2882.   tt_cmap14_get_info( TT_CMap       cmap,
  2883.                       TT_CMapInfo  *cmap_info )
  2884.   {
  2885.     FT_UNUSED( cmap );
  2886.  
  2887.     cmap_info->format   = 14;
  2888.     /* subtable 14 does not define a language field */
  2889.     cmap_info->language = 0xFFFFFFFFUL;
  2890.  
  2891.     return FT_Err_Ok;
  2892.   }
  2893.  
  2894.  
  2895.   static FT_UInt
  2896.   tt_cmap14_char_map_def_binary( FT_Byte    *base,
  2897.                                  FT_UInt32   char_code )
  2898.   {
  2899.     FT_UInt32  numRanges = TT_PEEK_ULONG( base );
  2900.     FT_UInt32  max, min;
  2901.  
  2902.  
  2903.     min = 0;
  2904.     max = numRanges;
  2905.  
  2906.     base += 4;
  2907.  
  2908.     /* binary search */
  2909.     while ( min < max )
  2910.     {
  2911.       FT_UInt32  mid   = ( min + max ) >> 1;
  2912.       FT_Byte*   p     = base + 4 * mid;
  2913.       FT_ULong   start = TT_NEXT_UINT24( p );
  2914.       FT_UInt    cnt   = FT_NEXT_BYTE( p );
  2915.  
  2916.  
  2917.       if ( char_code < start )
  2918.         max = mid;
  2919.       else if ( char_code > start+cnt )
  2920.         min = mid + 1;
  2921.       else
  2922.         return TRUE;
  2923.     }
  2924.  
  2925.     return FALSE;
  2926.   }
  2927.  
  2928.  
  2929.   static FT_UInt
  2930.   tt_cmap14_char_map_nondef_binary( FT_Byte    *base,
  2931.                                     FT_UInt32   char_code )
  2932.   {
  2933.     FT_UInt32  numMappings = TT_PEEK_ULONG( base );
  2934.     FT_UInt32  max, min;
  2935.  
  2936.  
  2937.     min = 0;
  2938.     max = numMappings;
  2939.  
  2940.     base += 4;
  2941.  
  2942.     /* binary search */
  2943.     while ( min < max )
  2944.     {
  2945.       FT_UInt32  mid = ( min + max ) >> 1;
  2946.       FT_Byte*   p   = base + 5 * mid;
  2947.       FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
  2948.  
  2949.  
  2950.       if ( char_code < uni )
  2951.         max = mid;
  2952.       else if ( char_code > uni )
  2953.         min = mid + 1;
  2954.       else
  2955.         return TT_PEEK_USHORT( p );
  2956.     }
  2957.  
  2958.     return 0;
  2959.   }
  2960.  
  2961.  
  2962.   static FT_Byte*
  2963.   tt_cmap14_find_variant( FT_Byte    *base,
  2964.                           FT_UInt32   variantCode )
  2965.   {
  2966.     FT_UInt32  numVar = TT_PEEK_ULONG( base );
  2967.     FT_UInt32  max, min;
  2968.  
  2969.  
  2970.     min = 0;
  2971.     max = numVar;
  2972.  
  2973.     base += 4;
  2974.  
  2975.     /* binary search */
  2976.     while ( min < max )
  2977.     {
  2978.       FT_UInt32  mid    = ( min + max ) >> 1;
  2979.       FT_Byte*   p      = base + 11 * mid;
  2980.       FT_ULong   varSel = TT_NEXT_UINT24( p );
  2981.  
  2982.  
  2983.       if ( variantCode < varSel )
  2984.         max = mid;
  2985.       else if ( variantCode > varSel )
  2986.         min = mid + 1;
  2987.       else
  2988.         return p;
  2989.     }
  2990.  
  2991.     return NULL;
  2992.   }
  2993.  
  2994.  
  2995.   FT_CALLBACK_DEF( FT_UInt )
  2996.   tt_cmap14_char_var_index( TT_CMap    cmap,
  2997.                             TT_CMap    ucmap,
  2998.                             FT_UInt32  charcode,
  2999.                             FT_UInt32  variantSelector )
  3000.   {
  3001.     FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
  3002.     FT_ULong  defOff;
  3003.     FT_ULong  nondefOff;
  3004.  
  3005.  
  3006.     if ( !p )
  3007.       return 0;
  3008.  
  3009.     defOff    = TT_NEXT_ULONG( p );
  3010.     nondefOff = TT_PEEK_ULONG( p );
  3011.  
  3012.     if ( defOff != 0                                                    &&
  3013.          tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
  3014.     {
  3015.       /* This is the default variant of this charcode.  GID not stored */
  3016.       /* here; stored in the normal Unicode charmap instead.           */
  3017.       return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode );
  3018.     }
  3019.  
  3020.     if ( nondefOff != 0 )
  3021.       return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
  3022.                                                charcode );
  3023.  
  3024.     return 0;
  3025.   }
  3026.  
  3027.  
  3028.   FT_CALLBACK_DEF( FT_Int )
  3029.   tt_cmap14_char_var_isdefault( TT_CMap    cmap,
  3030.                                 FT_UInt32  charcode,
  3031.                                 FT_UInt32  variantSelector )
  3032.   {
  3033.     FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
  3034.     FT_ULong  defOff;
  3035.     FT_ULong  nondefOff;
  3036.  
  3037.  
  3038.     if ( !p )
  3039.       return -1;
  3040.  
  3041.     defOff    = TT_NEXT_ULONG( p );
  3042.     nondefOff = TT_NEXT_ULONG( p );
  3043.  
  3044.     if ( defOff != 0                                                    &&
  3045.          tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
  3046.       return 1;
  3047.  
  3048.     if ( nondefOff != 0                                            &&
  3049.          tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
  3050.                                            charcode ) != 0         )
  3051.       return 0;
  3052.  
  3053.     return -1;
  3054.   }
  3055.  
  3056.  
  3057.   FT_CALLBACK_DEF( FT_UInt32* )
  3058.   tt_cmap14_variants( TT_CMap    cmap,
  3059.                       FT_Memory  memory )
  3060.   {
  3061.     TT_CMap14   cmap14 = (TT_CMap14)cmap;
  3062.     FT_UInt32   count  = cmap14->num_selectors;
  3063.     FT_Byte*    p      = cmap->data + 10;
  3064.     FT_UInt32*  result;
  3065.     FT_UInt32   i;
  3066.  
  3067.  
  3068.     if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
  3069.       return NULL;
  3070.  
  3071.     result = cmap14->results;
  3072.     for ( i = 0; i < count; ++i )
  3073.     {
  3074.       result[i] = (FT_UInt32)TT_NEXT_UINT24( p );
  3075.       p        += 8;
  3076.     }
  3077.     result[i] = 0;
  3078.  
  3079.     return result;
  3080.   }
  3081.  
  3082.  
  3083.   FT_CALLBACK_DEF( FT_UInt32 * )
  3084.   tt_cmap14_char_variants( TT_CMap    cmap,
  3085.                            FT_Memory  memory,
  3086.                            FT_UInt32  charCode )
  3087.   {
  3088.     TT_CMap14   cmap14 = (TT_CMap14)  cmap;
  3089.     FT_UInt32   count  = cmap14->num_selectors;
  3090.     FT_Byte*    p      = cmap->data + 10;
  3091.     FT_UInt32*  q;
  3092.  
  3093.  
  3094.     if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
  3095.       return NULL;
  3096.  
  3097.     for ( q = cmap14->results; count > 0; --count )
  3098.     {
  3099.       FT_UInt32  varSel    = TT_NEXT_UINT24( p );
  3100.       FT_ULong   defOff    = TT_NEXT_ULONG( p );
  3101.       FT_ULong   nondefOff = TT_NEXT_ULONG( p );
  3102.  
  3103.  
  3104.       if ( ( defOff != 0                                               &&
  3105.              tt_cmap14_char_map_def_binary( cmap->data + defOff,
  3106.                                             charCode )                 ) ||
  3107.            ( nondefOff != 0                                            &&
  3108.              tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
  3109.                                                charCode ) != 0         ) )
  3110.       {
  3111.         q[0] = varSel;
  3112.         q++;
  3113.       }
  3114.     }
  3115.     q[0] = 0;
  3116.  
  3117.     return cmap14->results;
  3118.   }
  3119.  
  3120.  
  3121.   static FT_UInt
  3122.   tt_cmap14_def_char_count( FT_Byte  *p )
  3123.   {
  3124.     FT_UInt32  numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
  3125.     FT_UInt    tot       = 0;
  3126.  
  3127.  
  3128.     p += 3;  /* point to the first `cnt' field */
  3129.     for ( ; numRanges > 0; numRanges-- )
  3130.     {
  3131.       tot += 1 + p[0];
  3132.       p   += 4;
  3133.     }
  3134.  
  3135.     return tot;
  3136.   }
  3137.  
  3138.  
  3139.   static FT_UInt32*
  3140.   tt_cmap14_get_def_chars( TT_CMap    cmap,
  3141.                            FT_Byte*   p,
  3142.                            FT_Memory  memory )
  3143.   {
  3144.     TT_CMap14   cmap14 = (TT_CMap14) cmap;
  3145.     FT_UInt32   numRanges;
  3146.     FT_UInt     cnt;
  3147.     FT_UInt32*  q;
  3148.  
  3149.  
  3150.     cnt       = tt_cmap14_def_char_count( p );
  3151.     numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
  3152.  
  3153.     if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) )
  3154.       return NULL;
  3155.  
  3156.     for ( q = cmap14->results; numRanges > 0; --numRanges )
  3157.     {
  3158.       FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
  3159.  
  3160.  
  3161.       cnt = FT_NEXT_BYTE( p ) + 1;
  3162.       do
  3163.       {
  3164.         q[0]  = uni;
  3165.         uni  += 1;
  3166.         q    += 1;
  3167.  
  3168.       } while ( --cnt != 0 );
  3169.     }
  3170.     q[0] = 0;
  3171.  
  3172.     return cmap14->results;
  3173.   }
  3174.  
  3175.  
  3176.   static FT_UInt32*
  3177.   tt_cmap14_get_nondef_chars( TT_CMap     cmap,
  3178.                               FT_Byte    *p,
  3179.                               FT_Memory   memory )
  3180.   {
  3181.     TT_CMap14   cmap14 = (TT_CMap14) cmap;
  3182.     FT_UInt32   numMappings;
  3183.     FT_UInt     i;
  3184.     FT_UInt32  *ret;
  3185.  
  3186.  
  3187.     numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
  3188.  
  3189.     if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) )
  3190.       return NULL;
  3191.  
  3192.     ret = cmap14->results;
  3193.     for ( i = 0; i < numMappings; ++i )
  3194.     {
  3195.       ret[i] = (FT_UInt32)TT_NEXT_UINT24( p );
  3196.       p += 2;
  3197.     }
  3198.     ret[i] = 0;
  3199.  
  3200.     return ret;
  3201.   }
  3202.  
  3203.  
  3204.   FT_CALLBACK_DEF( FT_UInt32 * )
  3205.   tt_cmap14_variant_chars( TT_CMap    cmap,
  3206.                            FT_Memory  memory,
  3207.                            FT_UInt32  variantSelector )
  3208.   {
  3209.     FT_Byte    *p  = tt_cmap14_find_variant( cmap->data + 6,
  3210.                                              variantSelector );
  3211.     FT_UInt32  *ret;
  3212.     FT_Int      i;
  3213.     FT_ULong    defOff;
  3214.     FT_ULong    nondefOff;
  3215.  
  3216.  
  3217.     if ( !p )
  3218.       return NULL;
  3219.  
  3220.     defOff    = TT_NEXT_ULONG( p );
  3221.     nondefOff = TT_NEXT_ULONG( p );
  3222.  
  3223.     if ( defOff == 0 && nondefOff == 0 )
  3224.       return NULL;
  3225.  
  3226.     if ( defOff == 0 )
  3227.       return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
  3228.                                          memory );
  3229.     else if ( nondefOff == 0 )
  3230.       return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
  3231.                                       memory );
  3232.     else
  3233.     {
  3234.       /* Both a default and a non-default glyph set?  That's probably not */
  3235.       /* good font design, but the spec allows for it...                  */
  3236.       TT_CMap14  cmap14 = (TT_CMap14) cmap;
  3237.       FT_UInt32  numRanges;
  3238.       FT_UInt32  numMappings;
  3239.       FT_UInt32  duni;
  3240.       FT_UInt32  dcnt;
  3241.       FT_UInt32  nuni;
  3242.       FT_Byte*   dp;
  3243.       FT_UInt    di, ni, k;
  3244.  
  3245.  
  3246.       p  = cmap->data + nondefOff;
  3247.       dp = cmap->data + defOff;
  3248.  
  3249.       numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
  3250.       dcnt        = tt_cmap14_def_char_count( dp );
  3251.       numRanges   = (FT_UInt32)TT_NEXT_ULONG( dp );
  3252.  
  3253.       if ( numMappings == 0 )
  3254.         return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
  3255.                                         memory );
  3256.       if ( dcnt == 0 )
  3257.         return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
  3258.                                            memory );
  3259.  
  3260.       if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) )
  3261.         return NULL;
  3262.  
  3263.       ret  = cmap14->results;
  3264.       duni = (FT_UInt32)TT_NEXT_UINT24( dp );
  3265.       dcnt = FT_NEXT_BYTE( dp );
  3266.       di   = 1;
  3267.       nuni = (FT_UInt32)TT_NEXT_UINT24( p );
  3268.       p   += 2;
  3269.       ni   = 1;
  3270.       i    = 0;
  3271.  
  3272.       for ( ;; )
  3273.       {
  3274.         if ( nuni > duni + dcnt )
  3275.         {
  3276.           for ( k = 0; k <= dcnt; ++k )
  3277.             ret[i++] = duni + k;
  3278.  
  3279.           ++di;
  3280.  
  3281.           if ( di > numRanges )
  3282.             break;
  3283.  
  3284.           duni = (FT_UInt32)TT_NEXT_UINT24( dp );
  3285.           dcnt = FT_NEXT_BYTE( dp );
  3286.         }
  3287.         else
  3288.         {
  3289.           if ( nuni < duni )
  3290.             ret[i++] = nuni;
  3291.           /* If it is within the default range then ignore it -- */
  3292.           /* that should not have happened                       */
  3293.           ++ni;
  3294.           if ( ni > numMappings )
  3295.             break;
  3296.  
  3297.           nuni = (FT_UInt32)TT_NEXT_UINT24( p );
  3298.           p += 2;
  3299.         }
  3300.       }
  3301.  
  3302.       if ( ni <= numMappings )
  3303.       {
  3304.         /* If we get here then we have run out of all default ranges.   */
  3305.         /* We have read one non-default mapping which we haven't stored */
  3306.         /* and there may be others that need to be read.                */
  3307.         ret[i++] = nuni;
  3308.         while ( ni < numMappings )
  3309.         {
  3310.           ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p );
  3311.           p += 2;
  3312.           ++ni;
  3313.         }
  3314.       }
  3315.       else if ( di <= numRanges )
  3316.       {
  3317.         /* If we get here then we have run out of all non-default     */
  3318.         /* mappings.  We have read one default range which we haven't */
  3319.         /* stored and there may be others that need to be read.       */
  3320.         for ( k = 0; k <= dcnt; ++k )
  3321.           ret[i++] = duni + k;
  3322.  
  3323.         while ( di < numRanges )
  3324.         {
  3325.           duni = (FT_UInt32)TT_NEXT_UINT24( dp );
  3326.           dcnt = FT_NEXT_BYTE( dp );
  3327.  
  3328.           for ( k = 0; k <= dcnt; ++k )
  3329.             ret[i++] = duni + k;
  3330.           ++di;
  3331.         }
  3332.       }
  3333.  
  3334.       ret[i] = 0;
  3335.  
  3336.       return ret;
  3337.     }
  3338.   }
  3339.  
  3340.  
  3341.   FT_DEFINE_TT_CMAP(
  3342.     tt_cmap14_class_rec,
  3343.     sizeof ( TT_CMap14Rec ),
  3344.  
  3345.     (FT_CMap_InitFunc)     tt_cmap14_init,
  3346.     (FT_CMap_DoneFunc)     tt_cmap14_done,
  3347.     (FT_CMap_CharIndexFunc)tt_cmap14_char_index,
  3348.     (FT_CMap_CharNextFunc) tt_cmap14_char_next,
  3349.  
  3350.     /* Format 14 extension functions */
  3351.     (FT_CMap_CharVarIndexFunc)    tt_cmap14_char_var_index,
  3352.     (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
  3353.     (FT_CMap_VariantListFunc)     tt_cmap14_variants,
  3354.     (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
  3355.     (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars,
  3356.  
  3357.     14,
  3358.     (TT_CMap_ValidateFunc)tt_cmap14_validate,
  3359.     (TT_CMap_Info_GetFunc)tt_cmap14_get_info )
  3360.  
  3361. #endif /* TT_CONFIG_CMAP_FORMAT_14 */
  3362.  
  3363.  
  3364. #ifndef FT_CONFIG_OPTION_PIC
  3365.  
  3366.   static const TT_CMap_Class  tt_cmap_classes[] =
  3367.   {
  3368. #define TTCMAPCITEM( a )  &a,
  3369. #include "ttcmapc.h"
  3370.     NULL,
  3371.   };
  3372.  
  3373. #else /*FT_CONFIG_OPTION_PIC*/
  3374.  
  3375.   void
  3376.   FT_Destroy_Class_tt_cmap_classes( FT_Library      library,
  3377.                                     TT_CMap_Class*  clazz )
  3378.   {
  3379.     FT_Memory  memory = library->memory;
  3380.  
  3381.  
  3382.     if ( clazz )
  3383.       FT_FREE( clazz );
  3384.   }
  3385.  
  3386.  
  3387.   FT_Error
  3388.   FT_Create_Class_tt_cmap_classes( FT_Library       library,
  3389.                                    TT_CMap_Class**  output_class )
  3390.   {
  3391.     TT_CMap_Class*     clazz  = NULL;
  3392.     TT_CMap_ClassRec*  recs;
  3393.     FT_Error           error;
  3394.     FT_Memory          memory = library->memory;
  3395.  
  3396.     int  i = 0;
  3397.  
  3398.  
  3399. #define TTCMAPCITEM( a ) i++;
  3400. #include "ttcmapc.h"
  3401.  
  3402.     /* allocate enough space for both the pointers */
  3403.     /* plus terminator and the class instances     */
  3404.     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * ( i + 1 ) +
  3405.                           sizeof ( TT_CMap_ClassRec ) * i ) )
  3406.       return error;
  3407.  
  3408.     /* the location of the class instances follows the array of pointers */
  3409.     recs = (TT_CMap_ClassRec*)( (char*)clazz +
  3410.                                 sizeof ( *clazz ) * ( i + 1 ) );
  3411.     i    = 0;
  3412.  
  3413. #undef TTCMAPCITEM
  3414. #define  TTCMAPCITEM( a )             \
  3415.     FT_Init_Class_ ## a( &recs[i] );  \
  3416.     clazz[i] = &recs[i];              \
  3417.     i++;
  3418. #include "ttcmapc.h"
  3419.  
  3420.     clazz[i] = NULL;
  3421.  
  3422.     *output_class = clazz;
  3423.     return FT_Err_Ok;
  3424.   }
  3425.  
  3426. #endif /*FT_CONFIG_OPTION_PIC*/
  3427.  
  3428.  
  3429.   /* parse the `cmap' table and build the corresponding TT_CMap objects */
  3430.   /* in the current face                                                */
  3431.   /*                                                                    */
  3432.   FT_LOCAL_DEF( FT_Error )
  3433.   tt_face_build_cmaps( TT_Face  face )
  3434.   {
  3435.     FT_Byte*           table = face->cmap_table;
  3436.     FT_Byte*           limit = table + face->cmap_size;
  3437.     FT_UInt volatile   num_cmaps;
  3438.     FT_Byte* volatile  p     = table;
  3439.     FT_Library         library = FT_FACE_LIBRARY( face );
  3440.  
  3441.     FT_UNUSED( library );
  3442.  
  3443.  
  3444.     if ( !p || p + 4 > limit )
  3445.       return FT_THROW( Invalid_Table );
  3446.  
  3447.     /* only recognize format 0 */
  3448.     if ( TT_NEXT_USHORT( p ) != 0 )
  3449.     {
  3450.       p -= 2;
  3451.       FT_ERROR(( "tt_face_build_cmaps:"
  3452.                  " unsupported `cmap' table format = %d\n",
  3453.                  TT_PEEK_USHORT( p ) ));
  3454.       return FT_THROW( Invalid_Table );
  3455.     }
  3456.  
  3457.     num_cmaps = TT_NEXT_USHORT( p );
  3458.  
  3459. #ifdef FT_MAX_CHARMAP_CACHEABLE
  3460.     if ( num_cmaps > FT_MAX_CHARMAP_CACHEABLE )
  3461.       FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables (%d)\n"
  3462.                  "                     subtable #%d and higher are loaded"
  3463.                  "                     but cannot be searched\n",
  3464.                  num_cmaps, FT_MAX_CHARMAP_CACHEABLE + 1 ));
  3465. #endif
  3466.  
  3467.     for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
  3468.     {
  3469.       FT_CharMapRec  charmap;
  3470.       FT_UInt32      offset;
  3471.  
  3472.  
  3473.       charmap.platform_id = TT_NEXT_USHORT( p );
  3474.       charmap.encoding_id = TT_NEXT_USHORT( p );
  3475.       charmap.face        = FT_FACE( face );
  3476.       charmap.encoding    = FT_ENCODING_NONE;  /* will be filled later */
  3477.       offset              = TT_NEXT_ULONG( p );
  3478.  
  3479.       if ( offset && offset <= face->cmap_size - 2 )
  3480.       {
  3481.         FT_Byte* volatile              cmap   = table + offset;
  3482.         volatile FT_UInt               format = TT_PEEK_USHORT( cmap );
  3483.         const TT_CMap_Class* volatile  pclazz = TT_CMAP_CLASSES_GET;
  3484.         TT_CMap_Class volatile         clazz;
  3485.  
  3486.  
  3487.         for ( ; *pclazz; pclazz++ )
  3488.         {
  3489.           clazz = *pclazz;
  3490.           if ( clazz->format == format )
  3491.           {
  3492.             volatile TT_ValidatorRec  valid;
  3493.             volatile FT_Error         error = FT_Err_Ok;
  3494.  
  3495.  
  3496.             ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
  3497.                                FT_VALIDATE_DEFAULT );
  3498.  
  3499.             valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
  3500.  
  3501.             if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer) == 0 )
  3502.             {
  3503.               /* validate this cmap sub-table */
  3504.               error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
  3505.             }
  3506.  
  3507.             if ( valid.validator.error == 0 )
  3508.             {
  3509.               FT_CMap  ttcmap;
  3510.  
  3511.  
  3512.               /* It might make sense to store the single variation         */
  3513.               /* selector cmap somewhere special.  But it would have to be */
  3514.               /* in the public FT_FaceRec, and we can't change that.       */
  3515.  
  3516.               if ( !FT_CMap_New( (FT_CMap_Class)clazz,
  3517.                                  cmap, &charmap, &ttcmap ) )
  3518.               {
  3519.                 /* it is simpler to directly set `flags' than adding */
  3520.                 /* a parameter to FT_CMap_New                        */
  3521.                 ((TT_CMap)ttcmap)->flags = (FT_Int)error;
  3522.               }
  3523.             }
  3524.             else
  3525.             {
  3526.               FT_TRACE0(( "tt_face_build_cmaps:"
  3527.                           " broken cmap sub-table ignored\n" ));
  3528.             }
  3529.             break;
  3530.           }
  3531.         }
  3532.  
  3533.         if ( *pclazz == NULL )
  3534.         {
  3535.           FT_TRACE0(( "tt_face_build_cmaps:"
  3536.                       " unsupported cmap sub-table ignored\n" ));
  3537.         }
  3538.       }
  3539.     }
  3540.  
  3541.     return FT_Err_Ok;
  3542.   }
  3543.  
  3544.  
  3545.   FT_LOCAL( FT_Error )
  3546.   tt_get_cmap_info( FT_CharMap    charmap,
  3547.                     TT_CMapInfo  *cmap_info )
  3548.   {
  3549.     FT_CMap        cmap  = (FT_CMap)charmap;
  3550.     TT_CMap_Class  clazz = (TT_CMap_Class)cmap->clazz;
  3551.  
  3552.  
  3553.     return clazz->get_cmap_info( charmap, cmap_info );
  3554.   }
  3555.  
  3556.  
  3557. /* END */
  3558.