tizen 2.3.1 release
[framework/graphics/freetype.git] / src / sfnt / ttcmap.c
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 )
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 )
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 )
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 )
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 )
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
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*
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 )
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 )
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 )
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 )
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
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
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 )
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     /* in certain fonts, the `length' field is invalid and goes */
849     /* out of bound.  We try to correct this here...            */
850     if ( table + length > valid->limit )
851     {
852       if ( valid->level >= FT_VALIDATE_TIGHT )
853         FT_INVALID_TOO_SHORT;
854
855       length = (FT_UInt)( valid->limit - table );
856     }
857
858     if ( length < 16 )
859       FT_INVALID_TOO_SHORT;
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
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
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 )
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 )
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 )
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
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 )
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 )
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 )
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
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     /* p + num_groups * 12 > valid->limit ? */
1673     if ( num_groups > (FT_UInt32)( valid->limit - p ) / 12 )
1674       FT_INVALID_TOO_SHORT;
1675
1676     /* check groups, they must be in increasing order */
1677     {
1678       FT_UInt32  n, start, end, start_id, count, last = 0;
1679
1680
1681       for ( n = 0; n < num_groups; n++ )
1682       {
1683         FT_UInt   hi, lo;
1684
1685
1686         start    = TT_NEXT_ULONG( p );
1687         end      = TT_NEXT_ULONG( p );
1688         start_id = TT_NEXT_ULONG( p );
1689
1690         if ( start > end )
1691           FT_INVALID_DATA;
1692
1693         if ( n > 0 && start <= last )
1694           FT_INVALID_DATA;
1695
1696         if ( valid->level >= FT_VALIDATE_TIGHT )
1697         {
1698           FT_UInt32  d = end - start;
1699
1700
1701           /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
1702           if ( d > TT_VALID_GLYPH_COUNT( valid )             ||
1703                start_id >= TT_VALID_GLYPH_COUNT( valid ) - d )
1704             FT_INVALID_GLYPH_ID;
1705
1706           count = (FT_UInt32)( end - start + 1 );
1707
1708           if ( start & ~0xFFFFU )
1709           {
1710             /* start_hi != 0; check that is32[i] is 1 for each i in */
1711             /* the `hi' and `lo' of the range [start..end]          */
1712             for ( ; count > 0; count--, start++ )
1713             {
1714               hi = (FT_UInt)( start >> 16 );
1715               lo = (FT_UInt)( start & 0xFFFFU );
1716
1717               if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
1718                 FT_INVALID_DATA;
1719
1720               if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
1721                 FT_INVALID_DATA;
1722             }
1723           }
1724           else
1725           {
1726             /* start_hi == 0; check that is32[i] is 0 for each i in */
1727             /* the range [start..end]                               */
1728
1729             /* end_hi cannot be != 0! */
1730             if ( end & ~0xFFFFU )
1731               FT_INVALID_DATA;
1732
1733             for ( ; count > 0; count--, start++ )
1734             {
1735               lo = (FT_UInt)( start & 0xFFFFU );
1736
1737               if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
1738                 FT_INVALID_DATA;
1739             }
1740           }
1741         }
1742
1743         last = end;
1744       }
1745     }
1746
1747     return FT_Err_Ok;
1748   }
1749
1750
1751   FT_CALLBACK_DEF( FT_UInt )
1752   tt_cmap8_char_index( TT_CMap    cmap,
1753                        FT_UInt32  char_code )
1754   {
1755     FT_Byte*   table      = cmap->data;
1756     FT_UInt    result     = 0;
1757     FT_Byte*   p          = table + 8204;
1758     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1759     FT_UInt32  start, end, start_id;
1760
1761
1762     for ( ; num_groups > 0; num_groups-- )
1763     {
1764       start    = TT_NEXT_ULONG( p );
1765       end      = TT_NEXT_ULONG( p );
1766       start_id = TT_NEXT_ULONG( p );
1767
1768       if ( char_code < start )
1769         break;
1770
1771       if ( char_code <= end )
1772       {
1773         result = (FT_UInt)( start_id + char_code - start );
1774         break;
1775       }
1776     }
1777     return result;
1778   }
1779
1780
1781   FT_CALLBACK_DEF( FT_UInt32 )
1782   tt_cmap8_char_next( TT_CMap     cmap,
1783                       FT_UInt32  *pchar_code )
1784   {
1785     FT_UInt32  result     = 0;
1786     FT_UInt32  char_code  = *pchar_code + 1;
1787     FT_UInt    gindex     = 0;
1788     FT_Byte*   table      = cmap->data;
1789     FT_Byte*   p          = table + 8204;
1790     FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1791     FT_UInt32  start, end, start_id;
1792
1793
1794     p = table + 8208;
1795
1796     for ( ; num_groups > 0; num_groups-- )
1797     {
1798       start    = TT_NEXT_ULONG( p );
1799       end      = TT_NEXT_ULONG( p );
1800       start_id = TT_NEXT_ULONG( p );
1801
1802       if ( char_code < start )
1803         char_code = start;
1804
1805       if ( char_code <= end )
1806       {
1807         gindex = (FT_UInt)( char_code - start + start_id );
1808         if ( gindex != 0 )
1809         {
1810           result = char_code;
1811           goto Exit;
1812         }
1813       }
1814     }
1815
1816   Exit:
1817     *pchar_code = result;
1818     return gindex;
1819   }
1820
1821
1822   FT_CALLBACK_DEF( FT_Error )
1823   tt_cmap8_get_info( TT_CMap       cmap,
1824                      TT_CMapInfo  *cmap_info )
1825   {
1826     FT_Byte*  p = cmap->data + 8;
1827
1828
1829     cmap_info->format   = 8;
1830     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1831
1832     return FT_Err_Ok;
1833   }
1834
1835
1836   FT_DEFINE_TT_CMAP(
1837     tt_cmap8_class_rec,
1838     sizeof ( TT_CMapRec ),
1839
1840     (FT_CMap_InitFunc)     tt_cmap_init,
1841     (FT_CMap_DoneFunc)     NULL,
1842     (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
1843     (FT_CMap_CharNextFunc) tt_cmap8_char_next,
1844
1845     NULL,
1846     NULL,
1847     NULL,
1848     NULL,
1849     NULL,
1850
1851     8,
1852     (TT_CMap_ValidateFunc)tt_cmap8_validate,
1853     (TT_CMap_Info_GetFunc)tt_cmap8_get_info )
1854
1855 #endif /* TT_CONFIG_CMAP_FORMAT_8 */
1856
1857
1858   /*************************************************************************/
1859   /*************************************************************************/
1860   /*****                                                               *****/
1861   /*****                          FORMAT 10                            *****/
1862   /*****                                                               *****/
1863   /*************************************************************************/
1864   /*************************************************************************/
1865
1866   /*************************************************************************/
1867   /*                                                                       */
1868   /* TABLE OVERVIEW                                                        */
1869   /* --------------                                                        */
1870   /*                                                                       */
1871   /*   NAME      OFFSET  TYPE               DESCRIPTION                    */
1872   /*                                                                       */
1873   /*   format     0      USHORT             must be 10                     */
1874   /*   reserved   2      USHORT             reserved                       */
1875   /*   length     4      ULONG              length in bytes                */
1876   /*   language   8      ULONG              Mac language code              */
1877   /*                                                                       */
1878   /*   start     12      ULONG              first char in range            */
1879   /*   count     16      ULONG              number of chars in range       */
1880   /*   glyphIds  20      USHORT[count]      glyph indices covered          */
1881   /*                                                                       */
1882
1883 #ifdef TT_CONFIG_CMAP_FORMAT_10
1884
1885   FT_CALLBACK_DEF( FT_Error )
1886   tt_cmap10_validate( FT_Byte*      table,
1887                       FT_Validator  valid )
1888   {
1889     FT_Byte*  p = table + 4;
1890     FT_ULong  length, count;
1891
1892
1893     if ( table + 20 > valid->limit )
1894       FT_INVALID_TOO_SHORT;
1895
1896     length = TT_NEXT_ULONG( p );
1897     p      = table + 16;
1898     count  = TT_NEXT_ULONG( p );
1899
1900     if ( length > (FT_ULong)( valid->limit - table ) ||
1901          /* length < 20 + count * 2 ? */
1902          length < 20                                 ||
1903          ( length - 20 ) / 2 < count                 )
1904       FT_INVALID_TOO_SHORT;
1905
1906     /* check glyph indices */
1907     if ( valid->level >= FT_VALIDATE_TIGHT )
1908     {
1909       FT_UInt  gindex;
1910
1911
1912       for ( ; count > 0; count-- )
1913       {
1914         gindex = TT_NEXT_USHORT( p );
1915         if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1916           FT_INVALID_GLYPH_ID;
1917       }
1918     }
1919
1920     return FT_Err_Ok;
1921   }
1922
1923
1924   FT_CALLBACK_DEF( FT_UInt )
1925   tt_cmap10_char_index( TT_CMap    cmap,
1926                         FT_UInt32  char_code )
1927   {
1928     FT_Byte*   table  = cmap->data;
1929     FT_UInt    result = 0;
1930     FT_Byte*   p      = table + 12;
1931     FT_UInt32  start  = TT_NEXT_ULONG( p );
1932     FT_UInt32  count  = TT_NEXT_ULONG( p );
1933     FT_UInt32  idx    = (FT_ULong)( char_code - start );
1934
1935
1936     if ( idx < count )
1937     {
1938       p     += 2 * idx;
1939       result = TT_PEEK_USHORT( p );
1940     }
1941     return result;
1942   }
1943
1944
1945   FT_CALLBACK_DEF( FT_UInt32 )
1946   tt_cmap10_char_next( TT_CMap     cmap,
1947                        FT_UInt32  *pchar_code )
1948   {
1949     FT_Byte*   table     = cmap->data;
1950     FT_UInt32  char_code = *pchar_code + 1;
1951     FT_UInt    gindex    = 0;
1952     FT_Byte*   p         = table + 12;
1953     FT_UInt32  start     = TT_NEXT_ULONG( p );
1954     FT_UInt32  count     = TT_NEXT_ULONG( p );
1955     FT_UInt32  idx;
1956
1957
1958     if ( char_code < start )
1959       char_code = start;
1960
1961     idx = (FT_UInt32)( char_code - start );
1962     p  += 2 * idx;
1963
1964     for ( ; idx < count; idx++ )
1965     {
1966       gindex = TT_NEXT_USHORT( p );
1967       if ( gindex != 0 )
1968         break;
1969       char_code++;
1970     }
1971
1972     *pchar_code = char_code;
1973     return gindex;
1974   }
1975
1976
1977   FT_CALLBACK_DEF( FT_Error )
1978   tt_cmap10_get_info( TT_CMap       cmap,
1979                       TT_CMapInfo  *cmap_info )
1980   {
1981     FT_Byte*  p = cmap->data + 8;
1982
1983
1984     cmap_info->format   = 10;
1985     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1986
1987     return FT_Err_Ok;
1988   }
1989
1990
1991   FT_DEFINE_TT_CMAP(
1992     tt_cmap10_class_rec,
1993     sizeof ( TT_CMapRec ),
1994
1995     (FT_CMap_InitFunc)     tt_cmap_init,
1996     (FT_CMap_DoneFunc)     NULL,
1997     (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
1998     (FT_CMap_CharNextFunc) tt_cmap10_char_next,
1999
2000     NULL,
2001     NULL,
2002     NULL,
2003     NULL,
2004     NULL,
2005
2006     10,
2007     (TT_CMap_ValidateFunc)tt_cmap10_validate,
2008     (TT_CMap_Info_GetFunc)tt_cmap10_get_info )
2009
2010 #endif /* TT_CONFIG_CMAP_FORMAT_10 */
2011
2012
2013   /*************************************************************************/
2014   /*************************************************************************/
2015   /*****                                                               *****/
2016   /*****                          FORMAT 12                            *****/
2017   /*****                                                               *****/
2018   /*************************************************************************/
2019   /*************************************************************************/
2020
2021   /*************************************************************************/
2022   /*                                                                       */
2023   /* TABLE OVERVIEW                                                        */
2024   /* --------------                                                        */
2025   /*                                                                       */
2026   /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
2027   /*                                                                       */
2028   /*   format      0          USHORT     must be 12                        */
2029   /*   reserved    2          USHORT     reserved                          */
2030   /*   length      4          ULONG      length in bytes                   */
2031   /*   language    8          ULONG      Mac language code                 */
2032   /*   count       12         ULONG      number of groups                  */
2033   /*               16                                                      */
2034   /*                                                                       */
2035   /* This header is followed by `count' groups of the following format:    */
2036   /*                                                                       */
2037   /*   start       0          ULONG      first charcode                    */
2038   /*   end         4          ULONG      last charcode                     */
2039   /*   startId     8          ULONG      start glyph ID for the group      */
2040   /*                                                                       */
2041
2042 #ifdef TT_CONFIG_CMAP_FORMAT_12
2043
2044   typedef struct  TT_CMap12Rec_
2045   {
2046     TT_CMapRec  cmap;
2047     FT_Bool     valid;
2048     FT_ULong    cur_charcode;
2049     FT_UInt     cur_gindex;
2050     FT_ULong    cur_group;
2051     FT_ULong    num_groups;
2052
2053   } TT_CMap12Rec, *TT_CMap12;
2054
2055
2056   FT_CALLBACK_DEF( FT_Error )
2057   tt_cmap12_init( TT_CMap12  cmap,
2058                   FT_Byte*   table )
2059   {
2060     cmap->cmap.data  = table;
2061
2062     table           += 12;
2063     cmap->num_groups = FT_PEEK_ULONG( table );
2064
2065     cmap->valid      = 0;
2066
2067     return FT_Err_Ok;
2068   }
2069
2070
2071   FT_CALLBACK_DEF( FT_Error )
2072   tt_cmap12_validate( FT_Byte*      table,
2073                       FT_Validator  valid )
2074   {
2075     FT_Byte*  p;
2076     FT_ULong  length;
2077     FT_ULong  num_groups;
2078
2079
2080     if ( table + 16 > valid->limit )
2081       FT_INVALID_TOO_SHORT;
2082
2083     p      = table + 4;
2084     length = TT_NEXT_ULONG( p );
2085
2086     p          = table + 12;
2087     num_groups = TT_NEXT_ULONG( p );
2088
2089     if ( length > (FT_ULong)( valid->limit - table ) ||
2090          /* length < 16 + 12 * num_groups ? */
2091          length < 16                                 ||
2092          ( length - 16 ) / 12 < num_groups           )
2093       FT_INVALID_TOO_SHORT;
2094
2095     /* check groups, they must be in increasing order */
2096     {
2097       FT_ULong  n, start, end, start_id, last = 0;
2098
2099
2100       for ( n = 0; n < num_groups; n++ )
2101       {
2102         start    = TT_NEXT_ULONG( p );
2103         end      = TT_NEXT_ULONG( p );
2104         start_id = TT_NEXT_ULONG( p );
2105
2106         if ( start > end )
2107           FT_INVALID_DATA;
2108
2109         if ( n > 0 && start <= last )
2110           FT_INVALID_DATA;
2111
2112         if ( valid->level >= FT_VALIDATE_TIGHT )
2113         {
2114           FT_UInt32  d = end - start;
2115
2116
2117           /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
2118           if ( d > TT_VALID_GLYPH_COUNT( valid )             ||
2119                start_id >= TT_VALID_GLYPH_COUNT( valid ) - d )
2120             FT_INVALID_GLYPH_ID;
2121         }
2122
2123         last = end;
2124       }
2125     }
2126
2127     return FT_Err_Ok;
2128   }
2129
2130
2131   /* search the index of the charcode next to cmap->cur_charcode */
2132   /* cmap->cur_group should be set up properly by caller         */
2133   /*                                                             */
2134   static void
2135   tt_cmap12_next( TT_CMap12  cmap )
2136   {
2137     FT_Byte*  p;
2138     FT_ULong  start, end, start_id, char_code;
2139     FT_ULong  n;
2140     FT_UInt   gindex;
2141
2142
2143     if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
2144       goto Fail;
2145
2146     char_code = cmap->cur_charcode + 1;
2147
2148     for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
2149     {
2150       p        = cmap->cmap.data + 16 + 12 * n;
2151       start    = TT_NEXT_ULONG( p );
2152       end      = TT_NEXT_ULONG( p );
2153       start_id = TT_PEEK_ULONG( p );
2154
2155       if ( char_code < start )
2156         char_code = start;
2157
2158       for ( ; char_code <= end; char_code++ )
2159       {
2160         gindex = (FT_UInt)( start_id + char_code - start );
2161
2162         if ( gindex )
2163         {
2164           cmap->cur_charcode = char_code;;
2165           cmap->cur_gindex   = gindex;
2166           cmap->cur_group    = n;
2167
2168           return;
2169         }
2170       }
2171     }
2172
2173   Fail:
2174     cmap->valid = 0;
2175   }
2176
2177
2178   static FT_UInt
2179   tt_cmap12_char_map_binary( TT_CMap     cmap,
2180                              FT_UInt32*  pchar_code,
2181                              FT_Bool     next )
2182   {
2183     FT_UInt    gindex     = 0;
2184     FT_Byte*   p          = cmap->data + 12;
2185     FT_UInt32  num_groups = TT_PEEK_ULONG( p );
2186     FT_UInt32  char_code  = *pchar_code;
2187     FT_UInt32  start, end, start_id;
2188     FT_UInt32  max, min, mid;
2189
2190
2191     if ( !num_groups )
2192       return 0;
2193
2194     /* make compiler happy */
2195     mid = num_groups;
2196     end = 0xFFFFFFFFUL;
2197
2198     if ( next )
2199       char_code++;
2200
2201     min = 0;
2202     max = num_groups;
2203
2204     /* binary search */
2205     while ( min < max )
2206     {
2207       mid = ( min + max ) >> 1;
2208       p   = cmap->data + 16 + 12 * mid;
2209
2210       start = TT_NEXT_ULONG( p );
2211       end   = TT_NEXT_ULONG( p );
2212
2213       if ( char_code < start )
2214         max = mid;
2215       else if ( char_code > end )
2216         min = mid + 1;
2217       else
2218       {
2219         start_id = TT_PEEK_ULONG( p );
2220         gindex = (FT_UInt)( start_id + char_code - start );
2221
2222         break;
2223       }
2224     }
2225
2226     if ( next )
2227     {
2228       TT_CMap12  cmap12 = (TT_CMap12)cmap;
2229
2230
2231       /* if `char_code' is not in any group, then `mid' is */
2232       /* the group nearest to `char_code'                  */
2233       /*                                                   */
2234
2235       if ( char_code > end )
2236       {
2237         mid++;
2238         if ( mid == num_groups )
2239           return 0;
2240       }
2241
2242       cmap12->valid        = 1;
2243       cmap12->cur_charcode = char_code;
2244       cmap12->cur_group    = mid;
2245
2246       if ( !gindex )
2247       {
2248         tt_cmap12_next( cmap12 );
2249
2250         if ( cmap12->valid )
2251           gindex = cmap12->cur_gindex;
2252       }
2253       else
2254         cmap12->cur_gindex = gindex;
2255
2256       if ( gindex )
2257         *pchar_code = cmap12->cur_charcode;
2258     }
2259
2260     return gindex;
2261   }
2262
2263
2264   FT_CALLBACK_DEF( FT_UInt )
2265   tt_cmap12_char_index( TT_CMap    cmap,
2266                         FT_UInt32  char_code )
2267   {
2268     return tt_cmap12_char_map_binary( cmap, &char_code, 0 );
2269   }
2270
2271
2272   FT_CALLBACK_DEF( FT_UInt32 )
2273   tt_cmap12_char_next( TT_CMap     cmap,
2274                        FT_UInt32  *pchar_code )
2275   {
2276     TT_CMap12  cmap12 = (TT_CMap12)cmap;
2277     FT_ULong   gindex;
2278
2279
2280     if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )
2281       return 0;
2282
2283     /* no need to search */
2284     if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
2285     {
2286       tt_cmap12_next( cmap12 );
2287       if ( cmap12->valid )
2288       {
2289         gindex = cmap12->cur_gindex;
2290
2291         /* XXX: check cur_charcode overflow is expected */
2292         if ( gindex )
2293           *pchar_code = (FT_UInt32)cmap12->cur_charcode;
2294       }
2295       else
2296         gindex = 0;
2297     }
2298     else
2299       gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
2300
2301     /* XXX: check gindex overflow is expected */
2302     return (FT_UInt32)gindex;
2303   }
2304
2305
2306   FT_CALLBACK_DEF( FT_Error )
2307   tt_cmap12_get_info( TT_CMap       cmap,
2308                       TT_CMapInfo  *cmap_info )
2309   {
2310     FT_Byte*  p = cmap->data + 8;
2311
2312
2313     cmap_info->format   = 12;
2314     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2315
2316     return FT_Err_Ok;
2317   }
2318
2319
2320   FT_DEFINE_TT_CMAP(
2321     tt_cmap12_class_rec,
2322     sizeof ( TT_CMap12Rec ),
2323
2324     (FT_CMap_InitFunc)     tt_cmap12_init,
2325     (FT_CMap_DoneFunc)     NULL,
2326     (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
2327     (FT_CMap_CharNextFunc) tt_cmap12_char_next,
2328
2329     NULL,
2330     NULL,
2331     NULL,
2332     NULL,
2333     NULL,
2334
2335     12,
2336     (TT_CMap_ValidateFunc)tt_cmap12_validate,
2337     (TT_CMap_Info_GetFunc)tt_cmap12_get_info )
2338
2339 #endif /* TT_CONFIG_CMAP_FORMAT_12 */
2340
2341
2342   /*************************************************************************/
2343   /*************************************************************************/
2344   /*****                                                               *****/
2345   /*****                          FORMAT 13                            *****/
2346   /*****                                                               *****/
2347   /*************************************************************************/
2348   /*************************************************************************/
2349
2350   /*************************************************************************/
2351   /*                                                                       */
2352   /* TABLE OVERVIEW                                                        */
2353   /* --------------                                                        */
2354   /*                                                                       */
2355   /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
2356   /*                                                                       */
2357   /*   format      0          USHORT     must be 13                        */
2358   /*   reserved    2          USHORT     reserved                          */
2359   /*   length      4          ULONG      length in bytes                   */
2360   /*   language    8          ULONG      Mac language code                 */
2361   /*   count       12         ULONG      number of groups                  */
2362   /*               16                                                      */
2363   /*                                                                       */
2364   /* This header is followed by `count' groups of the following format:    */
2365   /*                                                                       */
2366   /*   start       0          ULONG      first charcode                    */
2367   /*   end         4          ULONG      last charcode                     */
2368   /*   glyphId     8          ULONG      glyph ID for the whole group      */
2369   /*                                                                       */
2370
2371 #ifdef TT_CONFIG_CMAP_FORMAT_13
2372
2373   typedef struct  TT_CMap13Rec_
2374   {
2375     TT_CMapRec  cmap;
2376     FT_Bool     valid;
2377     FT_ULong    cur_charcode;
2378     FT_UInt     cur_gindex;
2379     FT_ULong    cur_group;
2380     FT_ULong    num_groups;
2381
2382   } TT_CMap13Rec, *TT_CMap13;
2383
2384
2385   FT_CALLBACK_DEF( FT_Error )
2386   tt_cmap13_init( TT_CMap13  cmap,
2387                   FT_Byte*   table )
2388   {
2389     cmap->cmap.data  = table;
2390
2391     table           += 12;
2392     cmap->num_groups = FT_PEEK_ULONG( table );
2393
2394     cmap->valid      = 0;
2395
2396     return FT_Err_Ok;
2397   }
2398
2399
2400   FT_CALLBACK_DEF( FT_Error )
2401   tt_cmap13_validate( FT_Byte*      table,
2402                       FT_Validator  valid )
2403   {
2404     FT_Byte*  p;
2405     FT_ULong  length;
2406     FT_ULong  num_groups;
2407
2408
2409     if ( table + 16 > valid->limit )
2410       FT_INVALID_TOO_SHORT;
2411
2412     p      = table + 4;
2413     length = TT_NEXT_ULONG( p );
2414
2415     p          = table + 12;
2416     num_groups = TT_NEXT_ULONG( p );
2417
2418     if ( length > (FT_ULong)( valid->limit - table ) ||
2419          /* length < 16 + 12 * num_groups ? */
2420          length < 16                                 ||
2421          ( length - 16 ) / 12 < num_groups           )
2422       FT_INVALID_TOO_SHORT;
2423
2424     /* check groups, they must be in increasing order */
2425     {
2426       FT_ULong  n, start, end, glyph_id, last = 0;
2427
2428
2429       for ( n = 0; n < num_groups; n++ )
2430       {
2431         start    = TT_NEXT_ULONG( p );
2432         end      = TT_NEXT_ULONG( p );
2433         glyph_id = TT_NEXT_ULONG( p );
2434
2435         if ( start > end )
2436           FT_INVALID_DATA;
2437
2438         if ( n > 0 && start <= last )
2439           FT_INVALID_DATA;
2440
2441         if ( valid->level >= FT_VALIDATE_TIGHT )
2442         {
2443           if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) )
2444             FT_INVALID_GLYPH_ID;
2445         }
2446
2447         last = end;
2448       }
2449     }
2450
2451     return FT_Err_Ok;
2452   }
2453
2454
2455   /* search the index of the charcode next to cmap->cur_charcode */
2456   /* cmap->cur_group should be set up properly by caller         */
2457   /*                                                             */
2458   static void
2459   tt_cmap13_next( TT_CMap13  cmap )
2460   {
2461     FT_Byte*  p;
2462     FT_ULong  start, end, glyph_id, char_code;
2463     FT_ULong  n;
2464     FT_UInt   gindex;
2465
2466
2467     if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
2468       goto Fail;
2469
2470     char_code = cmap->cur_charcode + 1;
2471
2472     for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
2473     {
2474       p        = cmap->cmap.data + 16 + 12 * n;
2475       start    = TT_NEXT_ULONG( p );
2476       end      = TT_NEXT_ULONG( p );
2477       glyph_id = TT_PEEK_ULONG( p );
2478
2479       if ( char_code < start )
2480         char_code = start;
2481
2482       if ( char_code <= end )
2483       {
2484         gindex = (FT_UInt)glyph_id;
2485
2486         if ( gindex )
2487         {
2488           cmap->cur_charcode = char_code;;
2489           cmap->cur_gindex   = gindex;
2490           cmap->cur_group    = n;
2491
2492           return;
2493         }
2494       }
2495     }
2496
2497   Fail:
2498     cmap->valid = 0;
2499   }
2500
2501
2502   static FT_UInt
2503   tt_cmap13_char_map_binary( TT_CMap     cmap,
2504                              FT_UInt32*  pchar_code,
2505                              FT_Bool     next )
2506   {
2507     FT_UInt    gindex     = 0;
2508     FT_Byte*   p          = cmap->data + 12;
2509     FT_UInt32  num_groups = TT_PEEK_ULONG( p );
2510     FT_UInt32  char_code  = *pchar_code;
2511     FT_UInt32  start, end;
2512     FT_UInt32  max, min, mid;
2513
2514
2515     if ( !num_groups )
2516       return 0;
2517
2518     /* make compiler happy */
2519     mid = num_groups;
2520     end = 0xFFFFFFFFUL;
2521
2522     if ( next )
2523       char_code++;
2524
2525     min = 0;
2526     max = num_groups;
2527
2528     /* binary search */
2529     while ( min < max )
2530     {
2531       mid = ( min + max ) >> 1;
2532       p   = cmap->data + 16 + 12 * mid;
2533
2534       start = TT_NEXT_ULONG( p );
2535       end   = TT_NEXT_ULONG( p );
2536
2537       if ( char_code < start )
2538         max = mid;
2539       else if ( char_code > end )
2540         min = mid + 1;
2541       else
2542       {
2543         gindex = (FT_UInt)TT_PEEK_ULONG( p );
2544
2545         break;
2546       }
2547     }
2548
2549     if ( next )
2550     {
2551       TT_CMap13  cmap13 = (TT_CMap13)cmap;
2552
2553
2554       /* if `char_code' is not in any group, then `mid' is */
2555       /* the group nearest to `char_code'                  */
2556
2557       if ( char_code > end )
2558       {
2559         mid++;
2560         if ( mid == num_groups )
2561           return 0;
2562       }
2563
2564       cmap13->valid        = 1;
2565       cmap13->cur_charcode = char_code;
2566       cmap13->cur_group    = mid;
2567
2568       if ( !gindex )
2569       {
2570         tt_cmap13_next( cmap13 );
2571
2572         if ( cmap13->valid )
2573           gindex = cmap13->cur_gindex;
2574       }
2575       else
2576         cmap13->cur_gindex = gindex;
2577
2578       if ( gindex )
2579         *pchar_code = cmap13->cur_charcode;
2580     }
2581
2582     return gindex;
2583   }
2584
2585
2586   FT_CALLBACK_DEF( FT_UInt )
2587   tt_cmap13_char_index( TT_CMap    cmap,
2588                         FT_UInt32  char_code )
2589   {
2590     return tt_cmap13_char_map_binary( cmap, &char_code, 0 );
2591   }
2592
2593
2594   FT_CALLBACK_DEF( FT_UInt32 )
2595   tt_cmap13_char_next( TT_CMap     cmap,
2596                        FT_UInt32  *pchar_code )
2597   {
2598     TT_CMap13  cmap13 = (TT_CMap13)cmap;
2599     FT_UInt    gindex;
2600
2601
2602     if ( cmap13->cur_charcode >= 0xFFFFFFFFUL )
2603       return 0;
2604
2605     /* no need to search */
2606     if ( cmap13->valid && cmap13->cur_charcode == *pchar_code )
2607     {
2608       tt_cmap13_next( cmap13 );
2609       if ( cmap13->valid )
2610       {
2611         gindex = cmap13->cur_gindex;
2612         if ( gindex )
2613           *pchar_code = cmap13->cur_charcode;
2614       }
2615       else
2616         gindex = 0;
2617     }
2618     else
2619       gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 );
2620
2621     return gindex;
2622   }
2623
2624
2625   FT_CALLBACK_DEF( FT_Error )
2626   tt_cmap13_get_info( TT_CMap       cmap,
2627                       TT_CMapInfo  *cmap_info )
2628   {
2629     FT_Byte*  p = cmap->data + 8;
2630
2631
2632     cmap_info->format   = 13;
2633     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2634
2635     return FT_Err_Ok;
2636   }
2637
2638
2639   FT_DEFINE_TT_CMAP(
2640     tt_cmap13_class_rec,
2641     sizeof ( TT_CMap13Rec ),
2642
2643     (FT_CMap_InitFunc)     tt_cmap13_init,
2644     (FT_CMap_DoneFunc)     NULL,
2645     (FT_CMap_CharIndexFunc)tt_cmap13_char_index,
2646     (FT_CMap_CharNextFunc) tt_cmap13_char_next,
2647
2648     NULL,
2649     NULL,
2650     NULL,
2651     NULL,
2652     NULL,
2653
2654     13,
2655     (TT_CMap_ValidateFunc)tt_cmap13_validate,
2656     (TT_CMap_Info_GetFunc)tt_cmap13_get_info )
2657
2658 #endif /* TT_CONFIG_CMAP_FORMAT_13 */
2659
2660
2661   /*************************************************************************/
2662   /*************************************************************************/
2663   /*****                                                               *****/
2664   /*****                           FORMAT 14                           *****/
2665   /*****                                                               *****/
2666   /*************************************************************************/
2667   /*************************************************************************/
2668
2669   /*************************************************************************/
2670   /*                                                                       */
2671   /* TABLE OVERVIEW                                                        */
2672   /* --------------                                                        */
2673   /*                                                                       */
2674   /*   NAME         OFFSET  TYPE    DESCRIPTION                            */
2675   /*                                                                       */
2676   /*   format         0     USHORT  must be 14                             */
2677   /*   length         2     ULONG   table length in bytes                  */
2678   /*   numSelector    6     ULONG   number of variation sel. records       */
2679   /*                                                                       */
2680   /* Followed by numSelector records, each of which looks like             */
2681   /*                                                                       */
2682   /*   varSelector    0     UINT24  Unicode codepoint of sel.              */
2683   /*   defaultOff     3     ULONG   offset to a default UVS table          */
2684   /*                                describing any variants to be found in */
2685   /*                                the normal Unicode subtable.           */
2686   /*   nonDefOff      7     ULONG   offset to a non-default UVS table      */
2687   /*                                describing any variants not in the     */
2688   /*                                standard cmap, with GIDs here          */
2689   /* (either offset may be 0 NULL)                                         */
2690   /*                                                                       */
2691   /* Selectors are sorted by code point.                                   */
2692   /*                                                                       */
2693   /* A default Unicode Variation Selector (UVS) subtable is just a list of */
2694   /* ranges of code points which are to be found in the standard cmap.  No */
2695   /* glyph IDs (GIDs) here.                                                */
2696   /*                                                                       */
2697   /*   numRanges      0     ULONG   number of ranges following             */
2698   /*                                                                       */
2699   /* A range looks like                                                    */
2700   /*                                                                       */
2701   /*   uniStart       0     UINT24  code point of the first character in   */
2702   /*                                this range                             */
2703   /*   additionalCnt  3     UBYTE   count of additional characters in this */
2704   /*                                range (zero means a range of a single  */
2705   /*                                character)                             */
2706   /*                                                                       */
2707   /* Ranges are sorted by `uniStart'.                                      */
2708   /*                                                                       */
2709   /* A non-default Unicode Variation Selector (UVS) subtable is a list of  */
2710   /* mappings from codepoint to GID.                                       */
2711   /*                                                                       */
2712   /*   numMappings    0     ULONG   number of mappings                     */
2713   /*                                                                       */
2714   /* A range looks like                                                    */
2715   /*                                                                       */
2716   /*   uniStart       0     UINT24  code point of the first character in   */
2717   /*                                this range                             */
2718   /*   GID            3     USHORT  and its GID                            */
2719   /*                                                                       */
2720   /* Ranges are sorted by `uniStart'.                                      */
2721
2722 #ifdef TT_CONFIG_CMAP_FORMAT_14
2723
2724   typedef struct  TT_CMap14Rec_
2725   {
2726     TT_CMapRec  cmap;
2727     FT_ULong    num_selectors;
2728
2729     /* This array is used to store the results of various
2730      * cmap 14 query functions.  The data is overwritten
2731      * on each call to these functions.
2732      */
2733     FT_UInt32   max_results;
2734     FT_UInt32*  results;
2735     FT_Memory   memory;
2736
2737   } TT_CMap14Rec, *TT_CMap14;
2738
2739
2740   FT_CALLBACK_DEF( void )
2741   tt_cmap14_done( TT_CMap14  cmap )
2742   {
2743     FT_Memory  memory = cmap->memory;
2744
2745
2746     cmap->max_results = 0;
2747     if ( memory != NULL && cmap->results != NULL )
2748       FT_FREE( cmap->results );
2749   }
2750
2751
2752   static FT_Error
2753   tt_cmap14_ensure( TT_CMap14  cmap,
2754                     FT_UInt32  num_results,
2755                     FT_Memory  memory )
2756   {
2757     FT_UInt32  old_max = cmap->max_results;
2758     FT_Error   error   = FT_Err_Ok;
2759
2760
2761     if ( num_results > cmap->max_results )
2762     {
2763        cmap->memory = memory;
2764
2765        if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) )
2766          return error;
2767
2768        cmap->max_results = num_results;
2769     }
2770
2771     return error;
2772   }
2773
2774
2775   FT_CALLBACK_DEF( FT_Error )
2776   tt_cmap14_init( TT_CMap14  cmap,
2777                   FT_Byte*   table )
2778   {
2779     cmap->cmap.data = table;
2780
2781     table               += 6;
2782     cmap->num_selectors  = FT_PEEK_ULONG( table );
2783     cmap->max_results    = 0;
2784     cmap->results        = NULL;
2785
2786     return FT_Err_Ok;
2787   }
2788
2789
2790   FT_CALLBACK_DEF( FT_Error )
2791   tt_cmap14_validate( FT_Byte*      table,
2792                       FT_Validator  valid )
2793   {
2794     FT_Byte*  p;
2795     FT_ULong  length;
2796     FT_ULong  num_selectors;
2797
2798
2799     if ( table + 2 + 4 + 4 > valid->limit )
2800       FT_INVALID_TOO_SHORT;
2801
2802     p             = table + 2;
2803     length        = TT_NEXT_ULONG( p );
2804     num_selectors = TT_NEXT_ULONG( p );
2805
2806     if ( length > (FT_ULong)( valid->limit - table ) ||
2807          /* length < 10 + 11 * num_selectors ? */
2808          length < 10                                 ||
2809          ( length - 10 ) / 11 < num_selectors        )
2810       FT_INVALID_TOO_SHORT;
2811
2812     /* check selectors, they must be in increasing order */
2813     {
2814       /* we start lastVarSel at 1 because a variant selector value of 0
2815        * isn't valid.
2816        */
2817       FT_ULong  n, lastVarSel = 1;
2818
2819
2820       for ( n = 0; n < num_selectors; n++ )
2821       {
2822         FT_ULong  varSel    = TT_NEXT_UINT24( p );
2823         FT_ULong  defOff    = TT_NEXT_ULONG( p );
2824         FT_ULong  nondefOff = TT_NEXT_ULONG( p );
2825
2826
2827         if ( defOff >= length || nondefOff >= length )
2828           FT_INVALID_TOO_SHORT;
2829
2830         if ( varSel < lastVarSel )
2831           FT_INVALID_DATA;
2832
2833         lastVarSel = varSel + 1;
2834
2835         /* check the default table (these glyphs should be reached     */
2836         /* through the normal Unicode cmap, no GIDs, just check order) */
2837         if ( defOff != 0 )
2838         {
2839           FT_Byte*  defp      = table + defOff;
2840           FT_ULong  numRanges = TT_NEXT_ULONG( defp );
2841           FT_ULong  i;
2842           FT_ULong  lastBase  = 0;
2843
2844
2845           /* defp + numRanges * 4 > valid->limit ? */
2846           if ( numRanges > (FT_ULong)( valid->limit - defp ) / 4 )
2847             FT_INVALID_TOO_SHORT;
2848
2849           for ( i = 0; i < numRanges; ++i )
2850           {
2851             FT_ULong  base = TT_NEXT_UINT24( defp );
2852             FT_ULong  cnt  = FT_NEXT_BYTE( defp );
2853
2854
2855             if ( base + cnt >= 0x110000UL )              /* end of Unicode */
2856               FT_INVALID_DATA;
2857
2858             if ( base < lastBase )
2859               FT_INVALID_DATA;
2860
2861             lastBase = base + cnt + 1U;
2862           }
2863         }
2864
2865         /* and the non-default table (these glyphs are specified here) */
2866         if ( nondefOff != 0 )
2867         {
2868           FT_Byte*  ndp         = table + nondefOff;
2869           FT_ULong  numMappings = TT_NEXT_ULONG( ndp );
2870           FT_ULong  i, lastUni  = 0;
2871
2872
2873           /* numMappings * 4 > (FT_ULong)( valid->limit - ndp ) ? */
2874           if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 4 )
2875             FT_INVALID_TOO_SHORT;
2876
2877           for ( i = 0; i < numMappings; ++i )
2878           {
2879             FT_ULong  uni = TT_NEXT_UINT24( ndp );
2880             FT_ULong  gid = TT_NEXT_USHORT( ndp );
2881
2882
2883             if ( uni >= 0x110000UL )                     /* end of Unicode */
2884               FT_INVALID_DATA;
2885
2886             if ( uni < lastUni )
2887               FT_INVALID_DATA;
2888
2889             lastUni = uni + 1U;
2890
2891             if ( valid->level >= FT_VALIDATE_TIGHT    &&
2892                  gid >= TT_VALID_GLYPH_COUNT( valid ) )
2893               FT_INVALID_GLYPH_ID;
2894           }
2895         }
2896       }
2897     }
2898
2899     return FT_Err_Ok;
2900   }
2901
2902
2903   FT_CALLBACK_DEF( FT_UInt )
2904   tt_cmap14_char_index( TT_CMap    cmap,
2905                         FT_UInt32  char_code )
2906   {
2907     FT_UNUSED( cmap );
2908     FT_UNUSED( char_code );
2909
2910     /* This can't happen */
2911     return 0;
2912   }
2913
2914
2915   FT_CALLBACK_DEF( FT_UInt32 )
2916   tt_cmap14_char_next( TT_CMap     cmap,
2917                        FT_UInt32  *pchar_code )
2918   {
2919     FT_UNUSED( cmap );
2920
2921     /* This can't happen */
2922     *pchar_code = 0;
2923     return 0;
2924   }
2925
2926
2927   FT_CALLBACK_DEF( FT_Error )
2928   tt_cmap14_get_info( TT_CMap       cmap,
2929                       TT_CMapInfo  *cmap_info )
2930   {
2931     FT_UNUSED( cmap );
2932
2933     cmap_info->format   = 14;
2934     /* subtable 14 does not define a language field */
2935     cmap_info->language = 0xFFFFFFFFUL;
2936
2937     return FT_Err_Ok;
2938   }
2939
2940
2941   static FT_UInt
2942   tt_cmap14_char_map_def_binary( FT_Byte    *base,
2943                                  FT_UInt32   char_code )
2944   {
2945     FT_UInt32  numRanges = TT_PEEK_ULONG( base );
2946     FT_UInt32  max, min;
2947
2948
2949     min = 0;
2950     max = numRanges;
2951
2952     base += 4;
2953
2954     /* binary search */
2955     while ( min < max )
2956     {
2957       FT_UInt32  mid   = ( min + max ) >> 1;
2958       FT_Byte*   p     = base + 4 * mid;
2959       FT_ULong   start = TT_NEXT_UINT24( p );
2960       FT_UInt    cnt   = FT_NEXT_BYTE( p );
2961
2962
2963       if ( char_code < start )
2964         max = mid;
2965       else if ( char_code > start+cnt )
2966         min = mid + 1;
2967       else
2968         return TRUE;
2969     }
2970
2971     return FALSE;
2972   }
2973
2974
2975   static FT_UInt
2976   tt_cmap14_char_map_nondef_binary( FT_Byte    *base,
2977                                     FT_UInt32   char_code )
2978   {
2979     FT_UInt32  numMappings = TT_PEEK_ULONG( base );
2980     FT_UInt32  max, min;
2981
2982
2983     min = 0;
2984     max = numMappings;
2985
2986     base += 4;
2987
2988     /* binary search */
2989     while ( min < max )
2990     {
2991       FT_UInt32  mid = ( min + max ) >> 1;
2992       FT_Byte*   p   = base + 5 * mid;
2993       FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
2994
2995
2996       if ( char_code < uni )
2997         max = mid;
2998       else if ( char_code > uni )
2999         min = mid + 1;
3000       else
3001         return TT_PEEK_USHORT( p );
3002     }
3003
3004     return 0;
3005   }
3006
3007
3008   static FT_Byte*
3009   tt_cmap14_find_variant( FT_Byte    *base,
3010                           FT_UInt32   variantCode )
3011   {
3012     FT_UInt32  numVar = TT_PEEK_ULONG( base );
3013     FT_UInt32  max, min;
3014
3015
3016     min = 0;
3017     max = numVar;
3018
3019     base += 4;
3020
3021     /* binary search */
3022     while ( min < max )
3023     {
3024       FT_UInt32  mid    = ( min + max ) >> 1;
3025       FT_Byte*   p      = base + 11 * mid;
3026       FT_ULong   varSel = TT_NEXT_UINT24( p );
3027
3028
3029       if ( variantCode < varSel )
3030         max = mid;
3031       else if ( variantCode > varSel )
3032         min = mid + 1;
3033       else
3034         return p;
3035     }
3036
3037     return NULL;
3038   }
3039
3040
3041   FT_CALLBACK_DEF( FT_UInt )
3042   tt_cmap14_char_var_index( TT_CMap    cmap,
3043                             TT_CMap    ucmap,
3044                             FT_UInt32  charcode,
3045                             FT_UInt32  variantSelector )
3046   {
3047     FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
3048     FT_ULong  defOff;
3049     FT_ULong  nondefOff;
3050
3051
3052     if ( !p )
3053       return 0;
3054
3055     defOff    = TT_NEXT_ULONG( p );
3056     nondefOff = TT_PEEK_ULONG( p );
3057
3058     if ( defOff != 0                                                    &&
3059          tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
3060     {
3061       /* This is the default variant of this charcode.  GID not stored */
3062       /* here; stored in the normal Unicode charmap instead.           */
3063       return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode );
3064     }
3065
3066     if ( nondefOff != 0 )
3067       return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3068                                                charcode );
3069
3070     return 0;
3071   }
3072
3073
3074   FT_CALLBACK_DEF( FT_Int )
3075   tt_cmap14_char_var_isdefault( TT_CMap    cmap,
3076                                 FT_UInt32  charcode,
3077                                 FT_UInt32  variantSelector )
3078   {
3079     FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
3080     FT_ULong  defOff;
3081     FT_ULong  nondefOff;
3082
3083
3084     if ( !p )
3085       return -1;
3086
3087     defOff    = TT_NEXT_ULONG( p );
3088     nondefOff = TT_NEXT_ULONG( p );
3089
3090     if ( defOff != 0                                                    &&
3091          tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
3092       return 1;
3093
3094     if ( nondefOff != 0                                            &&
3095          tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3096                                            charcode ) != 0         )
3097       return 0;
3098
3099     return -1;
3100   }
3101
3102
3103   FT_CALLBACK_DEF( FT_UInt32* )
3104   tt_cmap14_variants( TT_CMap    cmap,
3105                       FT_Memory  memory )
3106   {
3107     TT_CMap14   cmap14 = (TT_CMap14)cmap;
3108     FT_UInt32   count  = cmap14->num_selectors;
3109     FT_Byte*    p      = cmap->data + 10;
3110     FT_UInt32*  result;
3111     FT_UInt32   i;
3112
3113
3114     if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
3115       return NULL;
3116
3117     result = cmap14->results;
3118     for ( i = 0; i < count; ++i )
3119     {
3120       result[i] = (FT_UInt32)TT_NEXT_UINT24( p );
3121       p        += 8;
3122     }
3123     result[i] = 0;
3124
3125     return result;
3126   }
3127
3128
3129   FT_CALLBACK_DEF( FT_UInt32 * )
3130   tt_cmap14_char_variants( TT_CMap    cmap,
3131                            FT_Memory  memory,
3132                            FT_UInt32  charCode )
3133   {
3134     TT_CMap14   cmap14 = (TT_CMap14)  cmap;
3135     FT_UInt32   count  = cmap14->num_selectors;
3136     FT_Byte*    p      = cmap->data + 10;
3137     FT_UInt32*  q;
3138
3139
3140     if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
3141       return NULL;
3142
3143     for ( q = cmap14->results; count > 0; --count )
3144     {
3145       FT_UInt32  varSel    = TT_NEXT_UINT24( p );
3146       FT_ULong   defOff    = TT_NEXT_ULONG( p );
3147       FT_ULong   nondefOff = TT_NEXT_ULONG( p );
3148
3149
3150       if ( ( defOff != 0                                               &&
3151              tt_cmap14_char_map_def_binary( cmap->data + defOff,
3152                                             charCode )                 ) ||
3153            ( nondefOff != 0                                            &&
3154              tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3155                                                charCode ) != 0         ) )
3156       {
3157         q[0] = varSel;
3158         q++;
3159       }
3160     }
3161     q[0] = 0;
3162
3163     return cmap14->results;
3164   }
3165
3166
3167   static FT_UInt
3168   tt_cmap14_def_char_count( FT_Byte  *p )
3169   {
3170     FT_UInt32  numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
3171     FT_UInt    tot       = 0;
3172
3173
3174     p += 3;  /* point to the first `cnt' field */
3175     for ( ; numRanges > 0; numRanges-- )
3176     {
3177       tot += 1 + p[0];
3178       p   += 4;
3179     }
3180
3181     return tot;
3182   }
3183
3184
3185   static FT_UInt32*
3186   tt_cmap14_get_def_chars( TT_CMap    cmap,
3187                            FT_Byte*   p,
3188                            FT_Memory  memory )
3189   {
3190     TT_CMap14   cmap14 = (TT_CMap14) cmap;
3191     FT_UInt32   numRanges;
3192     FT_UInt     cnt;
3193     FT_UInt32*  q;
3194
3195
3196     cnt       = tt_cmap14_def_char_count( p );
3197     numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
3198
3199     if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) )
3200       return NULL;
3201
3202     for ( q = cmap14->results; numRanges > 0; --numRanges )
3203     {
3204       FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
3205
3206
3207       cnt = FT_NEXT_BYTE( p ) + 1;
3208       do
3209       {
3210         q[0]  = uni;
3211         uni  += 1;
3212         q    += 1;
3213
3214       } while ( --cnt != 0 );
3215     }
3216     q[0] = 0;
3217
3218     return cmap14->results;
3219   }
3220
3221
3222   static FT_UInt32*
3223   tt_cmap14_get_nondef_chars( TT_CMap     cmap,
3224                               FT_Byte    *p,
3225                               FT_Memory   memory )
3226   {
3227     TT_CMap14   cmap14 = (TT_CMap14) cmap;
3228     FT_UInt32   numMappings;
3229     FT_UInt     i;
3230     FT_UInt32  *ret;
3231
3232
3233     numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
3234
3235     if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) )
3236       return NULL;
3237
3238     ret = cmap14->results;
3239     for ( i = 0; i < numMappings; ++i )
3240     {
3241       ret[i] = (FT_UInt32)TT_NEXT_UINT24( p );
3242       p += 2;
3243     }
3244     ret[i] = 0;
3245
3246     return ret;
3247   }
3248
3249
3250   FT_CALLBACK_DEF( FT_UInt32 * )
3251   tt_cmap14_variant_chars( TT_CMap    cmap,
3252                            FT_Memory  memory,
3253                            FT_UInt32  variantSelector )
3254   {
3255     FT_Byte    *p  = tt_cmap14_find_variant( cmap->data + 6,
3256                                              variantSelector );
3257     FT_Int      i;
3258     FT_ULong    defOff;
3259     FT_ULong    nondefOff;
3260
3261
3262     if ( !p )
3263       return NULL;
3264
3265     defOff    = TT_NEXT_ULONG( p );
3266     nondefOff = TT_NEXT_ULONG( p );
3267
3268     if ( defOff == 0 && nondefOff == 0 )
3269       return NULL;
3270
3271     if ( defOff == 0 )
3272       return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
3273                                          memory );
3274     else if ( nondefOff == 0 )
3275       return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
3276                                       memory );
3277     else
3278     {
3279       /* Both a default and a non-default glyph set?  That's probably not */
3280       /* good font design, but the spec allows for it...                  */
3281       TT_CMap14  cmap14 = (TT_CMap14) cmap;
3282       FT_UInt32  numRanges;
3283       FT_UInt32  numMappings;
3284       FT_UInt32  duni;
3285       FT_UInt32  dcnt;
3286       FT_UInt32  nuni;
3287       FT_Byte*   dp;
3288       FT_UInt    di, ni, k;
3289
3290       FT_UInt32  *ret;
3291
3292
3293       p  = cmap->data + nondefOff;
3294       dp = cmap->data + defOff;
3295
3296       numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
3297       dcnt        = tt_cmap14_def_char_count( dp );
3298       numRanges   = (FT_UInt32)TT_NEXT_ULONG( dp );
3299
3300       if ( numMappings == 0 )
3301         return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
3302                                         memory );
3303       if ( dcnt == 0 )
3304         return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
3305                                            memory );
3306
3307       if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) )
3308         return NULL;
3309
3310       ret  = cmap14->results;
3311       duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3312       dcnt = FT_NEXT_BYTE( dp );
3313       di   = 1;
3314       nuni = (FT_UInt32)TT_NEXT_UINT24( p );
3315       p   += 2;
3316       ni   = 1;
3317       i    = 0;
3318
3319       for ( ;; )
3320       {
3321         if ( nuni > duni + dcnt )
3322         {
3323           for ( k = 0; k <= dcnt; ++k )
3324             ret[i++] = duni + k;
3325
3326           ++di;
3327
3328           if ( di > numRanges )
3329             break;
3330
3331           duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3332           dcnt = FT_NEXT_BYTE( dp );
3333         }
3334         else
3335         {
3336           if ( nuni < duni )
3337             ret[i++] = nuni;
3338           /* If it is within the default range then ignore it -- */
3339           /* that should not have happened                       */
3340           ++ni;
3341           if ( ni > numMappings )
3342             break;
3343
3344           nuni = (FT_UInt32)TT_NEXT_UINT24( p );
3345           p += 2;
3346         }
3347       }
3348
3349       if ( ni <= numMappings )
3350       {
3351         /* If we get here then we have run out of all default ranges.   */
3352         /* We have read one non-default mapping which we haven't stored */
3353         /* and there may be others that need to be read.                */
3354         ret[i++] = nuni;
3355         while ( ni < numMappings )
3356         {
3357           ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p );
3358           p += 2;
3359           ++ni;
3360         }
3361       }
3362       else if ( di <= numRanges )
3363       {
3364         /* If we get here then we have run out of all non-default     */
3365         /* mappings.  We have read one default range which we haven't */
3366         /* stored and there may be others that need to be read.       */
3367         for ( k = 0; k <= dcnt; ++k )
3368           ret[i++] = duni + k;
3369
3370         while ( di < numRanges )
3371         {
3372           duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3373           dcnt = FT_NEXT_BYTE( dp );
3374
3375           for ( k = 0; k <= dcnt; ++k )
3376             ret[i++] = duni + k;
3377           ++di;
3378         }
3379       }
3380
3381       ret[i] = 0;
3382
3383       return ret;
3384     }
3385   }
3386
3387
3388   FT_DEFINE_TT_CMAP(
3389     tt_cmap14_class_rec,
3390     sizeof ( TT_CMap14Rec ),
3391
3392     (FT_CMap_InitFunc)     tt_cmap14_init,
3393     (FT_CMap_DoneFunc)     tt_cmap14_done,
3394     (FT_CMap_CharIndexFunc)tt_cmap14_char_index,
3395     (FT_CMap_CharNextFunc) tt_cmap14_char_next,
3396
3397     /* Format 14 extension functions */
3398     (FT_CMap_CharVarIndexFunc)    tt_cmap14_char_var_index,
3399     (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
3400     (FT_CMap_VariantListFunc)     tt_cmap14_variants,
3401     (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
3402     (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars,
3403
3404     14,
3405     (TT_CMap_ValidateFunc)tt_cmap14_validate,
3406     (TT_CMap_Info_GetFunc)tt_cmap14_get_info )
3407
3408 #endif /* TT_CONFIG_CMAP_FORMAT_14 */
3409
3410
3411 #ifndef FT_CONFIG_OPTION_PIC
3412
3413   static const TT_CMap_Class  tt_cmap_classes[] =
3414   {
3415 #define TTCMAPCITEM( a )  &a,
3416 #include "ttcmapc.h"
3417     NULL,
3418   };
3419
3420 #else /*FT_CONFIG_OPTION_PIC*/
3421
3422   void
3423   FT_Destroy_Class_tt_cmap_classes( FT_Library      library,
3424                                     TT_CMap_Class*  clazz )
3425   {
3426     FT_Memory  memory = library->memory;
3427
3428
3429     if ( clazz )
3430       FT_FREE( clazz );
3431   }
3432
3433
3434   FT_Error
3435   FT_Create_Class_tt_cmap_classes( FT_Library       library,
3436                                    TT_CMap_Class**  output_class )
3437   {
3438     TT_CMap_Class*     clazz  = NULL;
3439     TT_CMap_ClassRec*  recs;
3440     FT_Error           error;
3441     FT_Memory          memory = library->memory;
3442
3443     int  i = 0;
3444
3445
3446 #define TTCMAPCITEM( a ) i++;
3447 #include "ttcmapc.h"
3448
3449     /* allocate enough space for both the pointers */
3450     /* plus terminator and the class instances     */
3451     if ( FT_ALLOC( clazz, sizeof ( *clazz ) * ( i + 1 ) +
3452                           sizeof ( TT_CMap_ClassRec ) * i ) )
3453       return error;
3454
3455     /* the location of the class instances follows the array of pointers */
3456     recs = (TT_CMap_ClassRec*)( (char*)clazz +
3457                                 sizeof ( *clazz ) * ( i + 1 ) );
3458     i    = 0;
3459
3460 #undef TTCMAPCITEM
3461 #define  TTCMAPCITEM( a )             \
3462     FT_Init_Class_ ## a( &recs[i] );  \
3463     clazz[i] = &recs[i];              \
3464     i++;
3465 #include "ttcmapc.h"
3466
3467     clazz[i] = NULL;
3468
3469     *output_class = clazz;
3470     return FT_Err_Ok;
3471   }
3472
3473 #endif /*FT_CONFIG_OPTION_PIC*/
3474
3475
3476   /* parse the `cmap' table and build the corresponding TT_CMap objects */
3477   /* in the current face                                                */
3478   /*                                                                    */
3479   FT_LOCAL_DEF( FT_Error )
3480   tt_face_build_cmaps( TT_Face  face )
3481   {
3482     FT_Byte*           table = face->cmap_table;
3483     FT_Byte*           limit = table + face->cmap_size;
3484     FT_UInt volatile   num_cmaps;
3485     FT_Byte* volatile  p     = table;
3486     FT_Library         library = FT_FACE_LIBRARY( face );
3487
3488     FT_UNUSED( library );
3489
3490
3491     if ( !p || p + 4 > limit )
3492       return FT_THROW( Invalid_Table );
3493
3494     /* only recognize format 0 */
3495     if ( TT_NEXT_USHORT( p ) != 0 )
3496     {
3497       FT_ERROR(( "tt_face_build_cmaps:"
3498                  " unsupported `cmap' table format = %d\n",
3499                  TT_PEEK_USHORT( p - 2 ) ));
3500       return FT_THROW( Invalid_Table );
3501     }
3502
3503     num_cmaps = TT_NEXT_USHORT( p );
3504
3505     for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
3506     {
3507       FT_CharMapRec  charmap;
3508       FT_UInt32      offset;
3509
3510
3511       charmap.platform_id = TT_NEXT_USHORT( p );
3512       charmap.encoding_id = TT_NEXT_USHORT( p );
3513       charmap.face        = FT_FACE( face );
3514       charmap.encoding    = FT_ENCODING_NONE;  /* will be filled later */
3515       offset              = TT_NEXT_ULONG( p );
3516
3517       if ( offset && offset <= face->cmap_size - 2 )
3518       {
3519         FT_Byte* volatile              cmap   = table + offset;
3520         volatile FT_UInt               format = TT_PEEK_USHORT( cmap );
3521         const TT_CMap_Class* volatile  pclazz = TT_CMAP_CLASSES_GET;
3522         TT_CMap_Class volatile         clazz;
3523
3524
3525         for ( ; *pclazz; pclazz++ )
3526         {
3527           clazz = *pclazz;
3528           if ( clazz->format == format )
3529           {
3530             volatile TT_ValidatorRec  valid;
3531             volatile FT_Error         error = FT_Err_Ok;
3532
3533
3534             ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
3535                                FT_VALIDATE_DEFAULT );
3536
3537             valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
3538
3539             if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer) == 0 )
3540             {
3541               /* validate this cmap sub-table */
3542               error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
3543             }
3544
3545             if ( valid.validator.error == 0 )
3546             {
3547               FT_CMap  ttcmap;
3548
3549
3550               /* It might make sense to store the single variation         */
3551               /* selector cmap somewhere special.  But it would have to be */
3552               /* in the public FT_FaceRec, and we can't change that.       */
3553
3554               if ( !FT_CMap_New( (FT_CMap_Class)clazz,
3555                                  cmap, &charmap, &ttcmap ) )
3556               {
3557                 /* it is simpler to directly set `flags' than adding */
3558                 /* a parameter to FT_CMap_New                        */
3559                 ((TT_CMap)ttcmap)->flags = (FT_Int)error;
3560               }
3561             }
3562             else
3563             {
3564               FT_TRACE0(( "tt_face_build_cmaps:"
3565                           " broken cmap sub-table ignored\n" ));
3566             }
3567             break;
3568           }
3569         }
3570
3571         if ( *pclazz == NULL )
3572         {
3573           FT_TRACE0(( "tt_face_build_cmaps:"
3574                       " unsupported cmap sub-table ignored\n" ));
3575         }
3576       }
3577     }
3578
3579     return FT_Err_Ok;
3580   }
3581
3582
3583   FT_LOCAL( FT_Error )
3584   tt_get_cmap_info( FT_CharMap    charmap,
3585                     TT_CMapInfo  *cmap_info )
3586   {
3587     FT_CMap        cmap  = (FT_CMap)charmap;
3588     TT_CMap_Class  clazz = (TT_CMap_Class)cmap->clazz;
3589
3590
3591     return clazz->get_cmap_info( charmap, cmap_info );
3592   }
3593
3594
3595 /* END */