ttcmap.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:71k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ttcmap.c                                                               */
  4. /*                                                                         */
  5. /*    TrueType character mapping table (cmap) support (body).              */
  6. /*                                                                         */
  7. /*  Copyright 2002, 2003, 2004, 2005, 2006, 2007 by                        */
  8. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  9. /*                                                                         */
  10. /*  This file is part of the FreeType project, and may only be used,       */
  11. /*  modified, and distributed under the terms of the FreeType project      */
  12. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13. /*  this file you indicate that you have read the license and              */
  14. /*  understand and accept it fully.                                        */
  15. /*                                                                         */
  16. /***************************************************************************/
  17. #include <ft2build.h>
  18. #include FT_INTERNAL_DEBUG_H
  19. #include "sferrors.h"           /* must come before FT_INTERNAL_VALIDATE_H */
  20. #include FT_INTERNAL_VALIDATE_H
  21. #include FT_INTERNAL_STREAM_H
  22. #include "ttload.h"
  23. #include "ttcmap.h"
  24.   /*************************************************************************/
  25.   /*                                                                       */
  26.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  27.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  28.   /* messages during execution.                                            */
  29.   /*                                                                       */
  30. #undef  FT_COMPONENT
  31. #define FT_COMPONENT  trace_ttcmap
  32. #define TT_PEEK_SHORT   FT_PEEK_SHORT
  33. #define TT_PEEK_USHORT  FT_PEEK_USHORT
  34. #define TT_PEEK_LONG    FT_PEEK_LONG
  35. #define TT_PEEK_ULONG   FT_PEEK_ULONG
  36. #define TT_NEXT_SHORT   FT_NEXT_SHORT
  37. #define TT_NEXT_USHORT  FT_NEXT_USHORT
  38. #define TT_NEXT_LONG    FT_NEXT_LONG
  39. #define TT_NEXT_ULONG   FT_NEXT_ULONG
  40.   FT_CALLBACK_DEF( FT_Error )
  41.   tt_cmap_init( TT_CMap   cmap,
  42.                 FT_Byte*  table )
  43.   {
  44.     cmap->data = table;
  45.     return SFNT_Err_Ok;
  46.   }
  47.   /*************************************************************************/
  48.   /*************************************************************************/
  49.   /*****                                                               *****/
  50.   /*****                           FORMAT 0                            *****/
  51.   /*****                                                               *****/
  52.   /*************************************************************************/
  53.   /*************************************************************************/
  54.   /*************************************************************************/
  55.   /*                                                                       */
  56.   /* TABLE OVERVIEW                                                        */
  57.   /* --------------                                                        */
  58.   /*                                                                       */
  59.   /*   NAME        OFFSET         TYPE          DESCRIPTION                */
  60.   /*                                                                       */
  61.   /*   format      0              USHORT        must be 0                  */
  62.   /*   length      2              USHORT        table length in bytes      */
  63.   /*   language    4              USHORT        Mac language code          */
  64.   /*   glyph_ids   6              BYTE[256]     array of glyph indices     */
  65.   /*               262                                                     */
  66.   /*                                                                       */
  67. #ifdef TT_CONFIG_CMAP_FORMAT_0
  68.   FT_CALLBACK_DEF( FT_Error )
  69.   tt_cmap0_validate( FT_Byte*      table,
  70.                      FT_Validator  valid )
  71.   {
  72.     FT_Byte*  p      = table + 2;
  73.     FT_UInt   length = TT_NEXT_USHORT( p );
  74.     if ( table + length > valid->limit || length < 262 )
  75.       FT_INVALID_TOO_SHORT;
  76.     /* check glyph indices whenever necessary */
  77.     if ( valid->level >= FT_VALIDATE_TIGHT )
  78.     {
  79.       FT_UInt  n, idx;
  80.       p = table + 6;
  81.       for ( n = 0; n < 256; n++ )
  82.       {
  83.         idx = *p++;
  84.         if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
  85.           FT_INVALID_GLYPH_ID;
  86.       }
  87.     }
  88.     return SFNT_Err_Ok;
  89.   }
  90.   FT_CALLBACK_DEF( FT_UInt )
  91.   tt_cmap0_char_index( TT_CMap    cmap,
  92.                        FT_UInt32  char_code )
  93.   {
  94.     FT_Byte*  table = cmap->data;
  95.     return char_code < 256 ? table[6 + char_code] : 0;
  96.   }
  97.   FT_CALLBACK_DEF( FT_UInt )
  98.   tt_cmap0_char_next( TT_CMap     cmap,
  99.                       FT_UInt32  *pchar_code )
  100.   {
  101.     FT_Byte*   table    = cmap->data;
  102.     FT_UInt32  charcode = *pchar_code;
  103.     FT_UInt32  result   = 0;
  104.     FT_UInt    gindex   = 0;
  105.     table += 6;  /* go to glyph ids */
  106.     while ( ++charcode < 256 )
  107.     {
  108.       gindex = table[charcode];
  109.       if ( gindex != 0 )
  110.       {
  111.         result = charcode;
  112.         break;
  113.       }
  114.     }
  115.     *pchar_code = result;
  116.     return gindex;
  117.   }
  118.   FT_CALLBACK_DEF( FT_Error )
  119.   tt_cmap0_get_info( TT_CMap       cmap,
  120.                      TT_CMapInfo  *cmap_info )
  121.   {
  122.     FT_Byte*  p = cmap->data + 4;
  123.     cmap_info->format = 0;
  124.     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
  125.     return SFNT_Err_Ok;
  126.   }
  127.   FT_CALLBACK_TABLE_DEF
  128.   const TT_CMap_ClassRec  tt_cmap0_class_rec =
  129.   {
  130.     {
  131.       sizeof ( TT_CMapRec ),
  132.       (FT_CMap_InitFunc)     tt_cmap_init,
  133.       (FT_CMap_DoneFunc)     NULL,
  134.       (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
  135.       (FT_CMap_CharNextFunc) tt_cmap0_char_next
  136.     },
  137.     0,
  138.     (TT_CMap_ValidateFunc)   tt_cmap0_validate,
  139.     (TT_CMap_Info_GetFunc)   tt_cmap0_get_info
  140.   };
  141. #endif /* TT_CONFIG_CMAP_FORMAT_0 */
  142.   /*************************************************************************/
  143.   /*************************************************************************/
  144.   /*****                                                               *****/
  145.   /*****                          FORMAT 2                             *****/
  146.   /*****                                                               *****/
  147.   /***** This is used for certain CJK encodings that encode text in a  *****/
  148.   /***** mixed 8/16 bits encoding along the following lines:           *****/
  149.   /*****                                                               *****/
  150.   /***** * Certain byte values correspond to an 8-bit character code   *****/
  151.   /*****   (typically in the range 0..127 for ASCII compatibility).    *****/
  152.   /*****                                                               *****/
  153.   /***** * Certain byte values signal the first byte of a 2-byte       *****/
  154.   /*****   character code (but these values are also valid as the      *****/
  155.   /*****   second byte of a 2-byte character).                         *****/
  156.   /*****                                                               *****/
  157.   /***** The following charmap lookup and iteration functions all      *****/
  158.   /***** assume that the value "charcode" correspond to following:     *****/
  159.   /*****                                                               *****/
  160.   /*****   - For one byte characters, "charcode" is simply the         *****/
  161.   /*****     character code.                                           *****/
  162.   /*****                                                               *****/
  163.   /*****   - For two byte characters, "charcode" is the 2-byte         *****/
  164.   /*****     character code in big endian format.  More exactly:       *****/
  165.   /*****                                                               *****/
  166.   /*****       (charcode >> 8)    is the first byte value              *****/
  167.   /*****       (charcode & 0xFF)  is the second byte value             *****/
  168.   /*****                                                               *****/
  169.   /***** Note that not all values of "charcode" are valid according    *****/
  170.   /***** to these rules, and the function moderately check the         *****/
  171.   /***** arguments.                                                    *****/
  172.   /*****                                                               *****/
  173.   /*************************************************************************/
  174.   /*************************************************************************/
  175.   /*************************************************************************/
  176.   /*                                                                       */
  177.   /* TABLE OVERVIEW                                                        */
  178.   /* --------------                                                        */
  179.   /*                                                                       */
  180.   /*   NAME        OFFSET         TYPE            DESCRIPTION              */
  181.   /*                                                                       */
  182.   /*   format      0              USHORT          must be 2                */
  183.   /*   length      2              USHORT          table length in bytes    */
  184.   /*   language    4              USHORT          Mac language code        */
  185.   /*   keys        6              USHORT[256]     sub-header keys          */
  186.   /*   subs        518            SUBHEAD[NSUBS]  sub-headers array        */
  187.   /*   glyph_ids   518+NSUB*8     USHORT[]        glyph id array           */
  188.   /*                                                                       */
  189.   /* The `keys' table is used to map charcode high-bytes to sub-headers.   */
  190.   /* The value of `NSUBS' is the number of sub-headers defined in the      */
  191.   /* table and is computed by finding the maximum of the `keys' table.     */
  192.   /*                                                                       */
  193.   /* Note that for any n, `keys[n]' is a byte offset within the `subs'     */
  194.   /* table, i.e., it is the corresponding sub-header index multiplied      */
  195.   /* by 8.                                                                 */
  196.   /*                                                                       */
  197.   /* Each sub-header has the following format:                             */
  198.   /*                                                                       */
  199.   /*   NAME        OFFSET      TYPE            DESCRIPTION                 */
  200.   /*                                                                       */
  201.   /*   first       0           USHORT          first valid low-byte        */
  202.   /*   count       2           USHORT          number of valid low-bytes   */
  203.   /*   delta       4           SHORT           see below                   */
  204.   /*   offset      6           USHORT          see below                   */
  205.   /*                                                                       */
  206.   /* A sub-header defines, for each high-byte, the range of valid          */
  207.   /* low-bytes within the charmap.  Note that the range defined by `first' */
  208.   /* and `count' must be completely included in the interval [0..255]      */
  209.   /* according to the specification.                                       */
  210.   /*                                                                       */
  211.   /* If a character code is contained within a given sub-header, then      */
  212.   /* mapping it to a glyph index is done as follows:                       */
  213.   /*                                                                       */
  214.   /* * The value of `offset' is read.  This is a _byte_ distance from the  */
  215.   /*   location of the `offset' field itself into a slice of the           */
  216.   /*   `glyph_ids' table.  Let's call it `slice' (it's a USHORT[] too).    */
  217.   /*                                                                       */
  218.   /* * The value `slice[char.lo - first]' is read.  If it is 0, there is   */
  219.   /*   no glyph for the charcode.  Otherwise, the value of `delta' is      */
  220.   /*   added to it (modulo 65536) to form a new glyph index.               */
  221.   /*                                                                       */
  222.   /* It is up to the validation routine to check that all offsets fall     */
  223.   /* within the glyph ids table (and not within the `subs' table itself or */
  224.   /* outside of the CMap).                                                 */
  225.   /*                                                                       */
  226. #ifdef TT_CONFIG_CMAP_FORMAT_2
  227.   FT_CALLBACK_DEF( FT_Error )
  228.   tt_cmap2_validate( FT_Byte*      table,
  229.                      FT_Validator  valid )
  230.   {
  231.     FT_Byte*  p      = table + 2;           /* skip format */
  232.     FT_UInt   length = TT_PEEK_USHORT( p );
  233.     FT_UInt   n, max_subs;
  234.     FT_Byte*  keys;                         /* keys table */
  235.     FT_Byte*  subs;                         /* sub-headers */
  236.     FT_Byte*  glyph_ids;                    /* glyph id array */
  237.     if ( table + length > valid->limit || length < 6 + 512 )
  238.       FT_INVALID_TOO_SHORT;
  239.     keys = table + 6;
  240.     /* parse keys to compute sub-headers count */
  241.     p        = keys;
  242.     max_subs = 0;
  243.     for ( n = 0; n < 256; n++ )
  244.     {
  245.       FT_UInt  idx = TT_NEXT_USHORT( p );
  246.       /* value must be multiple of 8 */
  247.       if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
  248.         FT_INVALID_DATA;
  249.       idx >>= 3;
  250.       if ( idx > max_subs )
  251.         max_subs = idx;
  252.     }
  253.     FT_ASSERT( p == table + 518 );
  254.     subs      = p;
  255.     glyph_ids = subs + (max_subs + 1) * 8;
  256.     if ( glyph_ids > valid->limit )
  257.       FT_INVALID_TOO_SHORT;
  258.     /* parse sub-headers */
  259.     for ( n = 0; n <= max_subs; n++ )
  260.     {
  261.       FT_UInt   first_code, code_count, offset;
  262.       FT_Int    delta;
  263.       FT_Byte*  ids;
  264.       first_code = TT_NEXT_USHORT( p );
  265.       code_count = TT_NEXT_USHORT( p );
  266.       delta      = TT_NEXT_SHORT( p );
  267.       offset     = TT_NEXT_USHORT( p );
  268.       /* check range within 0..255 */
  269.       if ( valid->level >= FT_VALIDATE_PARANOID )
  270.       {
  271.         if ( first_code >= 256 || first_code + code_count > 256 )
  272.           FT_INVALID_DATA;
  273.       }
  274.       /* check offset */
  275.       if ( offset != 0 )
  276.       {
  277.         ids = p - 2 + offset;
  278.         if ( ids < glyph_ids || ids + code_count*2 > table + length )
  279.           FT_INVALID_OFFSET;
  280.         /* check glyph ids */
  281.         if ( valid->level >= FT_VALIDATE_TIGHT )
  282.         {
  283.           FT_Byte*  limit = p + code_count * 2;
  284.           FT_UInt   idx;
  285.           for ( ; p < limit; )
  286.           {
  287.             idx = TT_NEXT_USHORT( p );
  288.             if ( idx != 0 )
  289.             {
  290.               idx = ( idx + delta ) & 0xFFFFU;
  291.               if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
  292.                 FT_INVALID_GLYPH_ID;
  293.             }
  294.           }
  295.         }
  296.       }
  297.     }
  298.     return SFNT_Err_Ok;
  299.   }
  300.   /* return sub header corresponding to a given character code */
  301.   /* NULL on invalid charcode                                  */
  302.   static FT_Byte*
  303.   tt_cmap2_get_subheader( FT_Byte*   table,
  304.                           FT_UInt32  char_code )
  305.   {
  306.     FT_Byte*  result = NULL;
  307.     if ( char_code < 0x10000UL )
  308.     {
  309.       FT_UInt   char_lo = (FT_UInt)( char_code & 0xFF );
  310.       FT_UInt   char_hi = (FT_UInt)( char_code >> 8 );
  311.       FT_Byte*  p       = table + 6;    /* keys table */
  312.       FT_Byte*  subs    = table + 518;  /* subheaders table */
  313.       FT_Byte*  sub;
  314.       if ( char_hi == 0 )
  315.       {
  316.         /* an 8-bit character code -- we use subHeader 0 in this case */
  317.         /* to test whether the character code is in the charmap       */
  318.         /*                                                            */
  319.         sub = subs;  /* jump to first sub-header */
  320.         /* check that the sub-header for this byte is 0, which */
  321.         /* indicates that it's really a valid one-byte value   */
  322.         /* Otherwise, return 0                                 */
  323.         /*                                                     */
  324.         p += char_lo * 2;
  325.         if ( TT_PEEK_USHORT( p ) != 0 )
  326.           goto Exit;
  327.       }
  328.       else
  329.       {
  330.         /* a 16-bit character code */
  331.         /* jump to key entry  */
  332.         p  += char_hi * 2;
  333.         /* jump to sub-header */
  334.         sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) );
  335.         /* check that the high byte isn't a valid one-byte value */
  336.         if ( sub == subs )
  337.           goto Exit;
  338.       }
  339.       result = sub;
  340.     }
  341.   Exit:
  342.     return result;
  343.   }
  344.   FT_CALLBACK_DEF( FT_UInt )
  345.   tt_cmap2_char_index( TT_CMap    cmap,
  346.                        FT_UInt32  char_code )
  347.   {
  348.     FT_Byte*  table   = cmap->data;
  349.     FT_UInt   result  = 0;
  350.     FT_Byte*  subheader;
  351.     subheader = tt_cmap2_get_subheader( table, char_code );
  352.     if ( subheader )
  353.     {
  354.       FT_Byte*  p   = subheader;
  355.       FT_UInt   idx = (FT_UInt)(char_code & 0xFF);
  356.       FT_UInt   start, count;
  357.       FT_Int    delta;
  358.       FT_UInt   offset;
  359.       start  = TT_NEXT_USHORT( p );
  360.       count  = TT_NEXT_USHORT( p );
  361.       delta  = TT_NEXT_SHORT ( p );
  362.       offset = TT_PEEK_USHORT( p );
  363.       idx -= start;
  364.       if ( idx < count && offset != 0 )
  365.       {
  366.         p  += offset + 2 * idx;
  367.         idx = TT_PEEK_USHORT( p );
  368.         if ( idx != 0 )
  369.           result = (FT_UInt)( idx + delta ) & 0xFFFFU;
  370.       }
  371.     }
  372.     return result;
  373.   }
  374.   FT_CALLBACK_DEF( FT_UInt )
  375.   tt_cmap2_char_next( TT_CMap     cmap,
  376.                       FT_UInt32  *pcharcode )
  377.   {
  378.     FT_Byte*   table    = cmap->data;
  379.     FT_UInt    gindex   = 0;
  380.     FT_UInt32  result   = 0;
  381.     FT_UInt32  charcode = *pcharcode + 1;
  382.     FT_Byte*   subheader;
  383.     while ( charcode < 0x10000UL )
  384.     {
  385.       subheader = tt_cmap2_get_subheader( table, charcode );
  386.       if ( subheader )
  387.       {
  388.         FT_Byte*  p       = subheader;
  389.         FT_UInt   start   = TT_NEXT_USHORT( p );
  390.         FT_UInt   count   = TT_NEXT_USHORT( p );
  391.         FT_Int    delta   = TT_NEXT_SHORT ( p );
  392.         FT_UInt   offset  = TT_PEEK_USHORT( p );
  393.         FT_UInt   char_lo = (FT_UInt)( charcode & 0xFF );
  394.         FT_UInt   pos, idx;
  395.         if ( offset == 0 )
  396.           goto Next_SubHeader;
  397.         if ( char_lo < start )
  398.         {
  399.           char_lo = start;
  400.           pos     = 0;
  401.         }
  402.         else
  403.           pos = (FT_UInt)( char_lo - start );
  404.         p       += offset + pos * 2;
  405.         charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo;
  406.         for ( ; pos < count; pos++, charcode++ )
  407.         {
  408.           idx = TT_NEXT_USHORT( p );
  409.           if ( idx != 0 )
  410.           {
  411.             gindex = ( idx + delta ) & 0xFFFFU;
  412.             if ( gindex != 0 )
  413.             {
  414.               result = charcode;
  415.               goto Exit;
  416.             }
  417.           }
  418.         }
  419.       }
  420.       /* jump to next sub-header, i.e. higher byte value */
  421.     Next_SubHeader:
  422.       charcode = FT_PAD_FLOOR( charcode, 256 ) + 256;
  423.     }
  424.   Exit:
  425.     *pcharcode = result;
  426.     return gindex;
  427.   }
  428.   FT_CALLBACK_DEF( FT_Error )
  429.   tt_cmap2_get_info( TT_CMap       cmap,
  430.                      TT_CMapInfo  *cmap_info )
  431.   {
  432.     FT_Byte*  p = cmap->data + 4;
  433.     cmap_info->format = 2;
  434.     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
  435.     return SFNT_Err_Ok;
  436.   }
  437.   FT_CALLBACK_TABLE_DEF
  438.   const TT_CMap_ClassRec  tt_cmap2_class_rec =
  439.   {
  440.     {
  441.       sizeof ( TT_CMapRec ),
  442.       (FT_CMap_InitFunc)     tt_cmap_init,
  443.       (FT_CMap_DoneFunc)     NULL,
  444.       (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
  445.       (FT_CMap_CharNextFunc) tt_cmap2_char_next
  446.     },
  447.     2,
  448.     (TT_CMap_ValidateFunc)   tt_cmap2_validate,
  449.     (TT_CMap_Info_GetFunc)   tt_cmap2_get_info
  450.   };
  451. #endif /* TT_CONFIG_CMAP_FORMAT_2 */
  452.   /*************************************************************************/
  453.   /*************************************************************************/
  454.   /*****                                                               *****/
  455.   /*****                           FORMAT 4                            *****/
  456.   /*****                                                               *****/
  457.   /*************************************************************************/
  458.   /*************************************************************************/
  459.   /*************************************************************************/
  460.   /*                                                                       */
  461.   /* TABLE OVERVIEW                                                        */
  462.   /* --------------                                                        */
  463.   /*                                                                       */
  464.   /*   NAME          OFFSET         TYPE              DESCRIPTION          */
  465.   /*                                                                       */
  466.   /*   format        0              USHORT            must be 4            */
  467.   /*   length        2              USHORT            table length         */
  468.   /*                                                  in bytes             */
  469.   /*   language      4              USHORT            Mac language code    */
  470.   /*                                                                       */
  471.   /*   segCountX2    6              USHORT            2*NUM_SEGS           */
  472.   /*   searchRange   8              USHORT            2*(1 << LOG_SEGS)    */
  473.   /*   entrySelector 10             USHORT            LOG_SEGS             */
  474.   /*   rangeShift    12             USHORT            segCountX2 -         */
  475.   /*                                                    searchRange        */
  476.   /*                                                                       */
  477.   /*   endCount      14             USHORT[NUM_SEGS]  end charcode for     */
  478.   /*                                                  each segment; last   */
  479.   /*                                                  is 0xFFFF            */
  480.   /*                                                                       */
  481.   /*   pad           14+NUM_SEGS*2  USHORT            padding              */
  482.   /*                                                                       */
  483.   /*   startCount    16+NUM_SEGS*2  USHORT[NUM_SEGS]  first charcode for   */
  484.   /*                                                  each segment         */
  485.   /*                                                                       */
  486.   /*   idDelta       16+NUM_SEGS*4  SHORT[NUM_SEGS]   delta for each       */
  487.   /*                                                  segment              */
  488.   /*   idOffset      16+NUM_SEGS*6  SHORT[NUM_SEGS]   range offset for     */
  489.   /*                                                  each segment; can be */
  490.   /*                                                  zero                 */
  491.   /*                                                                       */
  492.   /*   glyphIds      16+NUM_SEGS*8  USHORT[]          array of glyph id    */
  493.   /*                                                  ranges               */
  494.   /*                                                                       */
  495.   /* Character codes are modelled by a series of ordered (increasing)      */
  496.   /* intervals called segments.  Each segment has start and end codes,     */
  497.   /* provided by the `startCount' and `endCount' arrays.  Segments must    */
  498.   /* not be overlapping and the last segment should always contain the     */
  499.   /* `0xFFFF' endCount.                                                    */
  500.   /*                                                                       */
  501.   /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
  502.   /* ignored (they are traces of over-engineering in the TrueType          */
  503.   /* specification).                                                       */
  504.   /*                                                                       */
  505.   /* Each segment also has a signed `delta', as well as an optional offset */
  506.   /* within the `glyphIds' table.                                          */
  507.   /*                                                                       */
  508.   /* If a segment's idOffset is 0, the glyph index corresponding to any    */
  509.   /* charcode within the segment is obtained by adding the value of        */
  510.   /* `idDelta' directly to the charcode, modulo 65536.                     */
  511.   /*                                                                       */
  512.   /* Otherwise, a glyph index is taken from the glyph ids sub-array for    */
  513.   /* the segment, and the value of `idDelta' is added to it.               */
  514.   /*                                                                       */
  515.   /*                                                                       */
  516.   /* Finally, note that certain fonts contain invalid charmaps that        */
  517.   /* contain end=0xFFFF, start=0xFFFF, delta=0x0001, offset=0xFFFF at the  */
  518.   /* of their charmaps (e.g. opens___.ttf which comes with OpenOffice.org) */
  519.   /* we need special code to deal with them correctly...                   */
  520.   /*                                                                       */
  521. #ifdef TT_CONFIG_CMAP_FORMAT_4
  522.   typedef struct  TT_CMap4Rec_
  523.   {
  524.     TT_CMapRec  cmap;
  525.     FT_UInt32   cur_charcode;   /* current charcode */
  526.     FT_UInt     cur_gindex;     /* current glyph index */
  527.     FT_UInt     num_ranges;
  528.     FT_UInt     cur_range;
  529.     FT_UInt     cur_start;
  530.     FT_UInt     cur_end;
  531.     FT_Int      cur_delta;
  532.     FT_Byte*    cur_values;
  533.   } TT_CMap4Rec, *TT_CMap4;
  534.   FT_CALLBACK_DEF( FT_Error )
  535.   tt_cmap4_init( TT_CMap4  cmap,
  536.                  FT_Byte*  table )
  537.   {
  538.     FT_Byte*  p;
  539.     cmap->cmap.data    = table;
  540.     p                  = table + 6;
  541.     cmap->num_ranges   = FT_PEEK_USHORT( p ) >> 1;
  542.     cmap->cur_charcode = 0xFFFFFFFFUL;
  543.     cmap->cur_gindex   = 0;
  544.     return SFNT_Err_Ok;
  545.   }
  546.   static FT_Int
  547.   tt_cmap4_set_range( TT_CMap4  cmap,
  548.                       FT_UInt   range_index )
  549.   {
  550.     FT_Byte*  table = cmap->cmap.data;
  551.     FT_Byte*  p;
  552.     FT_UInt   num_ranges = cmap->num_ranges;
  553.     while ( range_index < num_ranges )
  554.     {
  555.       FT_UInt  offset;
  556.       p             = table + 14 + range_index * 2;
  557.       cmap->cur_end = FT_PEEK_USHORT( p );
  558.       p              += 2 + num_ranges * 2;
  559.       cmap->cur_start = FT_PEEK_USHORT( p );
  560.       p              += num_ranges * 2;
  561.       cmap->cur_delta = FT_PEEK_SHORT( p );
  562.       p     += num_ranges * 2;
  563.       offset = FT_PEEK_USHORT( p );
  564.       if ( offset != 0xFFFFU )
  565.       {
  566.         cmap->cur_values = offset ? p + offset : NULL;
  567.         cmap->cur_range  = range_index;
  568.         return 0;
  569.       }
  570.       /* we skip empty segments */
  571.       range_index++;
  572.     }
  573.     return -1;
  574.   }
  575.   /* search the index of the charcode next to cmap->cur_charcode; */
  576.   /* caller should call tt_cmap4_set_range with proper range      */
  577.   /* before calling this function                                 */
  578.   /*                                                              */
  579.   static void
  580.   tt_cmap4_next( TT_CMap4  cmap )
  581.   {
  582.     FT_UInt  charcode;
  583.     if ( cmap->cur_charcode >= 0xFFFFUL )
  584.       goto Fail;
  585.     charcode = cmap->cur_charcode + 1;
  586.     if ( charcode < cmap->cur_start )
  587.       charcode = cmap->cur_start;
  588.     for ( ;; )
  589.     {
  590.       FT_Byte*  values = cmap->cur_values;
  591.       FT_UInt   end    = cmap->cur_end;
  592.       FT_Int    delta  = cmap->cur_delta;
  593.       if ( charcode <= end )
  594.       {
  595.         if ( values )
  596.         {
  597.           FT_Byte*  p = values + 2 * ( charcode - cmap->cur_start );
  598.           do
  599.           {
  600.             FT_UInt  gindex = FT_NEXT_USHORT( p );
  601.             if ( gindex != 0 )
  602.             {
  603.               gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU );
  604.               if ( gindex != 0 )
  605.               {
  606.                 cmap->cur_charcode = charcode;
  607.                 cmap->cur_gindex   = gindex;
  608.                 return;
  609.               }
  610.             }
  611.           } while ( ++charcode <= end );
  612.         }
  613.         else
  614.         {
  615.           do
  616.           {
  617.             FT_UInt  gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU );
  618.             if ( gindex != 0 )
  619.             {
  620.               cmap->cur_charcode = charcode;
  621.               cmap->cur_gindex   = gindex;
  622.               return;
  623.             }
  624.           } while ( ++charcode <= end );
  625.         }
  626.       }
  627.       /* we need to find another range */
  628.       if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )
  629.         break;
  630.       if ( charcode < cmap->cur_start )
  631.         charcode = cmap->cur_start;
  632.     }
  633.   Fail:
  634.     cmap->cur_charcode = 0xFFFFFFFFUL;
  635.     cmap->cur_gindex   = 0;
  636.   }
  637.   FT_CALLBACK_DEF( FT_Error )
  638.   tt_cmap4_validate( FT_Byte*      table,
  639.                      FT_Validator  valid )
  640.   {
  641.     FT_Byte*  p      = table + 2;               /* skip format */
  642.     FT_UInt   length = TT_NEXT_USHORT( p );
  643.     FT_Byte   *ends, *starts, *offsets, *deltas, *glyph_ids;
  644.     FT_UInt   num_segs;
  645.     FT_Error  error = SFNT_Err_Ok;
  646.     if ( length < 16 )
  647.       FT_INVALID_TOO_SHORT;
  648.     /* in certain fonts, the `length' field is invalid and goes */
  649.     /* out of bound.  We try to correct this here...            */
  650.     if ( table + length > valid->limit )
  651.     {
  652.       if ( valid->level >= FT_VALIDATE_TIGHT )
  653.         FT_INVALID_TOO_SHORT;
  654.       length = (FT_UInt)( valid->limit - table );
  655.     }
  656.     p        = table + 6;
  657.     num_segs = TT_NEXT_USHORT( p );   /* read segCountX2 */
  658.     if ( valid->level >= FT_VALIDATE_PARANOID )
  659.     {
  660.       /* check that we have an even value here */
  661.       if ( num_segs & 1 )
  662.         FT_INVALID_DATA;
  663.     }
  664.     num_segs /= 2;
  665.     if ( length < 16 + num_segs * 2 * 4 )
  666.       FT_INVALID_TOO_SHORT;
  667.     /* check the search parameters - even though we never use them */
  668.     /*                                                             */
  669.     if ( valid->level >= FT_VALIDATE_PARANOID )
  670.     {
  671.       /* check the values of 'searchRange', 'entrySelector', 'rangeShift' */
  672.       FT_UInt  search_range   = TT_NEXT_USHORT( p );
  673.       FT_UInt  entry_selector = TT_NEXT_USHORT( p );
  674.       FT_UInt  range_shift    = TT_NEXT_USHORT( p );
  675.       if ( ( search_range | range_shift ) & 1 )  /* must be even values */
  676.         FT_INVALID_DATA;
  677.       search_range /= 2;
  678.       range_shift  /= 2;
  679.       /* `search range' is the greatest power of 2 that is <= num_segs */
  680.       if ( search_range                > num_segs                 ||
  681.            search_range * 2            < num_segs                 ||
  682.            search_range + range_shift != num_segs                 ||
  683.            search_range               != ( 1U << entry_selector ) )
  684.         FT_INVALID_DATA;
  685.     }
  686.     ends      = table   + 14;
  687.     starts    = table   + 16 + num_segs * 2;
  688.     deltas    = starts  + num_segs * 2;
  689.     offsets   = deltas  + num_segs * 2;
  690.     glyph_ids = offsets + num_segs * 2;
  691.     /* check last segment, its end count must be FFFF */
  692.     if ( valid->level >= FT_VALIDATE_PARANOID )
  693.     {
  694.       p = ends + ( num_segs - 1 ) * 2;
  695.       if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
  696.         FT_INVALID_DATA;
  697.     }
  698.     {
  699.       FT_UInt  start, end, offset, n;
  700.       FT_UInt  last_start = 0, last_end = 0;
  701.       FT_Int   delta;
  702.       FT_Byte*  p_start   = starts;
  703.       FT_Byte*  p_end     = ends;
  704.       FT_Byte*  p_delta   = deltas;
  705.       FT_Byte*  p_offset  = offsets;
  706.       for ( n = 0; n < num_segs; n++ )
  707.       {
  708.         p      = p_offset;
  709.         start  = TT_NEXT_USHORT( p_start );
  710.         end    = TT_NEXT_USHORT( p_end );
  711.         delta  = TT_NEXT_SHORT( p_delta );
  712.         offset = TT_NEXT_USHORT( p_offset );
  713.         if ( start > end )
  714.           FT_INVALID_DATA;
  715.         /* this test should be performed at default validation level;  */
  716.         /* unfortunately, some popular Asian fonts present overlapping */
  717.         /* ranges in their charmaps                                    */
  718.         /*                                                             */
  719.         if ( start <= last_end && n > 0 )
  720.         {
  721.           if ( valid->level >= FT_VALIDATE_TIGHT )
  722.             FT_INVALID_DATA;
  723.           else
  724.           {
  725.             /* allow overlapping segments, provided their start points */
  726.             /* and end points, respectively, are in ascending order.   */
  727.             /*                                                         */
  728.             if ( last_start > start || last_end > end )
  729.               error |= TT_CMAP_FLAG_UNSORTED;
  730.             else
  731.               error |= TT_CMAP_FLAG_OVERLAPPING;
  732.           }
  733.         }
  734.         if ( offset && offset != 0xFFFFU )
  735.         {
  736.           p += offset;  /* start of glyph id array */
  737.           /* check that we point within the glyph ids table only */
  738.           if ( valid->level >= FT_VALIDATE_TIGHT )
  739.           {
  740.             if ( p < glyph_ids                                ||
  741.                  p + ( end - start + 1 ) * 2 > table + length )
  742.               FT_INVALID_DATA;
  743.           }
  744.           else
  745.           {
  746.             if ( p < glyph_ids                              ||
  747.                  p + ( end - start + 1 ) * 2 > valid->limit )
  748.               FT_INVALID_DATA;
  749.           }
  750.           /* check glyph indices within the segment range */
  751.           if ( valid->level >= FT_VALIDATE_TIGHT )
  752.           {
  753.             FT_UInt  i, idx;
  754.             for ( i = start; i < end; i++ )
  755.             {
  756.               idx = FT_NEXT_USHORT( p );
  757.               if ( idx != 0 )
  758.               {
  759.                 idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
  760.                 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
  761.                   FT_INVALID_GLYPH_ID;
  762.               }
  763.             }
  764.           }
  765.         }
  766.         else if ( offset == 0xFFFFU )
  767.         {
  768.           /* Some fonts (erroneously?) use a range offset of 0xFFFF */
  769.           /* to mean missing glyph in cmap table                    */
  770.           /*                                                        */
  771.           if ( valid->level >= FT_VALIDATE_PARANOID                     ||
  772.                n != num_segs - 1                                        ||
  773.                !( start == 0xFFFFU && end == 0xFFFFU && delta == 0x1U ) )
  774.             FT_INVALID_DATA;
  775.         }
  776.         last_start = start;
  777.         last_end   = end;
  778.       }
  779.     }
  780.     return error;
  781.   }
  782.   static FT_UInt
  783.   tt_cmap4_char_map_linear( TT_CMap   cmap,
  784.                             FT_UInt*  pcharcode,
  785.                             FT_Bool   next )
  786.   {
  787.     FT_UInt    num_segs2, start, end, offset;
  788.     FT_Int     delta;
  789.     FT_UInt    i, num_segs;
  790.     FT_UInt32  charcode = *pcharcode;
  791.     FT_UInt    gindex   = 0;
  792.     FT_Byte*   p;
  793.     p = cmap->data + 6;
  794.     num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
  795.     num_segs = num_segs2 >> 1;
  796.     if ( !num_segs )
  797.       return 0;
  798.     if ( next )
  799.       charcode++;
  800.     /* linear search */
  801.     for ( ; charcode <= 0xFFFFU; charcode++ )
  802.     {
  803.       FT_Byte*  q;
  804.       p = cmap->data + 14;               /* ends table   */
  805.       q = cmap->data + 16 + num_segs2;   /* starts table */
  806.       for ( i = 0; i < num_segs; i++ )
  807.       {
  808.         end   = TT_NEXT_USHORT( p );
  809.         start = TT_NEXT_USHORT( q );
  810.         if ( charcode >= start && charcode <= end )
  811.         {
  812.           p       = q - 2 + num_segs2;
  813.           delta   = TT_PEEK_SHORT( p );
  814.           p      += num_segs2;
  815.           offset  = TT_PEEK_USHORT( p );
  816.           if ( offset == 0xFFFFU )
  817.             continue;
  818.           if ( offset )
  819.           {
  820.             p += offset + ( charcode - start ) * 2;
  821.             gindex = TT_PEEK_USHORT( p );
  822.             if ( gindex != 0 )
  823.               gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
  824.           }
  825.           else
  826.             gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
  827.           break;
  828.         }
  829.       }
  830.       if ( !next || gindex )
  831.         break;
  832.     }
  833.     if ( next && gindex )
  834.       *pcharcode = charcode;
  835.     return gindex;
  836.   }
  837.   static FT_UInt
  838.   tt_cmap4_char_map_binary( TT_CMap   cmap,
  839.                             FT_UInt*  pcharcode,
  840.                             FT_Bool   next )
  841.   {
  842.     FT_UInt   num_segs2, start, end, offset;
  843.     FT_Int    delta;
  844.     FT_UInt   max, min, mid, num_segs;
  845.     FT_UInt   charcode = *pcharcode;
  846.     FT_UInt   gindex   = 0;
  847.     FT_Byte*  p;
  848.     p = cmap->data + 6;
  849.     num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
  850.     if ( !num_segs2 )
  851.       return 0;
  852.     num_segs = num_segs2 >> 1;
  853.     /* make compiler happy */
  854.     mid = num_segs;
  855.     end = 0xFFFFU;
  856.     if ( next )
  857.       charcode++;
  858.     min = 0;
  859.     max = num_segs;
  860.     /* binary search */
  861.     while ( min < max )
  862.     {
  863.       mid    = ( min + max ) >> 1;
  864.       p      = cmap->data + 14 + mid * 2;
  865.       end    = TT_PEEK_USHORT( p );
  866.       p     += 2 + num_segs2;
  867.       start  = TT_PEEK_USHORT( p );
  868.       if ( charcode < start )
  869.         max = mid;
  870.       else if ( charcode > end )
  871.         min = mid + 1;
  872.       else
  873.       {
  874.         p     += num_segs2;
  875.         delta  = TT_PEEK_SHORT( p );
  876.         p     += num_segs2;
  877.         offset = TT_PEEK_USHORT( p );
  878.         /* search the first segment containing `charcode' */
  879.         if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING )
  880.         {
  881.           FT_UInt  i;
  882.           /* call the current segment `max' */
  883.           max = mid;
  884.           if ( offset == 0xFFFFU )
  885.             mid = max + 1;
  886.           /* search in segments before the current segment */
  887.           for ( i = max ; i > 0; i-- )
  888.           {
  889.             FT_UInt   prev_end;
  890.             FT_Byte*  old_p;
  891.             old_p    = p;
  892.             p        = cmap->data + 14 + ( i - 1 ) * 2;
  893.             prev_end = TT_PEEK_USHORT( p );
  894.             if ( charcode > prev_end )
  895.             {
  896.               p = old_p;
  897.               break;
  898.             }
  899.             end    = prev_end;
  900.             p     += 2 + num_segs2;
  901.             start  = TT_PEEK_USHORT( p );
  902.             p     += num_segs2;
  903.             delta  = TT_PEEK_SHORT( p );
  904.             p     += num_segs2;
  905.             offset = TT_PEEK_USHORT( p );
  906.             if ( offset != 0xFFFFU )
  907.               mid = i - 1;
  908.           }
  909.           /* no luck */
  910.           if ( mid == max + 1 )
  911.           {
  912.             if ( i != max )
  913.             {
  914.               p      = cmap->data + 14 + max * 2;
  915.               end    = TT_PEEK_USHORT( p );
  916.               p     += 2 + num_segs2;
  917.               start  = TT_PEEK_USHORT( p );
  918.               p     += num_segs2;
  919.               delta  = TT_PEEK_SHORT( p );
  920.               p     += num_segs2;
  921.               offset = TT_PEEK_USHORT( p );
  922.             }
  923.             mid = max;
  924.             /* search in segments after the current segment */
  925.             for ( i = max + 1; i < num_segs; i++ )
  926.             {
  927.               FT_UInt  next_end, next_start;
  928.               p          = cmap->data + 14 + i * 2;
  929.               next_end   = TT_PEEK_USHORT( p );
  930.               p         += 2 + num_segs2;
  931.               next_start = TT_PEEK_USHORT( p );
  932.               if ( charcode < next_start )
  933.                 break;
  934.               end    = next_end;
  935.               start  = next_start;
  936.               p     += num_segs2;
  937.               delta  = TT_PEEK_SHORT( p );
  938.               p     += num_segs2;
  939.               offset = TT_PEEK_USHORT( p );
  940.               if ( offset != 0xFFFFU )
  941.                 mid = i;
  942.             }
  943.             i--;
  944.             /* still no luck */
  945.             if ( mid == max )
  946.             {
  947.               mid = i;
  948.               break;
  949.             }
  950.           }
  951.           /* end, start, delta, and offset are for the i'th segment */
  952.           if ( mid != i )
  953.           {
  954.             p      = cmap->data + 14 + mid * 2;
  955.             end    = TT_PEEK_USHORT( p );
  956.             p     += 2 + num_segs2;
  957.             start  = TT_PEEK_USHORT( p );
  958.             p     += num_segs2;
  959.             delta  = TT_PEEK_SHORT( p );
  960.             p     += num_segs2;
  961.             offset = TT_PEEK_USHORT( p );
  962.           }
  963.         }
  964.         else
  965.         {
  966.           if ( offset == 0xFFFFU )
  967.             break;
  968.         }
  969.         if ( offset )
  970.         {
  971.           p += offset + ( charcode - start ) * 2;
  972.           gindex = TT_PEEK_USHORT( p );
  973.           if ( gindex != 0 )
  974.             gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
  975.         }
  976.         else
  977.           gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
  978.         break;
  979.       }
  980.     }
  981.     if ( next )
  982.     {
  983.       TT_CMap4  cmap4 = (TT_CMap4)cmap;
  984.       /* if `charcode' is not in any segment, then `mid' is */
  985.       /* the segment nearest to `charcode'                  */
  986.       /*                                                    */
  987.       if ( charcode > end )
  988.       {
  989.         mid++;
  990.         if ( mid == num_segs )
  991.           return 0;
  992.       }
  993.       if ( tt_cmap4_set_range( cmap4, mid ) )
  994.       {
  995.         if ( gindex )
  996.           *pcharcode = charcode;
  997.       }
  998.       else
  999.       {
  1000.         cmap4->cur_charcode = charcode;
  1001.         if ( gindex )
  1002.           cmap4->cur_gindex = gindex;
  1003.         else
  1004.         {
  1005.           cmap4->cur_charcode = charcode;
  1006.           tt_cmap4_next( cmap4 );
  1007.           gindex = cmap4->cur_gindex;
  1008.         }
  1009.         if ( gindex )
  1010.           *pcharcode = cmap4->cur_charcode;
  1011.       }
  1012.     }
  1013.     return gindex;
  1014.   }
  1015.   FT_CALLBACK_DEF( FT_UInt )
  1016.   tt_cmap4_char_index( TT_CMap    cmap,
  1017.                        FT_UInt32  char_code )
  1018.   {
  1019.     if ( char_code >= 0x10000UL )
  1020.       return 0;
  1021.     if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
  1022.       return tt_cmap4_char_map_linear( cmap, &char_code, 0 );
  1023.     else
  1024.       return tt_cmap4_char_map_binary( cmap, &char_code, 0 );
  1025.   }
  1026.   FT_CALLBACK_DEF( FT_UInt )
  1027.   tt_cmap4_char_next( TT_CMap     cmap,
  1028.                       FT_UInt32  *pchar_code )
  1029.   {
  1030.     FT_UInt  gindex;
  1031.     if ( *pchar_code >= 0xFFFFU )
  1032.       return 0;
  1033.     if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
  1034.       gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 );
  1035.     else
  1036.     {
  1037.       TT_CMap4  cmap4 = (TT_CMap4)cmap;
  1038.       /* no need to search */
  1039.       if ( *pchar_code == cmap4->cur_charcode )
  1040.       {
  1041.         tt_cmap4_next( cmap4 );
  1042.         gindex = cmap4->cur_gindex;
  1043.         if ( gindex )
  1044.           *pchar_code = cmap4->cur_charcode;
  1045.       }
  1046.       else
  1047.         gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 );
  1048.     }
  1049.     return gindex;
  1050.   }
  1051.   FT_CALLBACK_DEF( FT_Error )
  1052.   tt_cmap4_get_info( TT_CMap       cmap,
  1053.                      TT_CMapInfo  *cmap_info )
  1054.   {
  1055.     FT_Byte*  p = cmap->data + 4;
  1056.     cmap_info->format = 4;
  1057.     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
  1058.     return SFNT_Err_Ok;
  1059.   }
  1060.   FT_CALLBACK_TABLE_DEF
  1061.   const TT_CMap_ClassRec  tt_cmap4_class_rec =
  1062.   {
  1063.     {
  1064.       sizeof ( TT_CMap4Rec ),
  1065.       (FT_CMap_InitFunc)     tt_cmap4_init,
  1066.       (FT_CMap_DoneFunc)     NULL,
  1067.       (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
  1068.       (FT_CMap_CharNextFunc) tt_cmap4_char_next
  1069.     },
  1070.     4,
  1071.     (TT_CMap_ValidateFunc)   tt_cmap4_validate,
  1072.     (TT_CMap_Info_GetFunc)   tt_cmap4_get_info
  1073.   };
  1074. #endif /* TT_CONFIG_CMAP_FORMAT_4 */
  1075.   /*************************************************************************/
  1076.   /*************************************************************************/
  1077.   /*****                                                               *****/
  1078.   /*****                          FORMAT 6                             *****/
  1079.   /*****                                                               *****/
  1080.   /*************************************************************************/
  1081.   /*************************************************************************/
  1082.   /*************************************************************************/
  1083.   /*                                                                       */
  1084.   /* TABLE OVERVIEW                                                        */
  1085.   /* --------------                                                        */
  1086.   /*                                                                       */
  1087.   /*   NAME        OFFSET          TYPE             DESCRIPTION            */
  1088.   /*                                                                       */
  1089.   /*   format       0              USHORT           must be 4              */
  1090.   /*   length       2              USHORT           table length in bytes  */
  1091.   /*   language     4              USHORT           Mac language code      */
  1092.   /*                                                                       */
  1093.   /*   first        6              USHORT           first segment code     */
  1094.   /*   count        8              USHORT           segment size in chars  */
  1095.   /*   glyphIds     10             USHORT[count]    glyph ids              */
  1096.   /*                                                                       */
  1097.   /* A very simplified segment mapping.                                    */
  1098.   /*                                                                       */
  1099. #ifdef TT_CONFIG_CMAP_FORMAT_6
  1100.   FT_CALLBACK_DEF( FT_Error )
  1101.   tt_cmap6_validate( FT_Byte*      table,
  1102.                      FT_Validator  valid )
  1103.   {
  1104.     FT_Byte*  p;
  1105.     FT_UInt   length, count;
  1106.     if ( table + 10 > valid->limit )
  1107.       FT_INVALID_TOO_SHORT;
  1108.     p      = table + 2;
  1109.     length = TT_NEXT_USHORT( p );
  1110.     p      = table + 8;             /* skip language and start index */
  1111.     count  = TT_NEXT_USHORT( p );
  1112.     if ( table + length > valid->limit || length < 10 + count * 2 )
  1113.       FT_INVALID_TOO_SHORT;
  1114.     /* check glyph indices */
  1115.     if ( valid->level >= FT_VALIDATE_TIGHT )
  1116.     {
  1117.       FT_UInt  gindex;
  1118.       for ( ; count > 0; count-- )
  1119.       {
  1120.         gindex = TT_NEXT_USHORT( p );
  1121.         if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
  1122.           FT_INVALID_GLYPH_ID;
  1123.       }
  1124.     }
  1125.     return SFNT_Err_Ok;
  1126.   }
  1127.   FT_CALLBACK_DEF( FT_UInt )
  1128.   tt_cmap6_char_index( TT_CMap    cmap,
  1129.                        FT_UInt32  char_code )
  1130.   {
  1131.     FT_Byte*  table  = cmap->data;
  1132.     FT_UInt   result = 0;
  1133.     FT_Byte*  p      = table + 6;
  1134.     FT_UInt   start  = TT_NEXT_USHORT( p );
  1135.     FT_UInt   count  = TT_NEXT_USHORT( p );
  1136.     FT_UInt   idx    = (FT_UInt)( char_code - start );
  1137.     if ( idx < count )
  1138.     {
  1139.       p += 2 * idx;
  1140.       result = TT_PEEK_USHORT( p );
  1141.     }
  1142.     return result;
  1143.   }
  1144.   FT_CALLBACK_DEF( FT_UInt )
  1145.   tt_cmap6_char_next( TT_CMap     cmap,
  1146.                       FT_UInt32  *pchar_code )
  1147.   {
  1148.     FT_Byte*   table     = cmap->data;
  1149.     FT_UInt32  result    = 0;
  1150.     FT_UInt32  char_code = *pchar_code + 1;
  1151.     FT_UInt    gindex    = 0;
  1152.     FT_Byte*   p         = table + 6;
  1153.     FT_UInt    start     = TT_NEXT_USHORT( p );
  1154.     FT_UInt    count     = TT_NEXT_USHORT( p );
  1155.     FT_UInt    idx;
  1156.     if ( char_code >= 0x10000UL )
  1157.       goto Exit;
  1158.     if ( char_code < start )
  1159.       char_code = start;
  1160.     idx = (FT_UInt)( char_code - start );
  1161.     p  += 2 * idx;
  1162.     for ( ; idx < count; idx++ )
  1163.     {
  1164.       gindex = TT_NEXT_USHORT( p );
  1165.       if ( gindex != 0 )
  1166.       {
  1167.         result = char_code;
  1168.         break;
  1169.       }
  1170.       char_code++;
  1171.     }
  1172.   Exit:
  1173.     *pchar_code = result;
  1174.     return gindex;
  1175.   }
  1176.   FT_CALLBACK_DEF( FT_Error )
  1177.   tt_cmap6_get_info( TT_CMap       cmap,
  1178.                      TT_CMapInfo  *cmap_info )
  1179.   {
  1180.     FT_Byte*  p = cmap->data + 4;
  1181.     cmap_info->format = 6;
  1182.     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
  1183.     return SFNT_Err_Ok;
  1184.   }
  1185.   FT_CALLBACK_TABLE_DEF
  1186.   const TT_CMap_ClassRec  tt_cmap6_class_rec =
  1187.   {
  1188.     {
  1189.       sizeof ( TT_CMapRec ),
  1190.       (FT_CMap_InitFunc)     tt_cmap_init,
  1191.       (FT_CMap_DoneFunc)     NULL,
  1192.       (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
  1193.       (FT_CMap_CharNextFunc) tt_cmap6_char_next
  1194.     },
  1195.     6,
  1196.     (TT_CMap_ValidateFunc)   tt_cmap6_validate,
  1197.     (TT_CMap_Info_GetFunc)   tt_cmap6_get_info
  1198.   };
  1199. #endif /* TT_CONFIG_CMAP_FORMAT_6 */
  1200.   /*************************************************************************/
  1201.   /*************************************************************************/
  1202.   /*****                                                               *****/
  1203.   /*****                          FORMAT 8                             *****/
  1204.   /*****                                                               *****/
  1205.   /***** It's hard to completely understand what the OpenType spec     *****/
  1206.   /***** says about this format, but here is my conclusion.            *****/
  1207.   /*****                                                               *****/
  1208.   /***** The purpose of this format is to easily map UTF-16 text to    *****/
  1209.   /***** glyph indices.  Basically, the `char_code' must be in one of  *****/
  1210.   /***** the following formats:                                        *****/
  1211.   /*****                                                               *****/
  1212.   /*****   - A 16-bit value that isn't part of the Unicode Surrogates  *****/
  1213.   /*****     Area (i.e. U+D800-U+DFFF).                                *****/
  1214.   /*****                                                               *****/
  1215.   /*****   - A 32-bit value, made of two surrogate values, i.e.. if    *****/
  1216.   /*****     `char_code = (char_hi << 16) | char_lo', then both        *****/
  1217.   /*****     `char_hi' and `char_lo' must be in the Surrogates Area.   *****/
  1218.   /*****      Area.                                                    *****/
  1219.   /*****                                                               *****/
  1220.   /***** The 'is32' table embedded in the charmap indicates whether a  *****/
  1221.   /***** given 16-bit value is in the surrogates area or not.          *****/
  1222.   /*****                                                               *****/
  1223.   /***** So, for any given `char_code', we can assert the following:   *****/
  1224.   /*****                                                               *****/
  1225.   /*****   If `char_hi == 0' then we must have `is32[char_lo] == 0'.   *****/
  1226.   /*****                                                               *****/
  1227.   /*****   If `char_hi != 0' then we must have both                    *****/
  1228.   /*****   `is32[char_hi] != 0' and `is32[char_lo] != 0'.              *****/
  1229.   /*****                                                               *****/
  1230.   /*************************************************************************/
  1231.   /*************************************************************************/
  1232.   /*************************************************************************/
  1233.   /*                                                                       */
  1234.   /* TABLE OVERVIEW                                                        */
  1235.   /* --------------                                                        */
  1236.   /*                                                                       */
  1237.   /*   NAME        OFFSET         TYPE        DESCRIPTION                  */
  1238.   /*                                                                       */
  1239.   /*   format      0              USHORT      must be 8                    */
  1240.   /*   reserved    2              USHORT      reserved                     */
  1241.   /*   length      4              ULONG       length in bytes              */
  1242.   /*   language    8              ULONG       Mac language code            */
  1243.   /*   is32        12             BYTE[8192]  32-bitness bitmap            */
  1244.   /*   count       8204           ULONG       number of groups             */
  1245.   /*                                                                       */
  1246.   /* This header is followed by 'count' groups of the following format:    */
  1247.   /*                                                                       */
  1248.   /*   start       0              ULONG       first charcode               */
  1249.   /*   end         4              ULONG       last charcode                */
  1250.   /*   startId     8              ULONG       start glyph id for the group */
  1251.   /*                                                                       */
  1252. #ifdef TT_CONFIG_CMAP_FORMAT_8
  1253.   FT_CALLBACK_DEF( FT_Error )
  1254.   tt_cmap8_validate( FT_Byte*      table,
  1255.                      FT_Validator  valid )
  1256.   {
  1257.     FT_Byte*   p = table + 4;
  1258.     FT_Byte*   is32;
  1259.     FT_UInt32  length;
  1260.     FT_UInt32  num_groups;
  1261.     if ( table + 16 + 8192 > valid->limit )
  1262.       FT_INVALID_TOO_SHORT;
  1263.     length = TT_NEXT_ULONG( p );
  1264.     if ( table + length > valid->limit || length < 8208 )
  1265.       FT_INVALID_TOO_SHORT;
  1266.     is32       = table + 12;
  1267.     p          = is32  + 8192;          /* skip `is32' array */
  1268.     num_groups = TT_NEXT_ULONG( p );
  1269.     if ( p + num_groups * 12 > valid->limit )
  1270.       FT_INVALID_TOO_SHORT;
  1271.     /* check groups, they must be in increasing order */
  1272.     {
  1273.       FT_UInt32  n, start, end, start_id, count, last = 0;
  1274.       for ( n = 0; n < num_groups; n++ )
  1275.       {
  1276.         FT_UInt   hi, lo;
  1277.         start    = TT_NEXT_ULONG( p );
  1278.         end      = TT_NEXT_ULONG( p );
  1279.         start_id = TT_NEXT_ULONG( p );
  1280.         if ( start > end )
  1281.           FT_INVALID_DATA;
  1282.         if ( n > 0 && start <= last )
  1283.           FT_INVALID_DATA;
  1284.         if ( valid->level >= FT_VALIDATE_TIGHT )
  1285.         {
  1286.           if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
  1287.             FT_INVALID_GLYPH_ID;
  1288.           count = (FT_UInt32)( end - start + 1 );
  1289.           if ( start & ~0xFFFFU )
  1290.           {
  1291.             /* start_hi != 0; check that is32[i] is 1 for each i in */
  1292.             /* the `hi' and `lo' of the range [start..end]          */
  1293.             for ( ; count > 0; count--, start++ )
  1294.             {
  1295.               hi = (FT_UInt)( start >> 16 );
  1296.               lo = (FT_UInt)( start & 0xFFFFU );
  1297.               if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
  1298.                 FT_INVALID_DATA;
  1299.               if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
  1300.                 FT_INVALID_DATA;
  1301.             }
  1302.           }
  1303.           else
  1304.           {
  1305.             /* start_hi == 0; check that is32[i] is 0 for each i in */
  1306.             /* the range [start..end]                               */
  1307.             /* end_hi cannot be != 0! */
  1308.             if ( end & ~0xFFFFU )
  1309.               FT_INVALID_DATA;
  1310.             for ( ; count > 0; count--, start++ )
  1311.             {
  1312.               lo = (FT_UInt)( start & 0xFFFFU );
  1313.               if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
  1314.                 FT_INVALID_DATA;
  1315.             }
  1316.           }
  1317.         }
  1318.         last = end;
  1319.       }
  1320.     }
  1321.     return SFNT_Err_Ok;
  1322.   }
  1323.   FT_CALLBACK_DEF( FT_UInt )
  1324.   tt_cmap8_char_index( TT_CMap    cmap,
  1325.                        FT_UInt32  char_code )
  1326.   {
  1327.     FT_Byte*   table      = cmap->data;
  1328.     FT_UInt    result     = 0;
  1329.     FT_Byte*   p          = table + 8204;
  1330.     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
  1331.     FT_UInt32  start, end, start_id;
  1332.     for ( ; num_groups > 0; num_groups-- )
  1333.     {
  1334.       start    = TT_NEXT_ULONG( p );
  1335.       end      = TT_NEXT_ULONG( p );
  1336.       start_id = TT_NEXT_ULONG( p );
  1337.       if ( char_code < start )
  1338.         break;
  1339.       if ( char_code <= end )
  1340.       {
  1341.         result = (FT_UInt)( start_id + char_code - start );
  1342.         break;
  1343.       }
  1344.     }
  1345.     return result;
  1346.   }
  1347.   FT_CALLBACK_DEF( FT_UInt )
  1348.   tt_cmap8_char_next( TT_CMap     cmap,
  1349.                       FT_UInt32  *pchar_code )
  1350.   {
  1351.     FT_UInt32  result     = 0;
  1352.     FT_UInt32  char_code  = *pchar_code + 1;
  1353.     FT_UInt    gindex     = 0;
  1354.     FT_Byte*   table      = cmap->data;
  1355.     FT_Byte*   p          = table + 8204;
  1356.     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
  1357.     FT_UInt32  start, end, start_id;
  1358.     p = table + 8208;
  1359.     for ( ; num_groups > 0; num_groups-- )
  1360.     {
  1361.       start    = TT_NEXT_ULONG( p );
  1362.       end      = TT_NEXT_ULONG( p );
  1363.       start_id = TT_NEXT_ULONG( p );
  1364.       if ( char_code < start )
  1365.         char_code = start;
  1366.       if ( char_code <= end )
  1367.       {
  1368.         gindex = (FT_UInt)( char_code - start + start_id );
  1369.         if ( gindex != 0 )
  1370.         {
  1371.           result = char_code;
  1372.           goto Exit;
  1373.         }
  1374.       }
  1375.     }
  1376.   Exit:
  1377.     *pchar_code = result;
  1378.     return gindex;
  1379.   }
  1380.   FT_CALLBACK_DEF( FT_Error )
  1381.   tt_cmap8_get_info( TT_CMap       cmap,
  1382.                      TT_CMapInfo  *cmap_info )
  1383.   {
  1384.     FT_Byte*  p = cmap->data + 8;
  1385.     cmap_info->format = 8;
  1386.     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
  1387.     return SFNT_Err_Ok;
  1388.   }
  1389.   FT_CALLBACK_TABLE_DEF
  1390.   const TT_CMap_ClassRec  tt_cmap8_class_rec =
  1391.   {
  1392.     {
  1393.       sizeof ( TT_CMapRec ),
  1394.       (FT_CMap_InitFunc)     tt_cmap_init,
  1395.       (FT_CMap_DoneFunc)     NULL,
  1396.       (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
  1397.       (FT_CMap_CharNextFunc) tt_cmap8_char_next
  1398.     },
  1399.     8,
  1400.     (TT_CMap_ValidateFunc)   tt_cmap8_validate,
  1401.     (TT_CMap_Info_GetFunc)   tt_cmap8_get_info
  1402.   };
  1403. #endif /* TT_CONFIG_CMAP_FORMAT_8 */
  1404.   /*************************************************************************/
  1405.   /*************************************************************************/
  1406.   /*****                                                               *****/
  1407.   /*****                          FORMAT 10                            *****/
  1408.   /*****                                                               *****/
  1409.   /*************************************************************************/
  1410.   /*************************************************************************/
  1411.   /*************************************************************************/
  1412.   /*                                                                       */
  1413.   /* TABLE OVERVIEW                                                        */
  1414.   /* --------------                                                        */
  1415.   /*                                                                       */
  1416.   /*   NAME      OFFSET  TYPE               DESCRIPTION                    */
  1417.   /*                                                                       */
  1418.   /*   format     0      USHORT             must be 10                     */
  1419.   /*   reserved   2      USHORT             reserved                       */
  1420.   /*   length     4      ULONG              length in bytes                */
  1421.   /*   language   8      ULONG              Mac language code              */
  1422.   /*                                                                       */
  1423.   /*   start     12      ULONG              first char in range            */
  1424.   /*   count     16      ULONG              number of chars in range       */
  1425.   /*   glyphIds  20      USHORT[count]      glyph indices covered          */
  1426.   /*                                                                       */
  1427. #ifdef TT_CONFIG_CMAP_FORMAT_10
  1428.   FT_CALLBACK_DEF( FT_Error )
  1429.   tt_cmap10_validate( FT_Byte*      table,
  1430.                       FT_Validator  valid )
  1431.   {
  1432.     FT_Byte*  p = table + 4;
  1433.     FT_ULong  length, count;
  1434.     if ( table + 20 > valid->limit )
  1435.       FT_INVALID_TOO_SHORT;
  1436.     length = TT_NEXT_ULONG( p );
  1437.     p      = table + 16;
  1438.     count  = TT_NEXT_ULONG( p );
  1439.     if ( table + length > valid->limit || length < 20 + count * 2 )
  1440.       FT_INVALID_TOO_SHORT;
  1441.     /* check glyph indices */
  1442.     if ( valid->level >= FT_VALIDATE_TIGHT )
  1443.     {
  1444.       FT_UInt  gindex;
  1445.       for ( ; count > 0; count-- )
  1446.       {
  1447.         gindex = TT_NEXT_USHORT( p );
  1448.         if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
  1449.           FT_INVALID_GLYPH_ID;
  1450.       }
  1451.     }
  1452.     return SFNT_Err_Ok;
  1453.   }
  1454.   FT_CALLBACK_DEF( FT_UInt )
  1455.   tt_cmap10_char_index( TT_CMap    cmap,
  1456.                         FT_UInt32  char_code )
  1457.   {
  1458.     FT_Byte*   table  = cmap->data;
  1459.     FT_UInt    result = 0;
  1460.     FT_Byte*   p      = table + 12;
  1461.     FT_UInt32  start  = TT_NEXT_ULONG( p );
  1462.     FT_UInt32  count  = TT_NEXT_ULONG( p );
  1463.     FT_UInt32  idx    = (FT_ULong)( char_code - start );
  1464.     if ( idx < count )
  1465.     {
  1466.       p     += 2 * idx;
  1467.       result = TT_PEEK_USHORT( p );
  1468.     }
  1469.     return result;
  1470.   }
  1471.   FT_CALLBACK_DEF( FT_UInt )
  1472.   tt_cmap10_char_next( TT_CMap     cmap,
  1473.                        FT_UInt32  *pchar_code )
  1474.   {
  1475.     FT_Byte*   table     = cmap->data;
  1476.     FT_UInt32  char_code = *pchar_code + 1;
  1477.     FT_UInt    gindex    = 0;
  1478.     FT_Byte*   p         = table + 12;
  1479.     FT_UInt32  start     = TT_NEXT_ULONG( p );
  1480.     FT_UInt32  count     = TT_NEXT_ULONG( p );
  1481.     FT_UInt32  idx;
  1482.     if ( char_code < start )
  1483.       char_code = start;
  1484.     idx = (FT_UInt32)( char_code - start );
  1485.     p  += 2 * idx;
  1486.     for ( ; idx < count; idx++ )
  1487.     {
  1488.       gindex = TT_NEXT_USHORT( p );
  1489.       if ( gindex != 0 )
  1490.         break;
  1491.       char_code++;
  1492.     }
  1493.     *pchar_code = char_code;
  1494.     return gindex;
  1495.   }
  1496.   FT_CALLBACK_DEF( FT_Error )
  1497.   tt_cmap10_get_info( TT_CMap       cmap,
  1498.                       TT_CMapInfo  *cmap_info )
  1499.   {
  1500.     FT_Byte*  p = cmap->data + 8;
  1501.     cmap_info->format = 10;
  1502.     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
  1503.     return SFNT_Err_Ok;
  1504.   }
  1505.   FT_CALLBACK_TABLE_DEF
  1506.   const TT_CMap_ClassRec  tt_cmap10_class_rec =
  1507.   {
  1508.     {
  1509.       sizeof ( TT_CMapRec ),
  1510.       (FT_CMap_InitFunc)     tt_cmap_init,
  1511.       (FT_CMap_DoneFunc)     NULL,
  1512.       (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
  1513.       (FT_CMap_CharNextFunc) tt_cmap10_char_next
  1514.     },
  1515.     10,
  1516.     (TT_CMap_ValidateFunc)   tt_cmap10_validate,
  1517.     (TT_CMap_Info_GetFunc)   tt_cmap10_get_info
  1518.   };
  1519. #endif /* TT_CONFIG_CMAP_FORMAT_10 */
  1520.   /*************************************************************************/
  1521.   /*************************************************************************/
  1522.   /*****                                                               *****/
  1523.   /*****                          FORMAT 12                            *****/
  1524.   /*****                                                               *****/
  1525.   /*************************************************************************/
  1526.   /*************************************************************************/
  1527.   /*************************************************************************/
  1528.   /*                                                                       */
  1529.   /* TABLE OVERVIEW                                                        */
  1530.   /* --------------                                                        */
  1531.   /*                                                                       */
  1532.   /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
  1533.   /*                                                                       */
  1534.   /*   format      0          USHORT     must be 12                        */
  1535.   /*   reserved    2          USHORT     reserved                          */
  1536.   /*   length      4          ULONG      length in bytes                   */
  1537.   /*   language    8          ULONG      Mac language code                 */
  1538.   /*   count       12         ULONG      number of groups                  */
  1539.   /*               16                                                      */
  1540.   /*                                                                       */
  1541.   /* This header is followed by `count' groups of the following format:    */
  1542.   /*                                                                       */
  1543.   /*   start       0          ULONG      first charcode                    */
  1544.   /*   end         4          ULONG      last charcode                     */
  1545.   /*   startId     8          ULONG      start glyph id for the group      */
  1546.   /*                                                                       */
  1547. #ifdef TT_CONFIG_CMAP_FORMAT_12
  1548.   typedef struct  TT_CMap12Rec_
  1549.   {
  1550.     TT_CMapRec  cmap;
  1551.     FT_Bool     valid;
  1552.     FT_ULong    cur_charcode;
  1553.     FT_UInt     cur_gindex;
  1554.     FT_ULong    cur_group;
  1555.     FT_ULong    num_groups;
  1556.   } TT_CMap12Rec, *TT_CMap12;
  1557.   FT_CALLBACK_DEF( FT_Error )
  1558.   tt_cmap12_init( TT_CMap12  cmap,
  1559.                   FT_Byte*   table )
  1560.   {
  1561.     cmap->cmap.data  = table;
  1562.     table           += 12;
  1563.     cmap->num_groups = FT_PEEK_ULONG( table );
  1564.     cmap->valid      = 0;
  1565.     return SFNT_Err_Ok;
  1566.   }
  1567.   FT_CALLBACK_DEF( FT_Error )
  1568.   tt_cmap12_validate( FT_Byte*      table,
  1569.                       FT_Validator  valid )
  1570.   {
  1571.     FT_Byte*   p;
  1572.     FT_ULong   length;
  1573.     FT_ULong   num_groups;
  1574.     if ( table + 16 > valid->limit )
  1575.       FT_INVALID_TOO_SHORT;
  1576.     p      = table + 4;
  1577.     length = TT_NEXT_ULONG( p );
  1578.     p          = table + 12;
  1579.     num_groups = TT_NEXT_ULONG( p );
  1580.     if ( table + length > valid->limit || length < 16 + 12 * num_groups )
  1581.       FT_INVALID_TOO_SHORT;
  1582.     /* check groups, they must be in increasing order */
  1583.     {
  1584.       FT_ULong  n, start, end, start_id, last = 0;
  1585.       for ( n = 0; n < num_groups; n++ )
  1586.       {
  1587.         start    = TT_NEXT_ULONG( p );
  1588.         end      = TT_NEXT_ULONG( p );
  1589.         start_id = TT_NEXT_ULONG( p );
  1590.         if ( start > end )
  1591.           FT_INVALID_DATA;
  1592.         if ( n > 0 && start <= last )
  1593.           FT_INVALID_DATA;
  1594.         if ( valid->level >= FT_VALIDATE_TIGHT )
  1595.         {
  1596.           if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
  1597.             FT_INVALID_GLYPH_ID;
  1598.         }
  1599.         last = end;
  1600.       }
  1601.     }
  1602.     return SFNT_Err_Ok;
  1603.   }
  1604.   /* search the index of the charcode next to cmap->cur_charcode */
  1605.   /* cmap->cur_group should be set up properly by caller         */
  1606.   /*                                                             */
  1607.   static void
  1608.   tt_cmap12_next( TT_CMap12  cmap )
  1609.   {
  1610.     FT_Byte*  p;
  1611.     FT_ULong  start, end, start_id, char_code;
  1612.     FT_ULong  n;
  1613.     FT_UInt   gindex;
  1614.     if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
  1615.       goto Fail;
  1616.     char_code = cmap->cur_charcode + 1;
  1617.     n = cmap->cur_group;
  1618.     for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
  1619.     {
  1620.       p        = cmap->cmap.data + 16 + 12 * n;
  1621.       start    = TT_NEXT_ULONG( p );
  1622.       end      = TT_NEXT_ULONG( p );
  1623.       start_id = TT_PEEK_ULONG( p );
  1624.       if ( char_code < start )
  1625.         char_code = start;
  1626.       for ( ; char_code <= end; char_code++ )
  1627.       {
  1628.         gindex = (FT_UInt)( start_id + char_code - start );
  1629.         if ( gindex )
  1630.         {
  1631.           cmap->cur_charcode = char_code;;
  1632.           cmap->cur_gindex   = gindex;
  1633.           cmap->cur_group    = n;
  1634.           return;
  1635.         }
  1636.       }
  1637.     }
  1638.   Fail:
  1639.     cmap->valid = 0;
  1640.   }
  1641.   static FT_UInt
  1642.   tt_cmap12_char_map_binary( TT_CMap     cmap,
  1643.                              FT_UInt32*  pchar_code,
  1644.                              FT_Bool     next )
  1645.   {
  1646.     FT_UInt    gindex     = 0;
  1647.     FT_Byte*   p          = cmap->data + 12;
  1648.     FT_UInt32  num_groups = TT_PEEK_ULONG( p );
  1649.     FT_UInt32  char_code  = *pchar_code;
  1650.     FT_UInt32  start, end, start_id;
  1651.     FT_UInt32  max, min, mid;
  1652.     if ( !num_groups )
  1653.       return 0;
  1654.     /* make compiler happy */
  1655.     mid = num_groups;
  1656.     end = 0xFFFFFFFFUL;
  1657.     if ( next )
  1658.       char_code++;
  1659.     min = 0;
  1660.     max = num_groups;
  1661.     /* binary search */
  1662.     while ( min < max )
  1663.     {
  1664.       mid = ( min + max ) >> 1;
  1665.       p   = cmap->data + 16 + 12 * mid;
  1666.       start = TT_NEXT_ULONG( p );
  1667.       end   = TT_NEXT_ULONG( p );
  1668.       if ( char_code < start )
  1669.         max = mid;
  1670.       else if ( char_code > end )
  1671.         min = mid + 1;
  1672.       else
  1673.       {
  1674.         start_id = TT_PEEK_ULONG( p );
  1675.         gindex = (FT_UInt)( start_id + char_code - start );
  1676.         break;
  1677.       }
  1678.     }
  1679.     if ( next )
  1680.     {
  1681.       TT_CMap12  cmap12 = (TT_CMap12)cmap;
  1682.       /* if `char_code' is not in any group, then `mid' is */
  1683.       /* the group nearest to `char_code'                  */
  1684.       /*                                                   */
  1685.       if ( char_code > end )
  1686.       {
  1687.         mid++;
  1688.         if ( mid == num_groups )
  1689.           return 0;
  1690.       }
  1691.       cmap12->valid        = 1;
  1692.       cmap12->cur_charcode = char_code;
  1693.       cmap12->cur_group    = mid;
  1694.       if ( !gindex )
  1695.       {
  1696.         tt_cmap12_next( cmap12 );
  1697.         if ( cmap12->valid )
  1698.           gindex = cmap12->cur_gindex;
  1699.       }
  1700.       else
  1701.         cmap12->cur_gindex = gindex;
  1702.       if ( gindex )
  1703.         *pchar_code = cmap12->cur_charcode;
  1704.     }
  1705.     return gindex;
  1706.   }
  1707.   FT_CALLBACK_DEF( FT_UInt )
  1708.   tt_cmap12_char_index( TT_CMap    cmap,
  1709.                         FT_UInt32  char_code )
  1710.   {
  1711.     return tt_cmap12_char_map_binary( cmap, &char_code, 0 );
  1712.   }
  1713.   FT_CALLBACK_DEF( FT_UInt )
  1714.   tt_cmap12_char_next( TT_CMap     cmap,
  1715.                        FT_UInt32  *pchar_code )
  1716.   {
  1717.     TT_CMap12  cmap12 = (TT_CMap12)cmap;
  1718.     FT_ULong   gindex;
  1719.     if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )
  1720.       return 0;
  1721.     /* no need to search */
  1722.     if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
  1723.     {
  1724.       tt_cmap12_next( cmap12 );
  1725.       if ( cmap12->valid )
  1726.       {
  1727.         gindex = cmap12->cur_gindex;
  1728.         if ( gindex )
  1729.           *pchar_code = cmap12->cur_charcode;
  1730.       }
  1731.       else
  1732.         gindex = 0;
  1733.     }
  1734.     else
  1735.       gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
  1736.     return gindex;
  1737.   }
  1738.   FT_CALLBACK_DEF( FT_Error )
  1739.   tt_cmap12_get_info( TT_CMap       cmap,
  1740.                       TT_CMapInfo  *cmap_info )
  1741.   {
  1742.     FT_Byte*  p = cmap->data + 8;
  1743.     cmap_info->format = 12;
  1744.     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
  1745.     return SFNT_Err_Ok;
  1746.   }
  1747.   FT_CALLBACK_TABLE_DEF
  1748.   const TT_CMap_ClassRec  tt_cmap12_class_rec =
  1749.   {
  1750.     {
  1751.       sizeof ( TT_CMap12Rec ),
  1752.       (FT_CMap_InitFunc)     tt_cmap12_init,
  1753.       (FT_CMap_DoneFunc)     NULL,
  1754.       (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
  1755.       (FT_CMap_CharNextFunc) tt_cmap12_char_next
  1756.     },
  1757.     12,
  1758.     (TT_CMap_ValidateFunc)   tt_cmap12_validate,
  1759.     (TT_CMap_Info_GetFunc)   tt_cmap12_get_info
  1760.   };
  1761. #endif /* TT_CONFIG_CMAP_FORMAT_12 */
  1762.   static const TT_CMap_Class  tt_cmap_classes[] =
  1763.   {
  1764. #ifdef TT_CONFIG_CMAP_FORMAT_0
  1765.     &tt_cmap0_class_rec,
  1766. #endif
  1767. #ifdef TT_CONFIG_CMAP_FORMAT_2
  1768.     &tt_cmap2_class_rec,
  1769. #endif
  1770. #ifdef TT_CONFIG_CMAP_FORMAT_4
  1771.     &tt_cmap4_class_rec,
  1772. #endif
  1773. #ifdef TT_CONFIG_CMAP_FORMAT_6
  1774.     &tt_cmap6_class_rec,
  1775. #endif
  1776. #ifdef TT_CONFIG_CMAP_FORMAT_8
  1777.     &tt_cmap8_class_rec,
  1778. #endif
  1779. #ifdef TT_CONFIG_CMAP_FORMAT_10
  1780.     &tt_cmap10_class_rec,
  1781. #endif
  1782. #ifdef TT_CONFIG_CMAP_FORMAT_12
  1783.     &tt_cmap12_class_rec,
  1784. #endif
  1785.     NULL,
  1786.   };
  1787.   /* parse the `cmap' table and build the corresponding TT_CMap objects */
  1788.   /* in the current face                                                */
  1789.   /*                                                                    */
  1790.   FT_LOCAL_DEF( FT_Error )
  1791.   tt_face_build_cmaps( TT_Face  face )
  1792.   {
  1793.     FT_Byte*           table = face->cmap_table;
  1794.     FT_Byte*           limit = table + face->cmap_size;
  1795.     FT_UInt volatile   num_cmaps;
  1796.     FT_Byte* volatile  p     = table;
  1797.     if ( p + 4 > limit )
  1798.       return SFNT_Err_Invalid_Table;
  1799.     /* only recognize format 0 */
  1800.     if ( TT_NEXT_USHORT( p ) != 0 )
  1801.     {
  1802.       p -= 2;
  1803.       FT_ERROR(( "tt_face_build_cmaps: unsupported `cmap' table format = %dn",
  1804.                  TT_PEEK_USHORT( p ) ));
  1805.       return SFNT_Err_Invalid_Table;
  1806.     }
  1807.     num_cmaps = TT_NEXT_USHORT( p );
  1808.     for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
  1809.     {
  1810.       FT_CharMapRec  charmap;
  1811.       FT_UInt32      offset;
  1812.       charmap.platform_id = TT_NEXT_USHORT( p );
  1813.       charmap.encoding_id = TT_NEXT_USHORT( p );
  1814.       charmap.face        = FT_FACE( face );
  1815.       charmap.encoding    = FT_ENCODING_NONE;  /* will be filled later */
  1816.       offset              = TT_NEXT_ULONG( p );
  1817.       if ( offset && offset <= face->cmap_size - 2 )
  1818.       {
  1819.         FT_Byte* volatile              cmap   = table + offset;
  1820.         volatile FT_UInt               format = TT_PEEK_USHORT( cmap );
  1821.         const TT_CMap_Class* volatile  pclazz = tt_cmap_classes;
  1822.         TT_CMap_Class volatile         clazz;
  1823.         for ( ; *pclazz; pclazz++ )
  1824.         {
  1825.           clazz = *pclazz;
  1826.           if ( clazz->format == format )
  1827.           {
  1828.             volatile TT_ValidatorRec  valid;
  1829.             volatile FT_Error         error = SFNT_Err_Ok;
  1830.             ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
  1831.                                FT_VALIDATE_DEFAULT );
  1832.             valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
  1833.             if ( ft_setjmp(
  1834.               *((ft_jmp_buf*)&FT_VALIDATOR( &valid )->jump_buffer) ) == 0 )
  1835.             {
  1836.               /* validate this cmap sub-table */
  1837.               error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
  1838.             }
  1839.             if ( valid.validator.error == 0 )
  1840.             {
  1841.               FT_CMap  ttcmap;
  1842.               if ( !FT_CMap_New( (FT_CMap_Class)clazz,
  1843.                                  cmap, &charmap, &ttcmap ) )
  1844.               {
  1845.                 /* it is simpler to directly set `flags' than adding */
  1846.                 /* a parameter to FT_CMap_New                        */
  1847.                 ((TT_CMap)ttcmap)->flags = (FT_Int)error;
  1848.               }
  1849.             }
  1850.             else
  1851.             {
  1852.               FT_ERROR(( "tt_face_build_cmaps:" ));
  1853.               FT_ERROR(( " broken cmap sub-table ignored!n" ));
  1854.             }
  1855.             break;
  1856.           }
  1857.         }
  1858.       }
  1859.     }
  1860.     return SFNT_Err_Ok;
  1861.   }
  1862.   FT_LOCAL( FT_Error )
  1863.   tt_get_cmap_info( FT_CharMap    charmap,
  1864.                     TT_CMapInfo  *cmap_info )
  1865.   {
  1866.     FT_CMap        cmap  = (FT_CMap)charmap;
  1867.     TT_CMap_Class  clazz = (TT_CMap_Class)cmap->clazz;
  1868.     return clazz->get_cmap_info( charmap, cmap_info );
  1869.   }
  1870. /* END */