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