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-2010, 2012-2014 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 = ( 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)( 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 = ( 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)( ( 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)( ( 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     if ( length < 16 )
    849       FT_INVALID_TOO_SHORT;
    850 
    851     /* in certain fonts, the `length' field is invalid and goes */
    852     /* out of bound.  We try to correct this here...            */
    853     if ( table + length > valid->limit )
    854     {
    855       if ( valid->level >= FT_VALIDATE_TIGHT )
    856         FT_INVALID_TOO_SHORT;
    857 
    858       length = (FT_UInt)( valid->limit - table );
    859     }
    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)( 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)( gindex + delta ) & 0xFFFFU;
   1094           }
   1095           else
   1096             gindex = (FT_UInt)( 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)( gindex + delta ) & 0xFFFFU;
   1298         }
   1299         else
   1300           gindex = (FT_UInt)( 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     if ( p + num_groups * 12 > valid->limit )
   1673       FT_INVALID_TOO_SHORT;
   1674 
   1675     /* check groups, they must be in increasing order */
   1676     {
   1677       FT_UInt32  n, start, end, start_id, count, last = 0;
   1678 
   1679 
   1680       for ( n = 0; n < num_groups; n++ )
   1681       {
   1682         FT_UInt   hi, lo;
   1683 
   1684 
   1685         start    = TT_NEXT_ULONG( p );
   1686         end      = TT_NEXT_ULONG( p );
   1687         start_id = TT_NEXT_ULONG( p );
   1688 
   1689         if ( start > end )
   1690           FT_INVALID_DATA;
   1691 
   1692         if ( n > 0 && start <= last )
   1693           FT_INVALID_DATA;
   1694 
   1695         if ( valid->level >= FT_VALIDATE_TIGHT )
   1696         {
   1697           if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
   1698             FT_INVALID_GLYPH_ID;
   1699 
   1700           count = (FT_UInt32)( end - start + 1 );
   1701 
   1702           if ( start & ~0xFFFFU )
   1703           {
   1704             /* start_hi != 0; check that is32[i] is 1 for each i in */
   1705             /* the `hi' and `lo' of the range [start..end]          */
   1706             for ( ; count > 0; count--, start++ )
   1707             {
   1708               hi = (FT_UInt)( start >> 16 );
   1709               lo = (FT_UInt)( start & 0xFFFFU );
   1710 
   1711               if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
   1712                 FT_INVALID_DATA;
   1713 
   1714               if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
   1715                 FT_INVALID_DATA;
   1716             }
   1717           }
   1718           else
   1719           {
   1720             /* start_hi == 0; check that is32[i] is 0 for each i in */
   1721             /* the range [start..end]                               */
   1722 
   1723             /* end_hi cannot be != 0! */
   1724             if ( end & ~0xFFFFU )
   1725               FT_INVALID_DATA;
   1726 
   1727             for ( ; count > 0; count--, start++ )
   1728             {
   1729               lo = (FT_UInt)( start & 0xFFFFU );
   1730 
   1731               if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
   1732                 FT_INVALID_DATA;
   1733             }
   1734           }
   1735         }
   1736 
   1737         last = end;
   1738       }
   1739     }
   1740 
   1741     return FT_Err_Ok;
   1742   }
   1743 
   1744 
   1745   FT_CALLBACK_DEF( FT_UInt )
   1746   tt_cmap8_char_index( TT_CMap    cmap,
   1747                        FT_UInt32  char_code )
   1748   {
   1749     FT_Byte*   table      = cmap->data;
   1750     FT_UInt    result     = 0;
   1751     FT_Byte*   p          = table + 8204;
   1752     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
   1753     FT_UInt32  start, end, start_id;
   1754 
   1755 
   1756     for ( ; num_groups > 0; num_groups-- )
   1757     {
   1758       start    = TT_NEXT_ULONG( p );
   1759       end      = TT_NEXT_ULONG( p );
   1760       start_id = TT_NEXT_ULONG( p );
   1761 
   1762       if ( char_code < start )
   1763         break;
   1764 
   1765       if ( char_code <= end )
   1766       {
   1767         result = (FT_UInt)( start_id + char_code - start );
   1768         break;
   1769       }
   1770     }
   1771     return result;
   1772   }
   1773 
   1774 
   1775   FT_CALLBACK_DEF( FT_UInt32 )
   1776   tt_cmap8_char_next( TT_CMap     cmap,
   1777                       FT_UInt32  *pchar_code )
   1778   {
   1779     FT_UInt32  result     = 0;
   1780     FT_UInt32  char_code  = *pchar_code + 1;
   1781     FT_UInt    gindex     = 0;
   1782     FT_Byte*   table      = cmap->data;
   1783     FT_Byte*   p          = table + 8204;
   1784     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
   1785     FT_UInt32  start, end, start_id;
   1786 
   1787 
   1788     p = table + 8208;
   1789 
   1790     for ( ; num_groups > 0; num_groups-- )
   1791     {
   1792       start    = TT_NEXT_ULONG( p );
   1793       end      = TT_NEXT_ULONG( p );
   1794       start_id = TT_NEXT_ULONG( p );
   1795 
   1796       if ( char_code < start )
   1797         char_code = start;
   1798 
   1799       if ( char_code <= end )
   1800       {
   1801         gindex = (FT_UInt)( char_code - start + start_id );
   1802         if ( gindex != 0 )
   1803         {
   1804           result = char_code;
   1805           goto Exit;
   1806         }
   1807       }
   1808     }
   1809 
   1810   Exit:
   1811     *pchar_code = result;
   1812     return gindex;
   1813   }
   1814 
   1815 
   1816   FT_CALLBACK_DEF( FT_Error )
   1817   tt_cmap8_get_info( TT_CMap       cmap,
   1818                      TT_CMapInfo  *cmap_info )
   1819   {
   1820     FT_Byte*  p = cmap->data + 8;
   1821 
   1822 
   1823     cmap_info->format   = 8;
   1824     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
   1825 
   1826     return FT_Err_Ok;
   1827   }
   1828 
   1829 
   1830   FT_DEFINE_TT_CMAP(
   1831     tt_cmap8_class_rec,
   1832     sizeof ( TT_CMapRec ),
   1833 
   1834     (FT_CMap_InitFunc)     tt_cmap_init,
   1835     (FT_CMap_DoneFunc)     NULL,
   1836     (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
   1837     (FT_CMap_CharNextFunc) tt_cmap8_char_next,
   1838 
   1839     NULL,
   1840     NULL,
   1841     NULL,
   1842     NULL,
   1843     NULL,
   1844 
   1845     8,
   1846     (TT_CMap_ValidateFunc)tt_cmap8_validate,
   1847     (TT_CMap_Info_GetFunc)tt_cmap8_get_info )
   1848 
   1849 #endif /* TT_CONFIG_CMAP_FORMAT_8 */
   1850 
   1851 
   1852   /*************************************************************************/
   1853   /*************************************************************************/
   1854   /*****                                                               *****/
   1855   /*****                          FORMAT 10                            *****/
   1856   /*****                                                               *****/
   1857   /*************************************************************************/
   1858   /*************************************************************************/
   1859 
   1860   /*************************************************************************/
   1861   /*                                                                       */
   1862   /* TABLE OVERVIEW                                                        */
   1863   /* --------------                                                        */
   1864   /*                                                                       */
   1865   /*   NAME      OFFSET  TYPE               DESCRIPTION                    */
   1866   /*                                                                       */
   1867   /*   format     0      USHORT             must be 10                     */
   1868   /*   reserved   2      USHORT             reserved                       */
   1869   /*   length     4      ULONG              length in bytes                */
   1870   /*   language   8      ULONG              Mac language code              */
   1871   /*                                                                       */
   1872   /*   start     12      ULONG              first char in range            */
   1873   /*   count     16      ULONG              number of chars in range       */
   1874   /*   glyphIds  20      USHORT[count]      glyph indices covered          */
   1875   /*                                                                       */
   1876 
   1877 #ifdef TT_CONFIG_CMAP_FORMAT_10
   1878 
   1879   FT_CALLBACK_DEF( FT_Error )
   1880   tt_cmap10_validate( FT_Byte*      table,
   1881                       FT_Validator  valid )
   1882   {
   1883     FT_Byte*  p = table + 4;
   1884     FT_ULong  length, count;
   1885 
   1886 
   1887     if ( table + 20 > valid->limit )
   1888       FT_INVALID_TOO_SHORT;
   1889 
   1890     length = TT_NEXT_ULONG( p );
   1891     p      = table + 16;
   1892     count  = TT_NEXT_ULONG( p );
   1893 
   1894     if ( length > (FT_ULong)( valid->limit - table ) ||
   1895          length < 20 + count * 2                     )
   1896       FT_INVALID_TOO_SHORT;
   1897 
   1898     /* check glyph indices */
   1899     if ( valid->level >= FT_VALIDATE_TIGHT )
   1900     {
   1901       FT_UInt  gindex;
   1902 
   1903 
   1904       for ( ; count > 0; count-- )
   1905       {
   1906         gindex = TT_NEXT_USHORT( p );
   1907         if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
   1908           FT_INVALID_GLYPH_ID;
   1909       }
   1910     }
   1911 
   1912     return FT_Err_Ok;
   1913   }
   1914 
   1915 
   1916   FT_CALLBACK_DEF( FT_UInt )
   1917   tt_cmap10_char_index( TT_CMap    cmap,
   1918                         FT_UInt32  char_code )
   1919   {
   1920     FT_Byte*   table  = cmap->data;
   1921     FT_UInt    result = 0;
   1922     FT_Byte*   p      = table + 12;
   1923     FT_UInt32  start  = TT_NEXT_ULONG( p );
   1924     FT_UInt32  count  = TT_NEXT_ULONG( p );
   1925     FT_UInt32  idx    = (FT_ULong)( char_code - start );
   1926 
   1927 
   1928     if ( idx < count )
   1929     {
   1930       p     += 2 * idx;
   1931       result = TT_PEEK_USHORT( p );
   1932     }
   1933     return result;
   1934   }
   1935 
   1936 
   1937   FT_CALLBACK_DEF( FT_UInt32 )
   1938   tt_cmap10_char_next( TT_CMap     cmap,
   1939                        FT_UInt32  *pchar_code )
   1940   {
   1941     FT_Byte*   table     = cmap->data;
   1942     FT_UInt32  char_code = *pchar_code + 1;
   1943     FT_UInt    gindex    = 0;
   1944     FT_Byte*   p         = table + 12;
   1945     FT_UInt32  start     = TT_NEXT_ULONG( p );
   1946     FT_UInt32  count     = TT_NEXT_ULONG( p );
   1947     FT_UInt32  idx;
   1948 
   1949 
   1950     if ( char_code < start )
   1951       char_code = start;
   1952 
   1953     idx = (FT_UInt32)( char_code - start );
   1954     p  += 2 * idx;
   1955 
   1956     for ( ; idx < count; idx++ )
   1957     {
   1958       gindex = TT_NEXT_USHORT( p );
   1959       if ( gindex != 0 )
   1960         break;
   1961       char_code++;
   1962     }
   1963 
   1964     *pchar_code = char_code;
   1965     return gindex;
   1966   }
   1967 
   1968 
   1969   FT_CALLBACK_DEF( FT_Error )
   1970   tt_cmap10_get_info( TT_CMap       cmap,
   1971                       TT_CMapInfo  *cmap_info )
   1972   {
   1973     FT_Byte*  p = cmap->data + 8;
   1974 
   1975 
   1976     cmap_info->format   = 10;
   1977     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
   1978 
   1979     return FT_Err_Ok;
   1980   }
   1981 
   1982 
   1983   FT_DEFINE_TT_CMAP(
   1984     tt_cmap10_class_rec,
   1985     sizeof ( TT_CMapRec ),
   1986 
   1987     (FT_CMap_InitFunc)     tt_cmap_init,
   1988     (FT_CMap_DoneFunc)     NULL,
   1989     (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
   1990     (FT_CMap_CharNextFunc) tt_cmap10_char_next,
   1991 
   1992     NULL,
   1993     NULL,
   1994     NULL,
   1995     NULL,
   1996     NULL,
   1997 
   1998     10,
   1999     (TT_CMap_ValidateFunc)tt_cmap10_validate,
   2000     (TT_CMap_Info_GetFunc)tt_cmap10_get_info )
   2001 
   2002 #endif /* TT_CONFIG_CMAP_FORMAT_10 */
   2003 
   2004 
   2005   /*************************************************************************/
   2006   /*************************************************************************/
   2007   /*****                                                               *****/
   2008   /*****                          FORMAT 12                            *****/
   2009   /*****                                                               *****/
   2010   /*************************************************************************/
   2011   /*************************************************************************/
   2012 
   2013   /*************************************************************************/
   2014   /*                                                                       */
   2015   /* TABLE OVERVIEW                                                        */
   2016   /* --------------                                                        */
   2017   /*                                                                       */
   2018   /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
   2019   /*                                                                       */
   2020   /*   format      0          USHORT     must be 12                        */
   2021   /*   reserved    2          USHORT     reserved                          */
   2022   /*   length      4          ULONG      length in bytes                   */
   2023   /*   language    8          ULONG      Mac language code                 */
   2024   /*   count       12         ULONG      number of groups                  */
   2025   /*               16                                                      */
   2026   /*                                                                       */
   2027   /* This header is followed by `count' groups of the following format:    */
   2028   /*                                                                       */
   2029   /*   start       0          ULONG      first charcode                    */
   2030   /*   end         4          ULONG      last charcode                     */
   2031   /*   startId     8          ULONG      start glyph ID for the group      */
   2032   /*                                                                       */
   2033 
   2034 #ifdef TT_CONFIG_CMAP_FORMAT_12
   2035 
   2036   typedef struct  TT_CMap12Rec_
   2037   {
   2038     TT_CMapRec  cmap;
   2039     FT_Bool     valid;
   2040     FT_ULong    cur_charcode;
   2041     FT_UInt     cur_gindex;
   2042     FT_ULong    cur_group;
   2043     FT_ULong    num_groups;
   2044 
   2045   } TT_CMap12Rec, *TT_CMap12;
   2046 
   2047 
   2048   FT_CALLBACK_DEF( FT_Error )
   2049   tt_cmap12_init( TT_CMap12  cmap,
   2050                   FT_Byte*   table )
   2051   {
   2052     cmap->cmap.data  = table;
   2053 
   2054     table           += 12;
   2055     cmap->num_groups = FT_PEEK_ULONG( table );
   2056 
   2057     cmap->valid      = 0;
   2058 
   2059     return FT_Err_Ok;
   2060   }
   2061 
   2062 
   2063   FT_CALLBACK_DEF( FT_Error )
   2064   tt_cmap12_validate( FT_Byte*      table,
   2065                       FT_Validator  valid )
   2066   {
   2067     FT_Byte*  p;
   2068     FT_ULong  length;
   2069     FT_ULong  num_groups;
   2070 
   2071 
   2072     if ( table + 16 > valid->limit )
   2073       FT_INVALID_TOO_SHORT;
   2074 
   2075     p      = table + 4;
   2076     length = TT_NEXT_ULONG( p );
   2077 
   2078     p          = table + 12;
   2079     num_groups = TT_NEXT_ULONG( p );
   2080 
   2081     if ( length > (FT_ULong)( valid->limit - table ) ||
   2082          length < 16 + 12 * num_groups               )
   2083       FT_INVALID_TOO_SHORT;
   2084 
   2085     /* check groups, they must be in increasing order */
   2086     {
   2087       FT_ULong  n, start, end, start_id, last = 0;
   2088 
   2089 
   2090       for ( n = 0; n < num_groups; n++ )
   2091       {
   2092         start    = TT_NEXT_ULONG( p );
   2093         end      = TT_NEXT_ULONG( p );
   2094         start_id = TT_NEXT_ULONG( p );
   2095 
   2096         if ( start > end )
   2097           FT_INVALID_DATA;
   2098 
   2099         if ( n > 0 && start <= last )
   2100           FT_INVALID_DATA;
   2101 
   2102         if ( valid->level >= FT_VALIDATE_TIGHT )
   2103         {
   2104           if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
   2105             FT_INVALID_GLYPH_ID;
   2106         }
   2107 
   2108         last = end;
   2109       }
   2110     }
   2111 
   2112     return FT_Err_Ok;
   2113   }
   2114 
   2115 
   2116   /* search the index of the charcode next to cmap->cur_charcode */
   2117   /* cmap->cur_group should be set up properly by caller         */
   2118   /*                                                             */
   2119   static void
   2120   tt_cmap12_next( TT_CMap12  cmap )
   2121   {
   2122     FT_Byte*  p;
   2123     FT_ULong  start, end, start_id, char_code;
   2124     FT_ULong  n;
   2125     FT_UInt   gindex;
   2126 
   2127 
   2128     if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
   2129       goto Fail;
   2130 
   2131     char_code = cmap->cur_charcode + 1;
   2132 
   2133     for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
   2134     {
   2135       p        = cmap->cmap.data + 16 + 12 * n;
   2136       start    = TT_NEXT_ULONG( p );
   2137       end      = TT_NEXT_ULONG( p );
   2138       start_id = TT_PEEK_ULONG( p );
   2139 
   2140       if ( char_code < start )
   2141         char_code = start;
   2142 
   2143       for ( ; char_code <= end; char_code++ )
   2144       {
   2145         gindex = (FT_UInt)( start_id + char_code - start );
   2146 
   2147         if ( gindex )
   2148         {
   2149           cmap->cur_charcode = char_code;;
   2150           cmap->cur_gindex   = gindex;
   2151           cmap->cur_group    = n;
   2152 
   2153           return;
   2154         }
   2155       }
   2156     }
   2157 
   2158   Fail:
   2159     cmap->valid = 0;
   2160   }
   2161 
   2162 
   2163   static FT_UInt
   2164   tt_cmap12_char_map_binary( TT_CMap     cmap,
   2165                              FT_UInt32*  pchar_code,
   2166                              FT_Bool     next )
   2167   {
   2168     FT_UInt    gindex     = 0;
   2169     FT_Byte*   p          = cmap->data + 12;
   2170     FT_UInt32  num_groups = TT_PEEK_ULONG( p );
   2171     FT_UInt32  char_code  = *pchar_code;
   2172     FT_UInt32  start, end, start_id;
   2173     FT_UInt32  max, min, mid;
   2174 
   2175 
   2176     if ( !num_groups )
   2177       return 0;
   2178 
   2179     /* make compiler happy */
   2180     mid = num_groups;
   2181     end = 0xFFFFFFFFUL;
   2182 
   2183     if ( next )
   2184       char_code++;
   2185 
   2186     min = 0;
   2187     max = num_groups;
   2188 
   2189     /* binary search */
   2190     while ( min < max )
   2191     {
   2192       mid = ( min + max ) >> 1;
   2193       p   = cmap->data + 16 + 12 * mid;
   2194 
   2195       start = TT_NEXT_ULONG( p );
   2196       end   = TT_NEXT_ULONG( p );
   2197 
   2198       if ( char_code < start )
   2199         max = mid;
   2200       else if ( char_code > end )
   2201         min = mid + 1;
   2202       else
   2203       {
   2204         start_id = TT_PEEK_ULONG( p );
   2205         gindex = (FT_UInt)( start_id + char_code - start );
   2206 
   2207         break;
   2208       }
   2209     }
   2210 
   2211     if ( next )
   2212     {
   2213       TT_CMap12  cmap12 = (TT_CMap12)cmap;
   2214 
   2215 
   2216       /* if `char_code' is not in any group, then `mid' is */
   2217       /* the group nearest to `char_code'                  */
   2218       /*                                                   */
   2219 
   2220       if ( char_code > end )
   2221       {
   2222         mid++;
   2223         if ( mid == num_groups )
   2224           return 0;
   2225       }
   2226 
   2227       cmap12->valid        = 1;
   2228       cmap12->cur_charcode = char_code;
   2229       cmap12->cur_group    = mid;
   2230 
   2231       if ( !gindex )
   2232       {
   2233         tt_cmap12_next( cmap12 );
   2234 
   2235         if ( cmap12->valid )
   2236           gindex = cmap12->cur_gindex;
   2237       }
   2238       else
   2239         cmap12->cur_gindex = gindex;
   2240 
   2241       if ( gindex )
   2242         *pchar_code = cmap12->cur_charcode;
   2243     }
   2244 
   2245     return gindex;
   2246   }
   2247 
   2248 
   2249   FT_CALLBACK_DEF( FT_UInt )
   2250   tt_cmap12_char_index( TT_CMap    cmap,
   2251                         FT_UInt32  char_code )
   2252   {
   2253     return tt_cmap12_char_map_binary( cmap, &char_code, 0 );
   2254   }
   2255 
   2256 
   2257   FT_CALLBACK_DEF( FT_UInt32 )
   2258   tt_cmap12_char_next( TT_CMap     cmap,
   2259                        FT_UInt32  *pchar_code )
   2260   {
   2261     TT_CMap12  cmap12 = (TT_CMap12)cmap;
   2262     FT_ULong   gindex;
   2263 
   2264 
   2265     if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )
   2266       return 0;
   2267 
   2268     /* no need to search */
   2269     if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
   2270     {
   2271       tt_cmap12_next( cmap12 );
   2272       if ( cmap12->valid )
   2273       {
   2274         gindex = cmap12->cur_gindex;
   2275 
   2276         /* XXX: check cur_charcode overflow is expected */
   2277         if ( gindex )
   2278           *pchar_code = (FT_UInt32)cmap12->cur_charcode;
   2279       }
   2280       else
   2281         gindex = 0;
   2282     }
   2283     else
   2284       gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
   2285 
   2286     /* XXX: check gindex overflow is expected */
   2287     return (FT_UInt32)gindex;
   2288   }
   2289 
   2290 
   2291   FT_CALLBACK_DEF( FT_Error )
   2292   tt_cmap12_get_info( TT_CMap       cmap,
   2293                       TT_CMapInfo  *cmap_info )
   2294   {
   2295     FT_Byte*  p = cmap->data + 8;
   2296 
   2297 
   2298     cmap_info->format   = 12;
   2299     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
   2300 
   2301     return FT_Err_Ok;
   2302   }
   2303 
   2304 
   2305   FT_DEFINE_TT_CMAP(
   2306     tt_cmap12_class_rec,
   2307     sizeof ( TT_CMap12Rec ),
   2308 
   2309     (FT_CMap_InitFunc)     tt_cmap12_init,
   2310     (FT_CMap_DoneFunc)     NULL,
   2311     (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
   2312     (FT_CMap_CharNextFunc) tt_cmap12_char_next,
   2313 
   2314     NULL,
   2315     NULL,
   2316     NULL,
   2317     NULL,
   2318     NULL,
   2319 
   2320     12,
   2321     (TT_CMap_ValidateFunc)tt_cmap12_validate,
   2322     (TT_CMap_Info_GetFunc)tt_cmap12_get_info )
   2323 
   2324 #endif /* TT_CONFIG_CMAP_FORMAT_12 */
   2325 
   2326 
   2327   /*************************************************************************/
   2328   /*************************************************************************/
   2329   /*****                                                               *****/
   2330   /*****                          FORMAT 13                            *****/
   2331   /*****                                                               *****/
   2332   /*************************************************************************/
   2333   /*************************************************************************/
   2334 
   2335   /*************************************************************************/
   2336   /*                                                                       */
   2337   /* TABLE OVERVIEW                                                        */
   2338   /* --------------                                                        */
   2339   /*                                                                       */
   2340   /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
   2341   /*                                                                       */
   2342   /*   format      0          USHORT     must be 13                        */
   2343   /*   reserved    2          USHORT     reserved                          */
   2344   /*   length      4          ULONG      length in bytes                   */
   2345   /*   language    8          ULONG      Mac language code                 */
   2346   /*   count       12         ULONG      number of groups                  */
   2347   /*               16                                                      */
   2348   /*                                                                       */
   2349   /* This header is followed by `count' groups of the following format:    */
   2350   /*                                                                       */
   2351   /*   start       0          ULONG      first charcode                    */
   2352   /*   end         4          ULONG      last charcode                     */
   2353   /*   glyphId     8          ULONG      glyph ID for the whole group      */
   2354   /*                                                                       */
   2355 
   2356 #ifdef TT_CONFIG_CMAP_FORMAT_13
   2357 
   2358   typedef struct  TT_CMap13Rec_
   2359   {
   2360     TT_CMapRec  cmap;
   2361     FT_Bool     valid;
   2362     FT_ULong    cur_charcode;
   2363     FT_UInt     cur_gindex;
   2364     FT_ULong    cur_group;
   2365     FT_ULong    num_groups;
   2366 
   2367   } TT_CMap13Rec, *TT_CMap13;
   2368 
   2369 
   2370   FT_CALLBACK_DEF( FT_Error )
   2371   tt_cmap13_init( TT_CMap13  cmap,
   2372                   FT_Byte*   table )
   2373   {
   2374     cmap->cmap.data  = table;
   2375 
   2376     table           += 12;
   2377     cmap->num_groups = FT_PEEK_ULONG( table );
   2378 
   2379     cmap->valid      = 0;
   2380 
   2381     return FT_Err_Ok;
   2382   }
   2383 
   2384 
   2385   FT_CALLBACK_DEF( FT_Error )
   2386   tt_cmap13_validate( FT_Byte*      table,
   2387                       FT_Validator  valid )
   2388   {
   2389     FT_Byte*  p;
   2390     FT_ULong  length;
   2391     FT_ULong  num_groups;
   2392 
   2393 
   2394     if ( table + 16 > valid->limit )
   2395       FT_INVALID_TOO_SHORT;
   2396 
   2397     p      = table + 4;
   2398     length = TT_NEXT_ULONG( p );
   2399 
   2400     p          = table + 12;
   2401     num_groups = TT_NEXT_ULONG( p );
   2402 
   2403     if ( length > (FT_ULong)( valid->limit - table ) ||
   2404          length < 16 + 12 * num_groups               )
   2405       FT_INVALID_TOO_SHORT;
   2406 
   2407     /* check groups, they must be in increasing order */
   2408     {
   2409       FT_ULong  n, start, end, glyph_id, last = 0;
   2410 
   2411 
   2412       for ( n = 0; n < num_groups; n++ )
   2413       {
   2414         start    = TT_NEXT_ULONG( p );
   2415         end      = TT_NEXT_ULONG( p );
   2416         glyph_id = TT_NEXT_ULONG( p );
   2417 
   2418         if ( start > end )
   2419           FT_INVALID_DATA;
   2420 
   2421         if ( n > 0 && start <= last )
   2422           FT_INVALID_DATA;
   2423 
   2424         if ( valid->level >= FT_VALIDATE_TIGHT )
   2425         {
   2426           if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) )
   2427             FT_INVALID_GLYPH_ID;
   2428         }
   2429 
   2430         last = end;
   2431       }
   2432     }
   2433 
   2434     return FT_Err_Ok;
   2435   }
   2436 
   2437 
   2438   /* search the index of the charcode next to cmap->cur_charcode */
   2439   /* cmap->cur_group should be set up properly by caller         */
   2440   /*                                                             */
   2441   static void
   2442   tt_cmap13_next( TT_CMap13  cmap )
   2443   {
   2444     FT_Byte*  p;
   2445     FT_ULong  start, end, glyph_id, char_code;
   2446     FT_ULong  n;
   2447     FT_UInt   gindex;
   2448 
   2449 
   2450     if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
   2451       goto Fail;
   2452 
   2453     char_code = cmap->cur_charcode + 1;
   2454 
   2455     for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
   2456     {
   2457       p        = cmap->cmap.data + 16 + 12 * n;
   2458       start    = TT_NEXT_ULONG( p );
   2459       end      = TT_NEXT_ULONG( p );
   2460       glyph_id = TT_PEEK_ULONG( p );
   2461 
   2462       if ( char_code < start )
   2463         char_code = start;
   2464 
   2465       if ( char_code <= end )
   2466       {
   2467         gindex = (FT_UInt)glyph_id;
   2468 
   2469         if ( gindex )
   2470         {
   2471           cmap->cur_charcode = char_code;;
   2472           cmap->cur_gindex   = gindex;
   2473           cmap->cur_group    = n;
   2474 
   2475           return;
   2476         }
   2477       }
   2478     }
   2479 
   2480   Fail:
   2481     cmap->valid = 0;
   2482   }
   2483 
   2484 
   2485   static FT_UInt
   2486   tt_cmap13_char_map_binary( TT_CMap     cmap,
   2487                              FT_UInt32*  pchar_code,
   2488                              FT_Bool     next )
   2489   {
   2490     FT_UInt    gindex     = 0;
   2491     FT_Byte*   p          = cmap->data + 12;
   2492     FT_UInt32  num_groups = TT_PEEK_ULONG( p );
   2493     FT_UInt32  char_code  = *pchar_code;
   2494     FT_UInt32  start, end;
   2495     FT_UInt32  max, min, mid;
   2496 
   2497 
   2498     if ( !num_groups )
   2499       return 0;
   2500 
   2501     /* make compiler happy */
   2502     mid = num_groups;
   2503     end = 0xFFFFFFFFUL;
   2504 
   2505     if ( next )
   2506       char_code++;
   2507 
   2508     min = 0;
   2509     max = num_groups;
   2510 
   2511     /* binary search */
   2512     while ( min < max )
   2513     {
   2514       mid = ( min + max ) >> 1;
   2515       p   = cmap->data + 16 + 12 * mid;
   2516 
   2517       start = TT_NEXT_ULONG( p );
   2518       end   = TT_NEXT_ULONG( p );
   2519 
   2520       if ( char_code < start )
   2521         max = mid;
   2522       else if ( char_code > end )
   2523         min = mid + 1;
   2524       else
   2525       {
   2526         gindex = (FT_UInt)TT_PEEK_ULONG( p );
   2527 
   2528         break;
   2529       }
   2530     }
   2531 
   2532     if ( next )
   2533     {
   2534       TT_CMap13  cmap13 = (TT_CMap13)cmap;
   2535 
   2536 
   2537       /* if `char_code' is not in any group, then `mid' is */
   2538       /* the group nearest to `char_code'                  */
   2539 
   2540       if ( char_code > end )
   2541       {
   2542         mid++;
   2543         if ( mid == num_groups )
   2544           return 0;
   2545       }
   2546 
   2547       cmap13->valid        = 1;
   2548       cmap13->cur_charcode = char_code;
   2549       cmap13->cur_group    = mid;
   2550 
   2551       if ( !gindex )
   2552       {
   2553         tt_cmap13_next( cmap13 );
   2554 
   2555         if ( cmap13->valid )
   2556           gindex = cmap13->cur_gindex;
   2557       }
   2558       else
   2559         cmap13->cur_gindex = gindex;
   2560 
   2561       if ( gindex )
   2562         *pchar_code = cmap13->cur_charcode;
   2563     }
   2564 
   2565     return gindex;
   2566   }
   2567 
   2568 
   2569   FT_CALLBACK_DEF( FT_UInt )
   2570   tt_cmap13_char_index( TT_CMap    cmap,
   2571                         FT_UInt32  char_code )
   2572   {
   2573     return tt_cmap13_char_map_binary( cmap, &char_code, 0 );
   2574   }
   2575 
   2576 
   2577   FT_CALLBACK_DEF( FT_UInt32 )
   2578   tt_cmap13_char_next( TT_CMap     cmap,
   2579                        FT_UInt32  *pchar_code )
   2580   {
   2581     TT_CMap13  cmap13 = (TT_CMap13)cmap;
   2582     FT_UInt    gindex;
   2583 
   2584 
   2585     if ( cmap13->cur_charcode >= 0xFFFFFFFFUL )
   2586       return 0;
   2587 
   2588     /* no need to search */
   2589     if ( cmap13->valid && cmap13->cur_charcode == *pchar_code )
   2590     {
   2591       tt_cmap13_next( cmap13 );
   2592       if ( cmap13->valid )
   2593       {
   2594         gindex = cmap13->cur_gindex;
   2595         if ( gindex )
   2596           *pchar_code = cmap13->cur_charcode;
   2597       }
   2598       else
   2599         gindex = 0;
   2600     }
   2601     else
   2602       gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 );
   2603 
   2604     return gindex;
   2605   }
   2606 
   2607 
   2608   FT_CALLBACK_DEF( FT_Error )
   2609   tt_cmap13_get_info( TT_CMap       cmap,
   2610                       TT_CMapInfo  *cmap_info )
   2611   {
   2612     FT_Byte*  p = cmap->data + 8;
   2613 
   2614 
   2615     cmap_info->format   = 13;
   2616     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
   2617 
   2618     return FT_Err_Ok;
   2619   }
   2620 
   2621 
   2622   FT_DEFINE_TT_CMAP(
   2623     tt_cmap13_class_rec,
   2624     sizeof ( TT_CMap13Rec ),
   2625 
   2626     (FT_CMap_InitFunc)     tt_cmap13_init,
   2627     (FT_CMap_DoneFunc)     NULL,
   2628     (FT_CMap_CharIndexFunc)tt_cmap13_char_index,
   2629     (FT_CMap_CharNextFunc) tt_cmap13_char_next,
   2630 
   2631     NULL,
   2632     NULL,
   2633     NULL,
   2634     NULL,
   2635     NULL,
   2636 
   2637     13,
   2638     (TT_CMap_ValidateFunc)tt_cmap13_validate,
   2639     (TT_CMap_Info_GetFunc)tt_cmap13_get_info )
   2640 
   2641 #endif /* TT_CONFIG_CMAP_FORMAT_13 */
   2642 
   2643 
   2644   /*************************************************************************/
   2645   /*************************************************************************/
   2646   /*****                                                               *****/
   2647   /*****                           FORMAT 14                           *****/
   2648   /*****                                                               *****/
   2649   /*************************************************************************/
   2650   /*************************************************************************/
   2651 
   2652   /*************************************************************************/
   2653   /*                                                                       */
   2654   /* TABLE OVERVIEW                                                        */
   2655   /* --------------                                                        */
   2656   /*                                                                       */
   2657   /*   NAME         OFFSET  TYPE    DESCRIPTION                            */
   2658   /*                                                                       */
   2659   /*   format         0     USHORT  must be 14                             */
   2660   /*   length         2     ULONG   table length in bytes                  */
   2661   /*   numSelector    6     ULONG   number of variation sel. records       */
   2662   /*                                                                       */
   2663   /* Followed by numSelector records, each of which looks like             */
   2664   /*                                                                       */
   2665   /*   varSelector    0     UINT24  Unicode codepoint of sel.              */
   2666   /*   defaultOff     3     ULONG   offset to a default UVS table          */
   2667   /*                                describing any variants to be found in */
   2668   /*                                the normal Unicode subtable.           */
   2669   /*   nonDefOff      7     ULONG   offset to a non-default UVS table      */
   2670   /*                                describing any variants not in the     */
   2671   /*                                standard cmap, with GIDs here          */
   2672   /* (either offset may be 0 NULL)                                         */
   2673   /*                                                                       */
   2674   /* Selectors are sorted by code point.                                   */
   2675   /*                                                                       */
   2676   /* A default Unicode Variation Selector (UVS) subtable is just a list of */
   2677   /* ranges of code points which are to be found in the standard cmap.  No */
   2678   /* glyph IDs (GIDs) here.                                                */
   2679   /*                                                                       */
   2680   /*   numRanges      0     ULONG   number of ranges following             */
   2681   /*                                                                       */
   2682   /* A range looks like                                                    */
   2683   /*                                                                       */
   2684   /*   uniStart       0     UINT24  code point of the first character in   */
   2685   /*                                this range                             */
   2686   /*   additionalCnt  3     UBYTE   count of additional characters in this */
   2687   /*                                range (zero means a range of a single  */
   2688   /*                                character)                             */
   2689   /*                                                                       */
   2690   /* Ranges are sorted by `uniStart'.                                      */
   2691   /*                                                                       */
   2692   /* A non-default Unicode Variation Selector (UVS) subtable is a list of  */
   2693   /* mappings from codepoint to GID.                                       */
   2694   /*                                                                       */
   2695   /*   numMappings    0     ULONG   number of mappings                     */
   2696   /*                                                                       */
   2697   /* A range looks like                                                    */
   2698   /*                                                                       */
   2699   /*   uniStart       0     UINT24  code point of the first character in   */
   2700   /*                                this range                             */
   2701   /*   GID            3     USHORT  and its GID                            */
   2702   /*                                                                       */
   2703   /* Ranges are sorted by `uniStart'.                                      */
   2704 
   2705 #ifdef TT_CONFIG_CMAP_FORMAT_14
   2706 
   2707   typedef struct  TT_CMap14Rec_
   2708   {
   2709     TT_CMapRec  cmap;
   2710     FT_ULong    num_selectors;
   2711 
   2712     /* This array is used to store the results of various
   2713      * cmap 14 query functions.  The data is overwritten
   2714      * on each call to these functions.
   2715      */
   2716     FT_UInt32   max_results;
   2717     FT_UInt32*  results;
   2718     FT_Memory   memory;
   2719 
   2720   } TT_CMap14Rec, *TT_CMap14;
   2721 
   2722 
   2723   FT_CALLBACK_DEF( void )
   2724   tt_cmap14_done( TT_CMap14  cmap )
   2725   {
   2726     FT_Memory  memory = cmap->memory;
   2727 
   2728 
   2729     cmap->max_results = 0;
   2730     if ( memory != NULL && cmap->results != NULL )
   2731       FT_FREE( cmap->results );
   2732   }
   2733 
   2734 
   2735   static FT_Error
   2736   tt_cmap14_ensure( TT_CMap14  cmap,
   2737                     FT_UInt32  num_results,
   2738                     FT_Memory  memory )
   2739   {
   2740     FT_UInt32  old_max = cmap->max_results;
   2741     FT_Error   error   = FT_Err_Ok;
   2742 
   2743 
   2744     if ( num_results > cmap->max_results )
   2745     {
   2746        cmap->memory = memory;
   2747 
   2748        if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) )
   2749          return error;
   2750 
   2751        cmap->max_results = num_results;
   2752     }
   2753 
   2754     return error;
   2755   }
   2756 
   2757 
   2758   FT_CALLBACK_DEF( FT_Error )
   2759   tt_cmap14_init( TT_CMap14  cmap,
   2760                   FT_Byte*   table )
   2761   {
   2762     cmap->cmap.data = table;
   2763 
   2764     table               += 6;
   2765     cmap->num_selectors  = FT_PEEK_ULONG( table );
   2766     cmap->max_results    = 0;
   2767     cmap->results        = NULL;
   2768 
   2769     return FT_Err_Ok;
   2770   }
   2771 
   2772 
   2773   FT_CALLBACK_DEF( FT_Error )
   2774   tt_cmap14_validate( FT_Byte*      table,
   2775                       FT_Validator  valid )
   2776   {
   2777     FT_Byte*  p;
   2778     FT_ULong  length;
   2779     FT_ULong  num_selectors;
   2780 
   2781 
   2782     if ( table + 2 + 4 + 4 > valid->limit )
   2783       FT_INVALID_TOO_SHORT;
   2784 
   2785     p             = table + 2;
   2786     length        = TT_NEXT_ULONG( p );
   2787     num_selectors = TT_NEXT_ULONG( p );
   2788 
   2789     if ( length > (FT_ULong)( valid->limit - table ) ||
   2790          length < 10 + 11 * num_selectors            )
   2791       FT_INVALID_TOO_SHORT;
   2792 
   2793     /* check selectors, they must be in increasing order */
   2794     {
   2795       /* we start lastVarSel at 1 because a variant selector value of 0
   2796        * isn't valid.
   2797        */
   2798       FT_ULong  n, lastVarSel = 1;
   2799 
   2800 
   2801       for ( n = 0; n < num_selectors; n++ )
   2802       {
   2803         FT_ULong  varSel    = TT_NEXT_UINT24( p );
   2804         FT_ULong  defOff    = TT_NEXT_ULONG( p );
   2805         FT_ULong  nondefOff = TT_NEXT_ULONG( p );
   2806 
   2807 
   2808         if ( defOff >= length || nondefOff >= length )
   2809           FT_INVALID_TOO_SHORT;
   2810 
   2811         if ( varSel < lastVarSel )
   2812           FT_INVALID_DATA;
   2813 
   2814         lastVarSel = varSel + 1;
   2815 
   2816         /* check the default table (these glyphs should be reached     */
   2817         /* through the normal Unicode cmap, no GIDs, just check order) */
   2818         if ( defOff != 0 )
   2819         {
   2820           FT_Byte*  defp      = table + defOff;
   2821           FT_ULong  numRanges = TT_NEXT_ULONG( defp );
   2822           FT_ULong  i;
   2823           FT_ULong  lastBase  = 0;
   2824 
   2825 
   2826           if ( defp + numRanges * 4 > valid->limit )
   2827             FT_INVALID_TOO_SHORT;
   2828 
   2829           for ( i = 0; i < numRanges; ++i )
   2830           {
   2831             FT_ULong  base = TT_NEXT_UINT24( defp );
   2832             FT_ULong  cnt  = FT_NEXT_BYTE( defp );
   2833 
   2834 
   2835             if ( base + cnt >= 0x110000UL )              /* end of Unicode */
   2836               FT_INVALID_DATA;
   2837 
   2838             if ( base < lastBase )
   2839               FT_INVALID_DATA;
   2840 
   2841             lastBase = base + cnt + 1U;
   2842           }
   2843         }
   2844 
   2845         /* and the non-default table (these glyphs are specified here) */
   2846         if ( nondefOff != 0 )
   2847         {
   2848           FT_Byte*  ndp         = table + nondefOff;
   2849           FT_ULong  numMappings = TT_NEXT_ULONG( ndp );
   2850           FT_ULong  i, lastUni  = 0;
   2851 
   2852 
   2853           if ( numMappings * 4 > (FT_ULong)( valid->limit - ndp ) )
   2854             FT_INVALID_TOO_SHORT;
   2855 
   2856           for ( i = 0; i < numMappings; ++i )
   2857           {
   2858             FT_ULong  uni = TT_NEXT_UINT24( ndp );
   2859             FT_ULong  gid = TT_NEXT_USHORT( ndp );
   2860 
   2861 
   2862             if ( uni >= 0x110000UL )                     /* end of Unicode */
   2863               FT_INVALID_DATA;
   2864 
   2865             if ( uni < lastUni )
   2866               FT_INVALID_DATA;
   2867 
   2868             lastUni = uni + 1U;
   2869 
   2870             if ( valid->level >= FT_VALIDATE_TIGHT    &&
   2871                  gid >= TT_VALID_GLYPH_COUNT( valid ) )
   2872               FT_INVALID_GLYPH_ID;
   2873           }
   2874         }
   2875       }
   2876     }
   2877 
   2878     return FT_Err_Ok;
   2879   }
   2880 
   2881 
   2882   FT_CALLBACK_DEF( FT_UInt )
   2883   tt_cmap14_char_index( TT_CMap    cmap,
   2884                         FT_UInt32  char_code )
   2885   {
   2886     FT_UNUSED( cmap );
   2887     FT_UNUSED( char_code );
   2888 
   2889     /* This can't happen */
   2890     return 0;
   2891   }
   2892 
   2893 
   2894   FT_CALLBACK_DEF( FT_UInt32 )
   2895   tt_cmap14_char_next( TT_CMap     cmap,
   2896                        FT_UInt32  *pchar_code )
   2897   {
   2898     FT_UNUSED( cmap );
   2899 
   2900     /* This can't happen */
   2901     *pchar_code = 0;
   2902     return 0;
   2903   }
   2904 
   2905 
   2906   FT_CALLBACK_DEF( FT_Error )
   2907   tt_cmap14_get_info( TT_CMap       cmap,
   2908                       TT_CMapInfo  *cmap_info )
   2909   {
   2910     FT_UNUSED( cmap );
   2911 
   2912     cmap_info->format   = 14;
   2913     /* subtable 14 does not define a language field */
   2914     cmap_info->language = 0xFFFFFFFFUL;
   2915 
   2916     return FT_Err_Ok;
   2917   }
   2918 
   2919 
   2920   static FT_UInt
   2921   tt_cmap14_char_map_def_binary( FT_Byte    *base,
   2922                                  FT_UInt32   char_code )
   2923   {
   2924     FT_UInt32  numRanges = TT_PEEK_ULONG( base );
   2925     FT_UInt32  max, min;
   2926 
   2927 
   2928     min = 0;
   2929     max = numRanges;
   2930 
   2931     base += 4;
   2932 
   2933     /* binary search */
   2934     while ( min < max )
   2935     {
   2936       FT_UInt32  mid   = ( min + max ) >> 1;
   2937       FT_Byte*   p     = base + 4 * mid;
   2938       FT_ULong   start = TT_NEXT_UINT24( p );
   2939       FT_UInt    cnt   = FT_NEXT_BYTE( p );
   2940 
   2941 
   2942       if ( char_code < start )
   2943         max = mid;
   2944       else if ( char_code > start+cnt )
   2945         min = mid + 1;
   2946       else
   2947         return TRUE;
   2948     }
   2949 
   2950     return FALSE;
   2951   }
   2952 
   2953 
   2954   static FT_UInt
   2955   tt_cmap14_char_map_nondef_binary( FT_Byte    *base,
   2956                                     FT_UInt32   char_code )
   2957   {
   2958     FT_UInt32  numMappings = TT_PEEK_ULONG( base );
   2959     FT_UInt32  max, min;
   2960 
   2961 
   2962     min = 0;
   2963     max = numMappings;
   2964 
   2965     base += 4;
   2966 
   2967     /* binary search */
   2968     while ( min < max )
   2969     {
   2970       FT_UInt32  mid = ( min + max ) >> 1;
   2971       FT_Byte*   p   = base + 5 * mid;
   2972       FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
   2973 
   2974 
   2975       if ( char_code < uni )
   2976         max = mid;
   2977       else if ( char_code > uni )
   2978         min = mid + 1;
   2979       else
   2980         return TT_PEEK_USHORT( p );
   2981     }
   2982 
   2983     return 0;
   2984   }
   2985 
   2986 
   2987   static FT_Byte*
   2988   tt_cmap14_find_variant( FT_Byte    *base,
   2989                           FT_UInt32   variantCode )
   2990   {
   2991     FT_UInt32  numVar = TT_PEEK_ULONG( base );
   2992     FT_UInt32  max, min;
   2993 
   2994 
   2995     min = 0;
   2996     max = numVar;
   2997 
   2998     base += 4;
   2999 
   3000     /* binary search */
   3001     while ( min < max )
   3002     {
   3003       FT_UInt32  mid    = ( min + max ) >> 1;
   3004       FT_Byte*   p      = base + 11 * mid;
   3005       FT_ULong   varSel = TT_NEXT_UINT24( p );
   3006 
   3007 
   3008       if ( variantCode < varSel )
   3009         max = mid;
   3010       else if ( variantCode > varSel )
   3011         min = mid + 1;
   3012       else
   3013         return p;
   3014     }
   3015 
   3016     return NULL;
   3017   }
   3018 
   3019 
   3020   FT_CALLBACK_DEF( FT_UInt )
   3021   tt_cmap14_char_var_index( TT_CMap    cmap,
   3022                             TT_CMap    ucmap,
   3023                             FT_UInt32  charcode,
   3024                             FT_UInt32  variantSelector )
   3025   {
   3026     FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
   3027     FT_ULong  defOff;
   3028     FT_ULong  nondefOff;
   3029 
   3030 
   3031     if ( !p )
   3032       return 0;
   3033 
   3034     defOff    = TT_NEXT_ULONG( p );
   3035     nondefOff = TT_PEEK_ULONG( p );
   3036 
   3037     if ( defOff != 0                                                    &&
   3038          tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
   3039     {
   3040       /* This is the default variant of this charcode.  GID not stored */
   3041       /* here; stored in the normal Unicode charmap instead.           */
   3042       return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode );
   3043     }
   3044 
   3045     if ( nondefOff != 0 )
   3046       return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
   3047                                                charcode );
   3048 
   3049     return 0;
   3050   }
   3051 
   3052 
   3053   FT_CALLBACK_DEF( FT_Int )
   3054   tt_cmap14_char_var_isdefault( TT_CMap    cmap,
   3055                                 FT_UInt32  charcode,
   3056                                 FT_UInt32  variantSelector )
   3057   {
   3058     FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
   3059     FT_ULong  defOff;
   3060     FT_ULong  nondefOff;
   3061 
   3062 
   3063     if ( !p )
   3064       return -1;
   3065 
   3066     defOff    = TT_NEXT_ULONG( p );
   3067     nondefOff = TT_NEXT_ULONG( p );
   3068 
   3069     if ( defOff != 0                                                    &&
   3070          tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
   3071       return 1;
   3072 
   3073     if ( nondefOff != 0                                            &&
   3074          tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
   3075                                            charcode ) != 0         )
   3076       return 0;
   3077 
   3078     return -1;
   3079   }
   3080 
   3081 
   3082   FT_CALLBACK_DEF( FT_UInt32* )
   3083   tt_cmap14_variants( TT_CMap    cmap,
   3084                       FT_Memory  memory )
   3085   {
   3086     TT_CMap14   cmap14 = (TT_CMap14)cmap;
   3087     FT_UInt32   count  = cmap14->num_selectors;
   3088     FT_Byte*    p      = cmap->data + 10;
   3089     FT_UInt32*  result;
   3090     FT_UInt32   i;
   3091 
   3092 
   3093     if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
   3094       return NULL;
   3095 
   3096     result = cmap14->results;
   3097     for ( i = 0; i < count; ++i )
   3098     {
   3099       result[i] = (FT_UInt32)TT_NEXT_UINT24( p );
   3100       p        += 8;
   3101     }
   3102     result[i] = 0;
   3103 
   3104     return result;
   3105   }
   3106 
   3107 
   3108   FT_CALLBACK_DEF( FT_UInt32 * )
   3109   tt_cmap14_char_variants( TT_CMap    cmap,
   3110                            FT_Memory  memory,
   3111                            FT_UInt32  charCode )
   3112   {
   3113     TT_CMap14   cmap14 = (TT_CMap14)  cmap;
   3114     FT_UInt32   count  = cmap14->num_selectors;
   3115     FT_Byte*    p      = cmap->data + 10;
   3116     FT_UInt32*  q;
   3117 
   3118 
   3119     if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
   3120       return NULL;
   3121 
   3122     for ( q = cmap14->results; count > 0; --count )
   3123     {
   3124       FT_UInt32  varSel    = TT_NEXT_UINT24( p );
   3125       FT_ULong   defOff    = TT_NEXT_ULONG( p );
   3126       FT_ULong   nondefOff = TT_NEXT_ULONG( p );
   3127 
   3128 
   3129       if ( ( defOff != 0                                               &&
   3130              tt_cmap14_char_map_def_binary( cmap->data + defOff,
   3131                                             charCode )                 ) ||
   3132            ( nondefOff != 0                                            &&
   3133              tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
   3134                                                charCode ) != 0         ) )
   3135       {
   3136         q[0] = varSel;
   3137         q++;
   3138       }
   3139     }
   3140     q[0] = 0;
   3141 
   3142     return cmap14->results;
   3143   }
   3144 
   3145 
   3146   static FT_UInt
   3147   tt_cmap14_def_char_count( FT_Byte  *p )
   3148   {
   3149     FT_UInt32  numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
   3150     FT_UInt    tot       = 0;
   3151 
   3152 
   3153     p += 3;  /* point to the first `cnt' field */
   3154     for ( ; numRanges > 0; numRanges-- )
   3155     {
   3156       tot += 1 + p[0];
   3157       p   += 4;
   3158     }
   3159 
   3160     return tot;
   3161   }
   3162 
   3163 
   3164   static FT_UInt32*
   3165   tt_cmap14_get_def_chars( TT_CMap    cmap,
   3166                            FT_Byte*   p,
   3167                            FT_Memory  memory )
   3168   {
   3169     TT_CMap14   cmap14 = (TT_CMap14) cmap;
   3170     FT_UInt32   numRanges;
   3171     FT_UInt     cnt;
   3172     FT_UInt32*  q;
   3173 
   3174 
   3175     cnt       = tt_cmap14_def_char_count( p );
   3176     numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
   3177 
   3178     if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) )
   3179       return NULL;
   3180 
   3181     for ( q = cmap14->results; numRanges > 0; --numRanges )
   3182     {
   3183       FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
   3184 
   3185 
   3186       cnt = FT_NEXT_BYTE( p ) + 1;
   3187       do
   3188       {
   3189         q[0]  = uni;
   3190         uni  += 1;
   3191         q    += 1;
   3192 
   3193       } while ( --cnt != 0 );
   3194     }
   3195     q[0] = 0;
   3196 
   3197     return cmap14->results;
   3198   }
   3199 
   3200 
   3201   static FT_UInt32*
   3202   tt_cmap14_get_nondef_chars( TT_CMap     cmap,
   3203                               FT_Byte    *p,
   3204                               FT_Memory   memory )
   3205   {
   3206     TT_CMap14   cmap14 = (TT_CMap14) cmap;
   3207     FT_UInt32   numMappings;
   3208     FT_UInt     i;
   3209     FT_UInt32  *ret;
   3210 
   3211 
   3212     numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
   3213 
   3214     if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) )
   3215       return NULL;
   3216 
   3217     ret = cmap14->results;
   3218     for ( i = 0; i < numMappings; ++i )
   3219     {
   3220       ret[i] = (FT_UInt32)TT_NEXT_UINT24( p );
   3221       p += 2;
   3222     }
   3223     ret[i] = 0;
   3224 
   3225     return ret;
   3226   }
   3227 
   3228 
   3229   FT_CALLBACK_DEF( FT_UInt32 * )
   3230   tt_cmap14_variant_chars( TT_CMap    cmap,
   3231                            FT_Memory  memory,
   3232                            FT_UInt32  variantSelector )
   3233   {
   3234     FT_Byte    *p  = tt_cmap14_find_variant( cmap->data + 6,
   3235                                              variantSelector );
   3236     FT_Int      i;
   3237     FT_ULong    defOff;
   3238     FT_ULong    nondefOff;
   3239 
   3240 
   3241     if ( !p )
   3242       return NULL;
   3243 
   3244     defOff    = TT_NEXT_ULONG( p );
   3245     nondefOff = TT_NEXT_ULONG( p );
   3246 
   3247     if ( defOff == 0 && nondefOff == 0 )
   3248       return NULL;
   3249 
   3250     if ( defOff == 0 )
   3251       return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
   3252                                          memory );
   3253     else if ( nondefOff == 0 )
   3254       return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
   3255                                       memory );
   3256     else
   3257     {
   3258       /* Both a default and a non-default glyph set?  That's probably not */
   3259       /* good font design, but the spec allows for it...                  */
   3260       TT_CMap14  cmap14 = (TT_CMap14) cmap;
   3261       FT_UInt32  numRanges;
   3262       FT_UInt32  numMappings;
   3263       FT_UInt32  duni;
   3264       FT_UInt32  dcnt;
   3265       FT_UInt32  nuni;
   3266       FT_Byte*   dp;
   3267       FT_UInt    di, ni, k;
   3268 
   3269       FT_UInt32  *ret;
   3270 
   3271 
   3272       p  = cmap->data + nondefOff;
   3273       dp = cmap->data + defOff;
   3274 
   3275       numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
   3276       dcnt        = tt_cmap14_def_char_count( dp );
   3277       numRanges   = (FT_UInt32)TT_NEXT_ULONG( dp );
   3278 
   3279       if ( numMappings == 0 )
   3280         return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
   3281                                         memory );
   3282       if ( dcnt == 0 )
   3283         return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
   3284                                            memory );
   3285 
   3286       if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) )
   3287         return NULL;
   3288 
   3289       ret  = cmap14->results;
   3290       duni = (FT_UInt32)TT_NEXT_UINT24( dp );
   3291       dcnt = FT_NEXT_BYTE( dp );
   3292       di   = 1;
   3293       nuni = (FT_UInt32)TT_NEXT_UINT24( p );
   3294       p   += 2;
   3295       ni   = 1;
   3296       i    = 0;
   3297 
   3298       for ( ;; )
   3299       {
   3300         if ( nuni > duni + dcnt )
   3301         {
   3302           for ( k = 0; k <= dcnt; ++k )
   3303             ret[i++] = duni + k;
   3304 
   3305           ++di;
   3306 
   3307           if ( di > numRanges )
   3308             break;
   3309 
   3310           duni = (FT_UInt32)TT_NEXT_UINT24( dp );
   3311           dcnt = FT_NEXT_BYTE( dp );
   3312         }
   3313         else
   3314         {
   3315           if ( nuni < duni )
   3316             ret[i++] = nuni;
   3317           /* If it is within the default range then ignore it -- */
   3318           /* that should not have happened                       */
   3319           ++ni;
   3320           if ( ni > numMappings )
   3321             break;
   3322 
   3323           nuni = (FT_UInt32)TT_NEXT_UINT24( p );
   3324           p += 2;
   3325         }
   3326       }
   3327 
   3328       if ( ni <= numMappings )
   3329       {
   3330         /* If we get here then we have run out of all default ranges.   */
   3331         /* We have read one non-default mapping which we haven't stored */
   3332         /* and there may be others that need to be read.                */
   3333         ret[i++] = nuni;
   3334         while ( ni < numMappings )
   3335         {
   3336           ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p );
   3337           p += 2;
   3338           ++ni;
   3339         }
   3340       }
   3341       else if ( di <= numRanges )
   3342       {
   3343         /* If we get here then we have run out of all non-default     */
   3344         /* mappings.  We have read one default range which we haven't */
   3345         /* stored and there may be others that need to be read.       */
   3346         for ( k = 0; k <= dcnt; ++k )
   3347           ret[i++] = duni + k;
   3348 
   3349         while ( di < numRanges )
   3350         {
   3351           duni = (FT_UInt32)TT_NEXT_UINT24( dp );
   3352           dcnt = FT_NEXT_BYTE( dp );
   3353 
   3354           for ( k = 0; k <= dcnt; ++k )
   3355             ret[i++] = duni + k;
   3356           ++di;
   3357         }
   3358       }
   3359 
   3360       ret[i] = 0;
   3361 
   3362       return ret;
   3363     }
   3364   }
   3365 
   3366 
   3367   FT_DEFINE_TT_CMAP(
   3368     tt_cmap14_class_rec,
   3369     sizeof ( TT_CMap14Rec ),
   3370 
   3371     (FT_CMap_InitFunc)     tt_cmap14_init,
   3372     (FT_CMap_DoneFunc)     tt_cmap14_done,
   3373     (FT_CMap_CharIndexFunc)tt_cmap14_char_index,
   3374     (FT_CMap_CharNextFunc) tt_cmap14_char_next,
   3375 
   3376     /* Format 14 extension functions */
   3377     (FT_CMap_CharVarIndexFunc)    tt_cmap14_char_var_index,
   3378     (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
   3379     (FT_CMap_VariantListFunc)     tt_cmap14_variants,
   3380     (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
   3381     (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars,
   3382 
   3383     14,
   3384     (TT_CMap_ValidateFunc)tt_cmap14_validate,
   3385     (TT_CMap_Info_GetFunc)tt_cmap14_get_info )
   3386 
   3387 #endif /* TT_CONFIG_CMAP_FORMAT_14 */
   3388 
   3389 
   3390 #ifndef FT_CONFIG_OPTION_PIC
   3391 
   3392   static const TT_CMap_Class  tt_cmap_classes[] =
   3393   {
   3394 #define TTCMAPCITEM( a )  &a,
   3395 #include "ttcmapc.h"
   3396     NULL,
   3397   };
   3398 
   3399 #else /*FT_CONFIG_OPTION_PIC*/
   3400 
   3401   void
   3402   FT_Destroy_Class_tt_cmap_classes( FT_Library      library,
   3403                                     TT_CMap_Class*  clazz )
   3404   {
   3405     FT_Memory  memory = library->memory;
   3406 
   3407 
   3408     if ( clazz )
   3409       FT_FREE( clazz );
   3410   }
   3411 
   3412 
   3413   FT_Error
   3414   FT_Create_Class_tt_cmap_classes( FT_Library       library,
   3415                                    TT_CMap_Class**  output_class )
   3416   {
   3417     TT_CMap_Class*     clazz  = NULL;
   3418     TT_CMap_ClassRec*  recs;
   3419     FT_Error           error;
   3420     FT_Memory          memory = library->memory;
   3421 
   3422     int  i = 0;
   3423 
   3424 
   3425 #define TTCMAPCITEM( a ) i++;
   3426 #include "ttcmapc.h"
   3427 
   3428     /* allocate enough space for both the pointers */
   3429     /* plus terminator and the class instances     */
   3430     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * ( i + 1 ) +
   3431                           sizeof ( TT_CMap_ClassRec ) * i ) )
   3432       return error;
   3433 
   3434     /* the location of the class instances follows the array of pointers */
   3435     recs = (TT_CMap_ClassRec*)( (char*)clazz +
   3436                                 sizeof ( *clazz ) * ( i + 1 ) );
   3437     i    = 0;
   3438 
   3439 #undef TTCMAPCITEM
   3440 #define  TTCMAPCITEM( a )             \
   3441     FT_Init_Class_ ## a( &recs[i] );  \
   3442     clazz[i] = &recs[i];              \
   3443     i++;
   3444 #include "ttcmapc.h"
   3445 
   3446     clazz[i] = NULL;
   3447 
   3448     *output_class = clazz;
   3449     return FT_Err_Ok;
   3450   }
   3451 
   3452 #endif /*FT_CONFIG_OPTION_PIC*/
   3453 
   3454 
   3455   /* parse the `cmap' table and build the corresponding TT_CMap objects */
   3456   /* in the current face                                                */
   3457   /*                                                                    */
   3458   FT_LOCAL_DEF( FT_Error )
   3459   tt_face_build_cmaps( TT_Face  face )
   3460   {
   3461     FT_Byte*           table = face->cmap_table;
   3462     FT_Byte*           limit = table + face->cmap_size;
   3463     FT_UInt volatile   num_cmaps;
   3464     FT_Byte* volatile  p     = table;
   3465     FT_Library         library = FT_FACE_LIBRARY( face );
   3466 
   3467     FT_UNUSED( library );
   3468 
   3469 
   3470     if ( !p || p + 4 > limit )
   3471       return FT_THROW( Invalid_Table );
   3472 
   3473     /* only recognize format 0 */
   3474     if ( TT_NEXT_USHORT( p ) != 0 )
   3475     {
   3476       FT_ERROR(( "tt_face_build_cmaps:"
   3477                  " unsupported `cmap' table format = %d\n",
   3478                  TT_PEEK_USHORT( p - 2) ));
   3479       return FT_THROW( Invalid_Table );
   3480     }
   3481 
   3482     num_cmaps = TT_NEXT_USHORT( p );
   3483 
   3484 #ifdef FT_MAX_CHARMAP_CACHEABLE
   3485     if ( num_cmaps > FT_MAX_CHARMAP_CACHEABLE )
   3486       FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables (%d)\n"
   3487                  "                     subtable #%d and higher are loaded"
   3488                  "                     but cannot be searched\n",
   3489                  num_cmaps, FT_MAX_CHARMAP_CACHEABLE + 1 ));
   3490 #endif
   3491 
   3492     for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
   3493     {
   3494       FT_CharMapRec  charmap;
   3495       FT_UInt32      offset;
   3496 
   3497 
   3498       charmap.platform_id = TT_NEXT_USHORT( p );
   3499       charmap.encoding_id = TT_NEXT_USHORT( p );
   3500       charmap.face        = FT_FACE( face );
   3501       charmap.encoding    = FT_ENCODING_NONE;  /* will be filled later */
   3502       offset              = TT_NEXT_ULONG( p );
   3503 
   3504       if ( offset && offset <= face->cmap_size - 2 )
   3505       {
   3506         FT_Byte* volatile              cmap   = table + offset;
   3507         volatile FT_UInt               format = TT_PEEK_USHORT( cmap );
   3508         const TT_CMap_Class* volatile  pclazz = TT_CMAP_CLASSES_GET;
   3509         TT_CMap_Class volatile         clazz;
   3510 
   3511 
   3512         for ( ; *pclazz; pclazz++ )
   3513         {
   3514           clazz = *pclazz;
   3515           if ( clazz->format == format )
   3516           {
   3517             volatile TT_ValidatorRec  valid;
   3518             volatile FT_Error         error = FT_Err_Ok;
   3519 
   3520 
   3521             ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
   3522                                FT_VALIDATE_DEFAULT );
   3523 
   3524             valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
   3525 
   3526             if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer) == 0 )
   3527             {
   3528               /* validate this cmap sub-table */
   3529               error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
   3530             }
   3531 
   3532             if ( valid.validator.error == 0 )
   3533             {
   3534               FT_CMap  ttcmap;
   3535 
   3536 
   3537               /* It might make sense to store the single variation         */
   3538               /* selector cmap somewhere special.  But it would have to be */
   3539               /* in the public FT_FaceRec, and we can't change that.       */
   3540 
   3541               if ( !FT_CMap_New( (FT_CMap_Class)clazz,
   3542                                  cmap, &charmap, &ttcmap ) )
   3543               {
   3544                 /* it is simpler to directly set `flags' than adding */
   3545                 /* a parameter to FT_CMap_New                        */
   3546                 ((TT_CMap)ttcmap)->flags = (FT_Int)error;
   3547               }
   3548             }
   3549             else
   3550             {
   3551               FT_TRACE0(( "tt_face_build_cmaps:"
   3552                           " broken cmap sub-table ignored\n" ));
   3553             }
   3554             break;
   3555           }
   3556         }
   3557 
   3558         if ( *pclazz == NULL )
   3559         {
   3560           FT_TRACE0(( "tt_face_build_cmaps:"
   3561                       " unsupported cmap sub-table ignored\n" ));
   3562         }
   3563       }
   3564     }
   3565 
   3566     return FT_Err_Ok;
   3567   }
   3568 
   3569 
   3570   FT_LOCAL( FT_Error )
   3571   tt_get_cmap_info( FT_CharMap    charmap,
   3572                     TT_CMapInfo  *cmap_info )
   3573   {
   3574     FT_CMap        cmap  = (FT_CMap)charmap;
   3575     TT_CMap_Class  clazz = (TT_CMap_Class)cmap->clazz;
   3576 
   3577 
   3578     return clazz->get_cmap_info( charmap, cmap_info );
   3579   }
   3580 
   3581 
   3582 /* END */
   3583