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