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