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

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

PDF plugin: freetype library updated to version 2.3.9

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