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