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

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

PDF plugin: freetype library updated to version 2.3.5

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