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