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