source: trunk/poppler/freetype2/src/sfnt/ttcmap.c @ 262

Last change on this file since 262 was 262, checked in by Eugene Romanenko, 13 years ago

PDF plugin: freetype library updated to version 2.3.8

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