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