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