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