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