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