ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ttcmap.c
Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ttcmap.c                                                               */
00004 /*                                                                         */
00005 /*    TrueType character mapping table (cmap) support (body).              */
00006 /*                                                                         */
00007 /*  Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by      */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019 #include <ft2build.h>
00020 #include FT_INTERNAL_DEBUG_H
00021 
00022 #include "sferrors.h"           /* must come before FT_INTERNAL_VALIDATE_H */
00023 
00024 #include FT_INTERNAL_VALIDATE_H
00025 #include FT_INTERNAL_STREAM_H
00026 #include "ttload.h"
00027 #include "ttcmap.h"
00028 #include "sfntpic.h"
00029 
00030 
00031   /*************************************************************************/
00032   /*                                                                       */
00033   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00034   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00035   /* messages during execution.                                            */
00036   /*                                                                       */
00037 #undef  FT_COMPONENT
00038 #define FT_COMPONENT  trace_ttcmap
00039 
00040 
00041 #define TT_PEEK_SHORT   FT_PEEK_SHORT
00042 #define TT_PEEK_USHORT  FT_PEEK_USHORT
00043 #define TT_PEEK_UINT24  FT_PEEK_UOFF3
00044 #define TT_PEEK_LONG    FT_PEEK_LONG
00045 #define TT_PEEK_ULONG   FT_PEEK_ULONG
00046 
00047 #define TT_NEXT_SHORT   FT_NEXT_SHORT
00048 #define TT_NEXT_USHORT  FT_NEXT_USHORT
00049 #define TT_NEXT_UINT24  FT_NEXT_UOFF3
00050 #define TT_NEXT_LONG    FT_NEXT_LONG
00051 #define TT_NEXT_ULONG   FT_NEXT_ULONG
00052 
00053 
00054   FT_CALLBACK_DEF( FT_Error )
00055   tt_cmap_init( TT_CMap   cmap,
00056                 FT_Byte*  table )
00057   {
00058     cmap->data = table;
00059     return SFNT_Err_Ok;
00060   }
00061 
00062 
00063   /*************************************************************************/
00064   /*************************************************************************/
00065   /*****                                                               *****/
00066   /*****                           FORMAT 0                            *****/
00067   /*****                                                               *****/
00068   /*************************************************************************/
00069   /*************************************************************************/
00070 
00071   /*************************************************************************/
00072   /*                                                                       */
00073   /* TABLE OVERVIEW                                                        */
00074   /* --------------                                                        */
00075   /*                                                                       */
00076   /*   NAME        OFFSET         TYPE          DESCRIPTION                */
00077   /*                                                                       */
00078   /*   format      0              USHORT        must be 0                  */
00079   /*   length      2              USHORT        table length in bytes      */
00080   /*   language    4              USHORT        Mac language code          */
00081   /*   glyph_ids   6              BYTE[256]     array of glyph indices     */
00082   /*               262                                                     */
00083   /*                                                                       */
00084 
00085 #ifdef TT_CONFIG_CMAP_FORMAT_0
00086 
00087   FT_CALLBACK_DEF( FT_Error )
00088   tt_cmap0_validate( FT_Byte*      table,
00089                      FT_Validator  valid )
00090   {
00091     FT_Byte*  p      = table + 2;
00092     FT_UInt   length = TT_NEXT_USHORT( p );
00093 
00094 
00095     if ( table + length > valid->limit || length < 262 )
00096       FT_INVALID_TOO_SHORT;
00097 
00098     /* check glyph indices whenever necessary */
00099     if ( valid->level >= FT_VALIDATE_TIGHT )
00100     {
00101       FT_UInt  n, idx;
00102 
00103 
00104       p = table + 6;
00105       for ( n = 0; n < 256; n++ )
00106       {
00107         idx = *p++;
00108         if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
00109           FT_INVALID_GLYPH_ID;
00110       }
00111     }
00112 
00113     return SFNT_Err_Ok;
00114   }
00115 
00116 
00117   FT_CALLBACK_DEF( FT_UInt )
00118   tt_cmap0_char_index( TT_CMap    cmap,
00119                        FT_UInt32  char_code )
00120   {
00121     FT_Byte*  table = cmap->data;
00122 
00123 
00124     return char_code < 256 ? table[6 + char_code] : 0;
00125   }
00126 
00127 
00128   FT_CALLBACK_DEF( FT_UInt32 )
00129   tt_cmap0_char_next( TT_CMap     cmap,
00130                       FT_UInt32  *pchar_code )
00131   {
00132     FT_Byte*   table    = cmap->data;
00133     FT_UInt32  charcode = *pchar_code;
00134     FT_UInt32  result   = 0;
00135     FT_UInt    gindex   = 0;
00136 
00137 
00138     table += 6;  /* go to glyph IDs */
00139     while ( ++charcode < 256 )
00140     {
00141       gindex = table[charcode];
00142       if ( gindex != 0 )
00143       {
00144         result = charcode;
00145         break;
00146       }
00147     }
00148 
00149     *pchar_code = result;
00150     return gindex;
00151   }
00152 
00153 
00154   FT_CALLBACK_DEF( FT_Error )
00155   tt_cmap0_get_info( TT_CMap       cmap,
00156                      TT_CMapInfo  *cmap_info )
00157   {
00158     FT_Byte*  p = cmap->data + 4;
00159 
00160 
00161     cmap_info->format   = 0;
00162     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
00163 
00164     return SFNT_Err_Ok;
00165   }
00166 
00167 
00168   FT_DEFINE_TT_CMAP(tt_cmap0_class_rec,
00169       sizeof ( TT_CMapRec ),
00170 
00171       (FT_CMap_InitFunc)     tt_cmap_init,
00172       (FT_CMap_DoneFunc)     NULL,
00173       (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
00174       (FT_CMap_CharNextFunc) tt_cmap0_char_next,
00175 
00176       NULL, NULL, NULL, NULL, NULL
00177     ,
00178     0,
00179     (TT_CMap_ValidateFunc)   tt_cmap0_validate,
00180     (TT_CMap_Info_GetFunc)   tt_cmap0_get_info
00181   )
00182 
00183 #endif /* TT_CONFIG_CMAP_FORMAT_0 */
00184 
00185 
00186   /*************************************************************************/
00187   /*************************************************************************/
00188   /*****                                                               *****/
00189   /*****                          FORMAT 2                             *****/
00190   /*****                                                               *****/
00191   /***** This is used for certain CJK encodings that encode text in a  *****/
00192   /***** mixed 8/16 bits encoding along the following lines:           *****/
00193   /*****                                                               *****/
00194   /***** * Certain byte values correspond to an 8-bit character code   *****/
00195   /*****   (typically in the range 0..127 for ASCII compatibility).    *****/
00196   /*****                                                               *****/
00197   /***** * Certain byte values signal the first byte of a 2-byte       *****/
00198   /*****   character code (but these values are also valid as the      *****/
00199   /*****   second byte of a 2-byte character).                         *****/
00200   /*****                                                               *****/
00201   /***** The following charmap lookup and iteration functions all      *****/
00202   /***** assume that the value "charcode" correspond to following:     *****/
00203   /*****                                                               *****/
00204   /*****   - For one byte characters, "charcode" is simply the         *****/
00205   /*****     character code.                                           *****/
00206   /*****                                                               *****/
00207   /*****   - For two byte characters, "charcode" is the 2-byte         *****/
00208   /*****     character code in big endian format.  More exactly:       *****/
00209   /*****                                                               *****/
00210   /*****       (charcode >> 8)    is the first byte value              *****/
00211   /*****       (charcode & 0xFF)  is the second byte value             *****/
00212   /*****                                                               *****/
00213   /***** Note that not all values of "charcode" are valid according    *****/
00214   /***** to these rules, and the function moderately check the         *****/
00215   /***** arguments.                                                    *****/
00216   /*****                                                               *****/
00217   /*************************************************************************/
00218   /*************************************************************************/
00219 
00220   /*************************************************************************/
00221   /*                                                                       */
00222   /* TABLE OVERVIEW                                                        */
00223   /* --------------                                                        */
00224   /*                                                                       */
00225   /*   NAME        OFFSET         TYPE            DESCRIPTION              */
00226   /*                                                                       */
00227   /*   format      0              USHORT          must be 2                */
00228   /*   length      2              USHORT          table length in bytes    */
00229   /*   language    4              USHORT          Mac language code        */
00230   /*   keys        6              USHORT[256]     sub-header keys          */
00231   /*   subs        518            SUBHEAD[NSUBS]  sub-headers array        */
00232   /*   glyph_ids   518+NSUB*8     USHORT[]        glyph ID array           */
00233   /*                                                                       */
00234   /* The `keys' table is used to map charcode high-bytes to sub-headers.   */
00235   /* The value of `NSUBS' is the number of sub-headers defined in the      */
00236   /* table and is computed by finding the maximum of the `keys' table.     */
00237   /*                                                                       */
00238   /* Note that for any n, `keys[n]' is a byte offset within the `subs'     */
00239   /* table, i.e., it is the corresponding sub-header index multiplied      */
00240   /* by 8.                                                                 */
00241   /*                                                                       */
00242   /* Each sub-header has the following format:                             */
00243   /*                                                                       */
00244   /*   NAME        OFFSET      TYPE            DESCRIPTION                 */
00245   /*                                                                       */
00246   /*   first       0           USHORT          first valid low-byte        */
00247   /*   count       2           USHORT          number of valid low-bytes   */
00248   /*   delta       4           SHORT           see below                   */
00249   /*   offset      6           USHORT          see below                   */
00250   /*                                                                       */
00251   /* A sub-header defines, for each high-byte, the range of valid          */
00252   /* low-bytes within the charmap.  Note that the range defined by `first' */
00253   /* and `count' must be completely included in the interval [0..255]      */
00254   /* according to the specification.                                       */
00255   /*                                                                       */
00256   /* If a character code is contained within a given sub-header, then      */
00257   /* mapping it to a glyph index is done as follows:                       */
00258   /*                                                                       */
00259   /* * The value of `offset' is read.  This is a _byte_ distance from the  */
00260   /*   location of the `offset' field itself into a slice of the           */
00261   /*   `glyph_ids' table.  Let's call it `slice' (it is a USHORT[] too).   */
00262   /*                                                                       */
00263   /* * The value `slice[char.lo - first]' is read.  If it is 0, there is   */
00264   /*   no glyph for the charcode.  Otherwise, the value of `delta' is      */
00265   /*   added to it (modulo 65536) to form a new glyph index.               */
00266   /*                                                                       */
00267   /* It is up to the validation routine to check that all offsets fall     */
00268   /* within the glyph IDs table (and not within the `subs' table itself or */
00269   /* outside of the CMap).                                                 */
00270   /*                                                                       */
00271 
00272 #ifdef TT_CONFIG_CMAP_FORMAT_2
00273 
00274   FT_CALLBACK_DEF( FT_Error )
00275   tt_cmap2_validate( FT_Byte*      table,
00276                      FT_Validator  valid )
00277   {
00278     FT_Byte*  p      = table + 2;           /* skip format */
00279     FT_UInt   length = TT_PEEK_USHORT( p );
00280     FT_UInt   n, max_subs;
00281     FT_Byte*  keys;                         /* keys table */
00282     FT_Byte*  subs;                         /* sub-headers */
00283     FT_Byte*  glyph_ids;                    /* glyph ID array */
00284 
00285 
00286     if ( table + length > valid->limit || length < 6 + 512 )
00287       FT_INVALID_TOO_SHORT;
00288 
00289     keys = table + 6;
00290 
00291     /* parse keys to compute sub-headers count */
00292     p        = keys;
00293     max_subs = 0;
00294     for ( n = 0; n < 256; n++ )
00295     {
00296       FT_UInt  idx = TT_NEXT_USHORT( p );
00297 
00298 
00299       /* value must be multiple of 8 */
00300       if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
00301         FT_INVALID_DATA;
00302 
00303       idx >>= 3;
00304 
00305       if ( idx > max_subs )
00306         max_subs = idx;
00307     }
00308 
00309     FT_ASSERT( p == table + 518 );
00310 
00311     subs      = p;
00312     glyph_ids = subs + (max_subs + 1) * 8;
00313     if ( glyph_ids > valid->limit )
00314       FT_INVALID_TOO_SHORT;
00315 
00316     /* parse sub-headers */
00317     for ( n = 0; n <= max_subs; n++ )
00318     {
00319       FT_UInt   first_code, code_count, offset;
00320       FT_Int    delta;
00321       FT_Byte*  ids;
00322 
00323 
00324       first_code = TT_NEXT_USHORT( p );
00325       code_count = TT_NEXT_USHORT( p );
00326       delta      = TT_NEXT_SHORT( p );
00327       offset     = TT_NEXT_USHORT( p );
00328 
00329       /* many Dynalab fonts have empty sub-headers */
00330       if ( code_count == 0 )
00331         continue;
00332 
00333       /* check range within 0..255 */
00334       if ( valid->level >= FT_VALIDATE_PARANOID )
00335       {
00336         if ( first_code >= 256 || first_code + code_count > 256 )
00337           FT_INVALID_DATA;
00338       }
00339 
00340       /* check offset */
00341       if ( offset != 0 )
00342       {
00343         ids = p - 2 + offset;
00344         if ( ids < glyph_ids || ids + code_count*2 > table + length )
00345           FT_INVALID_OFFSET;
00346 
00347         /* check glyph IDs */
00348         if ( valid->level >= FT_VALIDATE_TIGHT )
00349         {
00350           FT_Byte*  limit = p + code_count * 2;
00351           FT_UInt   idx;
00352 
00353 
00354           for ( ; p < limit; )
00355           {
00356             idx = TT_NEXT_USHORT( p );
00357             if ( idx != 0 )
00358             {
00359               idx = ( idx + delta ) & 0xFFFFU;
00360               if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
00361                 FT_INVALID_GLYPH_ID;
00362             }
00363           }
00364         }
00365       }
00366     }
00367 
00368     return SFNT_Err_Ok;
00369   }
00370 
00371 
00372   /* return sub header corresponding to a given character code */
00373   /* NULL on invalid charcode                                  */
00374   static FT_Byte*
00375   tt_cmap2_get_subheader( FT_Byte*   table,
00376                           FT_UInt32  char_code )
00377   {
00378     FT_Byte*  result = NULL;
00379 
00380 
00381     if ( char_code < 0x10000UL )
00382     {
00383       FT_UInt   char_lo = (FT_UInt)( char_code & 0xFF );
00384       FT_UInt   char_hi = (FT_UInt)( char_code >> 8 );
00385       FT_Byte*  p       = table + 6;    /* keys table */
00386       FT_Byte*  subs    = table + 518;  /* subheaders table */
00387       FT_Byte*  sub;
00388 
00389 
00390       if ( char_hi == 0 )
00391       {
00392         /* an 8-bit character code -- we use subHeader 0 in this case */
00393         /* to test whether the character code is in the charmap       */
00394         /*                                                            */
00395         sub = subs;  /* jump to first sub-header */
00396 
00397         /* check that the sub-header for this byte is 0, which */
00398         /* indicates that it is really a valid one-byte value  */
00399         /* Otherwise, return 0                                 */
00400         /*                                                     */
00401         p += char_lo * 2;
00402         if ( TT_PEEK_USHORT( p ) != 0 )
00403           goto Exit;
00404       }
00405       else
00406       {
00407         /* a 16-bit character code */
00408 
00409         /* jump to key entry  */
00410         p  += char_hi * 2;
00411         /* jump to sub-header */
00412         sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) );
00413 
00414         /* check that the high byte isn't a valid one-byte value */
00415         if ( sub == subs )
00416           goto Exit;
00417       }
00418       result = sub;
00419     }
00420   Exit:
00421     return result;
00422   }
00423 
00424 
00425   FT_CALLBACK_DEF( FT_UInt )
00426   tt_cmap2_char_index( TT_CMap    cmap,
00427                        FT_UInt32  char_code )
00428   {
00429     FT_Byte*  table   = cmap->data;
00430     FT_UInt   result  = 0;
00431     FT_Byte*  subheader;
00432 
00433 
00434     subheader = tt_cmap2_get_subheader( table, char_code );
00435     if ( subheader )
00436     {
00437       FT_Byte*  p   = subheader;
00438       FT_UInt   idx = (FT_UInt)(char_code & 0xFF);
00439       FT_UInt   start, count;
00440       FT_Int    delta;
00441       FT_UInt   offset;
00442 
00443 
00444       start  = TT_NEXT_USHORT( p );
00445       count  = TT_NEXT_USHORT( p );
00446       delta  = TT_NEXT_SHORT ( p );
00447       offset = TT_PEEK_USHORT( p );
00448 
00449       idx -= start;
00450       if ( idx < count && offset != 0 )
00451       {
00452         p  += offset + 2 * idx;
00453         idx = TT_PEEK_USHORT( p );
00454 
00455         if ( idx != 0 )
00456           result = (FT_UInt)( idx + delta ) & 0xFFFFU;
00457       }
00458     }
00459     return result;
00460   }
00461 
00462 
00463   FT_CALLBACK_DEF( FT_UInt32 )
00464   tt_cmap2_char_next( TT_CMap     cmap,
00465                       FT_UInt32  *pcharcode )
00466   {
00467     FT_Byte*   table    = cmap->data;
00468     FT_UInt    gindex   = 0;
00469     FT_UInt32  result   = 0;
00470     FT_UInt32  charcode = *pcharcode + 1;
00471     FT_Byte*   subheader;
00472 
00473 
00474     while ( charcode < 0x10000UL )
00475     {
00476       subheader = tt_cmap2_get_subheader( table, charcode );
00477       if ( subheader )
00478       {
00479         FT_Byte*  p       = subheader;
00480         FT_UInt   start   = TT_NEXT_USHORT( p );
00481         FT_UInt   count   = TT_NEXT_USHORT( p );
00482         FT_Int    delta   = TT_NEXT_SHORT ( p );
00483         FT_UInt   offset  = TT_PEEK_USHORT( p );
00484         FT_UInt   char_lo = (FT_UInt)( charcode & 0xFF );
00485         FT_UInt   pos, idx;
00486 
00487 
00488         if ( offset == 0 )
00489           goto Next_SubHeader;
00490 
00491         if ( char_lo < start )
00492         {
00493           char_lo = start;
00494           pos     = 0;
00495         }
00496         else
00497           pos = (FT_UInt)( char_lo - start );
00498 
00499         p       += offset + pos * 2;
00500         charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo;
00501 
00502         for ( ; pos < count; pos++, charcode++ )
00503         {
00504           idx = TT_NEXT_USHORT( p );
00505 
00506           if ( idx != 0 )
00507           {
00508             gindex = ( idx + delta ) & 0xFFFFU;
00509             if ( gindex != 0 )
00510             {
00511               result = charcode;
00512               goto Exit;
00513             }
00514           }
00515         }
00516       }
00517 
00518       /* jump to next sub-header, i.e. higher byte value */
00519     Next_SubHeader:
00520       charcode = FT_PAD_FLOOR( charcode, 256 ) + 256;
00521     }
00522 
00523   Exit:
00524     *pcharcode = result;
00525 
00526     return gindex;
00527   }
00528 
00529 
00530   FT_CALLBACK_DEF( FT_Error )
00531   tt_cmap2_get_info( TT_CMap       cmap,
00532                      TT_CMapInfo  *cmap_info )
00533   {
00534     FT_Byte*  p = cmap->data + 4;
00535 
00536 
00537     cmap_info->format   = 2;
00538     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
00539 
00540     return SFNT_Err_Ok;
00541   }
00542 
00543 
00544   FT_DEFINE_TT_CMAP(tt_cmap2_class_rec,
00545       sizeof ( TT_CMapRec ),
00546 
00547       (FT_CMap_InitFunc)     tt_cmap_init,
00548       (FT_CMap_DoneFunc)     NULL,
00549       (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
00550       (FT_CMap_CharNextFunc) tt_cmap2_char_next,
00551 
00552       NULL, NULL, NULL, NULL, NULL
00553     ,
00554     2,
00555     (TT_CMap_ValidateFunc)   tt_cmap2_validate,
00556     (TT_CMap_Info_GetFunc)   tt_cmap2_get_info
00557   )
00558 
00559 #endif /* TT_CONFIG_CMAP_FORMAT_2 */
00560 
00561 
00562   /*************************************************************************/
00563   /*************************************************************************/
00564   /*****                                                               *****/
00565   /*****                           FORMAT 4                            *****/
00566   /*****                                                               *****/
00567   /*************************************************************************/
00568   /*************************************************************************/
00569 
00570   /*************************************************************************/
00571   /*                                                                       */
00572   /* TABLE OVERVIEW                                                        */
00573   /* --------------                                                        */
00574   /*                                                                       */
00575   /*   NAME          OFFSET         TYPE              DESCRIPTION          */
00576   /*                                                                       */
00577   /*   format        0              USHORT            must be 4            */
00578   /*   length        2              USHORT            table length         */
00579   /*                                                  in bytes             */
00580   /*   language      4              USHORT            Mac language code    */
00581   /*                                                                       */
00582   /*   segCountX2    6              USHORT            2*NUM_SEGS           */
00583   /*   searchRange   8              USHORT            2*(1 << LOG_SEGS)    */
00584   /*   entrySelector 10             USHORT            LOG_SEGS             */
00585   /*   rangeShift    12             USHORT            segCountX2 -         */
00586   /*                                                    searchRange        */
00587   /*                                                                       */
00588   /*   endCount      14             USHORT[NUM_SEGS]  end charcode for     */
00589   /*                                                  each segment; last   */
00590   /*                                                  is 0xFFFF            */
00591   /*                                                                       */
00592   /*   pad           14+NUM_SEGS*2  USHORT            padding              */
00593   /*                                                                       */
00594   /*   startCount    16+NUM_SEGS*2  USHORT[NUM_SEGS]  first charcode for   */
00595   /*                                                  each segment         */
00596   /*                                                                       */
00597   /*   idDelta       16+NUM_SEGS*4  SHORT[NUM_SEGS]   delta for each       */
00598   /*                                                  segment              */
00599   /*   idOffset      16+NUM_SEGS*6  SHORT[NUM_SEGS]   range offset for     */
00600   /*                                                  each segment; can be */
00601   /*                                                  zero                 */
00602   /*                                                                       */
00603   /*   glyphIds      16+NUM_SEGS*8  USHORT[]          array of glyph ID    */
00604   /*                                                  ranges               */
00605   /*                                                                       */
00606   /* Character codes are modelled by a series of ordered (increasing)      */
00607   /* intervals called segments.  Each segment has start and end codes,     */
00608   /* provided by the `startCount' and `endCount' arrays.  Segments must    */
00609   /* not overlap, and the last segment should always contain the value     */
00610   /* 0xFFFF for `endCount'.                                                */
00611   /*                                                                       */
00612   /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
00613   /* ignored (they are traces of over-engineering in the TrueType          */
00614   /* specification).                                                       */
00615   /*                                                                       */
00616   /* Each segment also has a signed `delta', as well as an optional offset */
00617   /* within the `glyphIds' table.                                          */
00618   /*                                                                       */
00619   /* If a segment's idOffset is 0, the glyph index corresponding to any    */
00620   /* charcode within the segment is obtained by adding the value of        */
00621   /* `idDelta' directly to the charcode, modulo 65536.                     */
00622   /*                                                                       */
00623   /* Otherwise, a glyph index is taken from the glyph IDs sub-array for    */
00624   /* the segment, and the value of `idDelta' is added to it.               */
00625   /*                                                                       */
00626   /*                                                                       */
00627   /* Finally, note that a lot of fonts contain an invalid last segment,    */
00628   /* where `start' and `end' are correctly set to 0xFFFF but both `delta'  */
00629   /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with     */
00630   /* OpenOffice.org).  We need special code to deal with them correctly.   */
00631   /*                                                                       */
00632 
00633 #ifdef TT_CONFIG_CMAP_FORMAT_4
00634 
00635   typedef struct  TT_CMap4Rec_
00636   {
00637     TT_CMapRec  cmap;
00638     FT_UInt32   cur_charcode;   /* current charcode */
00639     FT_UInt     cur_gindex;     /* current glyph index */
00640 
00641     FT_UInt     num_ranges;
00642     FT_UInt     cur_range;
00643     FT_UInt     cur_start;
00644     FT_UInt     cur_end;
00645     FT_Int      cur_delta;
00646     FT_Byte*    cur_values;
00647 
00648   } TT_CMap4Rec, *TT_CMap4;
00649 
00650 
00651   FT_CALLBACK_DEF( FT_Error )
00652   tt_cmap4_init( TT_CMap4  cmap,
00653                  FT_Byte*  table )
00654   {
00655     FT_Byte*  p;
00656 
00657 
00658     cmap->cmap.data    = table;
00659 
00660     p                  = table + 6;
00661     cmap->num_ranges   = FT_PEEK_USHORT( p ) >> 1;
00662     cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
00663     cmap->cur_gindex   = 0;
00664 
00665     return SFNT_Err_Ok;
00666   }
00667 
00668 
00669   static FT_Int
00670   tt_cmap4_set_range( TT_CMap4  cmap,
00671                       FT_UInt   range_index )
00672   {
00673     FT_Byte*  table = cmap->cmap.data;
00674     FT_Byte*  p;
00675     FT_UInt   num_ranges = cmap->num_ranges;
00676 
00677 
00678     while ( range_index < num_ranges )
00679     {
00680       FT_UInt  offset;
00681 
00682 
00683       p             = table + 14 + range_index * 2;
00684       cmap->cur_end = FT_PEEK_USHORT( p );
00685 
00686       p              += 2 + num_ranges * 2;
00687       cmap->cur_start = FT_PEEK_USHORT( p );
00688 
00689       p              += num_ranges * 2;
00690       cmap->cur_delta = FT_PEEK_SHORT( p );
00691 
00692       p     += num_ranges * 2;
00693       offset = FT_PEEK_USHORT( p );
00694 
00695       /* some fonts have an incorrect last segment; */
00696       /* we have to catch it                        */
00697       if ( range_index     >= num_ranges - 1 &&
00698            cmap->cur_start == 0xFFFFU        &&
00699            cmap->cur_end   == 0xFFFFU        )
00700       {
00701         TT_Face   face  = (TT_Face)cmap->cmap.cmap.charmap.face;
00702         FT_Byte*  limit = face->cmap_table + face->cmap_size;
00703 
00704 
00705         if ( offset && p + offset + 2 > limit )
00706         {
00707           cmap->cur_delta = 1;
00708           offset          = 0;
00709         }
00710       }
00711 
00712       if ( offset != 0xFFFFU )
00713       {
00714         cmap->cur_values = offset ? p + offset : NULL;
00715         cmap->cur_range  = range_index;
00716         return 0;
00717       }
00718 
00719       /* we skip empty segments */
00720       range_index++;
00721     }
00722 
00723     return -1;
00724   }
00725 
00726 
00727   /* search the index of the charcode next to cmap->cur_charcode; */
00728   /* caller should call tt_cmap4_set_range with proper range      */
00729   /* before calling this function                                 */
00730   /*                                                              */
00731   static void
00732   tt_cmap4_next( TT_CMap4  cmap )
00733   {
00734     FT_UInt  charcode;
00735 
00736 
00737     if ( cmap->cur_charcode >= 0xFFFFUL )
00738       goto Fail;
00739 
00740     charcode = (FT_UInt)cmap->cur_charcode + 1;
00741 
00742     if ( charcode < cmap->cur_start )
00743       charcode = cmap->cur_start;
00744 
00745     for ( ;; )
00746     {
00747       FT_Byte*  values = cmap->cur_values;
00748       FT_UInt   end    = cmap->cur_end;
00749       FT_Int    delta  = cmap->cur_delta;
00750 
00751 
00752       if ( charcode <= end )
00753       {
00754         if ( values )
00755         {
00756           FT_Byte*  p = values + 2 * ( charcode - cmap->cur_start );
00757 
00758 
00759           do
00760           {
00761             FT_UInt  gindex = FT_NEXT_USHORT( p );
00762 
00763 
00764             if ( gindex != 0 )
00765             {
00766               gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU );
00767               if ( gindex != 0 )
00768               {
00769                 cmap->cur_charcode = charcode;
00770                 cmap->cur_gindex   = gindex;
00771                 return;
00772               }
00773             }
00774           } while ( ++charcode <= end );
00775         }
00776         else
00777         {
00778           do
00779           {
00780             FT_UInt  gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU );
00781 
00782 
00783             if ( gindex != 0 )
00784             {
00785               cmap->cur_charcode = charcode;
00786               cmap->cur_gindex   = gindex;
00787               return;
00788             }
00789           } while ( ++charcode <= end );
00790         }
00791       }
00792 
00793       /* we need to find another range */
00794       if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )
00795         break;
00796 
00797       if ( charcode < cmap->cur_start )
00798         charcode = cmap->cur_start;
00799     }
00800 
00801   Fail:
00802     cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
00803     cmap->cur_gindex   = 0;
00804   }
00805 
00806 
00807   FT_CALLBACK_DEF( FT_Error )
00808   tt_cmap4_validate( FT_Byte*      table,
00809                      FT_Validator  valid )
00810   {
00811     FT_Byte*  p      = table + 2;               /* skip format */
00812     FT_UInt   length = TT_NEXT_USHORT( p );
00813     FT_Byte   *ends, *starts, *offsets, *deltas, *glyph_ids;
00814     FT_UInt   num_segs;
00815     FT_Error  error = SFNT_Err_Ok;
00816 
00817 
00818     if ( length < 16 )
00819       FT_INVALID_TOO_SHORT;
00820 
00821     /* in certain fonts, the `length' field is invalid and goes */
00822     /* out of bound.  We try to correct this here...            */
00823     if ( table + length > valid->limit )
00824     {
00825       if ( valid->level >= FT_VALIDATE_TIGHT )
00826         FT_INVALID_TOO_SHORT;
00827 
00828       length = (FT_UInt)( valid->limit - table );
00829     }
00830 
00831     p        = table + 6;
00832     num_segs = TT_NEXT_USHORT( p );   /* read segCountX2 */
00833 
00834     if ( valid->level >= FT_VALIDATE_PARANOID )
00835     {
00836       /* check that we have an even value here */
00837       if ( num_segs & 1 )
00838         FT_INVALID_DATA;
00839     }
00840 
00841     num_segs /= 2;
00842 
00843     if ( length < 16 + num_segs * 2 * 4 )
00844       FT_INVALID_TOO_SHORT;
00845 
00846     /* check the search parameters - even though we never use them */
00847     /*                                                             */
00848     if ( valid->level >= FT_VALIDATE_PARANOID )
00849     {
00850       /* check the values of `searchRange', `entrySelector', `rangeShift' */
00851       FT_UInt  search_range   = TT_NEXT_USHORT( p );
00852       FT_UInt  entry_selector = TT_NEXT_USHORT( p );
00853       FT_UInt  range_shift    = TT_NEXT_USHORT( p );
00854 
00855 
00856       if ( ( search_range | range_shift ) & 1 )  /* must be even values */
00857         FT_INVALID_DATA;
00858 
00859       search_range /= 2;
00860       range_shift  /= 2;
00861 
00862       /* `search range' is the greatest power of 2 that is <= num_segs */
00863 
00864       if ( search_range                > num_segs                 ||
00865            search_range * 2            < num_segs                 ||
00866            search_range + range_shift != num_segs                 ||
00867            search_range               != ( 1U << entry_selector ) )
00868         FT_INVALID_DATA;
00869     }
00870 
00871     ends      = table   + 14;
00872     starts    = table   + 16 + num_segs * 2;
00873     deltas    = starts  + num_segs * 2;
00874     offsets   = deltas  + num_segs * 2;
00875     glyph_ids = offsets + num_segs * 2;
00876 
00877     /* check last segment; its end count value must be 0xFFFF */
00878     if ( valid->level >= FT_VALIDATE_PARANOID )
00879     {
00880       p = ends + ( num_segs - 1 ) * 2;
00881       if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
00882         FT_INVALID_DATA;
00883     }
00884 
00885     {
00886       FT_UInt   start, end, offset, n;
00887       FT_UInt   last_start = 0, last_end = 0;
00888       FT_Int    delta;
00889       FT_Byte*  p_start   = starts;
00890       FT_Byte*  p_end     = ends;
00891       FT_Byte*  p_delta   = deltas;
00892       FT_Byte*  p_offset  = offsets;
00893 
00894 
00895       for ( n = 0; n < num_segs; n++ )
00896       {
00897         p      = p_offset;
00898         start  = TT_NEXT_USHORT( p_start );
00899         end    = TT_NEXT_USHORT( p_end );
00900         delta  = TT_NEXT_SHORT( p_delta );
00901         offset = TT_NEXT_USHORT( p_offset );
00902 
00903         if ( start > end )
00904           FT_INVALID_DATA;
00905 
00906         /* this test should be performed at default validation level; */
00907         /* unfortunately, some popular Asian fonts have overlapping   */
00908         /* ranges in their charmaps                                   */
00909         /*                                                            */
00910         if ( start <= last_end && n > 0 )
00911         {
00912           if ( valid->level >= FT_VALIDATE_TIGHT )
00913             FT_INVALID_DATA;
00914           else
00915           {
00916             /* allow overlapping segments, provided their start points */
00917             /* and end points, respectively, are in ascending order    */
00918             /*                                                         */
00919             if ( last_start > start || last_end > end )
00920               error |= TT_CMAP_FLAG_UNSORTED;
00921             else
00922               error |= TT_CMAP_FLAG_OVERLAPPING;
00923           }
00924         }
00925 
00926         if ( offset && offset != 0xFFFFU )
00927         {
00928           p += offset;  /* start of glyph ID array */
00929 
00930           /* check that we point within the glyph IDs table only */
00931           if ( valid->level >= FT_VALIDATE_TIGHT )
00932           {
00933             if ( p < glyph_ids                                ||
00934                  p + ( end - start + 1 ) * 2 > table + length )
00935               FT_INVALID_DATA;
00936           }
00937           /* Some fonts handle the last segment incorrectly.  In */
00938           /* theory, 0xFFFF might point to an ordinary glyph --  */
00939           /* a cmap 4 is versatile and could be used for any     */
00940           /* encoding, not only Unicode.  However, reality shows */
00941           /* that far too many fonts are sloppy and incorrectly  */
00942           /* set all fields but `start' and `end' for the last   */
00943           /* segment if it contains only a single character.     */
00944           /*                                                     */
00945           /* We thus omit the test here, delaying it to the      */
00946           /* routines which actually access the cmap.            */
00947           else if ( n != num_segs - 1                       ||
00948                     !( start == 0xFFFFU && end == 0xFFFFU ) )
00949           {
00950             if ( p < glyph_ids                              ||
00951                  p + ( end - start + 1 ) * 2 > valid->limit )
00952               FT_INVALID_DATA;
00953           }
00954 
00955           /* check glyph indices within the segment range */
00956           if ( valid->level >= FT_VALIDATE_TIGHT )
00957           {
00958             FT_UInt  i, idx;
00959 
00960 
00961             for ( i = start; i < end; i++ )
00962             {
00963               idx = FT_NEXT_USHORT( p );
00964               if ( idx != 0 )
00965               {
00966                 idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
00967 
00968                 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
00969                   FT_INVALID_GLYPH_ID;
00970               }
00971             }
00972           }
00973         }
00974         else if ( offset == 0xFFFFU )
00975         {
00976           /* some fonts (erroneously?) use a range offset of 0xFFFF */
00977           /* to mean missing glyph in cmap table                    */
00978           /*                                                        */
00979           if ( valid->level >= FT_VALIDATE_PARANOID    ||
00980                n != num_segs - 1                       ||
00981                !( start == 0xFFFFU && end == 0xFFFFU ) )
00982             FT_INVALID_DATA;
00983         }
00984 
00985         last_start = start;
00986         last_end   = end;
00987       }
00988     }
00989 
00990     return error;
00991   }
00992 
00993 
00994   static FT_UInt
00995   tt_cmap4_char_map_linear( TT_CMap     cmap,
00996                             FT_UInt32*  pcharcode,
00997                             FT_Bool     next )
00998   {
00999     FT_UInt    num_segs2, start, end, offset;
01000     FT_Int     delta;
01001     FT_UInt    i, num_segs;
01002     FT_UInt32  charcode = *pcharcode;
01003     FT_UInt    gindex   = 0;
01004     FT_Byte*   p;
01005 
01006 
01007     p = cmap->data + 6;
01008     num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
01009 
01010     num_segs = num_segs2 >> 1;
01011 
01012     if ( !num_segs )
01013       return 0;
01014 
01015     if ( next )
01016       charcode++;
01017 
01018     /* linear search */
01019     for ( ; charcode <= 0xFFFFU; charcode++ )
01020     {
01021       FT_Byte*  q;
01022 
01023 
01024       p = cmap->data + 14;               /* ends table   */
01025       q = cmap->data + 16 + num_segs2;   /* starts table */
01026 
01027       for ( i = 0; i < num_segs; i++ )
01028       {
01029         end   = TT_NEXT_USHORT( p );
01030         start = TT_NEXT_USHORT( q );
01031 
01032         if ( charcode >= start && charcode <= end )
01033         {
01034           p       = q - 2 + num_segs2;
01035           delta   = TT_PEEK_SHORT( p );
01036           p      += num_segs2;
01037           offset  = TT_PEEK_USHORT( p );
01038 
01039           /* some fonts have an incorrect last segment; */
01040           /* we have to catch it                        */
01041           if ( i >= num_segs - 1                  &&
01042                start == 0xFFFFU && end == 0xFFFFU )
01043           {
01044             TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
01045             FT_Byte*  limit = face->cmap_table + face->cmap_size;
01046 
01047 
01048             if ( offset && p + offset + 2 > limit )
01049             {
01050               delta  = 1;
01051               offset = 0;
01052             }
01053           }
01054 
01055           if ( offset == 0xFFFFU )
01056             continue;
01057 
01058           if ( offset )
01059           {
01060             p += offset + ( charcode - start ) * 2;
01061             gindex = TT_PEEK_USHORT( p );
01062             if ( gindex != 0 )
01063               gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
01064           }
01065           else
01066             gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
01067 
01068           break;
01069         }
01070       }
01071 
01072       if ( !next || gindex )
01073         break;
01074     }
01075 
01076     if ( next && gindex )
01077       *pcharcode = charcode;
01078 
01079     return gindex;
01080   }
01081 
01082 
01083   static FT_UInt
01084   tt_cmap4_char_map_binary( TT_CMap     cmap,
01085                             FT_UInt32*  pcharcode,
01086                             FT_Bool     next )
01087   {
01088     FT_UInt   num_segs2, start, end, offset;
01089     FT_Int    delta;
01090     FT_UInt   max, min, mid, num_segs;
01091     FT_UInt   charcode = (FT_UInt)*pcharcode;
01092     FT_UInt   gindex   = 0;
01093     FT_Byte*  p;
01094 
01095 
01096     p = cmap->data + 6;
01097     num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
01098 
01099     if ( !num_segs2 )
01100       return 0;
01101 
01102     num_segs = num_segs2 >> 1;
01103 
01104     /* make compiler happy */
01105     mid = num_segs;
01106     end = 0xFFFFU;
01107 
01108     if ( next )
01109       charcode++;
01110 
01111     min = 0;
01112     max = num_segs;
01113 
01114     /* binary search */
01115     while ( min < max )
01116     {
01117       mid    = ( min + max ) >> 1;
01118       p      = cmap->data + 14 + mid * 2;
01119       end    = TT_PEEK_USHORT( p );
01120       p     += 2 + num_segs2;
01121       start  = TT_PEEK_USHORT( p );
01122 
01123       if ( charcode < start )
01124         max = mid;
01125       else if ( charcode > end )
01126         min = mid + 1;
01127       else
01128       {
01129         p     += num_segs2;
01130         delta  = TT_PEEK_SHORT( p );
01131         p     += num_segs2;
01132         offset = TT_PEEK_USHORT( p );
01133 
01134         /* some fonts have an incorrect last segment; */
01135         /* we have to catch it                        */
01136         if ( mid >= num_segs - 1                &&
01137              start == 0xFFFFU && end == 0xFFFFU )
01138         {
01139           TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
01140           FT_Byte*  limit = face->cmap_table + face->cmap_size;
01141 
01142 
01143           if ( offset && p + offset + 2 > limit )
01144           {
01145             delta  = 1;
01146             offset = 0;
01147           }
01148         }
01149 
01150         /* search the first segment containing `charcode' */
01151         if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING )
01152         {
01153           FT_UInt  i;
01154 
01155 
01156           /* call the current segment `max' */
01157           max = mid;
01158 
01159           if ( offset == 0xFFFFU )
01160             mid = max + 1;
01161 
01162           /* search in segments before the current segment */
01163           for ( i = max ; i > 0; i-- )
01164           {
01165             FT_UInt   prev_end;
01166             FT_Byte*  old_p;
01167 
01168 
01169             old_p    = p;
01170             p        = cmap->data + 14 + ( i - 1 ) * 2;
01171             prev_end = TT_PEEK_USHORT( p );
01172 
01173             if ( charcode > prev_end )
01174             {
01175               p = old_p;
01176               break;
01177             }
01178 
01179             end    = prev_end;
01180             p     += 2 + num_segs2;
01181             start  = TT_PEEK_USHORT( p );
01182             p     += num_segs2;
01183             delta  = TT_PEEK_SHORT( p );
01184             p     += num_segs2;
01185             offset = TT_PEEK_USHORT( p );
01186 
01187             if ( offset != 0xFFFFU )
01188               mid = i - 1;
01189           }
01190 
01191           /* no luck */
01192           if ( mid == max + 1 )
01193           {
01194             if ( i != max )
01195             {
01196               p      = cmap->data + 14 + max * 2;
01197               end    = TT_PEEK_USHORT( p );
01198               p     += 2 + num_segs2;
01199               start  = TT_PEEK_USHORT( p );
01200               p     += num_segs2;
01201               delta  = TT_PEEK_SHORT( p );
01202               p     += num_segs2;
01203               offset = TT_PEEK_USHORT( p );
01204             }
01205 
01206             mid = max;
01207 
01208             /* search in segments after the current segment */
01209             for ( i = max + 1; i < num_segs; i++ )
01210             {
01211               FT_UInt  next_end, next_start;
01212 
01213 
01214               p          = cmap->data + 14 + i * 2;
01215               next_end   = TT_PEEK_USHORT( p );
01216               p         += 2 + num_segs2;
01217               next_start = TT_PEEK_USHORT( p );
01218 
01219               if ( charcode < next_start )
01220                 break;
01221 
01222               end    = next_end;
01223               start  = next_start;
01224               p     += num_segs2;
01225               delta  = TT_PEEK_SHORT( p );
01226               p     += num_segs2;
01227               offset = TT_PEEK_USHORT( p );
01228 
01229               if ( offset != 0xFFFFU )
01230                 mid = i;
01231             }
01232             i--;
01233 
01234             /* still no luck */
01235             if ( mid == max )
01236             {
01237               mid = i;
01238 
01239               break;
01240             }
01241           }
01242 
01243           /* end, start, delta, and offset are for the i'th segment */
01244           if ( mid != i )
01245           {
01246             p      = cmap->data + 14 + mid * 2;
01247             end    = TT_PEEK_USHORT( p );
01248             p     += 2 + num_segs2;
01249             start  = TT_PEEK_USHORT( p );
01250             p     += num_segs2;
01251             delta  = TT_PEEK_SHORT( p );
01252             p     += num_segs2;
01253             offset = TT_PEEK_USHORT( p );
01254           }
01255         }
01256         else
01257         {
01258           if ( offset == 0xFFFFU )
01259             break;
01260         }
01261 
01262         if ( offset )
01263         {
01264           p += offset + ( charcode - start ) * 2;
01265           gindex = TT_PEEK_USHORT( p );
01266           if ( gindex != 0 )
01267             gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
01268         }
01269         else
01270           gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
01271 
01272         break;
01273       }
01274     }
01275 
01276     if ( next )
01277     {
01278       TT_CMap4  cmap4 = (TT_CMap4)cmap;
01279 
01280 
01281       /* if `charcode' is not in any segment, then `mid' is */
01282       /* the segment nearest to `charcode'                  */
01283       /*                                                    */
01284 
01285       if ( charcode > end )
01286       {
01287         mid++;
01288         if ( mid == num_segs )
01289           return 0;
01290       }
01291 
01292       if ( tt_cmap4_set_range( cmap4, mid ) )
01293       {
01294         if ( gindex )
01295           *pcharcode = charcode;
01296       }
01297       else
01298       {
01299         cmap4->cur_charcode = charcode;
01300 
01301         if ( gindex )
01302           cmap4->cur_gindex = gindex;
01303         else
01304         {
01305           cmap4->cur_charcode = charcode;
01306           tt_cmap4_next( cmap4 );
01307           gindex = cmap4->cur_gindex;
01308         }
01309 
01310         if ( gindex )
01311           *pcharcode = cmap4->cur_charcode;
01312       }
01313     }
01314 
01315     return gindex;
01316   }
01317 
01318 
01319   FT_CALLBACK_DEF( FT_UInt )
01320   tt_cmap4_char_index( TT_CMap    cmap,
01321                        FT_UInt32  char_code )
01322   {
01323     if ( char_code >= 0x10000UL )
01324       return 0;
01325 
01326     if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
01327       return tt_cmap4_char_map_linear( cmap, &char_code, 0 );
01328     else
01329       return tt_cmap4_char_map_binary( cmap, &char_code, 0 );
01330   }
01331 
01332 
01333   FT_CALLBACK_DEF( FT_UInt32 )
01334   tt_cmap4_char_next( TT_CMap     cmap,
01335                       FT_UInt32  *pchar_code )
01336   {
01337     FT_UInt  gindex;
01338 
01339 
01340     if ( *pchar_code >= 0xFFFFU )
01341       return 0;
01342 
01343     if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
01344       gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 );
01345     else
01346     {
01347       TT_CMap4  cmap4 = (TT_CMap4)cmap;
01348 
01349 
01350       /* no need to search */
01351       if ( *pchar_code == cmap4->cur_charcode )
01352       {
01353         tt_cmap4_next( cmap4 );
01354         gindex = cmap4->cur_gindex;
01355         if ( gindex )
01356           *pchar_code = cmap4->cur_charcode;
01357       }
01358       else
01359         gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 );
01360     }
01361 
01362     return gindex;
01363   }
01364 
01365 
01366   FT_CALLBACK_DEF( FT_Error )
01367   tt_cmap4_get_info( TT_CMap       cmap,
01368                      TT_CMapInfo  *cmap_info )
01369   {
01370     FT_Byte*  p = cmap->data + 4;
01371 
01372 
01373     cmap_info->format   = 4;
01374     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
01375 
01376     return SFNT_Err_Ok;
01377   }
01378 
01379 
01380   FT_DEFINE_TT_CMAP(tt_cmap4_class_rec,
01381       sizeof ( TT_CMap4Rec ),
01382       (FT_CMap_InitFunc)     tt_cmap4_init,
01383       (FT_CMap_DoneFunc)     NULL,
01384       (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
01385       (FT_CMap_CharNextFunc) tt_cmap4_char_next,
01386 
01387       NULL, NULL, NULL, NULL, NULL
01388     ,
01389     4,
01390     (TT_CMap_ValidateFunc)   tt_cmap4_validate,
01391     (TT_CMap_Info_GetFunc)   tt_cmap4_get_info
01392   )
01393 
01394 #endif /* TT_CONFIG_CMAP_FORMAT_4 */
01395 
01396 
01397   /*************************************************************************/
01398   /*************************************************************************/
01399   /*****                                                               *****/
01400   /*****                          FORMAT 6                             *****/
01401   /*****                                                               *****/
01402   /*************************************************************************/
01403   /*************************************************************************/
01404 
01405   /*************************************************************************/
01406   /*                                                                       */
01407   /* TABLE OVERVIEW                                                        */
01408   /* --------------                                                        */
01409   /*                                                                       */
01410   /*   NAME        OFFSET          TYPE             DESCRIPTION            */
01411   /*                                                                       */
01412   /*   format       0              USHORT           must be 4              */
01413   /*   length       2              USHORT           table length in bytes  */
01414   /*   language     4              USHORT           Mac language code      */
01415   /*                                                                       */
01416   /*   first        6              USHORT           first segment code     */
01417   /*   count        8              USHORT           segment size in chars  */
01418   /*   glyphIds     10             USHORT[count]    glyph IDs              */
01419   /*                                                                       */
01420   /* A very simplified segment mapping.                                    */
01421   /*                                                                       */
01422 
01423 #ifdef TT_CONFIG_CMAP_FORMAT_6
01424 
01425   FT_CALLBACK_DEF( FT_Error )
01426   tt_cmap6_validate( FT_Byte*      table,
01427                      FT_Validator  valid )
01428   {
01429     FT_Byte*  p;
01430     FT_UInt   length, count;
01431 
01432 
01433     if ( table + 10 > valid->limit )
01434       FT_INVALID_TOO_SHORT;
01435 
01436     p      = table + 2;
01437     length = TT_NEXT_USHORT( p );
01438 
01439     p      = table + 8;             /* skip language and start index */
01440     count  = TT_NEXT_USHORT( p );
01441 
01442     if ( table + length > valid->limit || length < 10 + count * 2 )
01443       FT_INVALID_TOO_SHORT;
01444 
01445     /* check glyph indices */
01446     if ( valid->level >= FT_VALIDATE_TIGHT )
01447     {
01448       FT_UInt  gindex;
01449 
01450 
01451       for ( ; count > 0; count-- )
01452       {
01453         gindex = TT_NEXT_USHORT( p );
01454         if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
01455           FT_INVALID_GLYPH_ID;
01456       }
01457     }
01458 
01459     return SFNT_Err_Ok;
01460   }
01461 
01462 
01463   FT_CALLBACK_DEF( FT_UInt )
01464   tt_cmap6_char_index( TT_CMap    cmap,
01465                        FT_UInt32  char_code )
01466   {
01467     FT_Byte*  table  = cmap->data;
01468     FT_UInt   result = 0;
01469     FT_Byte*  p      = table + 6;
01470     FT_UInt   start  = TT_NEXT_USHORT( p );
01471     FT_UInt   count  = TT_NEXT_USHORT( p );
01472     FT_UInt   idx    = (FT_UInt)( char_code - start );
01473 
01474 
01475     if ( idx < count )
01476     {
01477       p += 2 * idx;
01478       result = TT_PEEK_USHORT( p );
01479     }
01480     return result;
01481   }
01482 
01483 
01484   FT_CALLBACK_DEF( FT_UInt32 )
01485   tt_cmap6_char_next( TT_CMap     cmap,
01486                       FT_UInt32  *pchar_code )
01487   {
01488     FT_Byte*   table     = cmap->data;
01489     FT_UInt32  result    = 0;
01490     FT_UInt32  char_code = *pchar_code + 1;
01491     FT_UInt    gindex    = 0;
01492 
01493     FT_Byte*   p         = table + 6;
01494     FT_UInt    start     = TT_NEXT_USHORT( p );
01495     FT_UInt    count     = TT_NEXT_USHORT( p );
01496     FT_UInt    idx;
01497 
01498 
01499     if ( char_code >= 0x10000UL )
01500       goto Exit;
01501 
01502     if ( char_code < start )
01503       char_code = start;
01504 
01505     idx = (FT_UInt)( char_code - start );
01506     p  += 2 * idx;
01507 
01508     for ( ; idx < count; idx++ )
01509     {
01510       gindex = TT_NEXT_USHORT( p );
01511       if ( gindex != 0 )
01512       {
01513         result = char_code;
01514         break;
01515       }
01516       char_code++;
01517     }
01518 
01519   Exit:
01520     *pchar_code = result;
01521     return gindex;
01522   }
01523 
01524 
01525   FT_CALLBACK_DEF( FT_Error )
01526   tt_cmap6_get_info( TT_CMap       cmap,
01527                      TT_CMapInfo  *cmap_info )
01528   {
01529     FT_Byte*  p = cmap->data + 4;
01530 
01531 
01532     cmap_info->format   = 6;
01533     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
01534 
01535     return SFNT_Err_Ok;
01536   }
01537 
01538 
01539   FT_DEFINE_TT_CMAP(tt_cmap6_class_rec,
01540       sizeof ( TT_CMapRec ),
01541 
01542       (FT_CMap_InitFunc)     tt_cmap_init,
01543       (FT_CMap_DoneFunc)     NULL,
01544       (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
01545       (FT_CMap_CharNextFunc) tt_cmap6_char_next,
01546 
01547       NULL, NULL, NULL, NULL, NULL
01548     ,
01549     6,
01550     (TT_CMap_ValidateFunc)   tt_cmap6_validate,
01551     (TT_CMap_Info_GetFunc)   tt_cmap6_get_info
01552   )
01553 
01554 #endif /* TT_CONFIG_CMAP_FORMAT_6 */
01555 
01556 
01557   /*************************************************************************/
01558   /*************************************************************************/
01559   /*****                                                               *****/
01560   /*****                          FORMAT 8                             *****/
01561   /*****                                                               *****/
01562   /***** It is hard to completely understand what the OpenType spec    *****/
01563   /***** says about this format, but here is my conclusion.            *****/
01564   /*****                                                               *****/
01565   /***** The purpose of this format is to easily map UTF-16 text to    *****/
01566   /***** glyph indices.  Basically, the `char_code' must be in one of  *****/
01567   /***** the following formats:                                        *****/
01568   /*****                                                               *****/
01569   /*****   - A 16-bit value that isn't part of the Unicode Surrogates  *****/
01570   /*****     Area (i.e. U+D800-U+DFFF).                                *****/
01571   /*****                                                               *****/
01572   /*****   - A 32-bit value, made of two surrogate values, i.e.. if    *****/
01573   /*****     `char_code = (char_hi << 16) | char_lo', then both        *****/
01574   /*****     `char_hi' and `char_lo' must be in the Surrogates Area.   *****/
01575   /*****      Area.                                                    *****/
01576   /*****                                                               *****/
01577   /***** The `is32' table embedded in the charmap indicates whether a  *****/
01578   /***** given 16-bit value is in the surrogates area or not.          *****/
01579   /*****                                                               *****/
01580   /***** So, for any given `char_code', we can assert the following:   *****/
01581   /*****                                                               *****/
01582   /*****   If `char_hi == 0' then we must have `is32[char_lo] == 0'.   *****/
01583   /*****                                                               *****/
01584   /*****   If `char_hi != 0' then we must have both                    *****/
01585   /*****   `is32[char_hi] != 0' and `is32[char_lo] != 0'.              *****/
01586   /*****                                                               *****/
01587   /*************************************************************************/
01588   /*************************************************************************/
01589 
01590   /*************************************************************************/
01591   /*                                                                       */
01592   /* TABLE OVERVIEW                                                        */
01593   /* --------------                                                        */
01594   /*                                                                       */
01595   /*   NAME        OFFSET         TYPE        DESCRIPTION                  */
01596   /*                                                                       */
01597   /*   format      0              USHORT      must be 8                    */
01598   /*   reserved    2              USHORT      reserved                     */
01599   /*   length      4              ULONG       length in bytes              */
01600   /*   language    8              ULONG       Mac language code            */
01601   /*   is32        12             BYTE[8192]  32-bitness bitmap            */
01602   /*   count       8204           ULONG       number of groups             */
01603   /*                                                                       */
01604   /* This header is followed by `count' groups of the following format:    */
01605   /*                                                                       */
01606   /*   start       0              ULONG       first charcode               */
01607   /*   end         4              ULONG       last charcode                */
01608   /*   startId     8              ULONG       start glyph ID for the group */
01609   /*                                                                       */
01610 
01611 #ifdef TT_CONFIG_CMAP_FORMAT_8
01612 
01613   FT_CALLBACK_DEF( FT_Error )
01614   tt_cmap8_validate( FT_Byte*      table,
01615                      FT_Validator  valid )
01616   {
01617     FT_Byte*   p = table + 4;
01618     FT_Byte*   is32;
01619     FT_UInt32  length;
01620     FT_UInt32  num_groups;
01621 
01622 
01623     if ( table + 16 + 8192 > valid->limit )
01624       FT_INVALID_TOO_SHORT;
01625 
01626     length = TT_NEXT_ULONG( p );
01627     if ( length > (FT_UInt32)( valid->limit - table ) || length < 8192 + 16 )
01628       FT_INVALID_TOO_SHORT;
01629 
01630     is32       = table + 12;
01631     p          = is32  + 8192;          /* skip `is32' array */
01632     num_groups = TT_NEXT_ULONG( p );
01633 
01634     if ( p + num_groups * 12 > valid->limit )
01635       FT_INVALID_TOO_SHORT;
01636 
01637     /* check groups, they must be in increasing order */
01638     {
01639       FT_UInt32  n, start, end, start_id, count, last = 0;
01640 
01641 
01642       for ( n = 0; n < num_groups; n++ )
01643       {
01644         FT_UInt   hi, lo;
01645 
01646 
01647         start    = TT_NEXT_ULONG( p );
01648         end      = TT_NEXT_ULONG( p );
01649         start_id = TT_NEXT_ULONG( p );
01650 
01651         if ( start > end )
01652           FT_INVALID_DATA;
01653 
01654         if ( n > 0 && start <= last )
01655           FT_INVALID_DATA;
01656 
01657         if ( valid->level >= FT_VALIDATE_TIGHT )
01658         {
01659           if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
01660             FT_INVALID_GLYPH_ID;
01661 
01662           count = (FT_UInt32)( end - start + 1 );
01663 
01664           if ( start & ~0xFFFFU )
01665           {
01666             /* start_hi != 0; check that is32[i] is 1 for each i in */
01667             /* the `hi' and `lo' of the range [start..end]          */
01668             for ( ; count > 0; count--, start++ )
01669             {
01670               hi = (FT_UInt)( start >> 16 );
01671               lo = (FT_UInt)( start & 0xFFFFU );
01672 
01673               if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
01674                 FT_INVALID_DATA;
01675 
01676               if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
01677                 FT_INVALID_DATA;
01678             }
01679           }
01680           else
01681           {
01682             /* start_hi == 0; check that is32[i] is 0 for each i in */
01683             /* the range [start..end]                               */
01684 
01685             /* end_hi cannot be != 0! */
01686             if ( end & ~0xFFFFU )
01687               FT_INVALID_DATA;
01688 
01689             for ( ; count > 0; count--, start++ )
01690             {
01691               lo = (FT_UInt)( start & 0xFFFFU );
01692 
01693               if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
01694                 FT_INVALID_DATA;
01695             }
01696           }
01697         }
01698 
01699         last = end;
01700       }
01701     }
01702 
01703     return SFNT_Err_Ok;
01704   }
01705 
01706 
01707   FT_CALLBACK_DEF( FT_UInt )
01708   tt_cmap8_char_index( TT_CMap    cmap,
01709                        FT_UInt32  char_code )
01710   {
01711     FT_Byte*   table      = cmap->data;
01712     FT_UInt    result     = 0;
01713     FT_Byte*   p          = table + 8204;
01714     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
01715     FT_UInt32  start, end, start_id;
01716 
01717 
01718     for ( ; num_groups > 0; num_groups-- )
01719     {
01720       start    = TT_NEXT_ULONG( p );
01721       end      = TT_NEXT_ULONG( p );
01722       start_id = TT_NEXT_ULONG( p );
01723 
01724       if ( char_code < start )
01725         break;
01726 
01727       if ( char_code <= end )
01728       {
01729         result = (FT_UInt)( start_id + char_code - start );
01730         break;
01731       }
01732     }
01733     return result;
01734   }
01735 
01736 
01737   FT_CALLBACK_DEF( FT_UInt32 )
01738   tt_cmap8_char_next( TT_CMap     cmap,
01739                       FT_UInt32  *pchar_code )
01740   {
01741     FT_UInt32  result     = 0;
01742     FT_UInt32  char_code  = *pchar_code + 1;
01743     FT_UInt    gindex     = 0;
01744     FT_Byte*   table      = cmap->data;
01745     FT_Byte*   p          = table + 8204;
01746     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
01747     FT_UInt32  start, end, start_id;
01748 
01749 
01750     p = table + 8208;
01751 
01752     for ( ; num_groups > 0; num_groups-- )
01753     {
01754       start    = TT_NEXT_ULONG( p );
01755       end      = TT_NEXT_ULONG( p );
01756       start_id = TT_NEXT_ULONG( p );
01757 
01758       if ( char_code < start )
01759         char_code = start;
01760 
01761       if ( char_code <= end )
01762       {
01763         gindex = (FT_UInt)( char_code - start + start_id );
01764         if ( gindex != 0 )
01765         {
01766           result = char_code;
01767           goto Exit;
01768         }
01769       }
01770     }
01771 
01772   Exit:
01773     *pchar_code = result;
01774     return gindex;
01775   }
01776 
01777 
01778   FT_CALLBACK_DEF( FT_Error )
01779   tt_cmap8_get_info( TT_CMap       cmap,
01780                      TT_CMapInfo  *cmap_info )
01781   {
01782     FT_Byte*  p = cmap->data + 8;
01783 
01784 
01785     cmap_info->format   = 8;
01786     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
01787 
01788     return SFNT_Err_Ok;
01789   }
01790 
01791 
01792   FT_DEFINE_TT_CMAP(tt_cmap8_class_rec,
01793       sizeof ( TT_CMapRec ),
01794 
01795       (FT_CMap_InitFunc)     tt_cmap_init,
01796       (FT_CMap_DoneFunc)     NULL,
01797       (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
01798       (FT_CMap_CharNextFunc) tt_cmap8_char_next,
01799 
01800       NULL, NULL, NULL, NULL, NULL
01801     ,
01802     8,
01803     (TT_CMap_ValidateFunc)   tt_cmap8_validate,
01804     (TT_CMap_Info_GetFunc)   tt_cmap8_get_info
01805   )
01806 
01807 #endif /* TT_CONFIG_CMAP_FORMAT_8 */
01808 
01809 
01810   /*************************************************************************/
01811   /*************************************************************************/
01812   /*****                                                               *****/
01813   /*****                          FORMAT 10                            *****/
01814   /*****                                                               *****/
01815   /*************************************************************************/
01816   /*************************************************************************/
01817 
01818   /*************************************************************************/
01819   /*                                                                       */
01820   /* TABLE OVERVIEW                                                        */
01821   /* --------------                                                        */
01822   /*                                                                       */
01823   /*   NAME      OFFSET  TYPE               DESCRIPTION                    */
01824   /*                                                                       */
01825   /*   format     0      USHORT             must be 10                     */
01826   /*   reserved   2      USHORT             reserved                       */
01827   /*   length     4      ULONG              length in bytes                */
01828   /*   language   8      ULONG              Mac language code              */
01829   /*                                                                       */
01830   /*   start     12      ULONG              first char in range            */
01831   /*   count     16      ULONG              number of chars in range       */
01832   /*   glyphIds  20      USHORT[count]      glyph indices covered          */
01833   /*                                                                       */
01834 
01835 #ifdef TT_CONFIG_CMAP_FORMAT_10
01836 
01837   FT_CALLBACK_DEF( FT_Error )
01838   tt_cmap10_validate( FT_Byte*      table,
01839                       FT_Validator  valid )
01840   {
01841     FT_Byte*  p = table + 4;
01842     FT_ULong  length, count;
01843 
01844 
01845     if ( table + 20 > valid->limit )
01846       FT_INVALID_TOO_SHORT;
01847 
01848     length = TT_NEXT_ULONG( p );
01849     p      = table + 16;
01850     count  = TT_NEXT_ULONG( p );
01851 
01852     if ( length > (FT_ULong)( valid->limit - table ) ||
01853          length < 20 + count * 2                     )
01854       FT_INVALID_TOO_SHORT;
01855 
01856     /* check glyph indices */
01857     if ( valid->level >= FT_VALIDATE_TIGHT )
01858     {
01859       FT_UInt  gindex;
01860 
01861 
01862       for ( ; count > 0; count-- )
01863       {
01864         gindex = TT_NEXT_USHORT( p );
01865         if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
01866           FT_INVALID_GLYPH_ID;
01867       }
01868     }
01869 
01870     return SFNT_Err_Ok;
01871   }
01872 
01873 
01874   FT_CALLBACK_DEF( FT_UInt )
01875   tt_cmap10_char_index( TT_CMap    cmap,
01876                         FT_UInt32  char_code )
01877   {
01878     FT_Byte*   table  = cmap->data;
01879     FT_UInt    result = 0;
01880     FT_Byte*   p      = table + 12;
01881     FT_UInt32  start  = TT_NEXT_ULONG( p );
01882     FT_UInt32  count  = TT_NEXT_ULONG( p );
01883     FT_UInt32  idx    = (FT_ULong)( char_code - start );
01884 
01885 
01886     if ( idx < count )
01887     {
01888       p     += 2 * idx;
01889       result = TT_PEEK_USHORT( p );
01890     }
01891     return result;
01892   }
01893 
01894 
01895   FT_CALLBACK_DEF( FT_UInt32 )
01896   tt_cmap10_char_next( TT_CMap     cmap,
01897                        FT_UInt32  *pchar_code )
01898   {
01899     FT_Byte*   table     = cmap->data;
01900     FT_UInt32  char_code = *pchar_code + 1;
01901     FT_UInt    gindex    = 0;
01902     FT_Byte*   p         = table + 12;
01903     FT_UInt32  start     = TT_NEXT_ULONG( p );
01904     FT_UInt32  count     = TT_NEXT_ULONG( p );
01905     FT_UInt32  idx;
01906 
01907 
01908     if ( char_code < start )
01909       char_code = start;
01910 
01911     idx = (FT_UInt32)( char_code - start );
01912     p  += 2 * idx;
01913 
01914     for ( ; idx < count; idx++ )
01915     {
01916       gindex = TT_NEXT_USHORT( p );
01917       if ( gindex != 0 )
01918         break;
01919       char_code++;
01920     }
01921 
01922     *pchar_code = char_code;
01923     return gindex;
01924   }
01925 
01926 
01927   FT_CALLBACK_DEF( FT_Error )
01928   tt_cmap10_get_info( TT_CMap       cmap,
01929                       TT_CMapInfo  *cmap_info )
01930   {
01931     FT_Byte*  p = cmap->data + 8;
01932 
01933 
01934     cmap_info->format   = 10;
01935     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
01936 
01937     return SFNT_Err_Ok;
01938   }
01939 
01940 
01941   FT_DEFINE_TT_CMAP(tt_cmap10_class_rec,
01942       sizeof ( TT_CMapRec ),
01943 
01944       (FT_CMap_InitFunc)     tt_cmap_init,
01945       (FT_CMap_DoneFunc)     NULL,
01946       (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
01947       (FT_CMap_CharNextFunc) tt_cmap10_char_next,
01948 
01949       NULL, NULL, NULL, NULL, NULL
01950     ,
01951     10,
01952     (TT_CMap_ValidateFunc)   tt_cmap10_validate,
01953     (TT_CMap_Info_GetFunc)   tt_cmap10_get_info
01954   )
01955 
01956 #endif /* TT_CONFIG_CMAP_FORMAT_10 */
01957 
01958 
01959   /*************************************************************************/
01960   /*************************************************************************/
01961   /*****                                                               *****/
01962   /*****                          FORMAT 12                            *****/
01963   /*****                                                               *****/
01964   /*************************************************************************/
01965   /*************************************************************************/
01966 
01967   /*************************************************************************/
01968   /*                                                                       */
01969   /* TABLE OVERVIEW                                                        */
01970   /* --------------                                                        */
01971   /*                                                                       */
01972   /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
01973   /*                                                                       */
01974   /*   format      0          USHORT     must be 12                        */
01975   /*   reserved    2          USHORT     reserved                          */
01976   /*   length      4          ULONG      length in bytes                   */
01977   /*   language    8          ULONG      Mac language code                 */
01978   /*   count       12         ULONG      number of groups                  */
01979   /*               16                                                      */
01980   /*                                                                       */
01981   /* This header is followed by `count' groups of the following format:    */
01982   /*                                                                       */
01983   /*   start       0          ULONG      first charcode                    */
01984   /*   end         4          ULONG      last charcode                     */
01985   /*   startId     8          ULONG      start glyph ID for the group      */
01986   /*                                                                       */
01987 
01988 #ifdef TT_CONFIG_CMAP_FORMAT_12
01989 
01990   typedef struct  TT_CMap12Rec_
01991   {
01992     TT_CMapRec  cmap;
01993     FT_Bool     valid;
01994     FT_ULong    cur_charcode;
01995     FT_UInt     cur_gindex;
01996     FT_ULong    cur_group;
01997     FT_ULong    num_groups;
01998 
01999   } TT_CMap12Rec, *TT_CMap12;
02000 
02001 
02002   FT_CALLBACK_DEF( FT_Error )
02003   tt_cmap12_init( TT_CMap12  cmap,
02004                   FT_Byte*   table )
02005   {
02006     cmap->cmap.data  = table;
02007 
02008     table           += 12;
02009     cmap->num_groups = FT_PEEK_ULONG( table );
02010 
02011     cmap->valid      = 0;
02012 
02013     return SFNT_Err_Ok;
02014   }
02015 
02016 
02017   FT_CALLBACK_DEF( FT_Error )
02018   tt_cmap12_validate( FT_Byte*      table,
02019                       FT_Validator  valid )
02020   {
02021     FT_Byte*   p;
02022     FT_ULong   length;
02023     FT_ULong   num_groups;
02024 
02025 
02026     if ( table + 16 > valid->limit )
02027       FT_INVALID_TOO_SHORT;
02028 
02029     p      = table + 4;
02030     length = TT_NEXT_ULONG( p );
02031 
02032     p          = table + 12;
02033     num_groups = TT_NEXT_ULONG( p );
02034 
02035     if ( length > (FT_ULong)( valid->limit - table ) ||
02036          length < 16 + 12 * num_groups               )
02037       FT_INVALID_TOO_SHORT;
02038 
02039     /* check groups, they must be in increasing order */
02040     {
02041       FT_ULong  n, start, end, start_id, last = 0;
02042 
02043 
02044       for ( n = 0; n < num_groups; n++ )
02045       {
02046         start    = TT_NEXT_ULONG( p );
02047         end      = TT_NEXT_ULONG( p );
02048         start_id = TT_NEXT_ULONG( p );
02049 
02050         if ( start > end )
02051           FT_INVALID_DATA;
02052 
02053         if ( n > 0 && start <= last )
02054           FT_INVALID_DATA;
02055 
02056         if ( valid->level >= FT_VALIDATE_TIGHT )
02057         {
02058           if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
02059             FT_INVALID_GLYPH_ID;
02060         }
02061 
02062         last = end;
02063       }
02064     }
02065 
02066     return SFNT_Err_Ok;
02067   }
02068 
02069 
02070   /* search the index of the charcode next to cmap->cur_charcode */
02071   /* cmap->cur_group should be set up properly by caller         */
02072   /*                                                             */
02073   static void
02074   tt_cmap12_next( TT_CMap12  cmap )
02075   {
02076     FT_Byte*  p;
02077     FT_ULong  start, end, start_id, char_code;
02078     FT_ULong  n;
02079     FT_UInt   gindex;
02080 
02081 
02082     if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
02083       goto Fail;
02084 
02085     char_code = cmap->cur_charcode + 1;
02086 
02087     n = cmap->cur_group;
02088 
02089     for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
02090     {
02091       p        = cmap->cmap.data + 16 + 12 * n;
02092       start    = TT_NEXT_ULONG( p );
02093       end      = TT_NEXT_ULONG( p );
02094       start_id = TT_PEEK_ULONG( p );
02095 
02096       if ( char_code < start )
02097         char_code = start;
02098 
02099       for ( ; char_code <= end; char_code++ )
02100       {
02101         gindex = (FT_UInt)( start_id + char_code - start );
02102 
02103         if ( gindex )
02104         {
02105           cmap->cur_charcode = char_code;;
02106           cmap->cur_gindex   = gindex;
02107           cmap->cur_group    = n;
02108 
02109           return;
02110         }
02111       }
02112     }
02113 
02114   Fail:
02115     cmap->valid = 0;
02116   }
02117 
02118 
02119   static FT_UInt
02120   tt_cmap12_char_map_binary( TT_CMap     cmap,
02121                              FT_UInt32*  pchar_code,
02122                              FT_Bool     next )
02123   {
02124     FT_UInt    gindex     = 0;
02125     FT_Byte*   p          = cmap->data + 12;
02126     FT_UInt32  num_groups = TT_PEEK_ULONG( p );
02127     FT_UInt32  char_code  = *pchar_code;
02128     FT_UInt32  start, end, start_id;
02129     FT_UInt32  max, min, mid;
02130 
02131 
02132     if ( !num_groups )
02133       return 0;
02134 
02135     /* make compiler happy */
02136     mid = num_groups;
02137     end = 0xFFFFFFFFUL;
02138 
02139     if ( next )
02140       char_code++;
02141 
02142     min = 0;
02143     max = num_groups;
02144 
02145     /* binary search */
02146     while ( min < max )
02147     {
02148       mid = ( min + max ) >> 1;
02149       p   = cmap->data + 16 + 12 * mid;
02150 
02151       start = TT_NEXT_ULONG( p );
02152       end   = TT_NEXT_ULONG( p );
02153 
02154       if ( char_code < start )
02155         max = mid;
02156       else if ( char_code > end )
02157         min = mid + 1;
02158       else
02159       {
02160         start_id = TT_PEEK_ULONG( p );
02161         gindex = (FT_UInt)( start_id + char_code - start );
02162 
02163         break;
02164       }
02165     }
02166 
02167     if ( next )
02168     {
02169       TT_CMap12  cmap12 = (TT_CMap12)cmap;
02170 
02171 
02172       /* if `char_code' is not in any group, then `mid' is */
02173       /* the group nearest to `char_code'                  */
02174       /*                                                   */
02175 
02176       if ( char_code > end )
02177       {
02178         mid++;
02179         if ( mid == num_groups )
02180           return 0;
02181       }
02182 
02183       cmap12->valid        = 1;
02184       cmap12->cur_charcode = char_code;
02185       cmap12->cur_group    = mid;
02186 
02187       if ( !gindex )
02188       {
02189         tt_cmap12_next( cmap12 );
02190 
02191         if ( cmap12->valid )
02192           gindex = cmap12->cur_gindex;
02193       }
02194       else
02195         cmap12->cur_gindex = gindex;
02196 
02197       if ( gindex )
02198         *pchar_code = cmap12->cur_charcode;
02199     }
02200 
02201     return gindex;
02202   }
02203 
02204 
02205   FT_CALLBACK_DEF( FT_UInt )
02206   tt_cmap12_char_index( TT_CMap    cmap,
02207                         FT_UInt32  char_code )
02208   {
02209     return tt_cmap12_char_map_binary( cmap, &char_code, 0 );
02210   }
02211 
02212 
02213   FT_CALLBACK_DEF( FT_UInt32 )
02214   tt_cmap12_char_next( TT_CMap     cmap,
02215                        FT_UInt32  *pchar_code )
02216   {
02217     TT_CMap12  cmap12 = (TT_CMap12)cmap;
02218     FT_ULong   gindex;
02219 
02220 
02221     if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )
02222       return 0;
02223 
02224     /* no need to search */
02225     if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
02226     {
02227       tt_cmap12_next( cmap12 );
02228       if ( cmap12->valid )
02229       {
02230         gindex = cmap12->cur_gindex;
02231 
02232         /* XXX: check cur_charcode overflow is expected */
02233         if ( gindex )
02234           *pchar_code = (FT_UInt32)cmap12->cur_charcode;
02235       }
02236       else
02237         gindex = 0;
02238     }
02239     else
02240       gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
02241 
02242     /* XXX: check gindex overflow is expected */
02243     return (FT_UInt32)gindex;
02244   }
02245 
02246 
02247   FT_CALLBACK_DEF( FT_Error )
02248   tt_cmap12_get_info( TT_CMap       cmap,
02249                       TT_CMapInfo  *cmap_info )
02250   {
02251     FT_Byte*  p = cmap->data + 8;
02252 
02253 
02254     cmap_info->format   = 12;
02255     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
02256 
02257     return SFNT_Err_Ok;
02258   }
02259 
02260 
02261   FT_DEFINE_TT_CMAP(tt_cmap12_class_rec,
02262       sizeof ( TT_CMap12Rec ),
02263 
02264       (FT_CMap_InitFunc)     tt_cmap12_init,
02265       (FT_CMap_DoneFunc)     NULL,
02266       (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
02267       (FT_CMap_CharNextFunc) tt_cmap12_char_next,
02268 
02269       NULL, NULL, NULL, NULL, NULL
02270     ,
02271     12,
02272     (TT_CMap_ValidateFunc)   tt_cmap12_validate,
02273     (TT_CMap_Info_GetFunc)   tt_cmap12_get_info
02274   )
02275 
02276 #endif /* TT_CONFIG_CMAP_FORMAT_12 */
02277 
02278 
02279   /*************************************************************************/
02280   /*************************************************************************/
02281   /*****                                                               *****/
02282   /*****                          FORMAT 13                            *****/
02283   /*****                                                               *****/
02284   /*************************************************************************/
02285   /*************************************************************************/
02286 
02287   /*************************************************************************/
02288   /*                                                                       */
02289   /* TABLE OVERVIEW                                                        */
02290   /* --------------                                                        */
02291   /*                                                                       */
02292   /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
02293   /*                                                                       */
02294   /*   format      0          USHORT     must be 13                        */
02295   /*   reserved    2          USHORT     reserved                          */
02296   /*   length      4          ULONG      length in bytes                   */
02297   /*   language    8          ULONG      Mac language code                 */
02298   /*   count       12         ULONG      number of groups                  */
02299   /*               16                                                      */
02300   /*                                                                       */
02301   /* This header is followed by `count' groups of the following format:    */
02302   /*                                                                       */
02303   /*   start       0          ULONG      first charcode                    */
02304   /*   end         4          ULONG      last charcode                     */
02305   /*   glyphId     8          ULONG      glyph ID for the whole group      */
02306   /*                                                                       */
02307 
02308 #ifdef TT_CONFIG_CMAP_FORMAT_13
02309 
02310   typedef struct  TT_CMap13Rec_
02311   {
02312     TT_CMapRec  cmap;
02313     FT_Bool     valid;
02314     FT_ULong    cur_charcode;
02315     FT_UInt     cur_gindex;
02316     FT_ULong    cur_group;
02317     FT_ULong    num_groups;
02318 
02319   } TT_CMap13Rec, *TT_CMap13;
02320 
02321 
02322   FT_CALLBACK_DEF( FT_Error )
02323   tt_cmap13_init( TT_CMap13  cmap,
02324                   FT_Byte*   table )
02325   {
02326     cmap->cmap.data  = table;
02327 
02328     table           += 12;
02329     cmap->num_groups = FT_PEEK_ULONG( table );
02330 
02331     cmap->valid      = 0;
02332 
02333     return SFNT_Err_Ok;
02334   }
02335 
02336 
02337   FT_CALLBACK_DEF( FT_Error )
02338   tt_cmap13_validate( FT_Byte*      table,
02339                       FT_Validator  valid )
02340   {
02341     FT_Byte*   p;
02342     FT_ULong   length;
02343     FT_ULong   num_groups;
02344 
02345 
02346     if ( table + 16 > valid->limit )
02347       FT_INVALID_TOO_SHORT;
02348 
02349     p      = table + 4;
02350     length = TT_NEXT_ULONG( p );
02351 
02352     p          = table + 12;
02353     num_groups = TT_NEXT_ULONG( p );
02354 
02355     if ( length > (FT_ULong)( valid->limit - table ) ||
02356          length < 16 + 12 * num_groups               )
02357       FT_INVALID_TOO_SHORT;
02358 
02359     /* check groups, they must be in increasing order */
02360     {
02361       FT_ULong  n, start, end, glyph_id, last = 0;
02362 
02363 
02364       for ( n = 0; n < num_groups; n++ )
02365       {
02366         start    = TT_NEXT_ULONG( p );
02367         end      = TT_NEXT_ULONG( p );
02368         glyph_id = TT_NEXT_ULONG( p );
02369 
02370         if ( start > end )
02371           FT_INVALID_DATA;
02372 
02373         if ( n > 0 && start <= last )
02374           FT_INVALID_DATA;
02375 
02376         if ( valid->level >= FT_VALIDATE_TIGHT )
02377         {
02378           if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) )
02379             FT_INVALID_GLYPH_ID;
02380         }
02381 
02382         last = end;
02383       }
02384     }
02385 
02386     return SFNT_Err_Ok;
02387   }
02388 
02389 
02390   /* search the index of the charcode next to cmap->cur_charcode */
02391   /* cmap->cur_group should be set up properly by caller         */
02392   /*                                                             */
02393   static void
02394   tt_cmap13_next( TT_CMap13  cmap )
02395   {
02396     FT_Byte*  p;
02397     FT_ULong  start, end, glyph_id, char_code;
02398     FT_ULong  n;
02399     FT_UInt   gindex;
02400 
02401 
02402     if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
02403       goto Fail;
02404 
02405     char_code = cmap->cur_charcode + 1;
02406 
02407     n = cmap->cur_group;
02408 
02409     for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
02410     {
02411       p        = cmap->cmap.data + 16 + 12 * n;
02412       start    = TT_NEXT_ULONG( p );
02413       end      = TT_NEXT_ULONG( p );
02414       glyph_id = TT_PEEK_ULONG( p );
02415 
02416       if ( char_code < start )
02417         char_code = start;
02418 
02419       if ( char_code <= end )
02420       {
02421         gindex = (FT_UInt)glyph_id;
02422 
02423         if ( gindex )
02424         {
02425           cmap->cur_charcode = char_code;;
02426           cmap->cur_gindex   = gindex;
02427           cmap->cur_group    = n;
02428 
02429           return;
02430         }
02431       }
02432     }
02433 
02434   Fail:
02435     cmap->valid = 0;
02436   }
02437 
02438 
02439   static FT_UInt
02440   tt_cmap13_char_map_binary( TT_CMap     cmap,
02441                              FT_UInt32*  pchar_code,
02442                              FT_Bool     next )
02443   {
02444     FT_UInt    gindex     = 0;
02445     FT_Byte*   p          = cmap->data + 12;
02446     FT_UInt32  num_groups = TT_PEEK_ULONG( p );
02447     FT_UInt32  char_code  = *pchar_code;
02448     FT_UInt32  start, end;
02449     FT_UInt32  max, min, mid;
02450 
02451 
02452     if ( !num_groups )
02453       return 0;
02454 
02455     /* make compiler happy */
02456     mid = num_groups;
02457     end = 0xFFFFFFFFUL;
02458 
02459     if ( next )
02460       char_code++;
02461 
02462     min = 0;
02463     max = num_groups;
02464 
02465     /* binary search */
02466     while ( min < max )
02467     {
02468       mid = ( min + max ) >> 1;
02469       p   = cmap->data + 16 + 12 * mid;
02470 
02471       start = TT_NEXT_ULONG( p );
02472       end   = TT_NEXT_ULONG( p );
02473 
02474       if ( char_code < start )
02475         max = mid;
02476       else if ( char_code > end )
02477         min = mid + 1;
02478       else
02479       {
02480         gindex = (FT_UInt)TT_PEEK_ULONG( p );
02481 
02482         break;
02483       }
02484     }
02485 
02486     if ( next )
02487     {
02488       TT_CMap13  cmap13 = (TT_CMap13)cmap;
02489 
02490 
02491       /* if `char_code' is not in any group, then `mid' is */
02492       /* the group nearest to `char_code'                  */
02493       /*                                                   */
02494 
02495       if ( char_code > end )
02496       {
02497         mid++;
02498         if ( mid == num_groups )
02499           return 0;
02500       }
02501 
02502       cmap13->valid        = 1;
02503       cmap13->cur_charcode = char_code;
02504       cmap13->cur_group    = mid;
02505 
02506       if ( !gindex )
02507       {
02508         tt_cmap13_next( cmap13 );
02509 
02510         if ( cmap13->valid )
02511           gindex = cmap13->cur_gindex;
02512       }
02513       else
02514         cmap13->cur_gindex = gindex;
02515 
02516       if ( gindex )
02517         *pchar_code = cmap13->cur_charcode;
02518     }
02519 
02520     return gindex;
02521   }
02522 
02523 
02524   FT_CALLBACK_DEF( FT_UInt )
02525   tt_cmap13_char_index( TT_CMap    cmap,
02526                         FT_UInt32  char_code )
02527   {
02528     return tt_cmap13_char_map_binary( cmap, &char_code, 0 );
02529   }
02530 
02531 
02532   FT_CALLBACK_DEF( FT_UInt32 )
02533   tt_cmap13_char_next( TT_CMap     cmap,
02534                        FT_UInt32  *pchar_code )
02535   {
02536     TT_CMap13  cmap13 = (TT_CMap13)cmap;
02537     FT_UInt    gindex;
02538 
02539 
02540     if ( cmap13->cur_charcode >= 0xFFFFFFFFUL )
02541       return 0;
02542 
02543     /* no need to search */
02544     if ( cmap13->valid && cmap13->cur_charcode == *pchar_code )
02545     {
02546       tt_cmap13_next( cmap13 );
02547       if ( cmap13->valid )
02548       {
02549         gindex = cmap13->cur_gindex;
02550         if ( gindex )
02551           *pchar_code = cmap13->cur_charcode;
02552       }
02553       else
02554         gindex = 0;
02555     }
02556     else
02557       gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 );
02558 
02559     return gindex;
02560   }
02561 
02562 
02563   FT_CALLBACK_DEF( FT_Error )
02564   tt_cmap13_get_info( TT_CMap       cmap,
02565                       TT_CMapInfo  *cmap_info )
02566   {
02567     FT_Byte*  p = cmap->data + 8;
02568 
02569 
02570     cmap_info->format   = 13;
02571     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
02572 
02573     return SFNT_Err_Ok;
02574   }
02575 
02576 
02577   FT_DEFINE_TT_CMAP(tt_cmap13_class_rec,
02578       sizeof ( TT_CMap13Rec ),
02579 
02580       (FT_CMap_InitFunc)     tt_cmap13_init,
02581       (FT_CMap_DoneFunc)     NULL,
02582       (FT_CMap_CharIndexFunc)tt_cmap13_char_index,
02583       (FT_CMap_CharNextFunc) tt_cmap13_char_next,
02584 
02585       NULL, NULL, NULL, NULL, NULL
02586     ,
02587     13,
02588     (TT_CMap_ValidateFunc)   tt_cmap13_validate,
02589     (TT_CMap_Info_GetFunc)   tt_cmap13_get_info
02590   )
02591 
02592 #endif /* TT_CONFIG_CMAP_FORMAT_13 */
02593 
02594 
02595   /*************************************************************************/
02596   /*************************************************************************/
02597   /*****                                                               *****/
02598   /*****                           FORMAT 14                           *****/
02599   /*****                                                               *****/
02600   /*************************************************************************/
02601   /*************************************************************************/
02602 
02603   /*************************************************************************/
02604   /*                                                                       */
02605   /* TABLE OVERVIEW                                                        */
02606   /* --------------                                                        */
02607   /*                                                                       */
02608   /*   NAME         OFFSET  TYPE    DESCRIPTION                            */
02609   /*                                                                       */
02610   /*   format         0     USHORT  must be 14                             */
02611   /*   length         2     ULONG   table length in bytes                  */
02612   /*   numSelector    6     ULONG   number of variation sel. records       */
02613   /*                                                                       */
02614   /* Followed by numSelector records, each of which looks like             */
02615   /*                                                                       */
02616   /*   varSelector    0     UINT24  Unicode codepoint of sel.              */
02617   /*   defaultOff     3     ULONG   offset to a default UVS table          */
02618   /*                                describing any variants to be found in */
02619   /*                                the normal Unicode subtable.           */
02620   /*   nonDefOff      7     ULONG   offset to a non-default UVS table      */
02621   /*                                describing any variants not in the     */
02622   /*                                standard cmap, with GIDs here          */
02623   /* (either offset may be 0 NULL)                                         */
02624   /*                                                                       */
02625   /* Selectors are sorted by code point.                                   */
02626   /*                                                                       */
02627   /* A default Unicode Variation Selector (UVS) subtable is just a list of */
02628   /* ranges of code points which are to be found in the standard cmap.  No */
02629   /* glyph IDs (GIDs) here.                                                */
02630   /*                                                                       */
02631   /*   numRanges      0     ULONG   number of ranges following             */
02632   /*                                                                       */
02633   /* A range looks like                                                    */
02634   /*                                                                       */
02635   /*   uniStart       0     UINT24  code point of the first character in   */
02636   /*                                this range                             */
02637   /*   additionalCnt  3     UBYTE   count of additional characters in this */
02638   /*                                range (zero means a range of a single  */
02639   /*                                character)                             */
02640   /*                                                                       */
02641   /* Ranges are sorted by `uniStart'.                                      */
02642   /*                                                                       */
02643   /* A non-default Unicode Variation Selector (UVS) subtable is a list of  */
02644   /* mappings from codepoint to GID.                                       */
02645   /*                                                                       */
02646   /*   numMappings    0     ULONG   number of mappings                     */
02647   /*                                                                       */
02648   /* A range looks like                                                    */
02649   /*                                                                       */
02650   /*   uniStart       0     UINT24  code point of the first character in   */
02651   /*                                this range                             */
02652   /*   GID            3     USHORT  and its GID                            */
02653   /*                                                                       */
02654   /* Ranges are sorted by `uniStart'.                                      */
02655 
02656 #ifdef TT_CONFIG_CMAP_FORMAT_14
02657 
02658   typedef struct  TT_CMap14Rec_
02659   {
02660     TT_CMapRec  cmap;
02661     FT_ULong    num_selectors;
02662 
02663     /* This array is used to store the results of various
02664      * cmap 14 query functions.  The data is overwritten
02665      * on each call to these functions.
02666      */
02667     FT_UInt32   max_results;
02668     FT_UInt32*  results;
02669     FT_Memory   memory;
02670 
02671   } TT_CMap14Rec, *TT_CMap14;
02672 
02673 
02674   FT_CALLBACK_DEF( void )
02675   tt_cmap14_done( TT_CMap14  cmap )
02676   {
02677     FT_Memory  memory = cmap->memory;
02678 
02679 
02680     cmap->max_results = 0;
02681     if ( memory != NULL && cmap->results != NULL )
02682       FT_FREE( cmap->results );
02683   }
02684 
02685 
02686   static FT_Error
02687   tt_cmap14_ensure( TT_CMap14  cmap,
02688                     FT_UInt32  num_results,
02689                     FT_Memory  memory )
02690   {
02691     FT_UInt32 old_max = cmap->max_results;
02692     FT_Error  error   = SFNT_Err_Ok;
02693 
02694 
02695     if ( num_results > cmap->max_results )
02696     {
02697        cmap->memory = memory;
02698 
02699        if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) )
02700          return error;
02701 
02702        cmap->max_results = num_results;
02703     }
02704 
02705     return error;
02706   }
02707 
02708 
02709   FT_CALLBACK_DEF( FT_Error )
02710   tt_cmap14_init( TT_CMap14  cmap,
02711                   FT_Byte*   table )
02712   {
02713     cmap->cmap.data = table;
02714 
02715     table               += 6;
02716     cmap->num_selectors = FT_PEEK_ULONG( table );
02717     cmap->max_results   = 0;
02718     cmap->results       = NULL;
02719 
02720     return SFNT_Err_Ok;
02721   }
02722 
02723 
02724   FT_CALLBACK_DEF( FT_Error )
02725   tt_cmap14_validate( FT_Byte*      table,
02726                       FT_Validator  valid )
02727   {
02728     FT_Byte*  p             = table + 2;
02729     FT_ULong  length        = TT_NEXT_ULONG( p );
02730     FT_ULong  num_selectors = TT_NEXT_ULONG( p );
02731 
02732 
02733     if ( length > (FT_ULong)( valid->limit - table ) ||
02734          length < 10 + 11 * num_selectors            )
02735       FT_INVALID_TOO_SHORT;
02736 
02737     /* check selectors, they must be in increasing order */
02738     {
02739       /* we start lastVarSel at 1 because a variant selector value of 0
02740        * isn't valid.
02741        */
02742       FT_ULong  n, lastVarSel = 1;
02743 
02744 
02745       for ( n = 0; n < num_selectors; n++ )
02746       {
02747         FT_ULong  varSel    = TT_NEXT_UINT24( p );
02748         FT_ULong  defOff    = TT_NEXT_ULONG( p );
02749         FT_ULong  nondefOff = TT_NEXT_ULONG( p );
02750 
02751 
02752         if ( defOff >= length || nondefOff >= length )
02753           FT_INVALID_TOO_SHORT;
02754 
02755         if ( varSel < lastVarSel )
02756           FT_INVALID_DATA;
02757 
02758         lastVarSel = varSel + 1;
02759 
02760         /* check the default table (these glyphs should be reached     */
02761         /* through the normal Unicode cmap, no GIDs, just check order) */
02762         if ( defOff != 0 )
02763         {
02764           FT_Byte*  defp      = table + defOff;
02765           FT_ULong  numRanges = TT_NEXT_ULONG( defp );
02766           FT_ULong  i;
02767           FT_ULong  lastBase  = 0;
02768 
02769 
02770           if ( defp + numRanges * 4 > valid->limit )
02771             FT_INVALID_TOO_SHORT;
02772 
02773           for ( i = 0; i < numRanges; ++i )
02774           {
02775             FT_ULong  base = TT_NEXT_UINT24( defp );
02776             FT_ULong  cnt  = FT_NEXT_BYTE( defp );
02777 
02778 
02779             if ( base + cnt >= 0x110000UL )              /* end of Unicode */
02780               FT_INVALID_DATA;
02781 
02782             if ( base < lastBase )
02783               FT_INVALID_DATA;
02784 
02785             lastBase = base + cnt + 1U;
02786           }
02787         }
02788 
02789         /* and the non-default table (these glyphs are specified here) */
02790         if ( nondefOff != 0 )
02791         {
02792           FT_Byte*  ndp         = table + nondefOff;
02793           FT_ULong  numMappings = TT_NEXT_ULONG( ndp );
02794           FT_ULong  i, lastUni = 0;
02795 
02796 
02797           if ( numMappings * 4 > (FT_ULong)( valid->limit - ndp ) )
02798             FT_INVALID_TOO_SHORT;
02799 
02800           for ( i = 0; i < numMappings; ++i )
02801           {
02802             FT_ULong  uni = TT_NEXT_UINT24( ndp );
02803             FT_ULong  gid = TT_NEXT_USHORT( ndp );
02804 
02805 
02806             if ( uni >= 0x110000UL )                     /* end of Unicode */
02807               FT_INVALID_DATA;
02808 
02809             if ( uni < lastUni )
02810               FT_INVALID_DATA;
02811 
02812             lastUni = uni + 1U;
02813 
02814             if ( valid->level >= FT_VALIDATE_TIGHT    &&
02815                  gid >= TT_VALID_GLYPH_COUNT( valid ) )
02816               FT_INVALID_GLYPH_ID;
02817           }
02818         }
02819       }
02820     }
02821 
02822     return SFNT_Err_Ok;
02823   }
02824 
02825 
02826   FT_CALLBACK_DEF( FT_UInt )
02827   tt_cmap14_char_index( TT_CMap    cmap,
02828                         FT_UInt32  char_code )
02829   {
02830     FT_UNUSED( cmap );
02831     FT_UNUSED( char_code );
02832 
02833     /* This can't happen */
02834     return 0;
02835   }
02836 
02837 
02838   FT_CALLBACK_DEF( FT_UInt32 )
02839   tt_cmap14_char_next( TT_CMap     cmap,
02840                        FT_UInt32  *pchar_code )
02841   {
02842     FT_UNUSED( cmap );
02843 
02844     /* This can't happen */
02845     *pchar_code = 0;
02846     return 0;
02847   }
02848 
02849 
02850   FT_CALLBACK_DEF( FT_Error )
02851   tt_cmap14_get_info( TT_CMap       cmap,
02852                       TT_CMapInfo  *cmap_info )
02853   {
02854     FT_UNUSED( cmap );
02855 
02856     cmap_info->format   = 14;
02857     /* subtable 14 does not define a language field */
02858     cmap_info->language = 0xFFFFFFFFUL;
02859 
02860     return SFNT_Err_Ok;
02861   }
02862 
02863 
02864   static FT_UInt
02865   tt_cmap14_char_map_def_binary( FT_Byte    *base,
02866                                  FT_UInt32   char_code )
02867   {
02868     FT_UInt32  numRanges = TT_PEEK_ULONG( base );
02869     FT_UInt32  max, min;
02870 
02871 
02872     min = 0;
02873     max = numRanges;
02874 
02875     base += 4;
02876 
02877     /* binary search */
02878     while ( min < max )
02879     {
02880       FT_UInt32  mid   = ( min + max ) >> 1;
02881       FT_Byte*   p     = base + 4 * mid;
02882       FT_ULong   start = TT_NEXT_UINT24( p );
02883       FT_UInt    cnt   = FT_NEXT_BYTE( p );
02884 
02885 
02886       if ( char_code < start )
02887         max = mid;
02888       else if ( char_code > start+cnt )
02889         min = mid + 1;
02890       else
02891         return TRUE;
02892     }
02893 
02894     return FALSE;
02895   }
02896 
02897 
02898   static FT_UInt
02899   tt_cmap14_char_map_nondef_binary( FT_Byte    *base,
02900                                     FT_UInt32   char_code )
02901   {
02902     FT_UInt32  numMappings = TT_PEEK_ULONG( base );
02903     FT_UInt32  max, min;
02904 
02905 
02906     min = 0;
02907     max = numMappings;
02908 
02909     base += 4;
02910 
02911     /* binary search */
02912     while ( min < max )
02913     {
02914       FT_UInt32  mid = ( min + max ) >> 1;
02915       FT_Byte*   p   = base + 5 * mid;
02916       FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
02917 
02918 
02919       if ( char_code < uni )
02920         max = mid;
02921       else if ( char_code > uni )
02922         min = mid + 1;
02923       else
02924         return TT_PEEK_USHORT( p );
02925     }
02926 
02927     return 0;
02928   }
02929 
02930 
02931   static FT_Byte*
02932   tt_cmap14_find_variant( FT_Byte    *base,
02933                           FT_UInt32   variantCode )
02934   {
02935     FT_UInt32  numVar = TT_PEEK_ULONG( base );
02936     FT_UInt32  max, min;
02937 
02938 
02939     min = 0;
02940     max = numVar;
02941 
02942     base += 4;
02943 
02944     /* binary search */
02945     while ( min < max )
02946     {
02947       FT_UInt32  mid    = ( min + max ) >> 1;
02948       FT_Byte*   p      = base + 11 * mid;
02949       FT_ULong   varSel = TT_NEXT_UINT24( p );
02950 
02951 
02952       if ( variantCode < varSel )
02953         max = mid;
02954       else if ( variantCode > varSel )
02955         min = mid + 1;
02956       else
02957         return p;
02958     }
02959 
02960     return NULL;
02961   }
02962 
02963 
02964   FT_CALLBACK_DEF( FT_UInt )
02965   tt_cmap14_char_var_index( TT_CMap    cmap,
02966                             TT_CMap    ucmap,
02967                             FT_UInt32  charcode,
02968                             FT_UInt32  variantSelector)
02969   {
02970     FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
02971     FT_ULong  defOff;
02972     FT_ULong  nondefOff;
02973 
02974 
02975     if ( !p )
02976       return 0;
02977 
02978     defOff    = TT_NEXT_ULONG( p );
02979     nondefOff = TT_PEEK_ULONG( p );
02980 
02981     if ( defOff != 0                                                    &&
02982          tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
02983     {
02984       /* This is the default variant of this charcode.  GID not stored */
02985       /* here; stored in the normal Unicode charmap instead.           */
02986       return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode );
02987     }
02988 
02989     if ( nondefOff != 0 )
02990       return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
02991                                                charcode );
02992 
02993     return 0;
02994   }
02995 
02996 
02997   FT_CALLBACK_DEF( FT_Int )
02998   tt_cmap14_char_var_isdefault( TT_CMap    cmap,
02999                                 FT_UInt32  charcode,
03000                                 FT_UInt32  variantSelector )
03001   {
03002     FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
03003     FT_ULong  defOff;
03004     FT_ULong  nondefOff;
03005 
03006 
03007     if ( !p )
03008       return -1;
03009 
03010     defOff    = TT_NEXT_ULONG( p );
03011     nondefOff = TT_NEXT_ULONG( p );
03012 
03013     if ( defOff != 0                                                    &&
03014          tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
03015       return 1;
03016 
03017     if ( nondefOff != 0                                            &&
03018          tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
03019                                            charcode ) != 0         )
03020       return 0;
03021 
03022     return -1;
03023   }
03024 
03025 
03026   FT_CALLBACK_DEF( FT_UInt32* )
03027   tt_cmap14_variants( TT_CMap    cmap,
03028                       FT_Memory  memory )
03029   {
03030     TT_CMap14   cmap14 = (TT_CMap14)cmap;
03031     FT_UInt32   count  = cmap14->num_selectors;
03032     FT_Byte*    p      = cmap->data + 10;
03033     FT_UInt32*  result;
03034     FT_UInt32   i;
03035 
03036 
03037     if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
03038       return NULL;
03039 
03040     result = cmap14->results;
03041     for ( i = 0; i < count; ++i )
03042     {
03043       result[i] = (FT_UInt32)TT_NEXT_UINT24( p );
03044       p        += 8;
03045     }
03046     result[i] = 0;
03047 
03048     return result;
03049   }
03050 
03051 
03052   FT_CALLBACK_DEF( FT_UInt32 * )
03053   tt_cmap14_char_variants( TT_CMap    cmap,
03054                            FT_Memory  memory,
03055                            FT_UInt32  charCode )
03056   {
03057     TT_CMap14   cmap14 = (TT_CMap14)  cmap;
03058     FT_UInt32   count  = cmap14->num_selectors;
03059     FT_Byte*    p      = cmap->data + 10;
03060     FT_UInt32*  q;
03061 
03062 
03063     if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
03064       return NULL;
03065 
03066     for ( q = cmap14->results; count > 0; --count )
03067     {
03068       FT_UInt32  varSel    = TT_NEXT_UINT24( p );
03069       FT_ULong   defOff    = TT_NEXT_ULONG( p );
03070       FT_ULong   nondefOff = TT_NEXT_ULONG( p );
03071 
03072 
03073       if ( ( defOff != 0                                               &&
03074              tt_cmap14_char_map_def_binary( cmap->data + defOff,
03075                                             charCode )                 ) ||
03076            ( nondefOff != 0                                            &&
03077              tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
03078                                                charCode ) != 0         ) )
03079       {
03080         q[0] = varSel;
03081         q++;
03082       }
03083     }
03084     q[0] = 0;
03085 
03086     return cmap14->results;
03087   }
03088 
03089 
03090   static FT_UInt
03091   tt_cmap14_def_char_count( FT_Byte  *p )
03092   {
03093     FT_UInt32  numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
03094     FT_UInt    tot       = 0;
03095 
03096 
03097     p += 3;  /* point to the first `cnt' field */
03098     for ( ; numRanges > 0; numRanges-- )
03099     {
03100       tot += 1 + p[0];
03101       p   += 4;
03102     }
03103 
03104     return tot;
03105   }
03106 
03107 
03108   static FT_UInt32*
03109   tt_cmap14_get_def_chars( TT_CMap     cmap,
03110                            FT_Byte*    p,
03111                            FT_Memory   memory )
03112   {
03113     TT_CMap14   cmap14 = (TT_CMap14) cmap;
03114     FT_UInt32   numRanges;
03115     FT_UInt     cnt;
03116     FT_UInt32*  q;
03117 
03118 
03119     cnt       = tt_cmap14_def_char_count( p );
03120     numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
03121 
03122     if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) )
03123       return NULL;
03124 
03125     for ( q = cmap14->results; numRanges > 0; --numRanges )
03126     {
03127       FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p );
03128 
03129 
03130       cnt = FT_NEXT_BYTE( p ) + 1;
03131       do
03132       {
03133         q[0]  = uni;
03134         uni  += 1;
03135         q    += 1;
03136       } while ( --cnt != 0 );
03137     }
03138     q[0] = 0;
03139 
03140     return cmap14->results;
03141   }
03142 
03143 
03144   static FT_UInt32*
03145   tt_cmap14_get_nondef_chars( TT_CMap     cmap,
03146                               FT_Byte    *p,
03147                               FT_Memory   memory )
03148   {
03149     TT_CMap14   cmap14 = (TT_CMap14) cmap;
03150     FT_UInt32   numMappings;
03151     FT_UInt     i;
03152     FT_UInt32  *ret;
03153 
03154 
03155     numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
03156 
03157     if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) )
03158       return NULL;
03159 
03160     ret = cmap14->results;
03161     for ( i = 0; i < numMappings; ++i )
03162     {
03163       ret[i] = (FT_UInt32)TT_NEXT_UINT24( p );
03164       p += 2;
03165     }
03166     ret[i] = 0;
03167 
03168     return ret;
03169   }
03170 
03171 
03172   FT_CALLBACK_DEF( FT_UInt32 * )
03173   tt_cmap14_variant_chars( TT_CMap    cmap,
03174                            FT_Memory  memory,
03175                            FT_UInt32  variantSelector )
03176   {
03177     FT_Byte    *p  = tt_cmap14_find_variant( cmap->data + 6,
03178                                              variantSelector );
03179     FT_UInt32  *ret;
03180     FT_Int      i;
03181     FT_ULong    defOff;
03182     FT_ULong    nondefOff;
03183 
03184 
03185     if ( !p )
03186       return NULL;
03187 
03188     defOff    = TT_NEXT_ULONG( p );
03189     nondefOff = TT_NEXT_ULONG( p );
03190 
03191     if ( defOff == 0 && nondefOff == 0 )
03192       return NULL;
03193 
03194     if ( defOff == 0 )
03195       return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
03196                                          memory );
03197     else if ( nondefOff == 0 )
03198       return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
03199                                       memory );
03200     else
03201     {
03202       /* Both a default and a non-default glyph set?  That's probably not */
03203       /* good font design, but the spec allows for it...                  */
03204       TT_CMap14  cmap14 = (TT_CMap14) cmap;
03205       FT_UInt32  numRanges;
03206       FT_UInt32  numMappings;
03207       FT_UInt32  duni;
03208       FT_UInt32  dcnt;
03209       FT_UInt32  nuni;
03210       FT_Byte*   dp;
03211       FT_UInt    di, ni, k;
03212 
03213 
03214       p  = cmap->data + nondefOff;
03215       dp = cmap->data + defOff;
03216 
03217       numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
03218       dcnt        = tt_cmap14_def_char_count( dp );
03219       numRanges   = (FT_UInt32)TT_NEXT_ULONG( dp );
03220 
03221       if ( numMappings == 0 )
03222         return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
03223                                         memory );
03224       if ( dcnt == 0 )
03225         return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
03226                                            memory );
03227 
03228       if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) )
03229         return NULL;
03230 
03231       ret  = cmap14->results;
03232       duni = (FT_UInt32)TT_NEXT_UINT24( dp );
03233       dcnt = FT_NEXT_BYTE( dp );
03234       di   = 1;
03235       nuni = (FT_UInt32)TT_NEXT_UINT24( p );
03236       p   += 2;
03237       ni   = 1;
03238       i    = 0;
03239 
03240       for ( ;; )
03241       {
03242         if ( nuni > duni + dcnt )
03243         {
03244           for ( k = 0; k <= dcnt; ++k )
03245             ret[i++] = duni + k;
03246 
03247           ++di;
03248 
03249           if ( di > numRanges )
03250             break;
03251 
03252           duni = (FT_UInt32)TT_NEXT_UINT24( dp );
03253           dcnt = FT_NEXT_BYTE( dp );
03254         }
03255         else
03256         {
03257           if ( nuni < duni )
03258             ret[i++] = nuni;
03259           /* If it is within the default range then ignore it -- */
03260           /* that should not have happened                       */
03261           ++ni;
03262           if ( ni > numMappings )
03263             break;
03264 
03265           nuni = (FT_UInt32)TT_NEXT_UINT24( p );
03266           p += 2;
03267         }
03268       }
03269 
03270       if ( ni <= numMappings )
03271       {
03272         /* If we get here then we have run out of all default ranges.   */
03273         /* We have read one non-default mapping which we haven't stored */
03274         /* and there may be others that need to be read.                */
03275         ret[i++] = nuni;
03276         while ( ni < numMappings )
03277         {
03278           ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p );
03279           p += 2;
03280           ++ni;
03281         }
03282       }
03283       else if ( di <= numRanges )
03284       {
03285         /* If we get here then we have run out of all non-default     */
03286         /* mappings.  We have read one default range which we haven't */
03287         /* stored and there may be others that need to be read.       */
03288         for ( k = 0; k <= dcnt; ++k )
03289           ret[i++] = duni + k;
03290 
03291         while ( di < numRanges )
03292         {
03293           duni = (FT_UInt32)TT_NEXT_UINT24( dp );
03294           dcnt = FT_NEXT_BYTE( dp );
03295 
03296           for ( k = 0; k <= dcnt; ++k )
03297             ret[i++] = duni + k;
03298           ++di;
03299         }
03300       }
03301 
03302       ret[i] = 0;
03303 
03304       return ret;
03305     }
03306   }
03307 
03308 
03309   FT_DEFINE_TT_CMAP(tt_cmap14_class_rec,
03310       sizeof ( TT_CMap14Rec ),
03311 
03312       (FT_CMap_InitFunc)     tt_cmap14_init,
03313       (FT_CMap_DoneFunc)     tt_cmap14_done,
03314       (FT_CMap_CharIndexFunc)tt_cmap14_char_index,
03315       (FT_CMap_CharNextFunc) tt_cmap14_char_next,
03316 
03317       /* Format 14 extension functions */
03318       (FT_CMap_CharVarIndexFunc)    tt_cmap14_char_var_index,
03319       (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
03320       (FT_CMap_VariantListFunc)     tt_cmap14_variants,
03321       (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
03322       (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars
03323     ,
03324     14,
03325     (TT_CMap_ValidateFunc)tt_cmap14_validate,
03326     (TT_CMap_Info_GetFunc)tt_cmap14_get_info
03327   )
03328 
03329 #endif /* TT_CONFIG_CMAP_FORMAT_14 */
03330 
03331 
03332 #ifndef FT_CONFIG_OPTION_PIC
03333 
03334   static const TT_CMap_Class  tt_cmap_classes[] =
03335   {
03336 #define TTCMAPCITEM(a) &a,
03337 #include "ttcmapc.h"
03338     NULL,
03339   };
03340 
03341 #else /*FT_CONFIG_OPTION_PIC*/
03342 
03343   void FT_Destroy_Class_tt_cmap_classes(FT_Library library, TT_CMap_Class* clazz)
03344   {
03345     FT_Memory memory = library->memory;
03346     if ( clazz )
03347       FT_FREE( clazz );
03348   }
03349 
03350   FT_Error FT_Create_Class_tt_cmap_classes(FT_Library library, TT_CMap_Class** output_class)
03351   {
03352     TT_CMap_Class*  clazz;
03353     TT_CMap_ClassRec* recs;
03354     FT_Error          error;
03355     FT_Memory memory = library->memory;
03356     int i = 0;
03357 
03358 #define TTCMAPCITEM(a) i++;
03359 #include "ttcmapc.h"
03360 
03361     /* allocate enough space for both the pointers +terminator and the class instances */
03362     if ( FT_ALLOC( clazz, sizeof(*clazz)*(i+1)+sizeof(TT_CMap_ClassRec)*i ) )
03363       return error;
03364 
03365     /* the location of the class instances follows the array of pointers */
03366     recs = (TT_CMap_ClassRec*) (((char*)clazz)+(sizeof(*clazz)*(i+1))); 
03367     i=0;
03368 
03369 #undef TTCMAPCITEM
03370 #define TTCMAPCITEM(a)           \
03371     FT_Init_Class_##a(&recs[i]); \
03372     clazz[i] = &recs[i];         \
03373     i++;
03374 #include "ttcmapc.h"
03375 
03376     clazz[i] = NULL;
03377 
03378     *output_class = clazz;
03379     return SFNT_Err_Ok;
03380   }
03381 
03382 #endif /*FT_CONFIG_OPTION_PIC*/
03383 
03384 
03385   /* parse the `cmap' table and build the corresponding TT_CMap objects */
03386   /* in the current face                                                */
03387   /*                                                                    */
03388   FT_LOCAL_DEF( FT_Error )
03389   tt_face_build_cmaps( TT_Face  face )
03390   {
03391     FT_Byte*           table = face->cmap_table;
03392     FT_Byte*           limit = table + face->cmap_size;
03393     FT_UInt volatile   num_cmaps;
03394     FT_Byte* volatile  p     = table;
03395     FT_Library         library = FT_FACE_LIBRARY( face );
03396 
03397     FT_UNUSED( library );
03398 
03399 
03400     if ( !p || p + 4 > limit )
03401       return SFNT_Err_Invalid_Table;
03402 
03403     /* only recognize format 0 */
03404     if ( TT_NEXT_USHORT( p ) != 0 )
03405     {
03406       p -= 2;
03407       FT_ERROR(( "tt_face_build_cmaps:"
03408                  " unsupported `cmap' table format = %d\n",
03409                  TT_PEEK_USHORT( p ) ));
03410       return SFNT_Err_Invalid_Table;
03411     }
03412 
03413     num_cmaps = TT_NEXT_USHORT( p );
03414 #ifdef FT_MAX_CHARMAP_CACHEABLE
03415     if ( num_cmaps > FT_MAX_CHARMAP_CACHEABLE )
03416       FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables(%d) "
03417                  "subtable#%d and later are loaded but cannot be searched\n",
03418                  num_cmaps, FT_MAX_CHARMAP_CACHEABLE + 1 ));
03419 #endif
03420 
03421     for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
03422     {
03423       FT_CharMapRec  charmap;
03424       FT_UInt32      offset;
03425 
03426 
03427       charmap.platform_id = TT_NEXT_USHORT( p );
03428       charmap.encoding_id = TT_NEXT_USHORT( p );
03429       charmap.face        = FT_FACE( face );
03430       charmap.encoding    = FT_ENCODING_NONE;  /* will be filled later */
03431       offset              = TT_NEXT_ULONG( p );
03432 
03433       if ( offset && offset <= face->cmap_size - 2 )
03434       {
03435         FT_Byte* volatile              cmap   = table + offset;
03436         volatile FT_UInt               format = TT_PEEK_USHORT( cmap );
03437         const TT_CMap_Class* volatile  pclazz = FT_TT_CMAP_CLASSES_GET;
03438         TT_CMap_Class volatile         clazz;
03439 
03440 
03441         for ( ; *pclazz; pclazz++ )
03442         {
03443           clazz = *pclazz;
03444           if ( clazz->format == format )
03445           {
03446             volatile TT_ValidatorRec  valid;
03447             volatile FT_Error         error = SFNT_Err_Ok;
03448 
03449 
03450             ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
03451                                FT_VALIDATE_DEFAULT );
03452 
03453             valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
03454 
03455             if ( ft_setjmp(
03456               *((ft_jmp_buf*)&FT_VALIDATOR( &valid )->jump_buffer) ) == 0 )
03457             {
03458               /* validate this cmap sub-table */
03459               error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
03460             }
03461 
03462             if ( valid.validator.error == 0 )
03463             {
03464               FT_CMap  ttcmap;
03465 
03466 
03467               /* It might make sense to store the single variation selector */
03468               /* cmap somewhere special.  But it would have to be in the    */
03469               /* public FT_FaceRec, and we can't change that.               */
03470 
03471               if ( !FT_CMap_New( (FT_CMap_Class)clazz,
03472                                  cmap, &charmap, &ttcmap ) )
03473               {
03474                 /* it is simpler to directly set `flags' than adding */
03475                 /* a parameter to FT_CMap_New                        */
03476                 ((TT_CMap)ttcmap)->flags = (FT_Int)error;
03477               }
03478             }
03479             else
03480             {
03481               FT_TRACE0(( "tt_face_build_cmaps:"
03482                           " broken cmap sub-table ignored\n" ));
03483             }
03484             break;
03485           }
03486         }
03487 
03488         if ( *pclazz == NULL )
03489         {
03490           FT_TRACE0(( "tt_face_build_cmaps:"
03491                       " unsupported cmap sub-table ignored\n" ));
03492         }
03493       }
03494     }
03495 
03496     return SFNT_Err_Ok;
03497   }
03498 
03499 
03500   FT_LOCAL( FT_Error )
03501   tt_get_cmap_info( FT_CharMap    charmap,
03502                     TT_CMapInfo  *cmap_info )
03503   {
03504     FT_CMap        cmap  = (FT_CMap)charmap;
03505     TT_CMap_Class  clazz = (TT_CMap_Class)cmap->clazz;
03506 
03507 
03508     return clazz->get_cmap_info( charmap, cmap_info );
03509   }
03510 
03511 
03512 /* END */

Generated on Sun May 27 2012 04:34:01 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.