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