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