• 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-2020 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     if ( length < 16 )
920       FT_INVALID_TOO_SHORT;
921 
922     p        = table + 6;
923     num_segs = TT_NEXT_USHORT( p );   /* read segCountX2 */
924 
925     if ( valid->level >= FT_VALIDATE_PARANOID )
926     {
927       /* check that we have an even value here */
928       if ( num_segs & 1 )
929         FT_INVALID_DATA;
930     }
931 
932     num_segs /= 2;
933 
934     if ( length < 16 + num_segs * 2 * 4 )
935       FT_INVALID_TOO_SHORT;
936 
937     /* check the search parameters - even though we never use them */
938     /*                                                             */
939     if ( valid->level >= FT_VALIDATE_PARANOID )
940     {
941       /* check the values of `searchRange', `entrySelector', `rangeShift' */
942       FT_UInt  search_range   = TT_NEXT_USHORT( p );
943       FT_UInt  entry_selector = TT_NEXT_USHORT( p );
944       FT_UInt  range_shift    = TT_NEXT_USHORT( p );
945 
946 
947       if ( ( search_range | range_shift ) & 1 )  /* must be even values */
948         FT_INVALID_DATA;
949 
950       search_range /= 2;
951       range_shift  /= 2;
952 
953       /* `search range' is the greatest power of 2 that is <= num_segs */
954 
955       if ( search_range                > num_segs                 ||
956            search_range * 2            < num_segs                 ||
957            search_range + range_shift != num_segs                 ||
958            search_range               != ( 1U << entry_selector ) )
959         FT_INVALID_DATA;
960     }
961 
962     ends      = table   + 14;
963     starts    = table   + 16 + num_segs * 2;
964     deltas    = starts  + num_segs * 2;
965     offsets   = deltas  + num_segs * 2;
966     glyph_ids = offsets + num_segs * 2;
967 
968     /* check last segment; its end count value must be 0xFFFF */
969     if ( valid->level >= FT_VALIDATE_PARANOID )
970     {
971       p = ends + ( num_segs - 1 ) * 2;
972       if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
973         FT_INVALID_DATA;
974     }
975 
976     {
977       FT_UInt   start, end, offset, n;
978       FT_UInt   last_start = 0, last_end = 0;
979       FT_Int    delta;
980       FT_Byte*  p_start   = starts;
981       FT_Byte*  p_end     = ends;
982       FT_Byte*  p_delta   = deltas;
983       FT_Byte*  p_offset  = offsets;
984 
985 
986       for ( n = 0; n < num_segs; n++ )
987       {
988         p      = p_offset;
989         start  = TT_NEXT_USHORT( p_start );
990         end    = TT_NEXT_USHORT( p_end );
991         delta  = TT_NEXT_SHORT( p_delta );
992         offset = TT_NEXT_USHORT( p_offset );
993 
994         if ( start > end )
995           FT_INVALID_DATA;
996 
997         /* this test should be performed at default validation level; */
998         /* unfortunately, some popular Asian fonts have overlapping   */
999         /* ranges in their charmaps                                   */
1000         /*                                                            */
1001         if ( start <= last_end && n > 0 )
1002         {
1003           if ( valid->level >= FT_VALIDATE_TIGHT )
1004             FT_INVALID_DATA;
1005           else
1006           {
1007             /* allow overlapping segments, provided their start points */
1008             /* and end points, respectively, are in ascending order    */
1009             /*                                                         */
1010             if ( last_start > start || last_end > end )
1011               error |= TT_CMAP_FLAG_UNSORTED;
1012             else
1013               error |= TT_CMAP_FLAG_OVERLAPPING;
1014           }
1015         }
1016 
1017         if ( offset && offset != 0xFFFFU )
1018         {
1019           p += offset;  /* start of glyph ID array */
1020 
1021           /* check that we point within the glyph IDs table only */
1022           if ( valid->level >= FT_VALIDATE_TIGHT )
1023           {
1024             if ( p < glyph_ids                                ||
1025                  p + ( end - start + 1 ) * 2 > table + length )
1026               FT_INVALID_DATA;
1027           }
1028           /* Some fonts handle the last segment incorrectly.  In */
1029           /* theory, 0xFFFF might point to an ordinary glyph --  */
1030           /* a cmap 4 is versatile and could be used for any     */
1031           /* encoding, not only Unicode.  However, reality shows */
1032           /* that far too many fonts are sloppy and incorrectly  */
1033           /* set all fields but `start' and `end' for the last   */
1034           /* segment if it contains only a single character.     */
1035           /*                                                     */
1036           /* We thus omit the test here, delaying it to the      */
1037           /* routines that actually access the cmap.             */
1038           else if ( n != num_segs - 1                       ||
1039                     !( start == 0xFFFFU && end == 0xFFFFU ) )
1040           {
1041             if ( p < glyph_ids                              ||
1042                  p + ( end - start + 1 ) * 2 > valid->limit )
1043               FT_INVALID_DATA;
1044           }
1045 
1046           /* check glyph indices within the segment range */
1047           if ( valid->level >= FT_VALIDATE_TIGHT )
1048           {
1049             FT_UInt  i, idx;
1050 
1051 
1052             for ( i = start; i < end; i++ )
1053             {
1054               idx = FT_NEXT_USHORT( p );
1055               if ( idx != 0 )
1056               {
1057                 idx = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
1058 
1059                 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
1060                   FT_INVALID_GLYPH_ID;
1061               }
1062             }
1063           }
1064         }
1065         else if ( offset == 0xFFFFU )
1066         {
1067           /* some fonts (erroneously?) use a range offset of 0xFFFF */
1068           /* to mean missing glyph in cmap table                    */
1069           /*                                                        */
1070           if ( valid->level >= FT_VALIDATE_PARANOID    ||
1071                n != num_segs - 1                       ||
1072                !( start == 0xFFFFU && end == 0xFFFFU ) )
1073             FT_INVALID_DATA;
1074         }
1075 
1076         last_start = start;
1077         last_end   = end;
1078       }
1079     }
1080 
1081     return error;
1082   }
1083 
1084 
1085   static FT_UInt
tt_cmap4_char_map_linear(TT_CMap cmap,FT_UInt32 * pcharcode,FT_Bool next)1086   tt_cmap4_char_map_linear( TT_CMap     cmap,
1087                             FT_UInt32*  pcharcode,
1088                             FT_Bool     next )
1089   {
1090     TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
1091     FT_Byte*  limit = face->cmap_table + face->cmap_size;
1092 
1093 
1094     FT_UInt    num_segs2, start, end, offset;
1095     FT_Int     delta;
1096     FT_UInt    i, num_segs;
1097     FT_UInt32  charcode = *pcharcode;
1098     FT_UInt    gindex   = 0;
1099     FT_Byte*   p;
1100     FT_Byte*   q;
1101 
1102 
1103     p = cmap->data + 6;
1104     num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
1105 
1106     num_segs = num_segs2 >> 1;
1107 
1108     if ( !num_segs )
1109       return 0;
1110 
1111     if ( next )
1112       charcode++;
1113 
1114     if ( charcode > 0xFFFFU )
1115       return 0;
1116 
1117     /* linear search */
1118     p = cmap->data + 14;               /* ends table   */
1119     q = cmap->data + 16 + num_segs2;   /* starts table */
1120 
1121     for ( i = 0; i < num_segs; i++ )
1122     {
1123       end   = TT_NEXT_USHORT( p );
1124       start = TT_NEXT_USHORT( q );
1125 
1126       if ( charcode < start )
1127       {
1128         if ( next )
1129           charcode = start;
1130         else
1131           break;
1132       }
1133 
1134     Again:
1135       if ( charcode <= end )
1136       {
1137         FT_Byte*  r;
1138 
1139 
1140         r       = q - 2 + num_segs2;
1141         delta   = TT_PEEK_SHORT( r );
1142         r      += num_segs2;
1143         offset  = TT_PEEK_USHORT( r );
1144 
1145         /* some fonts have an incorrect last segment; */
1146         /* we have to catch it                        */
1147         if ( i >= num_segs - 1                  &&
1148              start == 0xFFFFU && end == 0xFFFFU )
1149         {
1150           if ( offset && r + offset + 2 > limit )
1151           {
1152             delta  = 1;
1153             offset = 0;
1154           }
1155         }
1156 
1157         if ( offset == 0xFFFFU )
1158           continue;
1159 
1160         if ( offset )
1161         {
1162           r += offset + ( charcode - start ) * 2;
1163 
1164           /* if r > limit, the whole segment is invalid */
1165           if ( next && r > limit )
1166             continue;
1167 
1168           gindex = TT_PEEK_USHORT( r );
1169           if ( gindex )
1170           {
1171             gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
1172             if ( gindex >= (FT_UInt)face->root.num_glyphs )
1173               gindex = 0;
1174           }
1175         }
1176         else
1177         {
1178           gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
1179 
1180           if ( next && gindex >= (FT_UInt)face->root.num_glyphs )
1181           {
1182             /* we have an invalid glyph index; if there is an overflow, */
1183             /* we can adjust `charcode', otherwise the whole segment is */
1184             /* invalid                                                  */
1185             gindex = 0;
1186 
1187             if ( (FT_Int)charcode + delta < 0 &&
1188                  (FT_Int)end + delta >= 0     )
1189               charcode = (FT_UInt)( -delta );
1190 
1191             else if ( (FT_Int)charcode + delta < 0x10000L &&
1192                       (FT_Int)end + delta >= 0x10000L     )
1193               charcode = (FT_UInt)( 0x10000L - delta );
1194 
1195             else
1196               continue;
1197           }
1198         }
1199 
1200         if ( next && !gindex )
1201         {
1202           if ( charcode >= 0xFFFFU )
1203             break;
1204 
1205           charcode++;
1206           goto Again;
1207         }
1208 
1209         break;
1210       }
1211     }
1212 
1213     if ( next )
1214       *pcharcode = charcode;
1215 
1216     return gindex;
1217   }
1218 
1219 
1220   static FT_UInt
tt_cmap4_char_map_binary(TT_CMap cmap,FT_UInt32 * pcharcode,FT_Bool next)1221   tt_cmap4_char_map_binary( TT_CMap     cmap,
1222                             FT_UInt32*  pcharcode,
1223                             FT_Bool     next )
1224   {
1225     TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
1226     FT_Byte*  limit = face->cmap_table + face->cmap_size;
1227 
1228     FT_UInt   num_segs2, start, end, offset;
1229     FT_Int    delta;
1230     FT_UInt   max, min, mid, num_segs;
1231     FT_UInt   charcode = (FT_UInt)*pcharcode;
1232     FT_UInt   gindex   = 0;
1233     FT_Byte*  p;
1234 
1235 
1236     p = cmap->data + 6;
1237     num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
1238 
1239     if ( !num_segs2 )
1240       return 0;
1241 
1242     num_segs = num_segs2 >> 1;
1243 
1244     /* make compiler happy */
1245     mid = num_segs;
1246     end = 0xFFFFU;
1247 
1248     if ( next )
1249       charcode++;
1250 
1251     min = 0;
1252     max = num_segs;
1253 
1254     /* binary search */
1255     while ( min < max )
1256     {
1257       mid    = ( min + max ) >> 1;
1258       p      = cmap->data + 14 + mid * 2;
1259       end    = TT_PEEK_USHORT( p );
1260       p     += 2 + num_segs2;
1261       start  = TT_PEEK_USHORT( p );
1262 
1263       if ( charcode < start )
1264         max = mid;
1265       else if ( charcode > end )
1266         min = mid + 1;
1267       else
1268       {
1269         p     += num_segs2;
1270         delta  = TT_PEEK_SHORT( p );
1271         p     += num_segs2;
1272         offset = TT_PEEK_USHORT( p );
1273 
1274         /* some fonts have an incorrect last segment; */
1275         /* we have to catch it                        */
1276         if ( mid >= num_segs - 1                &&
1277              start == 0xFFFFU && end == 0xFFFFU )
1278         {
1279           if ( offset && p + offset + 2 > limit )
1280           {
1281             delta  = 1;
1282             offset = 0;
1283           }
1284         }
1285 
1286         /* search the first segment containing `charcode' */
1287         if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING )
1288         {
1289           FT_UInt  i;
1290 
1291 
1292           /* call the current segment `max' */
1293           max = mid;
1294 
1295           if ( offset == 0xFFFFU )
1296             mid = max + 1;
1297 
1298           /* search in segments before the current segment */
1299           for ( i = max; i > 0; i-- )
1300           {
1301             FT_UInt   prev_end;
1302             FT_Byte*  old_p;
1303 
1304 
1305             old_p    = p;
1306             p        = cmap->data + 14 + ( i - 1 ) * 2;
1307             prev_end = TT_PEEK_USHORT( p );
1308 
1309             if ( charcode > prev_end )
1310             {
1311               p = old_p;
1312               break;
1313             }
1314 
1315             end    = prev_end;
1316             p     += 2 + num_segs2;
1317             start  = TT_PEEK_USHORT( p );
1318             p     += num_segs2;
1319             delta  = TT_PEEK_SHORT( p );
1320             p     += num_segs2;
1321             offset = TT_PEEK_USHORT( p );
1322 
1323             if ( offset != 0xFFFFU )
1324               mid = i - 1;
1325           }
1326 
1327           /* no luck */
1328           if ( mid == max + 1 )
1329           {
1330             if ( i != max )
1331             {
1332               p      = cmap->data + 14 + max * 2;
1333               end    = TT_PEEK_USHORT( p );
1334               p     += 2 + num_segs2;
1335               start  = TT_PEEK_USHORT( p );
1336               p     += num_segs2;
1337               delta  = TT_PEEK_SHORT( p );
1338               p     += num_segs2;
1339               offset = TT_PEEK_USHORT( p );
1340             }
1341 
1342             mid = max;
1343 
1344             /* search in segments after the current segment */
1345             for ( i = max + 1; i < num_segs; i++ )
1346             {
1347               FT_UInt  next_end, next_start;
1348 
1349 
1350               p          = cmap->data + 14 + i * 2;
1351               next_end   = TT_PEEK_USHORT( p );
1352               p         += 2 + num_segs2;
1353               next_start = TT_PEEK_USHORT( p );
1354 
1355               if ( charcode < next_start )
1356                 break;
1357 
1358               end    = next_end;
1359               start  = next_start;
1360               p     += num_segs2;
1361               delta  = TT_PEEK_SHORT( p );
1362               p     += num_segs2;
1363               offset = TT_PEEK_USHORT( p );
1364 
1365               if ( offset != 0xFFFFU )
1366                 mid = i;
1367             }
1368             i--;
1369 
1370             /* still no luck */
1371             if ( mid == max )
1372             {
1373               mid = i;
1374 
1375               break;
1376             }
1377           }
1378 
1379           /* end, start, delta, and offset are for the i'th segment */
1380           if ( mid != i )
1381           {
1382             p      = cmap->data + 14 + mid * 2;
1383             end    = TT_PEEK_USHORT( p );
1384             p     += 2 + num_segs2;
1385             start  = TT_PEEK_USHORT( p );
1386             p     += num_segs2;
1387             delta  = TT_PEEK_SHORT( p );
1388             p     += num_segs2;
1389             offset = TT_PEEK_USHORT( p );
1390           }
1391         }
1392         else
1393         {
1394           if ( offset == 0xFFFFU )
1395             break;
1396         }
1397 
1398         if ( offset )
1399         {
1400           p += offset + ( charcode - start ) * 2;
1401 
1402           /* if p > limit, the whole segment is invalid */
1403           if ( next && p > limit )
1404             break;
1405 
1406           gindex = TT_PEEK_USHORT( p );
1407           if ( gindex )
1408           {
1409             gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
1410             if ( gindex >= (FT_UInt)face->root.num_glyphs )
1411               gindex = 0;
1412           }
1413         }
1414         else
1415         {
1416           gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
1417 
1418           if ( next && gindex >= (FT_UInt)face->root.num_glyphs )
1419           {
1420             /* we have an invalid glyph index; if there is an overflow, */
1421             /* we can adjust `charcode', otherwise the whole segment is */
1422             /* invalid                                                  */
1423             gindex = 0;
1424 
1425             if ( (FT_Int)charcode + delta < 0 &&
1426                  (FT_Int)end + delta >= 0     )
1427               charcode = (FT_UInt)( -delta );
1428 
1429             else if ( (FT_Int)charcode + delta < 0x10000L &&
1430                       (FT_Int)end + delta >= 0x10000L     )
1431               charcode = (FT_UInt)( 0x10000L - delta );
1432           }
1433         }
1434 
1435         break;
1436       }
1437     }
1438 
1439     if ( next )
1440     {
1441       TT_CMap4  cmap4 = (TT_CMap4)cmap;
1442 
1443 
1444       /* if `charcode' is not in any segment, then `mid' is */
1445       /* the segment nearest to `charcode'                  */
1446 
1447       if ( charcode > end )
1448       {
1449         mid++;
1450         if ( mid == num_segs )
1451           return 0;
1452       }
1453 
1454       if ( tt_cmap4_set_range( cmap4, mid ) )
1455       {
1456         if ( gindex )
1457           *pcharcode = charcode;
1458       }
1459       else
1460       {
1461         cmap4->cur_charcode = charcode;
1462 
1463         if ( gindex )
1464           cmap4->cur_gindex = gindex;
1465         else
1466         {
1467           cmap4->cur_charcode = charcode;
1468           tt_cmap4_next( cmap4 );
1469           gindex = cmap4->cur_gindex;
1470         }
1471 
1472         if ( gindex )
1473           *pcharcode = cmap4->cur_charcode;
1474       }
1475     }
1476 
1477     return gindex;
1478   }
1479 
1480 
1481   FT_CALLBACK_DEF( FT_UInt )
tt_cmap4_char_index(TT_CMap cmap,FT_UInt32 char_code)1482   tt_cmap4_char_index( TT_CMap    cmap,
1483                        FT_UInt32  char_code )
1484   {
1485     if ( char_code >= 0x10000UL )
1486       return 0;
1487 
1488     if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
1489       return tt_cmap4_char_map_linear( cmap, &char_code, 0 );
1490     else
1491       return tt_cmap4_char_map_binary( cmap, &char_code, 0 );
1492   }
1493 
1494 
1495   FT_CALLBACK_DEF( FT_UInt32 )
tt_cmap4_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)1496   tt_cmap4_char_next( TT_CMap     cmap,
1497                       FT_UInt32  *pchar_code )
1498   {
1499     FT_UInt  gindex;
1500 
1501 
1502     if ( *pchar_code >= 0xFFFFU )
1503       return 0;
1504 
1505     if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
1506       gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 );
1507     else
1508     {
1509       TT_CMap4  cmap4 = (TT_CMap4)cmap;
1510 
1511 
1512       /* no need to search */
1513       if ( *pchar_code == cmap4->cur_charcode )
1514       {
1515         tt_cmap4_next( cmap4 );
1516         gindex = cmap4->cur_gindex;
1517         if ( gindex )
1518           *pchar_code = cmap4->cur_charcode;
1519       }
1520       else
1521         gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 );
1522     }
1523 
1524     return gindex;
1525   }
1526 
1527 
1528   FT_CALLBACK_DEF( FT_Error )
tt_cmap4_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)1529   tt_cmap4_get_info( TT_CMap       cmap,
1530                      TT_CMapInfo  *cmap_info )
1531   {
1532     FT_Byte*  p = cmap->data + 4;
1533 
1534 
1535     cmap_info->format   = 4;
1536     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1537 
1538     return FT_Err_Ok;
1539   }
1540 
1541 
1542   FT_DEFINE_TT_CMAP(
1543     tt_cmap4_class_rec,
1544 
1545       sizeof ( TT_CMap4Rec ),
1546 
1547       (FT_CMap_InitFunc)     tt_cmap4_init,        /* init       */
1548       (FT_CMap_DoneFunc)     NULL,                 /* done       */
1549       (FT_CMap_CharIndexFunc)tt_cmap4_char_index,  /* char_index */
1550       (FT_CMap_CharNextFunc) tt_cmap4_char_next,   /* char_next  */
1551 
1552       (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
1553       (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
1554       (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
1555       (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
1556       (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
1557 
1558     4,
1559     (TT_CMap_ValidateFunc)tt_cmap4_validate,  /* validate      */
1560     (TT_CMap_Info_GetFunc)tt_cmap4_get_info   /* get_cmap_info */
1561   )
1562 
1563 #endif /* TT_CONFIG_CMAP_FORMAT_4 */
1564 
1565 
1566   /*************************************************************************/
1567   /*************************************************************************/
1568   /*****                                                               *****/
1569   /*****                          FORMAT 6                             *****/
1570   /*****                                                               *****/
1571   /*************************************************************************/
1572   /*************************************************************************/
1573 
1574   /**************************************************************************
1575    *
1576    * TABLE OVERVIEW
1577    * --------------
1578    *
1579    *   NAME        OFFSET          TYPE             DESCRIPTION
1580    *
1581    *   format       0              USHORT           must be 6
1582    *   length       2              USHORT           table length in bytes
1583    *   language     4              USHORT           Mac language code
1584    *
1585    *   first        6              USHORT           first segment code
1586    *   count        8              USHORT           segment size in chars
1587    *   glyphIds     10             USHORT[count]    glyph IDs
1588    *
1589    * A very simplified segment mapping.
1590    */
1591 
1592 #ifdef TT_CONFIG_CMAP_FORMAT_6
1593 
FT_CALLBACK_DEF(FT_Error)1594   FT_CALLBACK_DEF( FT_Error )
1595   tt_cmap6_validate( FT_Byte*      table,
1596                      FT_Validator  valid )
1597   {
1598     FT_Byte*  p;
1599     FT_UInt   length, count;
1600 
1601 
1602     if ( table + 10 > valid->limit )
1603       FT_INVALID_TOO_SHORT;
1604 
1605     p      = table + 2;
1606     length = TT_NEXT_USHORT( p );
1607 
1608     p      = table + 8;             /* skip language and start index */
1609     count  = TT_NEXT_USHORT( p );
1610 
1611     if ( table + length > valid->limit || length < 10 + count * 2 )
1612       FT_INVALID_TOO_SHORT;
1613 
1614     /* check glyph indices */
1615     if ( valid->level >= FT_VALIDATE_TIGHT )
1616     {
1617       FT_UInt  gindex;
1618 
1619 
1620       for ( ; count > 0; count-- )
1621       {
1622         gindex = TT_NEXT_USHORT( p );
1623         if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1624           FT_INVALID_GLYPH_ID;
1625       }
1626     }
1627 
1628     return FT_Err_Ok;
1629   }
1630 
1631 
1632   FT_CALLBACK_DEF( FT_UInt )
tt_cmap6_char_index(TT_CMap cmap,FT_UInt32 char_code)1633   tt_cmap6_char_index( TT_CMap    cmap,
1634                        FT_UInt32  char_code )
1635   {
1636     FT_Byte*  table  = cmap->data;
1637     FT_UInt   result = 0;
1638     FT_Byte*  p      = table + 6;
1639     FT_UInt   start  = TT_NEXT_USHORT( p );
1640     FT_UInt   count  = TT_NEXT_USHORT( p );
1641     FT_UInt   idx    = (FT_UInt)( char_code - start );
1642 
1643 
1644     if ( idx < count )
1645     {
1646       p += 2 * idx;
1647       result = TT_PEEK_USHORT( p );
1648     }
1649 
1650     return result;
1651   }
1652 
1653 
1654   FT_CALLBACK_DEF( FT_UInt32 )
tt_cmap6_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)1655   tt_cmap6_char_next( TT_CMap     cmap,
1656                       FT_UInt32  *pchar_code )
1657   {
1658     FT_Byte*   table     = cmap->data;
1659     FT_UInt32  result    = 0;
1660     FT_UInt32  char_code = *pchar_code + 1;
1661     FT_UInt    gindex    = 0;
1662 
1663     FT_Byte*   p         = table + 6;
1664     FT_UInt    start     = TT_NEXT_USHORT( p );
1665     FT_UInt    count     = TT_NEXT_USHORT( p );
1666     FT_UInt    idx;
1667 
1668 
1669     if ( char_code >= 0x10000UL )
1670       return 0;
1671 
1672     if ( char_code < start )
1673       char_code = start;
1674 
1675     idx = (FT_UInt)( char_code - start );
1676     p  += 2 * idx;
1677 
1678     for ( ; idx < count; idx++ )
1679     {
1680       gindex = TT_NEXT_USHORT( p );
1681       if ( gindex != 0 )
1682       {
1683         result = char_code;
1684         break;
1685       }
1686 
1687       if ( char_code >= 0xFFFFU )
1688         return 0;
1689 
1690       char_code++;
1691     }
1692 
1693     *pchar_code = result;
1694     return gindex;
1695   }
1696 
1697 
1698   FT_CALLBACK_DEF( FT_Error )
tt_cmap6_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)1699   tt_cmap6_get_info( TT_CMap       cmap,
1700                      TT_CMapInfo  *cmap_info )
1701   {
1702     FT_Byte*  p = cmap->data + 4;
1703 
1704 
1705     cmap_info->format   = 6;
1706     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1707 
1708     return FT_Err_Ok;
1709   }
1710 
1711 
1712   FT_DEFINE_TT_CMAP(
1713     tt_cmap6_class_rec,
1714 
1715       sizeof ( TT_CMapRec ),
1716 
1717       (FT_CMap_InitFunc)     tt_cmap_init,         /* init       */
1718       (FT_CMap_DoneFunc)     NULL,                 /* done       */
1719       (FT_CMap_CharIndexFunc)tt_cmap6_char_index,  /* char_index */
1720       (FT_CMap_CharNextFunc) tt_cmap6_char_next,   /* char_next  */
1721 
1722       (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
1723       (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
1724       (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
1725       (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
1726       (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
1727 
1728     6,
1729     (TT_CMap_ValidateFunc)tt_cmap6_validate,  /* validate      */
1730     (TT_CMap_Info_GetFunc)tt_cmap6_get_info   /* get_cmap_info */
1731   )
1732 
1733 #endif /* TT_CONFIG_CMAP_FORMAT_6 */
1734 
1735 
1736   /*************************************************************************/
1737   /*************************************************************************/
1738   /*****                                                               *****/
1739   /*****                          FORMAT 8                             *****/
1740   /*****                                                               *****/
1741   /***** It is hard to completely understand what the OpenType spec    *****/
1742   /***** says about this format, but here is my conclusion.            *****/
1743   /*****                                                               *****/
1744   /***** The purpose of this format is to easily map UTF-16 text to    *****/
1745   /***** glyph indices.  Basically, the `char_code' must be in one of  *****/
1746   /***** the following formats.                                        *****/
1747   /*****                                                               *****/
1748   /*****   - A 16-bit value that isn't part of the Unicode Surrogates  *****/
1749   /*****     Area (i.e. U+D800-U+DFFF).                                *****/
1750   /*****                                                               *****/
1751   /*****   - A 32-bit value, made of two surrogate values, i.e.. if    *****/
1752   /*****     `char_code = (char_hi << 16) | char_lo', then both        *****/
1753   /*****     `char_hi' and `char_lo' must be in the Surrogates Area.   *****/
1754   /*****      Area.                                                    *****/
1755   /*****                                                               *****/
1756   /***** The `is32' table embedded in the charmap indicates whether a  *****/
1757   /***** given 16-bit value is in the surrogates area or not.          *****/
1758   /*****                                                               *****/
1759   /***** So, for any given `char_code', we can assert the following.   *****/
1760   /*****                                                               *****/
1761   /*****   If `char_hi == 0' then we must have `is32[char_lo] == 0'.   *****/
1762   /*****                                                               *****/
1763   /*****   If `char_hi != 0' then we must have both                    *****/
1764   /*****   `is32[char_hi] != 0' and `is32[char_lo] != 0'.              *****/
1765   /*****                                                               *****/
1766   /*************************************************************************/
1767   /*************************************************************************/
1768 
1769   /**************************************************************************
1770    *
1771    * TABLE OVERVIEW
1772    * --------------
1773    *
1774    *   NAME        OFFSET         TYPE        DESCRIPTION
1775    *
1776    *   format      0              USHORT      must be 8
1777    *   reserved    2              USHORT      reserved
1778    *   length      4              ULONG       length in bytes
1779    *   language    8              ULONG       Mac language code
1780    *   is32        12             BYTE[8192]  32-bitness bitmap
1781    *   count       8204           ULONG       number of groups
1782    *
1783    * This header is followed by `count' groups of the following format:
1784    *
1785    *   start       0              ULONG       first charcode
1786    *   end         4              ULONG       last charcode
1787    *   startId     8              ULONG       start glyph ID for the group
1788    */
1789 
1790 #ifdef TT_CONFIG_CMAP_FORMAT_8
1791 
FT_CALLBACK_DEF(FT_Error)1792   FT_CALLBACK_DEF( FT_Error )
1793   tt_cmap8_validate( FT_Byte*      table,
1794                      FT_Validator  valid )
1795   {
1796     FT_Byte*   p = table + 4;
1797     FT_Byte*   is32;
1798     FT_UInt32  length;
1799     FT_UInt32  num_groups;
1800 
1801 
1802     if ( table + 16 + 8192 > valid->limit )
1803       FT_INVALID_TOO_SHORT;
1804 
1805     length = TT_NEXT_ULONG( p );
1806     if ( length > (FT_UInt32)( valid->limit - table ) || length < 8192 + 16 )
1807       FT_INVALID_TOO_SHORT;
1808 
1809     is32       = table + 12;
1810     p          = is32  + 8192;          /* skip `is32' array */
1811     num_groups = TT_NEXT_ULONG( p );
1812 
1813     /* p + num_groups * 12 > valid->limit ? */
1814     if ( num_groups > (FT_UInt32)( valid->limit - p ) / 12 )
1815       FT_INVALID_TOO_SHORT;
1816 
1817     /* check groups, they must be in increasing order */
1818     {
1819       FT_UInt32  n, start, end, start_id, count, last = 0;
1820 
1821 
1822       for ( n = 0; n < num_groups; n++ )
1823       {
1824         FT_UInt   hi, lo;
1825 
1826 
1827         start    = TT_NEXT_ULONG( p );
1828         end      = TT_NEXT_ULONG( p );
1829         start_id = TT_NEXT_ULONG( p );
1830 
1831         if ( start > end )
1832           FT_INVALID_DATA;
1833 
1834         if ( n > 0 && start <= last )
1835           FT_INVALID_DATA;
1836 
1837         if ( valid->level >= FT_VALIDATE_TIGHT )
1838         {
1839           FT_UInt32  d = end - start;
1840 
1841 
1842           /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
1843           if ( d > TT_VALID_GLYPH_COUNT( valid )             ||
1844                start_id >= TT_VALID_GLYPH_COUNT( valid ) - d )
1845             FT_INVALID_GLYPH_ID;
1846 
1847           count = (FT_UInt32)( end - start + 1 );
1848 
1849           if ( start & ~0xFFFFU )
1850           {
1851             /* start_hi != 0; check that is32[i] is 1 for each i in */
1852             /* the `hi' and `lo' of the range [start..end]          */
1853             for ( ; count > 0; count--, start++ )
1854             {
1855               hi = (FT_UInt)( start >> 16 );
1856               lo = (FT_UInt)( start & 0xFFFFU );
1857 
1858               if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
1859                 FT_INVALID_DATA;
1860 
1861               if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
1862                 FT_INVALID_DATA;
1863             }
1864           }
1865           else
1866           {
1867             /* start_hi == 0; check that is32[i] is 0 for each i in */
1868             /* the range [start..end]                               */
1869 
1870             /* end_hi cannot be != 0! */
1871             if ( end & ~0xFFFFU )
1872               FT_INVALID_DATA;
1873 
1874             for ( ; count > 0; count--, start++ )
1875             {
1876               lo = (FT_UInt)( start & 0xFFFFU );
1877 
1878               if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
1879                 FT_INVALID_DATA;
1880             }
1881           }
1882         }
1883 
1884         last = end;
1885       }
1886     }
1887 
1888     return FT_Err_Ok;
1889   }
1890 
1891 
1892   FT_CALLBACK_DEF( FT_UInt )
tt_cmap8_char_index(TT_CMap cmap,FT_UInt32 char_code)1893   tt_cmap8_char_index( TT_CMap    cmap,
1894                        FT_UInt32  char_code )
1895   {
1896     FT_Byte*   table      = cmap->data;
1897     FT_UInt    result     = 0;
1898     FT_Byte*   p          = table + 8204;
1899     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1900     FT_UInt32  start, end, start_id;
1901 
1902 
1903     for ( ; num_groups > 0; num_groups-- )
1904     {
1905       start    = TT_NEXT_ULONG( p );
1906       end      = TT_NEXT_ULONG( p );
1907       start_id = TT_NEXT_ULONG( p );
1908 
1909       if ( char_code < start )
1910         break;
1911 
1912       if ( char_code <= end )
1913       {
1914         if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
1915           return 0;
1916 
1917         result = (FT_UInt)( start_id + ( char_code - start ) );
1918         break;
1919       }
1920     }
1921     return result;
1922   }
1923 
1924 
1925   FT_CALLBACK_DEF( FT_UInt32 )
tt_cmap8_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)1926   tt_cmap8_char_next( TT_CMap     cmap,
1927                       FT_UInt32  *pchar_code )
1928   {
1929     FT_Face    face       = cmap->cmap.charmap.face;
1930     FT_UInt32  result     = 0;
1931     FT_UInt32  char_code;
1932     FT_UInt    gindex     = 0;
1933     FT_Byte*   table      = cmap->data;
1934     FT_Byte*   p          = table + 8204;
1935     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1936     FT_UInt32  start, end, start_id;
1937 
1938 
1939     if ( *pchar_code >= 0xFFFFFFFFUL )
1940       return 0;
1941 
1942     char_code = *pchar_code + 1;
1943 
1944     p = table + 8208;
1945 
1946     for ( ; num_groups > 0; num_groups-- )
1947     {
1948       start    = TT_NEXT_ULONG( p );
1949       end      = TT_NEXT_ULONG( p );
1950       start_id = TT_NEXT_ULONG( p );
1951 
1952       if ( char_code < start )
1953         char_code = start;
1954 
1955     Again:
1956       if ( char_code <= end )
1957       {
1958         /* ignore invalid group */
1959         if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
1960           continue;
1961 
1962         gindex = (FT_UInt)( start_id + ( char_code - start ) );
1963 
1964         /* does first element of group point to `.notdef' glyph? */
1965         if ( gindex == 0 )
1966         {
1967           if ( char_code >= 0xFFFFFFFFUL )
1968             break;
1969 
1970           char_code++;
1971           goto Again;
1972         }
1973 
1974         /* if `gindex' is invalid, the remaining values */
1975         /* in this group are invalid, too               */
1976         if ( gindex >= (FT_UInt)face->num_glyphs )
1977         {
1978           gindex = 0;
1979           continue;
1980         }
1981 
1982         result = char_code;
1983         break;
1984       }
1985     }
1986 
1987     *pchar_code = result;
1988     return gindex;
1989   }
1990 
1991 
1992   FT_CALLBACK_DEF( FT_Error )
tt_cmap8_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)1993   tt_cmap8_get_info( TT_CMap       cmap,
1994                      TT_CMapInfo  *cmap_info )
1995   {
1996     FT_Byte*  p = cmap->data + 8;
1997 
1998 
1999     cmap_info->format   = 8;
2000     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2001 
2002     return FT_Err_Ok;
2003   }
2004 
2005 
2006   FT_DEFINE_TT_CMAP(
2007     tt_cmap8_class_rec,
2008 
2009       sizeof ( TT_CMapRec ),
2010 
2011       (FT_CMap_InitFunc)     tt_cmap_init,         /* init       */
2012       (FT_CMap_DoneFunc)     NULL,                 /* done       */
2013       (FT_CMap_CharIndexFunc)tt_cmap8_char_index,  /* char_index */
2014       (FT_CMap_CharNextFunc) tt_cmap8_char_next,   /* char_next  */
2015 
2016       (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
2017       (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
2018       (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
2019       (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
2020       (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
2021 
2022     8,
2023     (TT_CMap_ValidateFunc)tt_cmap8_validate,  /* validate      */
2024     (TT_CMap_Info_GetFunc)tt_cmap8_get_info   /* get_cmap_info */
2025   )
2026 
2027 #endif /* TT_CONFIG_CMAP_FORMAT_8 */
2028 
2029 
2030   /*************************************************************************/
2031   /*************************************************************************/
2032   /*****                                                               *****/
2033   /*****                          FORMAT 10                            *****/
2034   /*****                                                               *****/
2035   /*************************************************************************/
2036   /*************************************************************************/
2037 
2038   /**************************************************************************
2039    *
2040    * TABLE OVERVIEW
2041    * --------------
2042    *
2043    *   NAME      OFFSET  TYPE               DESCRIPTION
2044    *
2045    *   format     0      USHORT             must be 10
2046    *   reserved   2      USHORT             reserved
2047    *   length     4      ULONG              length in bytes
2048    *   language   8      ULONG              Mac language code
2049    *
2050    *   start     12      ULONG              first char in range
2051    *   count     16      ULONG              number of chars in range
2052    *   glyphIds  20      USHORT[count]      glyph indices covered
2053    */
2054 
2055 #ifdef TT_CONFIG_CMAP_FORMAT_10
2056 
FT_CALLBACK_DEF(FT_Error)2057   FT_CALLBACK_DEF( FT_Error )
2058   tt_cmap10_validate( FT_Byte*      table,
2059                       FT_Validator  valid )
2060   {
2061     FT_Byte*  p = table + 4;
2062     FT_ULong  length, count;
2063 
2064 
2065     if ( table + 20 > valid->limit )
2066       FT_INVALID_TOO_SHORT;
2067 
2068     length = TT_NEXT_ULONG( p );
2069     p      = table + 16;
2070     count  = TT_NEXT_ULONG( p );
2071 
2072     if ( length > (FT_ULong)( valid->limit - table ) ||
2073          /* length < 20 + count * 2 ? */
2074          length < 20                                 ||
2075          ( length - 20 ) / 2 < count                 )
2076       FT_INVALID_TOO_SHORT;
2077 
2078     /* check glyph indices */
2079     if ( valid->level >= FT_VALIDATE_TIGHT )
2080     {
2081       FT_UInt  gindex;
2082 
2083 
2084       for ( ; count > 0; count-- )
2085       {
2086         gindex = TT_NEXT_USHORT( p );
2087         if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
2088           FT_INVALID_GLYPH_ID;
2089       }
2090     }
2091 
2092     return FT_Err_Ok;
2093   }
2094 
2095 
2096   FT_CALLBACK_DEF( FT_UInt )
tt_cmap10_char_index(TT_CMap cmap,FT_UInt32 char_code)2097   tt_cmap10_char_index( TT_CMap    cmap,
2098                         FT_UInt32  char_code )
2099   {
2100     FT_Byte*   table  = cmap->data;
2101     FT_UInt    result = 0;
2102     FT_Byte*   p      = table + 12;
2103     FT_UInt32  start  = TT_NEXT_ULONG( p );
2104     FT_UInt32  count  = TT_NEXT_ULONG( p );
2105     FT_UInt32  idx;
2106 
2107 
2108     if ( char_code < start )
2109       return 0;
2110 
2111     idx = char_code - start;
2112 
2113     if ( idx < count )
2114     {
2115       p     += 2 * idx;
2116       result = TT_PEEK_USHORT( p );
2117     }
2118 
2119     return result;
2120   }
2121 
2122 
2123   FT_CALLBACK_DEF( FT_UInt32 )
tt_cmap10_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)2124   tt_cmap10_char_next( TT_CMap     cmap,
2125                        FT_UInt32  *pchar_code )
2126   {
2127     FT_Byte*   table     = cmap->data;
2128     FT_UInt32  char_code;
2129     FT_UInt    gindex    = 0;
2130     FT_Byte*   p         = table + 12;
2131     FT_UInt32  start     = TT_NEXT_ULONG( p );
2132     FT_UInt32  count     = TT_NEXT_ULONG( p );
2133     FT_UInt32  idx;
2134 
2135 
2136     if ( *pchar_code >= 0xFFFFFFFFUL )
2137       return 0;
2138 
2139     char_code = *pchar_code + 1;
2140 
2141     if ( char_code < start )
2142       char_code = start;
2143 
2144     idx = char_code - start;
2145     p  += 2 * idx;
2146 
2147     for ( ; idx < count; idx++ )
2148     {
2149       gindex = TT_NEXT_USHORT( p );
2150       if ( gindex != 0 )
2151         break;
2152 
2153       if ( char_code >= 0xFFFFFFFFUL )
2154         return 0;
2155 
2156       char_code++;
2157     }
2158 
2159     *pchar_code = char_code;
2160     return gindex;
2161   }
2162 
2163 
2164   FT_CALLBACK_DEF( FT_Error )
tt_cmap10_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)2165   tt_cmap10_get_info( TT_CMap       cmap,
2166                       TT_CMapInfo  *cmap_info )
2167   {
2168     FT_Byte*  p = cmap->data + 8;
2169 
2170 
2171     cmap_info->format   = 10;
2172     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2173 
2174     return FT_Err_Ok;
2175   }
2176 
2177 
2178   FT_DEFINE_TT_CMAP(
2179     tt_cmap10_class_rec,
2180 
2181       sizeof ( TT_CMapRec ),
2182 
2183       (FT_CMap_InitFunc)     tt_cmap_init,          /* init       */
2184       (FT_CMap_DoneFunc)     NULL,                  /* done       */
2185       (FT_CMap_CharIndexFunc)tt_cmap10_char_index,  /* char_index */
2186       (FT_CMap_CharNextFunc) tt_cmap10_char_next,   /* char_next  */
2187 
2188       (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
2189       (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
2190       (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
2191       (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
2192       (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
2193 
2194     10,
2195     (TT_CMap_ValidateFunc)tt_cmap10_validate,  /* validate      */
2196     (TT_CMap_Info_GetFunc)tt_cmap10_get_info   /* get_cmap_info */
2197   )
2198 
2199 #endif /* TT_CONFIG_CMAP_FORMAT_10 */
2200 
2201 
2202   /*************************************************************************/
2203   /*************************************************************************/
2204   /*****                                                               *****/
2205   /*****                          FORMAT 12                            *****/
2206   /*****                                                               *****/
2207   /*************************************************************************/
2208   /*************************************************************************/
2209 
2210   /**************************************************************************
2211    *
2212    * TABLE OVERVIEW
2213    * --------------
2214    *
2215    *   NAME        OFFSET     TYPE       DESCRIPTION
2216    *
2217    *   format      0          USHORT     must be 12
2218    *   reserved    2          USHORT     reserved
2219    *   length      4          ULONG      length in bytes
2220    *   language    8          ULONG      Mac language code
2221    *   count       12         ULONG      number of groups
2222    *               16
2223    *
2224    * This header is followed by `count' groups of the following format:
2225    *
2226    *   start       0          ULONG      first charcode
2227    *   end         4          ULONG      last charcode
2228    *   startId     8          ULONG      start glyph ID for the group
2229    */
2230 
2231 #ifdef TT_CONFIG_CMAP_FORMAT_12
2232 
2233   typedef struct  TT_CMap12Rec_
2234   {
2235     TT_CMapRec  cmap;
2236     FT_Bool     valid;
2237     FT_ULong    cur_charcode;
2238     FT_UInt     cur_gindex;
2239     FT_ULong    cur_group;
2240     FT_ULong    num_groups;
2241 
2242   } TT_CMap12Rec, *TT_CMap12;
2243 
2244 
2245   FT_CALLBACK_DEF( FT_Error )
tt_cmap12_init(TT_CMap12 cmap,FT_Byte * table)2246   tt_cmap12_init( TT_CMap12  cmap,
2247                   FT_Byte*   table )
2248   {
2249     cmap->cmap.data  = table;
2250 
2251     table           += 12;
2252     cmap->num_groups = FT_PEEK_ULONG( table );
2253 
2254     cmap->valid      = 0;
2255 
2256     return FT_Err_Ok;
2257   }
2258 
2259 
2260   FT_CALLBACK_DEF( FT_Error )
tt_cmap12_validate(FT_Byte * table,FT_Validator valid)2261   tt_cmap12_validate( FT_Byte*      table,
2262                       FT_Validator  valid )
2263   {
2264     FT_Byte*  p;
2265     FT_ULong  length;
2266     FT_ULong  num_groups;
2267 
2268 
2269     if ( table + 16 > valid->limit )
2270       FT_INVALID_TOO_SHORT;
2271 
2272     p      = table + 4;
2273     length = TT_NEXT_ULONG( p );
2274 
2275     p          = table + 12;
2276     num_groups = TT_NEXT_ULONG( p );
2277 
2278     if ( length > (FT_ULong)( valid->limit - table ) ||
2279          /* length < 16 + 12 * num_groups ? */
2280          length < 16                                 ||
2281          ( length - 16 ) / 12 < num_groups           )
2282       FT_INVALID_TOO_SHORT;
2283 
2284     /* check groups, they must be in increasing order */
2285     {
2286       FT_ULong  n, start, end, start_id, last = 0;
2287 
2288 
2289       for ( n = 0; n < num_groups; n++ )
2290       {
2291         start    = TT_NEXT_ULONG( p );
2292         end      = TT_NEXT_ULONG( p );
2293         start_id = TT_NEXT_ULONG( p );
2294 
2295         if ( start > end )
2296           FT_INVALID_DATA;
2297 
2298         if ( n > 0 && start <= last )
2299           FT_INVALID_DATA;
2300 
2301         if ( valid->level >= FT_VALIDATE_TIGHT )
2302         {
2303           FT_UInt32  d = end - start;
2304 
2305 
2306           /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
2307           if ( d > TT_VALID_GLYPH_COUNT( valid )             ||
2308                start_id >= TT_VALID_GLYPH_COUNT( valid ) - d )
2309             FT_INVALID_GLYPH_ID;
2310         }
2311 
2312         last = end;
2313       }
2314     }
2315 
2316     return FT_Err_Ok;
2317   }
2318 
2319 
2320   /* search the index of the charcode next to cmap->cur_charcode */
2321   /* cmap->cur_group should be set up properly by caller         */
2322   /*                                                             */
2323   static void
tt_cmap12_next(TT_CMap12 cmap)2324   tt_cmap12_next( TT_CMap12  cmap )
2325   {
2326     FT_Face   face = cmap->cmap.cmap.charmap.face;
2327     FT_Byte*  p;
2328     FT_ULong  start, end, start_id, char_code;
2329     FT_ULong  n;
2330     FT_UInt   gindex;
2331 
2332 
2333     if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
2334       goto Fail;
2335 
2336     char_code = cmap->cur_charcode + 1;
2337 
2338     for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
2339     {
2340       p        = cmap->cmap.data + 16 + 12 * n;
2341       start    = TT_NEXT_ULONG( p );
2342       end      = TT_NEXT_ULONG( p );
2343       start_id = TT_PEEK_ULONG( p );
2344 
2345       if ( char_code < start )
2346         char_code = start;
2347 
2348     Again:
2349       if ( char_code <= end )
2350       {
2351         /* ignore invalid group */
2352         if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
2353           continue;
2354 
2355         gindex = (FT_UInt)( start_id + ( char_code - start ) );
2356 
2357         /* does first element of group point to `.notdef' glyph? */
2358         if ( gindex == 0 )
2359         {
2360           if ( char_code >= 0xFFFFFFFFUL )
2361             goto Fail;
2362 
2363           char_code++;
2364           goto Again;
2365         }
2366 
2367         /* if `gindex' is invalid, the remaining values */
2368         /* in this group are invalid, too               */
2369         if ( gindex >= (FT_UInt)face->num_glyphs )
2370           continue;
2371 
2372         cmap->cur_charcode = char_code;
2373         cmap->cur_gindex   = gindex;
2374         cmap->cur_group    = n;
2375 
2376         return;
2377       }
2378     }
2379 
2380   Fail:
2381     cmap->valid = 0;
2382   }
2383 
2384 
2385   static FT_UInt
tt_cmap12_char_map_binary(TT_CMap cmap,FT_UInt32 * pchar_code,FT_Bool next)2386   tt_cmap12_char_map_binary( TT_CMap     cmap,
2387                              FT_UInt32*  pchar_code,
2388                              FT_Bool     next )
2389   {
2390     FT_UInt    gindex     = 0;
2391     FT_Byte*   p          = cmap->data + 12;
2392     FT_UInt32  num_groups = TT_PEEK_ULONG( p );
2393     FT_UInt32  char_code  = *pchar_code;
2394     FT_UInt32  start, end, start_id;
2395     FT_UInt32  max, min, mid;
2396 
2397 
2398     if ( !num_groups )
2399       return 0;
2400 
2401     /* make compiler happy */
2402     mid = num_groups;
2403     end = 0xFFFFFFFFUL;
2404 
2405     if ( next )
2406     {
2407       if ( char_code >= 0xFFFFFFFFUL )
2408         return 0;
2409 
2410       char_code++;
2411     }
2412 
2413     min = 0;
2414     max = num_groups;
2415 
2416     /* binary search */
2417     while ( min < max )
2418     {
2419       mid = ( min + max ) >> 1;
2420       p   = cmap->data + 16 + 12 * mid;
2421 
2422       start = TT_NEXT_ULONG( p );
2423       end   = TT_NEXT_ULONG( p );
2424 
2425       if ( char_code < start )
2426         max = mid;
2427       else if ( char_code > end )
2428         min = mid + 1;
2429       else
2430       {
2431         start_id = TT_PEEK_ULONG( p );
2432 
2433         /* reject invalid glyph index */
2434         if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
2435           gindex = 0;
2436         else
2437           gindex = (FT_UInt)( start_id + ( char_code - start ) );
2438         break;
2439       }
2440     }
2441 
2442     if ( next )
2443     {
2444       FT_Face    face   = cmap->cmap.charmap.face;
2445       TT_CMap12  cmap12 = (TT_CMap12)cmap;
2446 
2447 
2448       /* if `char_code' is not in any group, then `mid' is */
2449       /* the group nearest to `char_code'                  */
2450 
2451       if ( char_code > end )
2452       {
2453         mid++;
2454         if ( mid == num_groups )
2455           return 0;
2456       }
2457 
2458       cmap12->valid        = 1;
2459       cmap12->cur_charcode = char_code;
2460       cmap12->cur_group    = mid;
2461 
2462       if ( gindex >= (FT_UInt)face->num_glyphs )
2463         gindex = 0;
2464 
2465       if ( !gindex )
2466       {
2467         tt_cmap12_next( cmap12 );
2468 
2469         if ( cmap12->valid )
2470           gindex = cmap12->cur_gindex;
2471       }
2472       else
2473         cmap12->cur_gindex = gindex;
2474 
2475       *pchar_code = cmap12->cur_charcode;
2476     }
2477 
2478     return gindex;
2479   }
2480 
2481 
2482   FT_CALLBACK_DEF( FT_UInt )
tt_cmap12_char_index(TT_CMap cmap,FT_UInt32 char_code)2483   tt_cmap12_char_index( TT_CMap    cmap,
2484                         FT_UInt32  char_code )
2485   {
2486     return tt_cmap12_char_map_binary( cmap, &char_code, 0 );
2487   }
2488 
2489 
2490   FT_CALLBACK_DEF( FT_UInt32 )
tt_cmap12_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)2491   tt_cmap12_char_next( TT_CMap     cmap,
2492                        FT_UInt32  *pchar_code )
2493   {
2494     TT_CMap12  cmap12 = (TT_CMap12)cmap;
2495     FT_UInt    gindex;
2496 
2497 
2498     /* no need to search */
2499     if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
2500     {
2501       tt_cmap12_next( cmap12 );
2502       if ( cmap12->valid )
2503       {
2504         gindex      = cmap12->cur_gindex;
2505         *pchar_code = (FT_UInt32)cmap12->cur_charcode;
2506       }
2507       else
2508         gindex = 0;
2509     }
2510     else
2511       gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
2512 
2513     return gindex;
2514   }
2515 
2516 
2517   FT_CALLBACK_DEF( FT_Error )
tt_cmap12_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)2518   tt_cmap12_get_info( TT_CMap       cmap,
2519                       TT_CMapInfo  *cmap_info )
2520   {
2521     FT_Byte*  p = cmap->data + 8;
2522 
2523 
2524     cmap_info->format   = 12;
2525     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2526 
2527     return FT_Err_Ok;
2528   }
2529 
2530 
2531   FT_DEFINE_TT_CMAP(
2532     tt_cmap12_class_rec,
2533 
2534       sizeof ( TT_CMap12Rec ),
2535 
2536       (FT_CMap_InitFunc)     tt_cmap12_init,        /* init       */
2537       (FT_CMap_DoneFunc)     NULL,                  /* done       */
2538       (FT_CMap_CharIndexFunc)tt_cmap12_char_index,  /* char_index */
2539       (FT_CMap_CharNextFunc) tt_cmap12_char_next,   /* char_next  */
2540 
2541       (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
2542       (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
2543       (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
2544       (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
2545       (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
2546 
2547     12,
2548     (TT_CMap_ValidateFunc)tt_cmap12_validate,  /* validate      */
2549     (TT_CMap_Info_GetFunc)tt_cmap12_get_info   /* get_cmap_info */
2550   )
2551 
2552 #endif /* TT_CONFIG_CMAP_FORMAT_12 */
2553 
2554 
2555   /*************************************************************************/
2556   /*************************************************************************/
2557   /*****                                                               *****/
2558   /*****                          FORMAT 13                            *****/
2559   /*****                                                               *****/
2560   /*************************************************************************/
2561   /*************************************************************************/
2562 
2563   /**************************************************************************
2564    *
2565    * TABLE OVERVIEW
2566    * --------------
2567    *
2568    *   NAME        OFFSET     TYPE       DESCRIPTION
2569    *
2570    *   format      0          USHORT     must be 13
2571    *   reserved    2          USHORT     reserved
2572    *   length      4          ULONG      length in bytes
2573    *   language    8          ULONG      Mac language code
2574    *   count       12         ULONG      number of groups
2575    *               16
2576    *
2577    * This header is followed by `count' groups of the following format:
2578    *
2579    *   start       0          ULONG      first charcode
2580    *   end         4          ULONG      last charcode
2581    *   glyphId     8          ULONG      glyph ID for the whole group
2582    */
2583 
2584 #ifdef TT_CONFIG_CMAP_FORMAT_13
2585 
2586   typedef struct  TT_CMap13Rec_
2587   {
2588     TT_CMapRec  cmap;
2589     FT_Bool     valid;
2590     FT_ULong    cur_charcode;
2591     FT_UInt     cur_gindex;
2592     FT_ULong    cur_group;
2593     FT_ULong    num_groups;
2594 
2595   } TT_CMap13Rec, *TT_CMap13;
2596 
2597 
2598   FT_CALLBACK_DEF( FT_Error )
tt_cmap13_init(TT_CMap13 cmap,FT_Byte * table)2599   tt_cmap13_init( TT_CMap13  cmap,
2600                   FT_Byte*   table )
2601   {
2602     cmap->cmap.data  = table;
2603 
2604     table           += 12;
2605     cmap->num_groups = FT_PEEK_ULONG( table );
2606 
2607     cmap->valid      = 0;
2608 
2609     return FT_Err_Ok;
2610   }
2611 
2612 
2613   FT_CALLBACK_DEF( FT_Error )
tt_cmap13_validate(FT_Byte * table,FT_Validator valid)2614   tt_cmap13_validate( FT_Byte*      table,
2615                       FT_Validator  valid )
2616   {
2617     FT_Byte*  p;
2618     FT_ULong  length;
2619     FT_ULong  num_groups;
2620 
2621 
2622     if ( table + 16 > valid->limit )
2623       FT_INVALID_TOO_SHORT;
2624 
2625     p      = table + 4;
2626     length = TT_NEXT_ULONG( p );
2627 
2628     p          = table + 12;
2629     num_groups = TT_NEXT_ULONG( p );
2630 
2631     if ( length > (FT_ULong)( valid->limit - table ) ||
2632          /* length < 16 + 12 * num_groups ? */
2633          length < 16                                 ||
2634          ( length - 16 ) / 12 < num_groups           )
2635       FT_INVALID_TOO_SHORT;
2636 
2637     /* check groups, they must be in increasing order */
2638     {
2639       FT_ULong  n, start, end, glyph_id, last = 0;
2640 
2641 
2642       for ( n = 0; n < num_groups; n++ )
2643       {
2644         start    = TT_NEXT_ULONG( p );
2645         end      = TT_NEXT_ULONG( p );
2646         glyph_id = TT_NEXT_ULONG( p );
2647 
2648         if ( start > end )
2649           FT_INVALID_DATA;
2650 
2651         if ( n > 0 && start <= last )
2652           FT_INVALID_DATA;
2653 
2654         if ( valid->level >= FT_VALIDATE_TIGHT )
2655         {
2656           if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) )
2657             FT_INVALID_GLYPH_ID;
2658         }
2659 
2660         last = end;
2661       }
2662     }
2663 
2664     return FT_Err_Ok;
2665   }
2666 
2667 
2668   /* search the index of the charcode next to cmap->cur_charcode */
2669   /* cmap->cur_group should be set up properly by caller         */
2670   /*                                                             */
2671   static void
tt_cmap13_next(TT_CMap13 cmap)2672   tt_cmap13_next( TT_CMap13  cmap )
2673   {
2674     FT_Face   face = cmap->cmap.cmap.charmap.face;
2675     FT_Byte*  p;
2676     FT_ULong  start, end, glyph_id, char_code;
2677     FT_ULong  n;
2678     FT_UInt   gindex;
2679 
2680 
2681     if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
2682       goto Fail;
2683 
2684     char_code = cmap->cur_charcode + 1;
2685 
2686     for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
2687     {
2688       p        = cmap->cmap.data + 16 + 12 * n;
2689       start    = TT_NEXT_ULONG( p );
2690       end      = TT_NEXT_ULONG( p );
2691       glyph_id = TT_PEEK_ULONG( p );
2692 
2693       if ( char_code < start )
2694         char_code = start;
2695 
2696       if ( char_code <= end )
2697       {
2698         gindex = (FT_UInt)glyph_id;
2699 
2700         if ( gindex && gindex < (FT_UInt)face->num_glyphs )
2701         {
2702           cmap->cur_charcode = char_code;
2703           cmap->cur_gindex   = gindex;
2704           cmap->cur_group    = n;
2705 
2706           return;
2707         }
2708       }
2709     }
2710 
2711   Fail:
2712     cmap->valid = 0;
2713   }
2714 
2715 
2716   static FT_UInt
tt_cmap13_char_map_binary(TT_CMap cmap,FT_UInt32 * pchar_code,FT_Bool next)2717   tt_cmap13_char_map_binary( TT_CMap     cmap,
2718                              FT_UInt32*  pchar_code,
2719                              FT_Bool     next )
2720   {
2721     FT_UInt    gindex     = 0;
2722     FT_Byte*   p          = cmap->data + 12;
2723     FT_UInt32  num_groups = TT_PEEK_ULONG( p );
2724     FT_UInt32  char_code  = *pchar_code;
2725     FT_UInt32  start, end;
2726     FT_UInt32  max, min, mid;
2727 
2728 
2729     if ( !num_groups )
2730       return 0;
2731 
2732     /* make compiler happy */
2733     mid = num_groups;
2734     end = 0xFFFFFFFFUL;
2735 
2736     if ( next )
2737     {
2738       if ( char_code >= 0xFFFFFFFFUL )
2739         return 0;
2740 
2741       char_code++;
2742     }
2743 
2744     min = 0;
2745     max = num_groups;
2746 
2747     /* binary search */
2748     while ( min < max )
2749     {
2750       mid = ( min + max ) >> 1;
2751       p   = cmap->data + 16 + 12 * mid;
2752 
2753       start = TT_NEXT_ULONG( p );
2754       end   = TT_NEXT_ULONG( p );
2755 
2756       if ( char_code < start )
2757         max = mid;
2758       else if ( char_code > end )
2759         min = mid + 1;
2760       else
2761       {
2762         gindex = (FT_UInt)TT_PEEK_ULONG( p );
2763 
2764         break;
2765       }
2766     }
2767 
2768     if ( next )
2769     {
2770       FT_Face    face   = cmap->cmap.charmap.face;
2771       TT_CMap13  cmap13 = (TT_CMap13)cmap;
2772 
2773 
2774       /* if `char_code' is not in any group, then `mid' is */
2775       /* the group nearest to `char_code'                  */
2776 
2777       if ( char_code > end )
2778       {
2779         mid++;
2780         if ( mid == num_groups )
2781           return 0;
2782       }
2783 
2784       cmap13->valid        = 1;
2785       cmap13->cur_charcode = char_code;
2786       cmap13->cur_group    = mid;
2787 
2788       if ( gindex >= (FT_UInt)face->num_glyphs )
2789         gindex = 0;
2790 
2791       if ( !gindex )
2792       {
2793         tt_cmap13_next( cmap13 );
2794 
2795         if ( cmap13->valid )
2796           gindex = cmap13->cur_gindex;
2797       }
2798       else
2799         cmap13->cur_gindex = gindex;
2800 
2801       *pchar_code = cmap13->cur_charcode;
2802     }
2803 
2804     return gindex;
2805   }
2806 
2807 
2808   FT_CALLBACK_DEF( FT_UInt )
tt_cmap13_char_index(TT_CMap cmap,FT_UInt32 char_code)2809   tt_cmap13_char_index( TT_CMap    cmap,
2810                         FT_UInt32  char_code )
2811   {
2812     return tt_cmap13_char_map_binary( cmap, &char_code, 0 );
2813   }
2814 
2815 
2816   FT_CALLBACK_DEF( FT_UInt32 )
tt_cmap13_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)2817   tt_cmap13_char_next( TT_CMap     cmap,
2818                        FT_UInt32  *pchar_code )
2819   {
2820     TT_CMap13  cmap13 = (TT_CMap13)cmap;
2821     FT_UInt    gindex;
2822 
2823 
2824     /* no need to search */
2825     if ( cmap13->valid && cmap13->cur_charcode == *pchar_code )
2826     {
2827       tt_cmap13_next( cmap13 );
2828       if ( cmap13->valid )
2829       {
2830         gindex      = cmap13->cur_gindex;
2831         *pchar_code = cmap13->cur_charcode;
2832       }
2833       else
2834         gindex = 0;
2835     }
2836     else
2837       gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 );
2838 
2839     return gindex;
2840   }
2841 
2842 
2843   FT_CALLBACK_DEF( FT_Error )
tt_cmap13_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)2844   tt_cmap13_get_info( TT_CMap       cmap,
2845                       TT_CMapInfo  *cmap_info )
2846   {
2847     FT_Byte*  p = cmap->data + 8;
2848 
2849 
2850     cmap_info->format   = 13;
2851     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2852 
2853     return FT_Err_Ok;
2854   }
2855 
2856 
2857   FT_DEFINE_TT_CMAP(
2858     tt_cmap13_class_rec,
2859 
2860       sizeof ( TT_CMap13Rec ),
2861 
2862       (FT_CMap_InitFunc)     tt_cmap13_init,        /* init       */
2863       (FT_CMap_DoneFunc)     NULL,                  /* done       */
2864       (FT_CMap_CharIndexFunc)tt_cmap13_char_index,  /* char_index */
2865       (FT_CMap_CharNextFunc) tt_cmap13_char_next,   /* char_next  */
2866 
2867       (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
2868       (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
2869       (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
2870       (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
2871       (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
2872 
2873     13,
2874     (TT_CMap_ValidateFunc)tt_cmap13_validate,  /* validate      */
2875     (TT_CMap_Info_GetFunc)tt_cmap13_get_info   /* get_cmap_info */
2876   )
2877 
2878 #endif /* TT_CONFIG_CMAP_FORMAT_13 */
2879 
2880 
2881   /*************************************************************************/
2882   /*************************************************************************/
2883   /*****                                                               *****/
2884   /*****                           FORMAT 14                           *****/
2885   /*****                                                               *****/
2886   /*************************************************************************/
2887   /*************************************************************************/
2888 
2889   /**************************************************************************
2890    *
2891    * TABLE OVERVIEW
2892    * --------------
2893    *
2894    *   NAME         OFFSET  TYPE    DESCRIPTION
2895    *
2896    *   format         0     USHORT  must be 14
2897    *   length         2     ULONG   table length in bytes
2898    *   numSelector    6     ULONG   number of variation sel. records
2899    *
2900    * Followed by numSelector records, each of which looks like
2901    *
2902    *   varSelector    0     UINT24  Unicode codepoint of sel.
2903    *   defaultOff     3     ULONG   offset to a default UVS table
2904    *                                describing any variants to be found in
2905    *                                the normal Unicode subtable.
2906    *   nonDefOff      7     ULONG   offset to a non-default UVS table
2907    *                                describing any variants not in the
2908    *                                standard cmap, with GIDs here
2909    * (either offset may be 0 NULL)
2910    *
2911    * Selectors are sorted by code point.
2912    *
2913    * A default Unicode Variation Selector (UVS) subtable is just a list of
2914    * ranges of code points which are to be found in the standard cmap.  No
2915    * glyph IDs (GIDs) here.
2916    *
2917    *   numRanges      0     ULONG   number of ranges following
2918    *
2919    * A range looks like
2920    *
2921    *   uniStart       0     UINT24  code point of the first character in
2922    *                                this range
2923    *   additionalCnt  3     UBYTE   count of additional characters in this
2924    *                                range (zero means a range of a single
2925    *                                character)
2926    *
2927    * Ranges are sorted by `uniStart'.
2928    *
2929    * A non-default Unicode Variation Selector (UVS) subtable is a list of
2930    * mappings from codepoint to GID.
2931    *
2932    *   numMappings    0     ULONG   number of mappings
2933    *
2934    * A range looks like
2935    *
2936    *   uniStart       0     UINT24  code point of the first character in
2937    *                                this range
2938    *   GID            3     USHORT  and its GID
2939    *
2940    * Ranges are sorted by `uniStart'.
2941    */
2942 
2943 #ifdef TT_CONFIG_CMAP_FORMAT_14
2944 
2945   typedef struct  TT_CMap14Rec_
2946   {
2947     TT_CMapRec  cmap;
2948     FT_ULong    num_selectors;
2949 
2950     /* This array is used to store the results of various
2951      * cmap 14 query functions.  The data is overwritten
2952      * on each call to these functions.
2953      */
2954     FT_UInt32   max_results;
2955     FT_UInt32*  results;
2956     FT_Memory   memory;
2957 
2958   } TT_CMap14Rec, *TT_CMap14;
2959 
2960 
2961   FT_CALLBACK_DEF( void )
tt_cmap14_done(TT_CMap14 cmap)2962   tt_cmap14_done( TT_CMap14  cmap )
2963   {
2964     FT_Memory  memory = cmap->memory;
2965 
2966 
2967     cmap->max_results = 0;
2968     if ( memory && cmap->results )
2969       FT_FREE( cmap->results );
2970   }
2971 
2972 
2973   static FT_Error
tt_cmap14_ensure(TT_CMap14 cmap,FT_UInt32 num_results,FT_Memory memory)2974   tt_cmap14_ensure( TT_CMap14  cmap,
2975                     FT_UInt32  num_results,
2976                     FT_Memory  memory )
2977   {
2978     FT_UInt32  old_max = cmap->max_results;
2979     FT_Error   error   = FT_Err_Ok;
2980 
2981 
2982     if ( num_results > cmap->max_results )
2983     {
2984        cmap->memory = memory;
2985 
2986        if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) )
2987          return error;
2988 
2989        cmap->max_results = num_results;
2990     }
2991 
2992     return error;
2993   }
2994 
2995 
2996   FT_CALLBACK_DEF( FT_Error )
tt_cmap14_init(TT_CMap14 cmap,FT_Byte * table)2997   tt_cmap14_init( TT_CMap14  cmap,
2998                   FT_Byte*   table )
2999   {
3000     cmap->cmap.data = table;
3001 
3002     table               += 6;
3003     cmap->num_selectors  = FT_PEEK_ULONG( table );
3004     cmap->max_results    = 0;
3005     cmap->results        = NULL;
3006 
3007     return FT_Err_Ok;
3008   }
3009 
3010 
3011   FT_CALLBACK_DEF( FT_Error )
tt_cmap14_validate(FT_Byte * table,FT_Validator valid)3012   tt_cmap14_validate( FT_Byte*      table,
3013                       FT_Validator  valid )
3014   {
3015     FT_Byte*  p;
3016     FT_ULong  length;
3017     FT_ULong  num_selectors;
3018 
3019 
3020     if ( table + 2 + 4 + 4 > valid->limit )
3021       FT_INVALID_TOO_SHORT;
3022 
3023     p             = table + 2;
3024     length        = TT_NEXT_ULONG( p );
3025     num_selectors = TT_NEXT_ULONG( p );
3026 
3027     if ( length > (FT_ULong)( valid->limit - table ) ||
3028          /* length < 10 + 11 * num_selectors ? */
3029          length < 10                                 ||
3030          ( length - 10 ) / 11 < num_selectors        )
3031       FT_INVALID_TOO_SHORT;
3032 
3033     /* check selectors, they must be in increasing order */
3034     {
3035       /* we start lastVarSel at 1 because a variant selector value of 0
3036        * isn't valid.
3037        */
3038       FT_ULong  n, lastVarSel = 1;
3039 
3040 
3041       for ( n = 0; n < num_selectors; n++ )
3042       {
3043         FT_ULong  varSel    = TT_NEXT_UINT24( p );
3044         FT_ULong  defOff    = TT_NEXT_ULONG( p );
3045         FT_ULong  nondefOff = TT_NEXT_ULONG( p );
3046 
3047 
3048         if ( defOff >= length || nondefOff >= length )
3049           FT_INVALID_TOO_SHORT;
3050 
3051         if ( varSel < lastVarSel )
3052           FT_INVALID_DATA;
3053 
3054         lastVarSel = varSel + 1;
3055 
3056         /* check the default table (these glyphs should be reached     */
3057         /* through the normal Unicode cmap, no GIDs, just check order) */
3058         if ( defOff != 0 )
3059         {
3060           FT_Byte*  defp     = table + defOff;
3061           FT_ULong  numRanges;
3062           FT_ULong  i;
3063           FT_ULong  lastBase = 0;
3064 
3065 
3066           if ( defp + 4 > valid->limit )
3067             FT_INVALID_TOO_SHORT;
3068 
3069           numRanges = TT_NEXT_ULONG( defp );
3070 
3071           /* defp + numRanges * 4 > valid->limit ? */
3072           if ( numRanges > (FT_ULong)( valid->limit - defp ) / 4 )
3073             FT_INVALID_TOO_SHORT;
3074 
3075           for ( i = 0; i < numRanges; i++ )
3076           {
3077             FT_ULong  base = TT_NEXT_UINT24( defp );
3078             FT_ULong  cnt  = FT_NEXT_BYTE( defp );
3079 
3080 
3081             if ( base + cnt >= 0x110000UL )              /* end of Unicode */
3082               FT_INVALID_DATA;
3083 
3084             if ( base < lastBase )
3085               FT_INVALID_DATA;
3086 
3087             lastBase = base + cnt + 1U;
3088           }
3089         }
3090 
3091         /* and the non-default table (these glyphs are specified here) */
3092         if ( nondefOff != 0 )
3093         {
3094           FT_Byte*  ndp        = table + nondefOff;
3095           FT_ULong  numMappings;
3096           FT_ULong  i, lastUni = 0;
3097 
3098 
3099           if ( ndp + 4 > valid->limit )
3100             FT_INVALID_TOO_SHORT;
3101 
3102           numMappings = TT_NEXT_ULONG( ndp );
3103 
3104           /* numMappings * 5 > (FT_ULong)( valid->limit - ndp ) ? */
3105           if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 5 )
3106             FT_INVALID_TOO_SHORT;
3107 
3108           for ( i = 0; i < numMappings; i++ )
3109           {
3110             FT_ULong  uni = TT_NEXT_UINT24( ndp );
3111             FT_ULong  gid = TT_NEXT_USHORT( ndp );
3112 
3113 
3114             if ( uni >= 0x110000UL )                     /* end of Unicode */
3115               FT_INVALID_DATA;
3116 
3117             if ( uni < lastUni )
3118               FT_INVALID_DATA;
3119 
3120             lastUni = uni + 1U;
3121 
3122             if ( valid->level >= FT_VALIDATE_TIGHT    &&
3123                  gid >= TT_VALID_GLYPH_COUNT( valid ) )
3124               FT_INVALID_GLYPH_ID;
3125           }
3126         }
3127       }
3128     }
3129 
3130     return FT_Err_Ok;
3131   }
3132 
3133 
3134   FT_CALLBACK_DEF( FT_UInt )
tt_cmap14_char_index(TT_CMap cmap,FT_UInt32 char_code)3135   tt_cmap14_char_index( TT_CMap    cmap,
3136                         FT_UInt32  char_code )
3137   {
3138     FT_UNUSED( cmap );
3139     FT_UNUSED( char_code );
3140 
3141     /* This can't happen */
3142     return 0;
3143   }
3144 
3145 
3146   FT_CALLBACK_DEF( FT_UInt32 )
tt_cmap14_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)3147   tt_cmap14_char_next( TT_CMap     cmap,
3148                        FT_UInt32  *pchar_code )
3149   {
3150     FT_UNUSED( cmap );
3151 
3152     /* This can't happen */
3153     *pchar_code = 0;
3154     return 0;
3155   }
3156 
3157 
3158   FT_CALLBACK_DEF( FT_Error )
tt_cmap14_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)3159   tt_cmap14_get_info( TT_CMap       cmap,
3160                       TT_CMapInfo  *cmap_info )
3161   {
3162     FT_UNUSED( cmap );
3163 
3164     cmap_info->format   = 14;
3165     /* subtable 14 does not define a language field */
3166     cmap_info->language = 0xFFFFFFFFUL;
3167 
3168     return FT_Err_Ok;
3169   }
3170 
3171 
3172   static FT_UInt
tt_cmap14_char_map_def_binary(FT_Byte * base,FT_UInt32 char_code)3173   tt_cmap14_char_map_def_binary( FT_Byte    *base,
3174                                  FT_UInt32   char_code )
3175   {
3176     FT_UInt32  numRanges = TT_PEEK_ULONG( base );
3177     FT_UInt32  max, min;
3178 
3179 
3180     min = 0;
3181     max = numRanges;
3182 
3183     base += 4;
3184 
3185     /* binary search */
3186     while ( min < max )
3187     {
3188       FT_UInt32  mid   = ( min + max ) >> 1;
3189       FT_Byte*   p     = base + 4 * mid;
3190       FT_ULong   start = TT_NEXT_UINT24( p );
3191       FT_UInt    cnt   = FT_NEXT_BYTE( p );
3192 
3193 
3194       if ( char_code < start )
3195         max = mid;
3196       else if ( char_code > start + cnt )
3197         min = mid + 1;
3198       else
3199         return TRUE;
3200     }
3201 
3202     return FALSE;
3203   }
3204 
3205 
3206   static FT_UInt
tt_cmap14_char_map_nondef_binary(FT_Byte * base,FT_UInt32 char_code)3207   tt_cmap14_char_map_nondef_binary( FT_Byte    *base,
3208                                     FT_UInt32   char_code )
3209   {
3210     FT_UInt32  numMappings = TT_PEEK_ULONG( base );
3211     FT_UInt32  max, min;
3212 
3213 
3214     min = 0;
3215     max = numMappings;
3216 
3217     base += 4;
3218 
3219     /* binary search */
3220     while ( min < max )
3221     {
3222       FT_UInt32  mid = ( min + max ) >> 1;
3223       FT_Byte*   p   = base + 5 * mid;
3224       FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
3225 
3226 
3227       if ( char_code < uni )
3228         max = mid;
3229       else if ( char_code > uni )
3230         min = mid + 1;
3231       else
3232         return TT_PEEK_USHORT( p );
3233     }
3234 
3235     return 0;
3236   }
3237 
3238 
3239   static FT_Byte*
tt_cmap14_find_variant(FT_Byte * base,FT_UInt32 variantCode)3240   tt_cmap14_find_variant( FT_Byte    *base,
3241                           FT_UInt32   variantCode )
3242   {
3243     FT_UInt32  numVar = TT_PEEK_ULONG( base );
3244     FT_UInt32  max, min;
3245 
3246 
3247     min = 0;
3248     max = numVar;
3249 
3250     base += 4;
3251 
3252     /* binary search */
3253     while ( min < max )
3254     {
3255       FT_UInt32  mid    = ( min + max ) >> 1;
3256       FT_Byte*   p      = base + 11 * mid;
3257       FT_ULong   varSel = TT_NEXT_UINT24( p );
3258 
3259 
3260       if ( variantCode < varSel )
3261         max = mid;
3262       else if ( variantCode > varSel )
3263         min = mid + 1;
3264       else
3265         return p;
3266     }
3267 
3268     return NULL;
3269   }
3270 
3271 
3272   FT_CALLBACK_DEF( FT_UInt )
tt_cmap14_char_var_index(TT_CMap cmap,TT_CMap ucmap,FT_UInt32 charcode,FT_UInt32 variantSelector)3273   tt_cmap14_char_var_index( TT_CMap    cmap,
3274                             TT_CMap    ucmap,
3275                             FT_UInt32  charcode,
3276                             FT_UInt32  variantSelector )
3277   {
3278     FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
3279     FT_ULong  defOff;
3280     FT_ULong  nondefOff;
3281 
3282 
3283     if ( !p )
3284       return 0;
3285 
3286     defOff    = TT_NEXT_ULONG( p );
3287     nondefOff = TT_PEEK_ULONG( p );
3288 
3289     if ( defOff != 0                                                    &&
3290          tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
3291     {
3292       /* This is the default variant of this charcode.  GID not stored */
3293       /* here; stored in the normal Unicode charmap instead.           */
3294       return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode );
3295     }
3296 
3297     if ( nondefOff != 0 )
3298       return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3299                                                charcode );
3300 
3301     return 0;
3302   }
3303 
3304 
3305   FT_CALLBACK_DEF( FT_Int )
tt_cmap14_char_var_isdefault(TT_CMap cmap,FT_UInt32 charcode,FT_UInt32 variantSelector)3306   tt_cmap14_char_var_isdefault( TT_CMap    cmap,
3307                                 FT_UInt32  charcode,
3308                                 FT_UInt32  variantSelector )
3309   {
3310     FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
3311     FT_ULong  defOff;
3312     FT_ULong  nondefOff;
3313 
3314 
3315     if ( !p )
3316       return -1;
3317 
3318     defOff    = TT_NEXT_ULONG( p );
3319     nondefOff = TT_NEXT_ULONG( p );
3320 
3321     if ( defOff != 0                                                    &&
3322          tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
3323       return 1;
3324 
3325     if ( nondefOff != 0                                            &&
3326          tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3327                                            charcode ) != 0         )
3328       return 0;
3329 
3330     return -1;
3331   }
3332 
3333 
3334   FT_CALLBACK_DEF( FT_UInt32* )
tt_cmap14_variants(TT_CMap cmap,FT_Memory memory)3335   tt_cmap14_variants( TT_CMap    cmap,
3336                       FT_Memory  memory )
3337   {
3338     TT_CMap14   cmap14 = (TT_CMap14)cmap;
3339     FT_UInt32   count  = cmap14->num_selectors;
3340     FT_Byte*    p      = cmap->data + 10;
3341     FT_UInt32*  result;
3342     FT_UInt32   i;
3343 
3344 
3345     if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
3346       return NULL;
3347 
3348     result = cmap14->results;
3349     for ( i = 0; i < count; i++ )
3350     {
3351       result[i] = (FT_UInt32)TT_NEXT_UINT24( p );
3352       p        += 8;
3353     }
3354     result[i] = 0;
3355 
3356     return result;
3357   }
3358 
3359 
3360   FT_CALLBACK_DEF( FT_UInt32 * )
tt_cmap14_char_variants(TT_CMap cmap,FT_Memory memory,FT_UInt32 charCode)3361   tt_cmap14_char_variants( TT_CMap    cmap,
3362                            FT_Memory  memory,
3363                            FT_UInt32  charCode )
3364   {
3365     TT_CMap14   cmap14 = (TT_CMap14)  cmap;
3366     FT_UInt32   count  = cmap14->num_selectors;
3367     FT_Byte*    p      = cmap->data + 10;
3368     FT_UInt32*  q;
3369 
3370 
3371     if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
3372       return NULL;
3373 
3374     for ( q = cmap14->results; count > 0; count-- )
3375     {
3376       FT_UInt32  varSel    = TT_NEXT_UINT24( p );
3377       FT_ULong   defOff    = TT_NEXT_ULONG( p );
3378       FT_ULong   nondefOff = TT_NEXT_ULONG( p );
3379 
3380 
3381       if ( ( defOff != 0                                               &&
3382              tt_cmap14_char_map_def_binary( cmap->data + defOff,
3383                                             charCode )                 ) ||
3384            ( nondefOff != 0                                            &&
3385              tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3386                                                charCode ) != 0         ) )
3387       {
3388         q[0] = varSel;
3389         q++;
3390       }
3391     }
3392     q[0] = 0;
3393 
3394     return cmap14->results;
3395   }
3396 
3397 
3398   static FT_UInt
tt_cmap14_def_char_count(FT_Byte * p)3399   tt_cmap14_def_char_count( FT_Byte  *p )
3400   {
3401     FT_UInt32  numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
3402     FT_UInt    tot       = 0;
3403 
3404 
3405     p += 3;  /* point to the first `cnt' field */
3406     for ( ; numRanges > 0; numRanges-- )
3407     {
3408       tot += 1 + p[0];
3409       p   += 4;
3410     }
3411 
3412     return tot;
3413   }
3414 
3415 
3416   static FT_UInt32*
tt_cmap14_get_def_chars(TT_CMap cmap,FT_Byte * p,FT_Memory memory)3417   tt_cmap14_get_def_chars( TT_CMap    cmap,
3418                            FT_Byte*   p,
3419                            FT_Memory  memory )
3420   {
3421     TT_CMap14   cmap14 = (TT_CMap14) cmap;
3422     FT_UInt32   numRanges;
3423     FT_UInt     cnt;
3424     FT_UInt32*  q;
3425 
3426 
3427     cnt       = tt_cmap14_def_char_count( p );
3428     numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
3429 
3430     if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) )
3431       return NULL;
3432 
3433     for ( q = cmap14->results; numRanges > 0; numRanges-- )
3434     {
3435       FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
3436 
3437 
3438       cnt = FT_NEXT_BYTE( p ) + 1;
3439       do
3440       {
3441         q[0]  = uni;
3442         uni  += 1;
3443         q    += 1;
3444 
3445       } while ( --cnt != 0 );
3446     }
3447     q[0] = 0;
3448 
3449     return cmap14->results;
3450   }
3451 
3452 
3453   static FT_UInt32*
tt_cmap14_get_nondef_chars(TT_CMap cmap,FT_Byte * p,FT_Memory memory)3454   tt_cmap14_get_nondef_chars( TT_CMap     cmap,
3455                               FT_Byte    *p,
3456                               FT_Memory   memory )
3457   {
3458     TT_CMap14   cmap14 = (TT_CMap14) cmap;
3459     FT_UInt32   numMappings;
3460     FT_UInt     i;
3461     FT_UInt32  *ret;
3462 
3463 
3464     numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
3465 
3466     if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) )
3467       return NULL;
3468 
3469     ret = cmap14->results;
3470     for ( i = 0; i < numMappings; i++ )
3471     {
3472       ret[i] = (FT_UInt32)TT_NEXT_UINT24( p );
3473       p += 2;
3474     }
3475     ret[i] = 0;
3476 
3477     return ret;
3478   }
3479 
3480 
3481   FT_CALLBACK_DEF( FT_UInt32 * )
tt_cmap14_variant_chars(TT_CMap cmap,FT_Memory memory,FT_UInt32 variantSelector)3482   tt_cmap14_variant_chars( TT_CMap    cmap,
3483                            FT_Memory  memory,
3484                            FT_UInt32  variantSelector )
3485   {
3486     FT_Byte    *p  = tt_cmap14_find_variant( cmap->data + 6,
3487                                              variantSelector );
3488     FT_Int      i;
3489     FT_ULong    defOff;
3490     FT_ULong    nondefOff;
3491 
3492 
3493     if ( !p )
3494       return NULL;
3495 
3496     defOff    = TT_NEXT_ULONG( p );
3497     nondefOff = TT_NEXT_ULONG( p );
3498 
3499     if ( defOff == 0 && nondefOff == 0 )
3500       return NULL;
3501 
3502     if ( defOff == 0 )
3503       return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
3504                                          memory );
3505     else if ( nondefOff == 0 )
3506       return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
3507                                       memory );
3508     else
3509     {
3510       /* Both a default and a non-default glyph set?  That's probably not */
3511       /* good font design, but the spec allows for it...                  */
3512       TT_CMap14  cmap14 = (TT_CMap14) cmap;
3513       FT_UInt32  numRanges;
3514       FT_UInt32  numMappings;
3515       FT_UInt32  duni;
3516       FT_UInt32  dcnt;
3517       FT_UInt32  nuni;
3518       FT_Byte*   dp;
3519       FT_UInt    di, ni, k;
3520 
3521       FT_UInt32  *ret;
3522 
3523 
3524       p  = cmap->data + nondefOff;
3525       dp = cmap->data + defOff;
3526 
3527       numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
3528       dcnt        = tt_cmap14_def_char_count( dp );
3529       numRanges   = (FT_UInt32)TT_NEXT_ULONG( dp );
3530 
3531       if ( numMappings == 0 )
3532         return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
3533                                         memory );
3534       if ( dcnt == 0 )
3535         return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
3536                                            memory );
3537 
3538       if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) )
3539         return NULL;
3540 
3541       ret  = cmap14->results;
3542       duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3543       dcnt = FT_NEXT_BYTE( dp );
3544       di   = 1;
3545       nuni = (FT_UInt32)TT_NEXT_UINT24( p );
3546       p   += 2;
3547       ni   = 1;
3548       i    = 0;
3549 
3550       for (;;)
3551       {
3552         if ( nuni > duni + dcnt )
3553         {
3554           for ( k = 0; k <= dcnt; k++ )
3555             ret[i++] = duni + k;
3556 
3557           di++;
3558 
3559           if ( di > numRanges )
3560             break;
3561 
3562           duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3563           dcnt = FT_NEXT_BYTE( dp );
3564         }
3565         else
3566         {
3567           if ( nuni < duni )
3568             ret[i++] = nuni;
3569           /* If it is within the default range then ignore it -- */
3570           /* that should not have happened                       */
3571           ni++;
3572           if ( ni > numMappings )
3573             break;
3574 
3575           nuni = (FT_UInt32)TT_NEXT_UINT24( p );
3576           p += 2;
3577         }
3578       }
3579 
3580       if ( ni <= numMappings )
3581       {
3582         /* If we get here then we have run out of all default ranges.   */
3583         /* We have read one non-default mapping which we haven't stored */
3584         /* and there may be others that need to be read.                */
3585         ret[i++] = nuni;
3586         while ( ni < numMappings )
3587         {
3588           ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p );
3589           p += 2;
3590           ni++;
3591         }
3592       }
3593       else if ( di <= numRanges )
3594       {
3595         /* If we get here then we have run out of all non-default     */
3596         /* mappings.  We have read one default range which we haven't */
3597         /* stored and there may be others that need to be read.       */
3598         for ( k = 0; k <= dcnt; k++ )
3599           ret[i++] = duni + k;
3600 
3601         while ( di < numRanges )
3602         {
3603           duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3604           dcnt = FT_NEXT_BYTE( dp );
3605 
3606           for ( k = 0; k <= dcnt; k++ )
3607             ret[i++] = duni + k;
3608           di++;
3609         }
3610       }
3611 
3612       ret[i] = 0;
3613 
3614       return ret;
3615     }
3616   }
3617 
3618 
3619   FT_DEFINE_TT_CMAP(
3620     tt_cmap14_class_rec,
3621 
3622       sizeof ( TT_CMap14Rec ),
3623 
3624       (FT_CMap_InitFunc)     tt_cmap14_init,        /* init       */
3625       (FT_CMap_DoneFunc)     tt_cmap14_done,        /* done       */
3626       (FT_CMap_CharIndexFunc)tt_cmap14_char_index,  /* char_index */
3627       (FT_CMap_CharNextFunc) tt_cmap14_char_next,   /* char_next  */
3628 
3629       /* Format 14 extension functions */
3630       (FT_CMap_CharVarIndexFunc)    tt_cmap14_char_var_index,
3631       (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
3632       (FT_CMap_VariantListFunc)     tt_cmap14_variants,
3633       (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
3634       (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars,
3635 
3636     14,
3637     (TT_CMap_ValidateFunc)tt_cmap14_validate,  /* validate      */
3638     (TT_CMap_Info_GetFunc)tt_cmap14_get_info   /* get_cmap_info */
3639   )
3640 
3641 #endif /* TT_CONFIG_CMAP_FORMAT_14 */
3642 
3643 
3644   /*************************************************************************/
3645   /*************************************************************************/
3646   /*****                                                               *****/
3647   /*****                       SYNTHETIC UNICODE                       *****/
3648   /*****                                                               *****/
3649   /*************************************************************************/
3650   /*************************************************************************/
3651 
3652   /*        This charmap is generated using postscript glyph names.        */
3653 
3654 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
3655 
FT_CALLBACK_DEF(const char *)3656   FT_CALLBACK_DEF( const char * )
3657   tt_get_glyph_name( TT_Face  face,
3658                      FT_UInt  idx )
3659   {
3660     FT_String*  PSname = NULL;
3661 
3662 
3663     tt_face_get_ps_name( face, idx, &PSname );
3664 
3665     return PSname;
3666   }
3667 
3668 
3669   FT_CALLBACK_DEF( FT_Error )
tt_cmap_unicode_init(PS_Unicodes unicodes,FT_Pointer pointer)3670   tt_cmap_unicode_init( PS_Unicodes  unicodes,
3671                         FT_Pointer   pointer )
3672   {
3673     TT_Face             face    = (TT_Face)FT_CMAP_FACE( unicodes );
3674     FT_Memory           memory  = FT_FACE_MEMORY( face );
3675     FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)face->psnames;
3676 
3677     FT_UNUSED( pointer );
3678 
3679 
3680     if ( !psnames->unicodes_init )
3681       return FT_THROW( Unimplemented_Feature );
3682 
3683     return psnames->unicodes_init( memory,
3684                                    unicodes,
3685                                    face->root.num_glyphs,
3686                                    (PS_GetGlyphNameFunc)&tt_get_glyph_name,
3687                                    (PS_FreeGlyphNameFunc)NULL,
3688                                    (FT_Pointer)face );
3689   }
3690 
3691 
3692   FT_CALLBACK_DEF( void )
tt_cmap_unicode_done(PS_Unicodes unicodes)3693   tt_cmap_unicode_done( PS_Unicodes  unicodes )
3694   {
3695     FT_Face    face   = FT_CMAP_FACE( unicodes );
3696     FT_Memory  memory = FT_FACE_MEMORY( face );
3697 
3698 
3699     FT_FREE( unicodes->maps );
3700     unicodes->num_maps = 0;
3701   }
3702 
3703 
3704   FT_CALLBACK_DEF( FT_UInt )
tt_cmap_unicode_char_index(PS_Unicodes unicodes,FT_UInt32 char_code)3705   tt_cmap_unicode_char_index( PS_Unicodes  unicodes,
3706                               FT_UInt32    char_code )
3707   {
3708     TT_Face             face    = (TT_Face)FT_CMAP_FACE( unicodes );
3709     FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)face->psnames;
3710 
3711 
3712     return psnames->unicodes_char_index( unicodes, char_code );
3713   }
3714 
3715 
3716   FT_CALLBACK_DEF( FT_UInt32 )
tt_cmap_unicode_char_next(PS_Unicodes unicodes,FT_UInt32 * pchar_code)3717   tt_cmap_unicode_char_next( PS_Unicodes  unicodes,
3718                              FT_UInt32   *pchar_code )
3719   {
3720     TT_Face             face    = (TT_Face)FT_CMAP_FACE( unicodes );
3721     FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)face->psnames;
3722 
3723 
3724     return psnames->unicodes_char_next( unicodes, pchar_code );
3725   }
3726 
3727 
3728   FT_DEFINE_TT_CMAP(
3729     tt_cmap_unicode_class_rec,
3730 
3731       sizeof ( PS_UnicodesRec ),
3732 
3733       (FT_CMap_InitFunc)     tt_cmap_unicode_init,        /* init       */
3734       (FT_CMap_DoneFunc)     tt_cmap_unicode_done,        /* done       */
3735       (FT_CMap_CharIndexFunc)tt_cmap_unicode_char_index,  /* char_index */
3736       (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next,   /* char_next  */
3737 
3738       (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
3739       (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
3740       (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
3741       (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
3742       (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
3743 
3744     ~0U,
3745     (TT_CMap_ValidateFunc)NULL,  /* validate      */
3746     (TT_CMap_Info_GetFunc)NULL   /* get_cmap_info */
3747   )
3748 
3749 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
3750 
3751 
3752   static const TT_CMap_Class  tt_cmap_classes[] =
3753   {
3754 #undef  TTCMAPCITEM
3755 #define TTCMAPCITEM( a )  &a,
3756 #include "ttcmapc.h"
3757     NULL,
3758   };
3759 
3760 
3761   /* parse the `cmap' table and build the corresponding TT_CMap objects */
3762   /* in the current face                                                */
3763   /*                                                                    */
3764   FT_LOCAL_DEF( FT_Error )
tt_face_build_cmaps(TT_Face face)3765   tt_face_build_cmaps( TT_Face  face )
3766   {
3767     FT_Byte* const     table   = face->cmap_table;
3768     FT_Byte*           limit;
3769     FT_UInt volatile   num_cmaps;
3770     FT_Byte* volatile  p       = table;
3771     FT_Library         library = FT_FACE_LIBRARY( face );
3772 
3773     FT_UNUSED( library );
3774 
3775 
3776     if ( !p || face->cmap_size < 4 )
3777       return FT_THROW( Invalid_Table );
3778 
3779     /* Version 1.8.3 of the OpenType specification contains the following */
3780     /* (https://docs.microsoft.com/en-us/typography/opentype/spec/cmap):  */
3781     /*                                                                    */
3782     /*   The 'cmap' table version number remains at 0x0000 for fonts that */
3783     /*   make use of the newer subtable formats.                          */
3784     /*                                                                    */
3785     /* This essentially means that a version format test is useless.      */
3786 
3787     /* ignore format */
3788     p += 2;
3789 
3790     num_cmaps = TT_NEXT_USHORT( p );
3791     FT_TRACE4(( "tt_face_build_cmaps: %d cmaps\n", num_cmaps ));
3792 
3793     limit = table + face->cmap_size;
3794     for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
3795     {
3796       FT_CharMapRec  charmap;
3797       FT_UInt32      offset;
3798 
3799 
3800       charmap.platform_id = TT_NEXT_USHORT( p );
3801       charmap.encoding_id = TT_NEXT_USHORT( p );
3802       charmap.face        = FT_FACE( face );
3803       charmap.encoding    = FT_ENCODING_NONE;  /* will be filled later */
3804       offset              = TT_NEXT_ULONG( p );
3805 
3806       if ( offset && offset <= face->cmap_size - 2 )
3807       {
3808         FT_Byte* volatile              cmap   = table + offset;
3809         volatile FT_UInt               format = TT_PEEK_USHORT( cmap );
3810         const TT_CMap_Class* volatile  pclazz = tt_cmap_classes;
3811         TT_CMap_Class volatile         clazz;
3812 
3813 
3814         for ( ; *pclazz; pclazz++ )
3815         {
3816           clazz = *pclazz;
3817           if ( clazz->format == format )
3818           {
3819             volatile TT_ValidatorRec  valid;
3820             volatile FT_Error         error = FT_Err_Ok;
3821 
3822 
3823             ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
3824                                FT_VALIDATE_DEFAULT );
3825 
3826             valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
3827 
3828             if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer) == 0 )
3829             {
3830               /* validate this cmap sub-table */
3831               error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
3832             }
3833 
3834             if ( !valid.validator.error )
3835             {
3836               FT_CMap  ttcmap;
3837 
3838 
3839               /* It might make sense to store the single variation         */
3840               /* selector cmap somewhere special.  But it would have to be */
3841               /* in the public FT_FaceRec, and we can't change that.       */
3842 
3843               if ( !FT_CMap_New( (FT_CMap_Class)clazz,
3844                                  cmap, &charmap, &ttcmap ) )
3845               {
3846                 /* it is simpler to directly set `flags' than adding */
3847                 /* a parameter to FT_CMap_New                        */
3848                 ((TT_CMap)ttcmap)->flags = (FT_Int)error;
3849               }
3850             }
3851             else
3852             {
3853               FT_TRACE0(( "tt_face_build_cmaps:"
3854                           " broken cmap sub-table ignored\n" ));
3855             }
3856             break;
3857           }
3858         }
3859 
3860         if ( !*pclazz )
3861         {
3862           FT_TRACE0(( "tt_face_build_cmaps:"
3863                       " unsupported cmap sub-table ignored\n" ));
3864         }
3865       }
3866     }
3867 
3868     return FT_Err_Ok;
3869   }
3870 
3871 
3872   FT_LOCAL( FT_Error )
tt_get_cmap_info(FT_CharMap charmap,TT_CMapInfo * cmap_info)3873   tt_get_cmap_info( FT_CharMap    charmap,
3874                     TT_CMapInfo  *cmap_info )
3875   {
3876     FT_CMap        cmap  = (FT_CMap)charmap;
3877     TT_CMap_Class  clazz = (TT_CMap_Class)cmap->clazz;
3878 
3879     if ( clazz->get_cmap_info )
3880       return clazz->get_cmap_info( charmap, cmap_info );
3881     else
3882       return FT_THROW( Invalid_CharMap_Format );
3883   }
3884 
3885 
3886 /* END */
3887