(root)/
freetype-2.13.2/
src/
sfnt/
ttcmap.c
       1  /****************************************************************************
       2   *
       3   * ttcmap.c
       4   *
       5   *   TrueType character mapping table (cmap) support (body).
       6   *
       7   * Copyright (C) 2002-2023 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 = (FT_ULong)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 = (FT_ULong)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 = (FT_ULong)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 = (FT_ULong)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 = (FT_ULong)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 = (FT_ULong)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 = (FT_ULong)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 = (FT_ULong)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://docs.microsoft.com/en-us/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: %d 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 */