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