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