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 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   = 0;
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           FT_Byte*  ndp         = table + nondefOff;
02792           FT_ULong  numMappings = TT_NEXT_ULONG( ndp );
02793           FT_ULong  i, lastUni = 0;
02794 
02795 
02796           if ( numMappings * 4 > (FT_ULong)( valid->limit - ndp ) )
02797             FT_INVALID_TOO_SHORT;
02798 
02799           for ( i = 0; i < numMappings; ++i )
02800           {
02801             FT_ULong  uni = TT_NEXT_UINT24( ndp );
02802             FT_ULong  gid = TT_NEXT_USHORT( ndp );
02803 
02804 
02805             if ( uni >= 0x110000UL )                     /* end of Unicode */
02806               FT_INVALID_DATA;
02807 
02808             if ( uni < lastUni )
02809               FT_INVALID_DATA;
02810 
02811             lastUni = uni + 1U;
02812 
02813             if ( valid->level >= FT_VALIDATE_TIGHT    &&
02814                  gid >= TT_VALID_GLYPH_COUNT( valid ) )
02815               FT_INVALID_GLYPH_ID;
02816           }
02817         }
02818       }
02819     }
02820 
02821     return SFNT_Err_Ok;
02822   }
02823 
02824 
02825   FT_CALLBACK_DEF( FT_UInt )
02826   tt_cmap14_char_index( TT_CMap    cmap,
02827                         FT_UInt32  char_code )
02828   {
02829     FT_UNUSED( cmap );
02830     FT_UNUSED( char_code );
02831 
02832     /* This can't happen */
02833     return 0;
02834   }
02835 
02836 
02837   FT_CALLBACK_DEF( FT_UInt32 )
02838   tt_cmap14_char_next( TT_CMap     cmap,
02839                        FT_UInt32  *pchar_code )
02840   {
02841     FT_UNUSED( cmap );
02842 
02843     /* This can't happen */
02844     *pchar_code = 0;
02845     return 0;
02846   }
02847 
02848 
02849   FT_CALLBACK_DEF( FT_Error )
02850   tt_cmap14_get_info( TT_CMap       cmap,
02851                       TT_CMapInfo  *cmap_info )
02852   {
02853     FT_UNUSED( cmap );
02854 
02855     cmap_info->format   = 14;
02856     /* subtable 14 does not define a language field */
02857     cmap_info->language = 0xFFFFFFFFUL;
02858 
02859     return SFNT_Err_Ok;
02860   }
02861 
02862 
02863   static FT_UInt
02864   tt_cmap14_char_map_def_binary( FT_Byte    *base,
02865                                  FT_UInt32   char_code )
02866   {
02867     FT_UInt32  numRanges = TT_PEEK_ULONG( base );
02868     FT_UInt32  max, min;
02869 
02870 
02871     min = 0;
02872     max = numRanges;
02873 
02874     base += 4;
02875 
02876     /* binary search */
02877     while ( min < max )
02878     {
02879       FT_UInt32  mid   = ( min + max ) >> 1;
02880       FT_Byte*   p     = base + 4 * mid;
02881       FT_ULong   start = TT_NEXT_UINT24( p );
02882       FT_UInt    cnt   = FT_NEXT_BYTE( p );
02883 
02884 
02885       if ( char_code < start )
02886         max = mid;
02887       else if ( char_code > start+cnt )
02888         min = mid + 1;
02889       else
02890         return TRUE;
02891     }
02892 
02893     return FALSE;
02894   }
02895 
02896 
02897   static FT_UInt
02898   tt_cmap14_char_map_nondef_binary( FT_Byte    *base,
02899                                     FT_UInt32   char_code )
02900   {
02901     FT_UInt32  numMappings = TT_PEEK_ULONG( base );
02902     FT_UInt32  max, min;
02903 
02904 
02905     min = 0;
02906     max = numMappings;
02907 
02908     base += 4;
02909 
02910     /* binary search */
02911     while ( min < max )
02912     {
02913       FT_UInt32  mid = ( min + max ) >> 1;
02914       FT_Byte*   p   = base + 5 * mid;
02915       FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
02916 
02917 
02918       if ( char_code < uni )
02919         max = mid;
02920       else if ( char_code > uni )
02921         min = mid + 1;
02922       else
02923         return TT_PEEK_USHORT( p );
02924     }
02925 
02926     return 0;
02927   }
02928 
02929 
02930   static FT_Byte*
02931   tt_cmap14_find_variant( FT_Byte    *base,
02932                           FT_UInt32   variantCode )
02933   {
02934     FT_UInt32  numVar = TT_PEEK_ULONG( base );
02935     FT_UInt32  max, min;
02936 
02937 
02938     min = 0;
02939     max = numVar;
02940 
02941     base += 4;
02942 
02943     /* binary search */
02944     while ( min < max )
02945     {
02946       FT_UInt32  mid    = ( min + max ) >> 1;
02947       FT_Byte*   p      = base + 11 * mid;
02948       FT_ULong   varSel = TT_NEXT_UINT24( p );
02949 
02950 
02951       if ( variantCode < varSel )
02952         max = mid;
02953       else if ( variantCode > varSel )
02954         min = mid + 1;
02955       else
02956         return p;
02957     }
02958 
02959     return NULL;
02960   }
02961 
02962 
02963   FT_CALLBACK_DEF( FT_UInt )
02964   tt_cmap14_char_var_index( TT_CMap    cmap,
02965                             TT_CMap    ucmap,
02966                             FT_UInt32  charcode,
02967                             FT_UInt32  variantSelector)
02968   {
02969     FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
02970     FT_ULong  defOff;
02971     FT_ULong  nondefOff;
02972 
02973 
02974     if ( !p )
02975       return 0;
02976 
02977     defOff    = TT_NEXT_ULONG( p );
02978     nondefOff = TT_PEEK_ULONG( p );
02979 
02980     if ( defOff != 0                                                    &&
02981          tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
02982     {
02983       /* This is the default variant of this charcode.  GID not stored */
02984       /* here; stored in the normal Unicode charmap instead.           */
02985       return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode );
02986     }
02987 
02988     if ( nondefOff != 0 )
02989       return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
02990                                                charcode );
02991 
02992     return 0;
02993   }
02994 
02995 
02996   FT_CALLBACK_DEF( FT_Int )
02997   tt_cmap14_char_var_isdefault( TT_CMap    cmap,
02998                                 FT_UInt32  charcode,
02999                                 FT_UInt32  variantSelector )
03000   {
03001     FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
03002     FT_ULong  defOff;
03003     FT_ULong  nondefOff;
03004 
03005 
03006     if ( !p )
03007       return -1;
03008 
03009     defOff    = TT_NEXT_ULONG( p );
03010     nondefOff = TT_NEXT_ULONG( p );
03011 
03012     if ( defOff != 0                                                    &&
03013          tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
03014       return 1;
03015 
03016     if ( nondefOff != 0                                            &&
03017          tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
03018                                            charcode ) != 0         )
03019       return 0;
03020 
03021     return -1;
03022   }
03023 
03024 
03025   FT_CALLBACK_DEF( FT_UInt32* )
03026   tt_cmap14_variants( TT_CMap    cmap,
03027                       FT_Memory  memory )
03028   {
03029     TT_CMap14   cmap14 = (TT_CMap14)cmap;
03030     FT_UInt32   count  = cmap14->num_selectors;
03031     FT_Byte*    p      = cmap->data + 10;
03032     FT_UInt32*  result;
03033     FT_UInt32   i;
03034 
03035 
03036     if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
03037       return NULL;
03038 
03039     result = cmap14->results;
03040     for ( i = 0; i < count; ++i )
03041     {
03042       result[i] = (FT_UInt32)TT_NEXT_UINT24( p );
03043       p        += 8;
03044     }
03045     result[i] = 0;
03046 
03047     return result;
03048   }
03049 
03050 
03051   FT_CALLBACK_DEF( FT_UInt32 * )
03052   tt_cmap14_char_variants( TT_CMap    cmap,
03053                            FT_Memory  memory,
03054                            FT_UInt32  charCode )
03055   {
03056     TT_CMap14   cmap14 = (TT_CMap14)  cmap;
03057     FT_UInt32   count  = cmap14->num_selectors;
03058     FT_Byte*    p      = cmap->data + 10;
03059     FT_UInt32*  q;
03060 
03061 
03062     if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
03063       return NULL;
03064 
03065     for ( q = cmap14->results; count > 0; --count )
03066     {
03067       FT_UInt32  varSel    = TT_NEXT_UINT24( p );
03068       FT_ULong   defOff    = TT_NEXT_ULONG( p );
03069       FT_ULong   nondefOff = TT_NEXT_ULONG( p );
03070 
03071 
03072       if ( ( defOff != 0                                               &&
03073              tt_cmap14_char_map_def_binary( cmap->data + defOff,
03074                                             charCode )                 ) ||
03075            ( nondefOff != 0                                            &&
03076              tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
03077                                                charCode ) != 0         ) )
03078       {
03079         q[0] = varSel;
03080         q++;
03081       }
03082     }
03083     q[0] = 0;
03084 
03085     return cmap14->results;
03086   }
03087 
03088 
03089   static FT_UInt
03090   tt_cmap14_def_char_count( FT_Byte  *p )
03091   {
03092     FT_UInt32  numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
03093     FT_UInt    tot       = 0;
03094 
03095 
03096     p += 3;  /* point to the first `cnt' field */
03097     for ( ; numRanges > 0; numRanges-- )
03098     {
03099       tot += 1 + p[0];
03100       p   += 4;
03101     }
03102 
03103     return tot;
03104   }
03105 
03106 
03107   static FT_UInt32*
03108   tt_cmap14_get_def_chars( TT_CMap     cmap,
03109                            FT_Byte*    p,
03110                            FT_Memory   memory )
03111   {
03112     TT_CMap14   cmap14 = (TT_CMap14) cmap;
03113     FT_UInt32   numRanges;
03114     FT_UInt     cnt;
03115     FT_UInt32*  q;
03116 
03117 
03118     cnt       = tt_cmap14_def_char_count( p );
03119     numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
03120 
03121     if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) )
03122       return NULL;
03123 
03124     for ( q = cmap14->results; numRanges > 0; --numRanges )
03125     {
03126       FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p );
03127 
03128 
03129       cnt = FT_NEXT_BYTE( p ) + 1;
03130       do
03131       {
03132         q[0]  = uni;
03133         uni  += 1;
03134         q    += 1;
03135       } while ( --cnt != 0 );
03136     }
03137     q[0] = 0;
03138 
03139     return cmap14->results;
03140   }
03141 
03142 
03143   static FT_UInt32*
03144   tt_cmap14_get_nondef_chars( TT_CMap     cmap,
03145                               FT_Byte    *p,
03146                               FT_Memory   memory )
03147   {
03148     TT_CMap14   cmap14 = (TT_CMap14) cmap;
03149     FT_UInt32   numMappings;
03150     FT_UInt     i;
03151     FT_UInt32  *ret;
03152 
03153 
03154     numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
03155 
03156     if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) )
03157       return NULL;
03158 
03159     ret = cmap14->results;
03160     for ( i = 0; i < numMappings; ++i )
03161     {
03162       ret[i] = (FT_UInt32)TT_NEXT_UINT24( p );
03163       p += 2;
03164     }
03165     ret[i] = 0;
03166 
03167     return ret;
03168   }
03169 
03170 
03171   FT_CALLBACK_DEF( FT_UInt32 * )
03172   tt_cmap14_variant_chars( TT_CMap    cmap,
03173                            FT_Memory  memory,
03174                            FT_UInt32  variantSelector )
03175   {
03176     FT_Byte    *p  = tt_cmap14_find_variant( cmap->data + 6,
03177                                              variantSelector );
03178     FT_UInt32  *ret;
03179     FT_Int      i;
03180     FT_ULong    defOff;
03181     FT_ULong    nondefOff;
03182 
03183 
03184     if ( !p )
03185       return NULL;
03186 
03187     defOff    = TT_NEXT_ULONG( p );
03188     nondefOff = TT_NEXT_ULONG( p );
03189 
03190     if ( defOff == 0 && nondefOff == 0 )
03191       return NULL;
03192 
03193     if ( defOff == 0 )
03194       return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
03195                                          memory );
03196     else if ( nondefOff == 0 )
03197       return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
03198                                       memory );
03199     else
03200     {
03201       /* Both a default and a non-default glyph set?  That's probably not */
03202       /* good font design, but the spec allows for it...                  */
03203       TT_CMap14  cmap14 = (TT_CMap14) cmap;
03204       FT_UInt32  numRanges;
03205       FT_UInt32  numMappings;
03206       FT_UInt32  duni;
03207       FT_UInt32  dcnt;
03208       FT_UInt32  nuni;
03209       FT_Byte*   dp;
03210       FT_UInt    di, ni, k;
03211 
03212 
03213       p  = cmap->data + nondefOff;
03214       dp = cmap->data + defOff;
03215 
03216       numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
03217       dcnt        = tt_cmap14_def_char_count( dp );
03218       numRanges   = (FT_UInt32)TT_NEXT_ULONG( dp );
03219 
03220       if ( numMappings == 0 )
03221         return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
03222                                         memory );
03223       if ( dcnt == 0 )
03224         return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
03225                                            memory );
03226 
03227       if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) )
03228         return NULL;
03229 
03230       ret  = cmap14->results;
03231       duni = (FT_UInt32)TT_NEXT_UINT24( dp );
03232       dcnt = FT_NEXT_BYTE( dp );
03233       di   = 1;
03234       nuni = (FT_UInt32)TT_NEXT_UINT24( p );
03235       p   += 2;
03236       ni   = 1;
03237       i    = 0;
03238 
03239       for ( ;; )
03240       {
03241         if ( nuni > duni + dcnt )
03242         {
03243           for ( k = 0; k <= dcnt; ++k )
03244             ret[i++] = duni + k;
03245 
03246           ++di;
03247 
03248           if ( di > numRanges )
03249             break;
03250 
03251           duni = (FT_UInt32)TT_NEXT_UINT24( dp );
03252           dcnt = FT_NEXT_BYTE( dp );
03253         }
03254         else
03255         {
03256           if ( nuni < duni )
03257             ret[i++] = nuni;
03258           /* If it is within the default range then ignore it -- */
03259           /* that should not have happened                       */
03260           ++ni;
03261           if ( ni > numMappings )
03262             break;
03263 
03264           nuni = (FT_UInt32)TT_NEXT_UINT24( p );
03265           p += 2;
03266         }
03267       }
03268 
03269       if ( ni <= numMappings )
03270       {
03271         /* If we get here then we have run out of all default ranges.   */
03272         /* We have read one non-default mapping which we haven't stored */
03273         /* and there may be others that need to be read.                */
03274         ret[i++] = nuni;
03275         while ( ni < numMappings )
03276         {
03277           ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p );
03278           p += 2;
03279           ++ni;
03280         }
03281       }
03282       else if ( di <= numRanges )
03283       {
03284         /* If we get here then we have run out of all non-default     */
03285         /* mappings.  We have read one default range which we haven't */
03286         /* stored and there may be others that need to be read.       */
03287         for ( k = 0; k <= dcnt; ++k )
03288           ret[i++] = duni + k;
03289 
03290         while ( di < numRanges )
03291         {
03292           duni = (FT_UInt32)TT_NEXT_UINT24( dp );
03293           dcnt = FT_NEXT_BYTE( dp );
03294 
03295           for ( k = 0; k <= dcnt; ++k )
03296             ret[i++] = duni + k;
03297           ++di;
03298         }
03299       }
03300 
03301       ret[i] = 0;
03302 
03303       return ret;
03304     }
03305   }
03306 
03307 
03308   FT_DEFINE_TT_CMAP(tt_cmap14_class_rec,
03309       sizeof ( TT_CMap14Rec ),
03310 
03311       (FT_CMap_InitFunc)     tt_cmap14_init,
03312       (FT_CMap_DoneFunc)     tt_cmap14_done,
03313       (FT_CMap_CharIndexFunc)tt_cmap14_char_index,
03314       (FT_CMap_CharNextFunc) tt_cmap14_char_next,
03315 
03316       /* Format 14 extension functions */
03317       (FT_CMap_CharVarIndexFunc)    tt_cmap14_char_var_index,
03318       (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
03319       (FT_CMap_VariantListFunc)     tt_cmap14_variants,
03320       (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
03321       (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars
03322     ,
03323     14,
03324     (TT_CMap_ValidateFunc)tt_cmap14_validate,
03325     (TT_CMap_Info_GetFunc)tt_cmap14_get_info
03326   )
03327 
03328 #endif /* TT_CONFIG_CMAP_FORMAT_14 */
03329 
03330 
03331 #ifndef FT_CONFIG_OPTION_PIC
03332 
03333   static const TT_CMap_Class  tt_cmap_classes[] =
03334   {
03335 #define TTCMAPCITEM(a) &a,
03336 #include "ttcmapc.h"
03337     NULL,
03338   };
03339 
03340 #else /*FT_CONFIG_OPTION_PIC*/
03341 
03342   void FT_Destroy_Class_tt_cmap_classes(FT_Library library, TT_CMap_Class* clazz)
03343   {
03344     FT_Memory memory = library->memory;
03345     if ( clazz )
03346       FT_FREE( clazz );
03347   }
03348 
03349   FT_Error FT_Create_Class_tt_cmap_classes(FT_Library library, TT_CMap_Class** output_class)
03350   {
03351     TT_CMap_Class*  clazz;
03352     TT_CMap_ClassRec* recs;
03353     FT_Error          error;
03354     FT_Memory memory = library->memory;
03355     int i = 0;
03356 
03357 #define TTCMAPCITEM(a) i++;
03358 #include "ttcmapc.h"
03359 
03360     /* allocate enough space for both the pointers +terminator and the class instances */
03361     if ( FT_ALLOC( clazz, sizeof(*clazz)*(i+1)+sizeof(TT_CMap_ClassRec)*i ) )
03362       return error;
03363 
03364     /* the location of the class instances follows the array of pointers */
03365     recs = (TT_CMap_ClassRec*) (((char*)clazz)+(sizeof(*clazz)*(i+1))); 
03366     i=0;
03367 
03368 #undef TTCMAPCITEM
03369 #define TTCMAPCITEM(a)           \
03370     FT_Init_Class_##a(&recs[i]); \
03371     clazz[i] = &recs[i];         \
03372     i++;
03373 #include "ttcmapc.h"
03374 
03375     clazz[i] = NULL;
03376 
03377     *output_class = clazz;
03378     return FT_Err_Ok;
03379   }
03380 
03381 #endif /*FT_CONFIG_OPTION_PIC*/
03382 
03383 
03384   /* parse the `cmap' table and build the corresponding TT_CMap objects */
03385   /* in the current face                                                */
03386   /*                                                                    */
03387   FT_LOCAL_DEF( FT_Error )
03388   tt_face_build_cmaps( TT_Face  face )
03389   {
03390     FT_Byte*           table = face->cmap_table;
03391     FT_Byte*           limit = table + face->cmap_size;
03392     FT_UInt volatile   num_cmaps;
03393     FT_Byte* volatile  p     = table;
03394     FT_Library         library = FT_FACE_LIBRARY(face);
03395     FT_UNUSED(library);
03396 
03397 
03398     if ( p + 4 > limit )
03399       return SFNT_Err_Invalid_Table;
03400 
03401     /* only recognize format 0 */
03402     if ( TT_NEXT_USHORT( p ) != 0 )
03403     {
03404       p -= 2;
03405       FT_ERROR(( "tt_face_build_cmaps:"
03406                  " unsupported `cmap' table format = %d\n",
03407                  TT_PEEK_USHORT( p ) ));
03408       return SFNT_Err_Invalid_Table;
03409     }
03410 
03411     num_cmaps = TT_NEXT_USHORT( p );
03412 
03413     for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
03414     {
03415       FT_CharMapRec  charmap;
03416       FT_UInt32      offset;
03417 
03418 
03419       charmap.platform_id = TT_NEXT_USHORT( p );
03420       charmap.encoding_id = TT_NEXT_USHORT( p );
03421       charmap.face        = FT_FACE( face );
03422       charmap.encoding    = FT_ENCODING_NONE;  /* will be filled later */
03423       offset              = TT_NEXT_ULONG( p );
03424 
03425       if ( offset && offset <= face->cmap_size - 2 )
03426       {
03427         FT_Byte* volatile              cmap   = table + offset;
03428         volatile FT_UInt               format = TT_PEEK_USHORT( cmap );
03429         const TT_CMap_Class* volatile  pclazz = FT_TT_CMAP_CLASSES_GET;
03430         TT_CMap_Class volatile         clazz;
03431 
03432 
03433         for ( ; *pclazz; pclazz++ )
03434         {
03435           clazz = *pclazz;
03436           if ( clazz->format == format )
03437           {
03438             volatile TT_ValidatorRec  valid;
03439             volatile FT_Error         error = SFNT_Err_Ok;
03440 
03441 
03442             ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
03443                                FT_VALIDATE_DEFAULT );
03444 
03445             valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
03446 
03447             if ( ft_setjmp(
03448               *((ft_jmp_buf*)&FT_VALIDATOR( &valid )->jump_buffer) ) == 0 )
03449             {
03450               /* validate this cmap sub-table */
03451               error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
03452             }
03453 
03454             if ( valid.validator.error == 0 )
03455             {
03456               FT_CMap  ttcmap;
03457 
03458 
03459               /* It might make sense to store the single variation selector */
03460               /* cmap somewhere special.  But it would have to be in the    */
03461               /* public FT_FaceRec, and we can't change that.               */
03462 
03463               if ( !FT_CMap_New( (FT_CMap_Class)clazz,
03464                                  cmap, &charmap, &ttcmap ) )
03465               {
03466                 /* it is simpler to directly set `flags' than adding */
03467                 /* a parameter to FT_CMap_New                        */
03468                 ((TT_CMap)ttcmap)->flags = (FT_Int)error;
03469               }
03470             }
03471             else
03472             {
03473               FT_TRACE0(( "tt_face_build_cmaps:"
03474                           " broken cmap sub-table ignored\n" ));
03475             }
03476             break;
03477           }
03478         }
03479 
03480         if ( *pclazz == NULL )
03481         {
03482           FT_TRACE0(( "tt_face_build_cmaps:"
03483                       " unsupported cmap sub-table ignored\n" ));
03484         }
03485       }
03486     }
03487 
03488     return SFNT_Err_Ok;
03489   }
03490 
03491 
03492   FT_LOCAL( FT_Error )
03493   tt_get_cmap_info( FT_CharMap    charmap,
03494                     TT_CMapInfo  *cmap_info )
03495   {
03496     FT_CMap        cmap  = (FT_CMap)charmap;
03497     TT_CMap_Class  clazz = (TT_CMap_Class)cmap->clazz;
03498 
03499 
03500     return clazz->get_cmap_info( charmap, cmap_info );
03501   }
03502 
03503 
03504 /* END */

Generated on Tue Jul 5 14:13:51 2011 for ROOT_528-00b_version by  doxygen 1.5.1