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