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