tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ttcmap.c (111810B)


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