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