source: trunk/poppler/freetype-2.1.10/src/sfnt/ttcmap.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 15 years ago

First import

File size: 68.3 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  ttcmap.c                                                               */
4/*                                                                         */
5/*    TrueType character mapping table (cmap) support (body).              */
6/*                                                                         */
7/*  Copyright 2002, 2003, 2004, 2005 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_LONG    FT_PEEK_LONG
43#define TT_PEEK_ULONG   FT_PEEK_ULONG
44
45#define TT_NEXT_SHORT   FT_NEXT_SHORT
46#define TT_NEXT_USHORT  FT_NEXT_USHORT
47#define TT_NEXT_LONG    FT_NEXT_LONG
48#define TT_NEXT_ULONG   FT_NEXT_ULONG
49
50
51  FT_CALLBACK_DEF( FT_Error )
52  tt_cmap_init( TT_CMap   cmap,
53                FT_Byte*  table )
54  {
55    cmap->data = table;
56    return SFNT_Err_Ok;
57  }
58
59
60  /*************************************************************************/
61  /*************************************************************************/
62  /*****                                                               *****/
63  /*****                           FORMAT 0                            *****/
64  /*****                                                               *****/
65  /*************************************************************************/
66  /*************************************************************************/
67
68  /*************************************************************************/
69  /*                                                                       */
70  /* TABLE OVERVIEW                                                        */
71  /* --------------                                                        */
72  /*                                                                       */
73  /*   NAME        OFFSET         TYPE          DESCRIPTION                */
74  /*                                                                       */
75  /*   format      0              USHORT        must be 0                  */
76  /*   length      2              USHORT        table length in bytes      */
77  /*   language    4              USHORT        Mac language code          */
78  /*   glyph_ids   6              BYTE[256]     array of glyph indices     */
79  /*               262                                                     */
80  /*                                                                       */
81
82#ifdef TT_CONFIG_CMAP_FORMAT_0
83
84  FT_CALLBACK_DEF( FT_Error )
85  tt_cmap0_validate( FT_Byte*      table,
86                     FT_Validator  valid )
87  {
88    FT_Byte*  p      = table + 2;
89    FT_UInt   length = TT_NEXT_USHORT( p );
90
91
92    if ( table + length > valid->limit || length < 262 )
93      FT_INVALID_TOO_SHORT;
94
95    /* check glyph indices whenever necessary */
96    if ( valid->level >= FT_VALIDATE_TIGHT )
97    {
98      FT_UInt  n, idx;
99
100
101      p = table + 6;
102      for ( n = 0; n < 256; n++ )
103      {
104        idx = *p++;
105        if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
106          FT_INVALID_GLYPH_ID;
107      }
108    }
109
110    return SFNT_Err_Ok;
111  }
112
113
114  FT_CALLBACK_DEF( FT_UInt )
115  tt_cmap0_char_index( TT_CMap    cmap,
116                       FT_UInt32  char_code )
117  {
118    FT_Byte*  table = cmap->data;
119
120
121    return char_code < 256 ? table[6 + char_code] : 0;
122  }
123
124
125  FT_CALLBACK_DEF( FT_UInt )
126  tt_cmap0_char_next( TT_CMap     cmap,
127                      FT_UInt32  *pchar_code )
128  {
129    FT_Byte*   table    = cmap->data;
130    FT_UInt32  charcode = *pchar_code;
131    FT_UInt32  result   = 0;
132    FT_UInt    gindex   = 0;
133
134
135    table += 6;  /* go to glyph ids */
136    while ( ++charcode < 256 )
137    {
138      gindex = table[charcode];
139      if ( gindex != 0 )
140      {
141        result = charcode;
142        break;
143      }
144    }
145
146    *pchar_code = result;
147    return gindex;
148  }
149
150
151  FT_CALLBACK_DEF( FT_Error )
152  tt_cmap0_get_info( TT_CMap       cmap,
153                     TT_CMapInfo  *cmap_info )
154  {
155    FT_Byte*  p = cmap->data + 4;
156
157
158    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
159
160    return SFNT_Err_Ok;
161  }
162
163
164  FT_CALLBACK_TABLE_DEF
165  const TT_CMap_ClassRec  tt_cmap0_class_rec =
166  {
167    {
168      sizeof ( TT_CMapRec ),
169
170      (FT_CMap_InitFunc)     tt_cmap_init,
171      (FT_CMap_DoneFunc)     NULL,
172      (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
173      (FT_CMap_CharNextFunc) tt_cmap0_char_next
174    },
175    0,
176    (TT_CMap_ValidateFunc)   tt_cmap0_validate,
177    (TT_CMap_Info_GetFunc)   tt_cmap0_get_info
178  };
179
180#endif /* TT_CONFIG_CMAP_FORMAT_0 */
181
182
183  /*************************************************************************/
184  /*************************************************************************/
185  /*****                                                               *****/
186  /*****                          FORMAT 2                             *****/
187  /*****                                                               *****/
188  /***** This is used for certain CJK encodings that encode text in a  *****/
189  /***** mixed 8/16 bits encoding along the following lines:           *****/
190  /*****                                                               *****/
191  /***** * Certain byte values correspond to an 8-bit character code   *****/
192  /*****   (typically in the range 0..127 for ASCII compatibility).    *****/
193  /*****                                                               *****/
194  /***** * Certain byte values signal the first byte of a 2-byte       *****/
195  /*****   character code (but these values are also valid as the      *****/
196  /*****   second byte of a 2-byte character).                         *****/
197  /*****                                                               *****/
198  /***** The following charmap lookup and iteration functions all      *****/
199  /***** assume that the value "charcode" correspond to following:     *****/
200  /*****                                                               *****/
201  /*****   - For one byte characters, "charcode" is simply the         *****/
202  /*****     character code.                                           *****/
203  /*****                                                               *****/
204  /*****   - For two byte characters, "charcode" is the 2-byte         *****/
205  /*****     character code in big endian format.  More exactly:       *****/
206  /*****                                                               *****/
207  /*****       (charcode >> 8)    is the first byte value              *****/
208  /*****       (charcode & 0xFF)  is the second byte value             *****/
209  /*****                                                               *****/
210  /***** Note that not all values of "charcode" are valid according    *****/
211  /***** to these rules, and the function moderately check the         *****/
212  /***** arguments.                                                    *****/
213  /*****                                                               *****/
214  /*************************************************************************/
215  /*************************************************************************/
216
217  /*************************************************************************/
218  /*                                                                       */
219  /* TABLE OVERVIEW                                                        */
220  /* --------------                                                        */
221  /*                                                                       */
222  /*   NAME        OFFSET         TYPE            DESCRIPTION              */
223  /*                                                                       */
224  /*   format      0              USHORT          must be 2                */
225  /*   length      2              USHORT          table length in bytes    */
226  /*   language    4              USHORT          Mac language code        */
227  /*   keys        6              USHORT[256]     sub-header keys          */
228  /*   subs        518            SUBHEAD[NSUBS]  sub-headers array        */
229  /*   glyph_ids   518+NSUB*8     USHORT[]        glyph id array           */
230  /*                                                                       */
231  /* The `keys' table is used to map charcode high-bytes to sub-headers.   */
232  /* The value of `NSUBS' is the number of sub-headers defined in the      */
233  /* table and is computed by finding the maximum of the `keys' table.     */
234  /*                                                                       */
235  /* Note that for any n, `keys[n]' is a byte offset within the `subs'     */
236  /* table, i.e., it is the corresponding sub-header index multiplied      */
237  /* by 8.                                                                 */
238  /*                                                                       */
239  /* Each sub-header has the following format:                             */
240  /*                                                                       */
241  /*   NAME        OFFSET      TYPE            DESCRIPTION                 */
242  /*                                                                       */
243  /*   first       0           USHORT          first valid low-byte        */
244  /*   count       2           USHORT          number of valid low-bytes   */
245  /*   delta       4           SHORT           see below                   */
246  /*   offset      6           USHORT          see below                   */
247  /*                                                                       */
248  /* A sub-header defines, for each high-byte, the range of valid          */
249  /* low-bytes within the charmap.  Note that the range defined by `first' */
250  /* and `count' must be completely included in the interval [0..255]      */
251  /* according to the specification.                                       */
252  /*                                                                       */
253  /* If a character code is contained within a given sub-header, then      */
254  /* mapping it to a glyph index is done as follows:                       */
255  /*                                                                       */
256  /* * The value of `offset' is read.  This is a _byte_ distance from the  */
257  /*   location of the `offset' field itself into a slice of the           */
258  /*   `glyph_ids' table.  Let's call it `slice' (it's a USHORT[] too).    */
259  /*                                                                       */
260  /* * The value `slice[char.lo - first]' is read.  If it is 0, there is   */
261  /*   no glyph for the charcode.  Otherwise, the value of `delta' is      */
262  /*   added to it (modulo 65536) to form a new glyph index.               */
263  /*                                                                       */
264  /* It is up to the validation routine to check that all offsets fall     */
265  /* within the glyph ids table (and not within the `subs' table itself or */
266  /* outside of the CMap).                                                 */
267  /*                                                                       */
268
269#ifdef TT_CONFIG_CMAP_FORMAT_2
270
271  FT_CALLBACK_DEF( FT_Error )
272  tt_cmap2_validate( FT_Byte*      table,
273                     FT_Validator  valid )
274  {
275    FT_Byte*  p      = table + 2;           /* skip format */
276    FT_UInt   length = TT_PEEK_USHORT( p );
277    FT_UInt   n, max_subs;
278    FT_Byte*  keys;                         /* keys table */
279    FT_Byte*  subs;                         /* sub-headers */
280    FT_Byte*  glyph_ids;                    /* glyph id array */
281
282
283    if ( table + length > valid->limit || length < 6 + 512 )
284      FT_INVALID_TOO_SHORT;
285
286    keys = table + 6;
287
288    /* parse keys to compute sub-headers count */
289    p        = keys;
290    max_subs = 0;
291    for ( n = 0; n < 256; n++ )
292    {
293      FT_UInt  idx = TT_NEXT_USHORT( p );
294
295
296      /* value must be multiple of 8 */
297      if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
298        FT_INVALID_DATA;
299
300      idx >>= 3;
301
302      if ( idx > max_subs )
303        max_subs = idx;
304    }
305
306    FT_ASSERT( p == table + 518 );
307
308    subs      = p;
309    glyph_ids = subs + (max_subs + 1) * 8;
310    if ( glyph_ids > valid->limit )
311      FT_INVALID_TOO_SHORT;
312
313    /* parse sub-headers */
314    for ( n = 0; n <= max_subs; n++ )
315    {
316      FT_UInt   first_code, code_count, offset;
317      FT_Int    delta;
318      FT_Byte*  ids;
319
320
321      first_code = TT_NEXT_USHORT( p );
322      code_count = TT_NEXT_USHORT( p );
323      delta      = TT_NEXT_SHORT( p );
324      offset     = TT_NEXT_USHORT( p );
325
326      /* check range within 0..255 */
327      if ( valid->level >= FT_VALIDATE_PARANOID )
328      {
329        if ( first_code >= 256 || first_code + code_count > 256 )
330          FT_INVALID_DATA;
331      }
332
333      /* check offset */
334      if ( offset != 0 )
335      {
336        ids = p - 2 + offset;
337        if ( ids < glyph_ids || ids + code_count*2 > table + length )
338          FT_INVALID_OFFSET;
339
340        /* check glyph ids */
341        if ( valid->level >= FT_VALIDATE_TIGHT )
342        {
343          FT_Byte*  limit = p + code_count * 2;
344          FT_UInt   idx;
345
346
347          for ( ; p < limit; )
348          {
349            idx = TT_NEXT_USHORT( p );
350            if ( idx != 0 )
351            {
352              idx = ( idx + delta ) & 0xFFFFU;
353              if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
354                FT_INVALID_GLYPH_ID;
355            }
356          }
357        }
358      }
359    }
360
361    return SFNT_Err_Ok;
362  }
363
364
365  /* return sub header corresponding to a given character code */
366  /* NULL on invalid charcode                                  */
367  static FT_Byte*
368  tt_cmap2_get_subheader( FT_Byte*   table,
369                          FT_UInt32  char_code )
370  {
371    FT_Byte*  result = NULL;
372
373
374    if ( char_code < 0x10000UL )
375    {
376      FT_UInt   char_lo = (FT_UInt)( char_code & 0xFF );
377      FT_UInt   char_hi = (FT_UInt)( char_code >> 8 );
378      FT_Byte*  p       = table + 6;    /* keys table */
379      FT_Byte*  subs    = table + 518;  /* subheaders table */
380      FT_Byte*  sub;
381
382
383      if ( char_hi == 0 )
384      {
385        /* an 8-bit character code -- we use subHeader 0 in this case */
386        /* to test whether the character code is in the charmap       */
387        /*                                                            */
388        sub = subs;  /* jump to first sub-header */
389
390        /* check that the sub-header for this byte is 0, which */
391        /* indicates that it's really a valid one-byte value   */
392        /* Otherwise, return 0                                 */
393        /*                                                     */
394        p += char_lo * 2;
395        if ( TT_PEEK_USHORT( p ) != 0 )
396          goto Exit;
397      }
398      else
399      {
400        /* a 16-bit character code */
401
402        /* jump to key entry  */
403        p  += char_hi * 2;
404        /* jump to sub-header */
405        sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) );
406
407        /* check that the high byte isn't a valid one-byte value */
408        if ( sub == subs )
409          goto Exit;
410      }
411      result = sub;
412    }
413  Exit:
414    return result;
415  }
416
417
418  FT_CALLBACK_DEF( FT_UInt )
419  tt_cmap2_char_index( TT_CMap    cmap,
420                       FT_UInt32  char_code )
421  {
422    FT_Byte*  table   = cmap->data;
423    FT_UInt   result  = 0;
424    FT_Byte*  subheader;
425
426
427    subheader = tt_cmap2_get_subheader( table, char_code );
428    if ( subheader )
429    {
430      FT_Byte*  p   = subheader;
431      FT_UInt   idx = (FT_UInt)(char_code & 0xFF);
432      FT_UInt   start, count;
433      FT_Int    delta;
434      FT_UInt   offset;
435
436
437      start  = TT_NEXT_USHORT( p );
438      count  = TT_NEXT_USHORT( p );
439      delta  = TT_NEXT_SHORT ( p );
440      offset = TT_PEEK_USHORT( p );
441
442      idx -= start;
443      if ( idx < count && offset != 0 )
444      {
445        p  += offset + 2 * idx;
446        idx = TT_PEEK_USHORT( p );
447
448        if ( idx != 0 )
449          result = (FT_UInt)( idx + delta ) & 0xFFFFU;
450      }
451    }
452    return result;
453  }
454
455
456  FT_CALLBACK_DEF( FT_UInt )
457  tt_cmap2_char_next( TT_CMap     cmap,
458                      FT_UInt32  *pcharcode )
459  {
460    FT_Byte*   table    = cmap->data;
461    FT_UInt    gindex   = 0;
462    FT_UInt32  result   = 0;
463    FT_UInt32  charcode = *pcharcode + 1;
464    FT_Byte*   subheader;
465
466
467    while ( charcode < 0x10000UL )
468    {
469      subheader = tt_cmap2_get_subheader( table, charcode );
470      if ( subheader )
471      {
472        FT_Byte*  p       = subheader;
473        FT_UInt   start   = TT_NEXT_USHORT( p );
474        FT_UInt   count   = TT_NEXT_USHORT( p );
475        FT_Int    delta   = TT_NEXT_SHORT ( p );
476        FT_UInt   offset  = TT_PEEK_USHORT( p );
477        FT_UInt   char_lo = (FT_UInt)( charcode & 0xFF );
478        FT_UInt   pos, idx;
479
480
481        if ( offset == 0 )
482          goto Next_SubHeader;
483
484        if ( char_lo < start )
485        {
486          char_lo = start;
487          pos     = 0;
488        }
489        else
490          pos = (FT_UInt)( char_lo - start );
491
492        p       += offset + pos * 2;
493        charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo;
494
495        for ( ; pos < count; pos++, charcode++ )
496        {
497          idx = TT_NEXT_USHORT( p );
498
499          if ( idx != 0 )
500          {
501            gindex = ( idx + delta ) & 0xFFFFU;
502            if ( gindex != 0 )
503            {
504              result = charcode;
505              goto Exit;
506            }
507          }
508        }
509      }
510
511      /* jump to next sub-header, i.e. higher byte value */
512    Next_SubHeader:
513      charcode = FT_PAD_FLOOR( charcode, 256 ) + 256;
514    }
515
516  Exit:
517    *pcharcode = result;
518
519    return gindex;
520  }
521
522
523  FT_CALLBACK_DEF( FT_Error )
524  tt_cmap2_get_info( TT_CMap       cmap,
525                     TT_CMapInfo  *cmap_info )
526  {
527    FT_Byte*  p = cmap->data + 4;
528
529
530    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
531
532    return SFNT_Err_Ok;
533  }
534
535
536  FT_CALLBACK_TABLE_DEF
537  const TT_CMap_ClassRec  tt_cmap2_class_rec =
538  {
539    {
540      sizeof ( TT_CMapRec ),
541
542      (FT_CMap_InitFunc)     tt_cmap_init,
543      (FT_CMap_DoneFunc)     NULL,
544      (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
545      (FT_CMap_CharNextFunc) tt_cmap2_char_next
546    },
547    2,
548    (TT_CMap_ValidateFunc)   tt_cmap2_validate,
549    (TT_CMap_Info_GetFunc)   tt_cmap2_get_info
550  };
551
552#endif /* TT_CONFIG_CMAP_FORMAT_2 */
553
554
555  /*************************************************************************/
556  /*************************************************************************/
557  /*****                                                               *****/
558  /*****                           FORMAT 4                            *****/
559  /*****                                                               *****/
560  /*************************************************************************/
561  /*************************************************************************/
562
563  /*************************************************************************/
564  /*                                                                       */
565  /* TABLE OVERVIEW                                                        */
566  /* --------------                                                        */
567  /*                                                                       */
568  /*   NAME          OFFSET         TYPE              DESCRIPTION          */
569  /*                                                                       */
570  /*   format        0              USHORT            must be 4            */
571  /*   length        2              USHORT            table length         */
572  /*                                                  in bytes             */
573  /*   language      4              USHORT            Mac language code    */
574  /*                                                                       */
575  /*   segCountX2    6              USHORT            2*NUM_SEGS           */
576  /*   searchRange   8              USHORT            2*(1 << LOG_SEGS)    */
577  /*   entrySelector 10             USHORT            LOG_SEGS             */
578  /*   rangeShift    12             USHORT            segCountX2 -         */
579  /*                                                    searchRange        */
580  /*                                                                       */
581  /*   endCount      14             USHORT[NUM_SEGS]  end charcode for     */
582  /*                                                  each segment; last   */
583  /*                                                  is 0xFFFF            */
584  /*                                                                       */
585  /*   pad           14+NUM_SEGS*2  USHORT            padding              */
586  /*                                                                       */
587  /*   startCount    16+NUM_SEGS*2  USHORT[NUM_SEGS]  first charcode for   */
588  /*                                                  each segment         */
589  /*                                                                       */
590  /*   idDelta       16+NUM_SEGS*4  SHORT[NUM_SEGS]   delta for each       */
591  /*                                                  segment              */
592  /*   idOffset      16+NUM_SEGS*6  SHORT[NUM_SEGS]   range offset for     */
593  /*                                                  each segment; can be */
594  /*                                                  zero                 */
595  /*                                                                       */
596  /*   glyphIds      16+NUM_SEGS*8  USHORT[]          array of glyph id    */
597  /*                                                  ranges               */
598  /*                                                                       */
599  /* Character codes are modelled by a series of ordered (increasing)      */
600  /* intervals called segments.  Each segment has start and end codes,     */
601  /* provided by the `startCount' and `endCount' arrays.  Segments must    */
602  /* not be overlapping and the last segment should always contain the     */
603  /* `0xFFFF' endCount.                                                    */
604  /*                                                                       */
605  /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
606  /* ignored (they are traces of over-engineering in the TrueType          */
607  /* specification).                                                       */
608  /*                                                                       */
609  /* Each segment also has a signed `delta', as well as an optional offset */
610  /* within the `glyphIds' table.                                          */
611  /*                                                                       */
612  /* If a segment's idOffset is 0, the glyph index corresponding to any    */
613  /* charcode within the segment is obtained by adding the value of        */
614  /* `idDelta' directly to the charcode, modulo 65536.                     */
615  /*                                                                       */
616  /* Otherwise, a glyph index is taken from the glyph ids sub-array for    */
617  /* the segment, and the value of `idDelta' is added to it.               */
618  /*                                                                       */
619  /*                                                                       */
620  /* Finally, note that certain fonts contain invalid charmaps that        */
621  /* contain end=0xFFFF, start=0xFFFF, delta=0x0001, offset=0xFFFF at the  */
622  /* of their charmaps (e.g. opens___.ttf which comes with OpenOffice.org) */
623  /* we need special code to deal with them correctly...                   */
624  /*                                                                       */
625
626#ifdef TT_CONFIG_CMAP_FORMAT_4
627
628#define  OPT_CMAP4
629
630#ifdef OPT_CMAP4
631
632  typedef struct  TT_CMap4Rec_
633  {
634    TT_CMapRec  cmap;
635    FT_UInt32   old_charcode;   /* old charcode */
636    FT_UInt32   cur_charcode;   /* current charcode */
637    FT_UInt     cur_gindex;     /* current glyph index */
638
639    FT_UInt     table_length;
640    FT_UInt     num_ranges;
641    FT_UInt     cur_range;
642    FT_UInt     cur_start;
643    FT_UInt     cur_end;
644    FT_Int      cur_delta;
645    FT_Byte*    cur_values;
646
647  } TT_CMap4Rec, *TT_CMap4;
648
649
650  FT_CALLBACK_DEF( FT_Error )
651  tt_cmap4_init( TT_CMap4  cmap,
652                 FT_Byte*  table )
653  {
654    FT_Byte*  p;
655
656
657    cmap->cmap.data    = table;
658
659    p                  = table + 2;
660    cmap->table_length = FT_PEEK_USHORT( p );
661
662    p                  = table + 6;
663    cmap->num_ranges   = FT_PEEK_USHORT( p ) >> 1;
664    cmap->cur_range    = cmap->num_ranges;
665    cmap->old_charcode = 0xFFFFFFFFUL;
666    cmap->cur_charcode = 0;
667    cmap->cur_gindex   = 0;
668
669    return SFNT_Err_Ok;
670  }
671
672
673  static FT_Int
674  tt_cmap4_set_range( TT_CMap4  cmap,
675                      FT_UInt   range_index )
676  {
677    FT_Byte*  table = cmap->cmap.data;
678    FT_Byte*  p;
679    FT_UInt   num_ranges = cmap->num_ranges;
680
681
682    while ( range_index < num_ranges )
683    {
684      FT_UInt  offset;
685
686
687      p             = table + 14 + range_index * 2;
688      cmap->cur_end = FT_PEEK_USHORT( p );
689
690      p              += 2 + num_ranges * 2;
691      cmap->cur_start = FT_PEEK_USHORT( p );
692
693      p              += num_ranges * 2;
694      cmap->cur_delta = FT_PEEK_SHORT( p );
695
696      p     += num_ranges * 2;
697      offset = FT_PEEK_USHORT( p );
698
699      if ( offset != 0xFFFFU )
700      {
701        cmap->cur_values = offset ? p + offset : NULL;
702        cmap->cur_range  = range_index;
703        return 0;
704      }
705
706      /* we skip empty segments */
707      range_index++;
708    }
709
710    cmap->old_charcode = 0xFFFFFFFFUL;
711    cmap->cur_charcode = 0;
712    cmap->cur_gindex   = 0;
713    cmap->cur_range    = num_ranges;
714    return -1;
715  }
716
717
718  static void
719  tt_cmap4_next( TT_CMap4  cmap )
720  {
721    FT_UInt  charcode   = cmap->cur_charcode + 1;
722
723
724    cmap->old_charcode = cmap->cur_charcode;
725
726    for ( ;; )
727    {
728      FT_Byte*  values = cmap->cur_values;
729      FT_UInt   end    = cmap->cur_end;
730      FT_Int    delta  = cmap->cur_delta;
731
732
733      if ( charcode <= end )
734      {
735        if ( values )
736        {
737          FT_Byte*  p = values + 2 * ( charcode - cmap->cur_start );
738
739
740          do
741          {
742            FT_UInt  gindex = FT_NEXT_USHORT( p );
743
744
745            if ( gindex != 0 )
746            {
747              gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU );
748              if ( gindex != 0 )
749              {
750                cmap->cur_charcode = charcode;
751                cmap->cur_gindex   = gindex;
752                return;
753              }
754            }
755          } while ( ++charcode <= end );
756        }
757        else
758        {
759          do
760          {
761            FT_UInt  gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU );
762
763
764            if ( gindex != 0 )
765            {
766              cmap->cur_charcode = charcode;
767              cmap->cur_gindex   = gindex;
768              return;
769            }
770          } while ( ++charcode <= end );
771        }
772      }
773
774      /* we need to find another range */
775      if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )
776        break;
777
778      charcode = cmap->cur_start;
779    }
780  }
781
782
783  static void
784  tt_cmap4_reset( TT_CMap4  cmap,
785                  FT_UInt   code,
786                  FT_UInt   range_index )
787  {
788    if ( tt_cmap4_set_range( cmap, range_index ) >= 0 )
789    {
790      cmap->cur_charcode = code;
791      tt_cmap4_next( cmap );
792    }
793  }
794
795#endif /* OPT_CMAP4 */
796
797
798
799  FT_CALLBACK_DEF( FT_Error )
800  tt_cmap4_validate( FT_Byte*      table,
801                     FT_Validator  valid )
802  {
803    FT_Byte*  p      = table + 2;               /* skip format */
804    FT_UInt   length = TT_NEXT_USHORT( p );
805    FT_Byte   *ends, *starts, *offsets, *deltas, *glyph_ids;
806    FT_UInt   num_segs;
807    FT_Error  error = SFNT_Err_Ok;
808
809
810    /* in certain fonts, the `length' field is invalid and goes */
811    /* out of bound.  We try to correct this here...            */
812    if ( length < 16 )
813      FT_INVALID_TOO_SHORT;
814
815    if ( table + length > valid->limit )
816    {
817      if ( valid->level >= FT_VALIDATE_TIGHT )
818        FT_INVALID_TOO_SHORT;
819
820      length = (FT_UInt)( valid->limit - table );
821    }
822
823    p        = table + 6;
824    num_segs = TT_NEXT_USHORT( p );   /* read segCountX2 */
825
826    if ( valid->level >= FT_VALIDATE_PARANOID )
827    {
828      /* check that we have an even value here */
829      if ( num_segs & 1 )
830        FT_INVALID_DATA;
831    }
832
833    num_segs /= 2;
834
835    /* check the search parameters - even though we never use them */
836    /*                                                             */
837    if ( valid->level >= FT_VALIDATE_PARANOID )
838    {
839      /* check the values of 'searchRange', 'entrySelector', 'rangeShift' */
840      FT_UInt  search_range   = TT_NEXT_USHORT( p );
841      FT_UInt  entry_selector = TT_NEXT_USHORT( p );
842      FT_UInt  range_shift    = TT_NEXT_USHORT( p );
843
844
845      if ( ( search_range | range_shift ) & 1 )  /* must be even values */
846        FT_INVALID_DATA;
847
848      search_range /= 2;
849      range_shift  /= 2;
850
851      /* `search range' is the greatest power of 2 that is <= num_segs */
852
853      if ( search_range                > num_segs                 ||
854           search_range * 2            < num_segs                 ||
855           search_range + range_shift != num_segs                 ||
856           search_range               != ( 1U << entry_selector ) )
857        FT_INVALID_DATA;
858    }
859
860    ends      = table   + 14;
861    starts    = table   + 16 + num_segs * 2;
862    deltas    = starts  + num_segs * 2;
863    offsets   = deltas  + num_segs * 2;
864    glyph_ids = offsets + num_segs * 2;
865
866    if ( glyph_ids > table + length )
867      FT_INVALID_TOO_SHORT;
868
869    /* check last segment, its end count must be FFFF */
870    if ( valid->level >= FT_VALIDATE_PARANOID )
871    {
872      p = ends + ( num_segs - 1 ) * 2;
873      if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
874        FT_INVALID_DATA;
875    }
876
877    /* check that segments are sorted in increasing order and do not */
878    /* overlap; check also the offsets                               */
879    {
880      FT_UInt  start, end, last = 0, offset, n;
881      FT_Int   delta;
882
883
884      for ( n = 0; n < num_segs; n++ )
885      {
886        p = starts + n * 2;
887        start = TT_PEEK_USHORT( p );
888        p = ends + n * 2;
889        end = TT_PEEK_USHORT( p );
890        p = deltas + n * 2;
891        delta = TT_PEEK_SHORT( p );
892        p = offsets + n * 2;
893        offset = TT_PEEK_USHORT( p );
894
895        if ( start > end )
896          FT_INVALID_DATA;
897
898        /* this test should be performed at default validation level;  */
899        /* unfortunately, some popular Asian fonts present overlapping */
900        /* ranges in their charmaps                                    */
901        /*                                                             */
902        if ( n > 0 && start <= last )
903        {
904          if ( valid->level >= FT_VALIDATE_TIGHT )
905            FT_INVALID_DATA;
906          else
907            error = SFNT_Err_Invalid_CharMap_Format;
908        }
909
910        if ( offset && offset != 0xFFFFU )
911        {
912          p += offset;  /* start of glyph id array */
913
914          /* check that we point within the glyph ids table only */
915          if ( valid->level >= FT_VALIDATE_TIGHT )
916          {
917            if ( p < glyph_ids                                ||
918                 p + ( end - start + 1 ) * 2 > table + length )
919              FT_INVALID_DATA;
920          }
921          else
922          {
923            if ( p < glyph_ids                              ||
924                 p + ( end - start + 1 ) * 2 > valid->limit )
925              FT_INVALID_DATA;
926          }
927
928          /* check glyph indices within the segment range */
929          if ( valid->level >= FT_VALIDATE_TIGHT )
930          {
931            FT_UInt  i, idx;
932
933
934            for ( i = start; i < end; i++ )
935            {
936              idx = FT_NEXT_USHORT( p );
937              if ( idx != 0 )
938              {
939                idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
940
941                if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
942                  FT_INVALID_GLYPH_ID;
943              }
944            }
945          }
946        }
947        else if ( offset == 0xFFFFU )
948        {
949          /* Some fonts (erroneously?) use a range offset of 0xFFFF */
950          /* to mean missing glyph in cmap table                    */
951          /*                                                        */
952          if ( valid->level >= FT_VALIDATE_PARANOID                     ||
953               n != num_segs - 1                                        ||
954               !( start == 0xFFFFU && end == 0xFFFFU && delta == 0x1U ) )
955            FT_INVALID_DATA;
956        }
957
958        last = end;
959      }
960    }
961
962    return error;
963  }
964
965
966  FT_CALLBACK_DEF( FT_UInt )
967  tt_cmap4_char_index( TT_CMap    cmap,
968                       FT_UInt32  char_code )
969  {
970    FT_Byte*  table  = cmap->data;
971    FT_UInt   result = 0;
972
973
974    if ( char_code < 0x10000UL )
975    {
976      FT_UInt   idx, num_segs2;
977      FT_Int    delta;
978      FT_UInt   code = (FT_UInt)char_code;
979      FT_Byte*  p;
980
981      p         = table + 6;
982      num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );  /* be paranoid! */
983
984      if ( !cmap->unsorted )
985      {
986        /* Some fonts have more than 170 segments in their charmaps! */
987        /* We changed this function to use a more efficient binary   */
988        /* search for improving performance                          */
989        FT_UInt  min = 0;
990        FT_UInt  max = num_segs2 >> 1;
991        FT_UInt  mid, start, end, offset;
992
993
994        while ( min < max )
995        {
996          mid   = ( min + max ) >> 1;
997          p     = table + 14 + mid * 2;
998          end   = TT_NEXT_USHORT( p );
999          p    += num_segs2;
1000          start = TT_PEEK_USHORT( p);
1001
1002          if ( code < start )
1003            max = mid;
1004          else if ( code > end )
1005            min = mid + 1;
1006          else
1007          {
1008            /* we found the segment */
1009            idx = code;
1010
1011            p += num_segs2;
1012            delta = TT_PEEK_SHORT( p );
1013
1014            p += num_segs2;
1015            offset = TT_PEEK_USHORT( p );
1016
1017            if ( offset == 0xFFFFU )
1018              goto Exit;
1019
1020            if ( offset != 0 )
1021            {
1022              p  += offset + 2 * ( idx - start );
1023              idx = TT_PEEK_USHORT( p );
1024            }
1025
1026            if ( idx != 0 )
1027              result = (FT_UInt)( idx + delta ) & 0xFFFFU;
1028
1029            goto Exit;
1030          }
1031        }
1032      }
1033      else
1034      {
1035        FT_UInt   n;
1036        FT_Byte*  q;
1037
1038
1039        p = table + 14;               /* ends table   */
1040        q = table + 16 + num_segs2;   /* starts table */
1041
1042
1043        for ( n = 0; n < num_segs2; n += 2 )
1044        {
1045          FT_UInt  end   = TT_NEXT_USHORT( p );
1046          FT_UInt  start = TT_NEXT_USHORT( q );
1047          FT_UInt  offset;
1048
1049
1050          if ( code < start )
1051            break;
1052
1053          if ( code <= end )
1054          {
1055            idx = code;
1056
1057            p = q + num_segs2 - 2;
1058            delta = TT_PEEK_SHORT( p );
1059            p += num_segs2;
1060            offset = TT_PEEK_USHORT( p );
1061
1062            if ( offset == 0xFFFFU )
1063              goto Exit;
1064
1065            if ( offset != 0 )
1066            {
1067              p  += offset + 2 * ( idx - start );
1068              idx = TT_PEEK_USHORT( p );
1069            }
1070
1071            if ( idx != 0 )
1072              result = (FT_UInt)( idx + delta ) & 0xFFFFU;
1073          }
1074        }
1075      }
1076    }
1077
1078  Exit:
1079    return result;
1080  }
1081
1082
1083  FT_CALLBACK_DEF( FT_UInt )
1084  tt_cmap4_char_next( TT_CMap     cmap,
1085                      FT_UInt32  *pchar_code )
1086  {
1087    FT_Byte*   table     = cmap->data;
1088    FT_UInt32  result    = 0;
1089    FT_UInt    gindex    = 0;
1090    FT_UInt32  char_code = *pchar_code;
1091    FT_Byte*   p;
1092    FT_UInt    code, num_segs2;
1093
1094
1095    if ( char_code >= 0xFFFFUL )
1096      goto Exit;
1097
1098#ifdef OPT_CMAP4
1099      {
1100        TT_CMap4  cmap4 = (TT_CMap4)cmap;
1101
1102
1103        if ( char_code == cmap4->old_charcode )
1104        {
1105          result = cmap4->cur_charcode;
1106          gindex = cmap4->cur_gindex;
1107          if ( result != 0 )
1108          {
1109            tt_cmap4_next( cmap4 );
1110            goto Exit;
1111          }
1112        }
1113      }
1114#endif /* OPT_CMAP4 */
1115
1116    code      = (FT_UInt)char_code + 1;
1117    p         = table + 6;
1118    num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); /* ensure even-ness */
1119
1120    if ( !cmap->unsorted )
1121    {
1122      for (;;)
1123      {
1124        /* Some fonts have more than 170 segments in their charmaps! */
1125        /* We changed this function to use a more efficient binary   */
1126        /* search                                                    */
1127        FT_UInt  offset;
1128        FT_Int   delta;
1129        FT_UInt  min = 0;
1130        FT_UInt  max = num_segs2 >> 1;
1131        FT_UInt  mid, start, end;
1132        FT_UInt  hi;
1133
1134
1135        /* we begin by finding the segment which end is
1136           closer to our code point */
1137        hi = max + 1;
1138        while ( min < max )
1139        {
1140          mid = ( min + max ) >> 1;
1141          p   = table + 14 + mid * 2;
1142          end = TT_PEEK_USHORT( p );
1143
1144          if ( end < code )
1145            min = mid + 1;
1146          else
1147          {
1148            hi  = mid;
1149            max = mid;
1150          }
1151        }
1152
1153        if ( hi > max )
1154        {
1155          /* the point is behind the last segment;
1156             we will exit right now */
1157          goto Exit;
1158        }
1159
1160        p   = table + 14 + hi * 2;
1161        end = TT_PEEK_USHORT( p );
1162
1163        p    += 2 + num_segs2;
1164        start = TT_PEEK_USHORT( p );
1165
1166        if ( code < start )
1167          code = start;
1168
1169        p    += num_segs2;
1170        delta = TT_PEEK_USHORT( p );
1171
1172        p     += num_segs2;
1173        offset = TT_PEEK_USHORT( p );
1174
1175        if ( offset != 0 && offset != 0xFFFFU )
1176        {
1177          /* parse the glyph ids array for non-zero index */
1178          p += offset + ( code - start ) * 2;
1179          while ( code <= end )
1180          {
1181            gindex = TT_NEXT_USHORT( p );
1182            if ( gindex != 0 )
1183            {
1184              gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
1185              if ( gindex != 0 )
1186              {
1187                result = code;
1188#ifdef OPT_CMAP4
1189                tt_cmap4_reset( (TT_CMap4)cmap, code, hi );
1190#endif
1191                goto Exit;
1192              }
1193            }
1194            code++;
1195          }
1196        }
1197        else if ( offset == 0xFFFFU )
1198        {
1199          /* an offset of 0xFFFF means an empty segment in certain fonts! */
1200          code = end + 1;
1201        }
1202        else  /* offset == 0 */
1203        {
1204          gindex = (FT_UInt)( code + delta ) & 0xFFFFU;
1205          if ( gindex != 0 )
1206          {
1207            result = code;
1208#ifdef OPT_CMAP4
1209            tt_cmap4_reset( (TT_CMap4)cmap, code, hi );
1210#endif
1211            goto Exit;
1212          }
1213          code++;
1214        }
1215      }
1216    }
1217    else
1218    {
1219      for ( ;; )
1220      {
1221        FT_UInt   offset, n;
1222        FT_Int    delta;
1223        FT_Byte*  q;
1224
1225
1226        p = table + 14;              /* ends table  */
1227        q = table + 16 + num_segs2;  /* starts table */
1228
1229        for ( n = 0; n < num_segs2; n += 2 )
1230        {
1231          FT_UInt  end   = TT_NEXT_USHORT( p );
1232          FT_UInt  start = TT_NEXT_USHORT( q );
1233
1234
1235          if ( code < start )
1236            code = start;
1237
1238          if ( code <= end )
1239          {
1240            p = q + num_segs2 - 2;
1241            delta = TT_PEEK_SHORT( p );
1242            p += num_segs2;
1243            offset = TT_PEEK_USHORT( p );
1244
1245            if ( offset != 0 && offset != 0xFFFFU )
1246            {
1247              /* parse the glyph ids array for non-0 index */
1248              p += offset + ( code - start ) * 2;
1249              while ( code <= end )
1250              {
1251                gindex = TT_NEXT_USHORT( p );
1252                if ( gindex != 0 )
1253                {
1254                  gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
1255                  if ( gindex != 0 )
1256                    break;
1257                }
1258                code++;
1259              }
1260            }
1261            else if ( offset == 0xFFFFU )
1262            {
1263              /* an offset of 0xFFFF means an empty glyph in certain fonts! */
1264              code = end;
1265              break;
1266            }
1267            else
1268              gindex = (FT_UInt)( code + delta ) & 0xFFFFU;
1269
1270            if ( gindex == 0 )
1271              break;
1272
1273            result = code;
1274            goto Exit;
1275          }
1276        }
1277        /* loop to next trial charcode */
1278        if ( code >= 0xFFFFU )
1279          break;
1280
1281        code++;
1282      }
1283    }
1284
1285  Exit:
1286    *pchar_code = result;
1287    return gindex;
1288  }
1289
1290
1291  FT_CALLBACK_DEF( FT_Error )
1292  tt_cmap4_get_info( TT_CMap       cmap,
1293                     TT_CMapInfo  *cmap_info )
1294  {
1295    FT_Byte*  p = cmap->data + 4;
1296
1297
1298    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1299
1300    return SFNT_Err_Ok;
1301  }
1302
1303
1304  FT_CALLBACK_TABLE_DEF
1305  const TT_CMap_ClassRec  tt_cmap4_class_rec =
1306  {
1307    {
1308#ifdef OPT_CMAP4
1309      sizeof ( TT_CMap4Rec ),
1310      (FT_CMap_InitFunc)     tt_cmap4_init,
1311#else
1312      sizeof ( TT_CMapRec ),
1313      (FT_CMap_InitFunc)     tt_cmap_init,
1314#endif
1315      (FT_CMap_DoneFunc)     NULL,
1316      (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
1317      (FT_CMap_CharNextFunc) tt_cmap4_char_next
1318    },
1319    4,
1320    (TT_CMap_ValidateFunc)   tt_cmap4_validate,
1321    (TT_CMap_Info_GetFunc)   tt_cmap4_get_info
1322  };
1323
1324#endif /* TT_CONFIG_CMAP_FORMAT_4 */
1325
1326
1327  /*************************************************************************/
1328  /*************************************************************************/
1329  /*****                                                               *****/
1330  /*****                          FORMAT 6                             *****/
1331  /*****                                                               *****/
1332  /*************************************************************************/
1333  /*************************************************************************/
1334
1335  /*************************************************************************/
1336  /*                                                                       */
1337  /* TABLE OVERVIEW                                                        */
1338  /* --------------                                                        */
1339  /*                                                                       */
1340  /*   NAME        OFFSET          TYPE             DESCRIPTION            */
1341  /*                                                                       */
1342  /*   format       0              USHORT           must be 4              */
1343  /*   length       2              USHORT           table length in bytes  */
1344  /*   language     4              USHORT           Mac language code      */
1345  /*                                                                       */
1346  /*   first        6              USHORT           first segment code     */
1347  /*   count        8              USHORT           segment size in chars  */
1348  /*   glyphIds     10             USHORT[count]    glyph ids              */
1349  /*                                                                       */
1350  /* A very simplified segment mapping.                                    */
1351  /*                                                                       */
1352
1353#ifdef TT_CONFIG_CMAP_FORMAT_6
1354
1355  FT_CALLBACK_DEF( FT_Error )
1356  tt_cmap6_validate( FT_Byte*      table,
1357                     FT_Validator  valid )
1358  {
1359    FT_Byte*  p;
1360    FT_UInt   length, count;
1361
1362
1363    if ( table + 10 > valid->limit )
1364      FT_INVALID_TOO_SHORT;
1365
1366    p      = table + 2;
1367    length = TT_NEXT_USHORT( p );
1368
1369    p      = table + 8;             /* skip language and start index */
1370    count  = TT_NEXT_USHORT( p );
1371
1372    if ( table + length > valid->limit || length < 10 + count * 2 )
1373      FT_INVALID_TOO_SHORT;
1374
1375    /* check glyph indices */
1376    if ( valid->level >= FT_VALIDATE_TIGHT )
1377    {
1378      FT_UInt  gindex;
1379
1380
1381      for ( ; count > 0; count-- )
1382      {
1383        gindex = TT_NEXT_USHORT( p );
1384        if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1385          FT_INVALID_GLYPH_ID;
1386      }
1387    }
1388
1389    return SFNT_Err_Ok;
1390  }
1391
1392
1393  FT_CALLBACK_DEF( FT_UInt )
1394  tt_cmap6_char_index( TT_CMap    cmap,
1395                       FT_UInt32  char_code )
1396  {
1397    FT_Byte*  table  = cmap->data;
1398    FT_UInt   result = 0;
1399    FT_Byte*  p      = table + 6;
1400    FT_UInt   start  = TT_NEXT_USHORT( p );
1401    FT_UInt   count  = TT_NEXT_USHORT( p );
1402    FT_UInt   idx    = (FT_UInt)( char_code - start );
1403
1404
1405    if ( idx < count )
1406    {
1407      p += 2 * idx;
1408      result = TT_PEEK_USHORT( p );
1409    }
1410    return result;
1411  }
1412
1413
1414  FT_CALLBACK_DEF( FT_UInt )
1415  tt_cmap6_char_next( TT_CMap     cmap,
1416                      FT_UInt32  *pchar_code )
1417  {
1418    FT_Byte*   table     = cmap->data;
1419    FT_UInt32  result    = 0;
1420    FT_UInt32  char_code = *pchar_code + 1;
1421    FT_UInt    gindex    = 0;
1422
1423    FT_Byte*   p         = table + 6;
1424    FT_UInt    start     = TT_NEXT_USHORT( p );
1425    FT_UInt    count     = TT_NEXT_USHORT( p );
1426    FT_UInt    idx;
1427
1428
1429    if ( char_code >= 0x10000UL )
1430      goto Exit;
1431
1432    if ( char_code < start )
1433      char_code = start;
1434
1435    idx = (FT_UInt)( char_code - start );
1436    p  += 2 * idx;
1437
1438    for ( ; idx < count; idx++ )
1439    {
1440      gindex = TT_NEXT_USHORT( p );
1441      if ( gindex != 0 )
1442      {
1443        result = char_code;
1444        break;
1445      }
1446      char_code++;
1447    }
1448
1449  Exit:
1450    *pchar_code = result;
1451    return gindex;
1452  }
1453
1454
1455  FT_CALLBACK_DEF( FT_Error )
1456  tt_cmap6_get_info( TT_CMap       cmap,
1457                     TT_CMapInfo  *cmap_info )
1458  {
1459    FT_Byte*  p = cmap->data + 4;
1460
1461
1462    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1463
1464    return SFNT_Err_Ok;
1465  }
1466
1467
1468  FT_CALLBACK_TABLE_DEF
1469  const TT_CMap_ClassRec  tt_cmap6_class_rec =
1470  {
1471    {
1472      sizeof ( TT_CMapRec ),
1473
1474      (FT_CMap_InitFunc)     tt_cmap_init,
1475      (FT_CMap_DoneFunc)     NULL,
1476      (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
1477      (FT_CMap_CharNextFunc) tt_cmap6_char_next
1478    },
1479    6,
1480    (TT_CMap_ValidateFunc)   tt_cmap6_validate,
1481    (TT_CMap_Info_GetFunc)   tt_cmap6_get_info
1482  };
1483
1484#endif /* TT_CONFIG_CMAP_FORMAT_6 */
1485
1486
1487  /*************************************************************************/
1488  /*************************************************************************/
1489  /*****                                                               *****/
1490  /*****                          FORMAT 8                             *****/
1491  /*****                                                               *****/
1492  /***** It's hard to completely understand what the OpenType spec     *****/
1493  /***** says about this format, but here is my conclusion.            *****/
1494  /*****                                                               *****/
1495  /***** The purpose of this format is to easily map UTF-16 text to    *****/
1496  /***** glyph indices.  Basically, the `char_code' must be in one of  *****/
1497  /***** the following formats:                                        *****/
1498  /*****                                                               *****/
1499  /*****   - A 16-bit value that isn't part of the Unicode Surrogates  *****/
1500  /*****     Area (i.e. U+D800-U+DFFF).                                *****/
1501  /*****                                                               *****/
1502  /*****   - A 32-bit value, made of two surrogate values, i.e.. if    *****/
1503  /*****     `char_code = (char_hi << 16) | char_lo', then both        *****/
1504  /*****     `char_hi' and `char_lo' must be in the Surrogates Area.   *****/
1505  /*****      Area.                                                    *****/
1506  /*****                                                               *****/
1507  /***** The 'is32' table embedded in the charmap indicates whether a  *****/
1508  /***** given 16-bit value is in the surrogates area or not.          *****/
1509  /*****                                                               *****/
1510  /***** So, for any given `char_code', we can assert the following:   *****/
1511  /*****                                                               *****/
1512  /*****   If `char_hi == 0' then we must have `is32[char_lo] == 0'.   *****/
1513  /*****                                                               *****/
1514  /*****   If `char_hi != 0' then we must have both                    *****/
1515  /*****   `is32[char_hi] != 0' and `is32[char_lo] != 0'.              *****/
1516  /*****                                                               *****/
1517  /*************************************************************************/
1518  /*************************************************************************/
1519
1520  /*************************************************************************/
1521  /*                                                                       */
1522  /* TABLE OVERVIEW                                                        */
1523  /* --------------                                                        */
1524  /*                                                                       */
1525  /*   NAME        OFFSET         TYPE        DESCRIPTION                  */
1526  /*                                                                       */
1527  /*   format      0              USHORT      must be 8                    */
1528  /*   reseved     2              USHORT      reserved                     */
1529  /*   length      4              ULONG       length in bytes              */
1530  /*   language    8              ULONG       Mac language code            */
1531  /*   is32        12             BYTE[8192]  32-bitness bitmap            */
1532  /*   count       8204           ULONG       number of groups             */
1533  /*                                                                       */
1534  /* This header is followed by 'count' groups of the following format:    */
1535  /*                                                                       */
1536  /*   start       0              ULONG       first charcode               */
1537  /*   end         4              ULONG       last charcode                */
1538  /*   startId     8              ULONG       start glyph id for the group */
1539  /*                                                                       */
1540
1541#ifdef TT_CONFIG_CMAP_FORMAT_8
1542
1543  FT_CALLBACK_DEF( FT_Error )
1544  tt_cmap8_validate( FT_Byte*      table,
1545                     FT_Validator  valid )
1546  {
1547    FT_Byte*   p = table + 4;
1548    FT_Byte*   is32;
1549    FT_UInt32  length;
1550    FT_UInt32  num_groups;
1551
1552
1553    if ( table + 16 + 8192 > valid->limit )
1554      FT_INVALID_TOO_SHORT;
1555
1556    length = TT_NEXT_ULONG( p );
1557    if ( table + length > valid->limit || length < 8208 )
1558      FT_INVALID_TOO_SHORT;
1559
1560    is32       = table + 12;
1561    p          = is32  + 8192;          /* skip `is32' array */
1562    num_groups = TT_NEXT_ULONG( p );
1563
1564    if ( p + num_groups * 12 > valid->limit )
1565      FT_INVALID_TOO_SHORT;
1566
1567    /* check groups, they must be in increasing order */
1568    {
1569      FT_UInt32  n, start, end, start_id, count, last = 0;
1570
1571
1572      for ( n = 0; n < num_groups; n++ )
1573      {
1574        FT_UInt   hi, lo;
1575
1576
1577        start    = TT_NEXT_ULONG( p );
1578        end      = TT_NEXT_ULONG( p );
1579        start_id = TT_NEXT_ULONG( p );
1580
1581        if ( start > end )
1582          FT_INVALID_DATA;
1583
1584        if ( n > 0 && start <= last )
1585          FT_INVALID_DATA;
1586
1587        if ( valid->level >= FT_VALIDATE_TIGHT )
1588        {
1589          if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
1590            FT_INVALID_GLYPH_ID;
1591
1592          count = (FT_UInt32)( end - start + 1 );
1593
1594          if ( start & ~0xFFFFU )
1595          {
1596            /* start_hi != 0; check that is32[i] is 1 for each i in */
1597            /* the `hi' and `lo' of the range [start..end]          */
1598            for ( ; count > 0; count--, start++ )
1599            {
1600              hi = (FT_UInt)( start >> 16 );
1601              lo = (FT_UInt)( start & 0xFFFFU );
1602
1603              if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
1604                FT_INVALID_DATA;
1605
1606              if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
1607                FT_INVALID_DATA;
1608            }
1609          }
1610          else
1611          {
1612            /* start_hi == 0; check that is32[i] is 0 for each i in */
1613            /* the range [start..end]                               */
1614
1615            /* end_hi cannot be != 0! */
1616            if ( end & ~0xFFFFU )
1617              FT_INVALID_DATA;
1618
1619            for ( ; count > 0; count--, start++ )
1620            {
1621              lo = (FT_UInt)( start & 0xFFFFU );
1622
1623              if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
1624                FT_INVALID_DATA;
1625            }
1626          }
1627        }
1628
1629        last = end;
1630      }
1631    }
1632
1633    return SFNT_Err_Ok;
1634  }
1635
1636
1637  FT_CALLBACK_DEF( FT_UInt )
1638  tt_cmap8_char_index( TT_CMap    cmap,
1639                       FT_UInt32  char_code )
1640  {
1641    FT_Byte*   table      = cmap->data;
1642    FT_UInt    result     = 0;
1643    FT_Byte*   p          = table + 8204;
1644    FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1645    FT_UInt32  start, end, start_id;
1646
1647
1648    for ( ; num_groups > 0; num_groups-- )
1649    {
1650      start    = TT_NEXT_ULONG( p );
1651      end      = TT_NEXT_ULONG( p );
1652      start_id = TT_NEXT_ULONG( p );
1653
1654      if ( char_code < start )
1655        break;
1656
1657      if ( char_code <= end )
1658      {
1659        result = (FT_UInt)( start_id + char_code - start );
1660        break;
1661      }
1662    }
1663    return result;
1664  }
1665
1666
1667  FT_CALLBACK_DEF( FT_UInt )
1668  tt_cmap8_char_next( TT_CMap     cmap,
1669                      FT_UInt32  *pchar_code )
1670  {
1671    FT_UInt32  result     = 0;
1672    FT_UInt32  char_code  = *pchar_code + 1;
1673    FT_UInt    gindex     = 0;
1674    FT_Byte*   table      = cmap->data;
1675    FT_Byte*   p          = table + 8204;
1676    FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1677    FT_UInt32  start, end, start_id;
1678
1679
1680    p = table + 8208;
1681
1682    for ( ; num_groups > 0; num_groups-- )
1683    {
1684      start    = TT_NEXT_ULONG( p );
1685      end      = TT_NEXT_ULONG( p );
1686      start_id = TT_NEXT_ULONG( p );
1687
1688      if ( char_code < start )
1689        char_code = start;
1690
1691      if ( char_code <= end )
1692      {
1693        gindex = (FT_UInt)( char_code - start + start_id );
1694        if ( gindex != 0 )
1695        {
1696          result = char_code;
1697          goto Exit;
1698        }
1699      }
1700    }
1701
1702  Exit:
1703    *pchar_code = result;
1704    return gindex;
1705  }
1706
1707
1708  FT_CALLBACK_DEF( FT_Error )
1709  tt_cmap8_get_info( TT_CMap       cmap,
1710                     TT_CMapInfo  *cmap_info )
1711  {
1712    FT_Byte*  p = cmap->data + 8;
1713
1714
1715    cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1716
1717    return SFNT_Err_Ok;
1718  }
1719
1720
1721  FT_CALLBACK_TABLE_DEF
1722  const TT_CMap_ClassRec  tt_cmap8_class_rec =
1723  {
1724    {
1725      sizeof ( TT_CMapRec ),
1726
1727      (FT_CMap_InitFunc)     tt_cmap_init,
1728      (FT_CMap_DoneFunc)     NULL,
1729      (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
1730      (FT_CMap_CharNextFunc) tt_cmap8_char_next
1731    },
1732    8,
1733    (TT_CMap_ValidateFunc)   tt_cmap8_validate,
1734    (TT_CMap_Info_GetFunc)   tt_cmap8_get_info
1735  };
1736
1737#endif /* TT_CONFIG_CMAP_FORMAT_8 */
1738
1739
1740  /*************************************************************************/
1741  /*************************************************************************/
1742  /*****                                                               *****/
1743  /*****                          FORMAT 10                            *****/
1744  /*****                                                               *****/
1745  /*************************************************************************/
1746  /*************************************************************************/
1747
1748  /*************************************************************************/
1749  /*                                                                       */
1750  /* TABLE OVERVIEW                                                        */
1751  /* --------------                                                        */
1752  /*                                                                       */
1753  /*   NAME      OFFSET  TYPE               DESCRIPTION                    */
1754  /*                                                                       */
1755  /*   format     0      USHORT             must be 10                     */
1756  /*   reserved   2      USHORT             reserved                       */
1757  /*   length     4      ULONG              length in bytes                */
1758  /*   language   8      ULONG              Mac language code              */
1759  /*                                                                       */
1760  /*   start     12      ULONG              first char in range            */
1761  /*   count     16      ULONG              number of chars in range       */
1762  /*   glyphIds  20      USHORT[count]      glyph indices covered          */
1763  /*                                                                       */
1764
1765#ifdef TT_CONFIG_CMAP_FORMAT_10
1766
1767  FT_CALLBACK_DEF( FT_Error )
1768  tt_cmap10_validate( FT_Byte*      table,
1769                      FT_Validator  valid )
1770  {
1771    FT_Byte*  p = table + 4;
1772    FT_ULong  length, count;
1773
1774
1775    if ( table + 20 > valid->limit )
1776      FT_INVALID_TOO_SHORT;
1777
1778    length = TT_NEXT_ULONG( p );
1779    p      = table + 16;
1780    count  = TT_NEXT_ULONG( p );
1781
1782    if ( table + length > valid->limit || length < 20 + count * 2 )
1783      FT_INVALID_TOO_SHORT;
1784
1785    /* check glyph indices */
1786    if ( valid->level >= FT_VALIDATE_TIGHT )
1787    {
1788      FT_UInt  gindex;
1789
1790
1791      for ( ; count > 0; count-- )
1792      {
1793        gindex = TT_NEXT_USHORT( p );
1794        if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1795          FT_INVALID_GLYPH_ID;
1796      }
1797    }
1798
1799    return SFNT_Err_Ok;
1800  }
1801
1802
1803  FT_CALLBACK_DEF( FT_UInt )
1804  tt_cmap10_char_index( TT_CMap    cmap,
1805                        FT_UInt32  char_code )
1806  {
1807    FT_Byte*   table  = cmap->data;
1808    FT_UInt    result = 0;
1809    FT_Byte*   p      = table + 12;
1810    FT_UInt32  start  = TT_NEXT_ULONG( p );
1811    FT_UInt32  count  = TT_NEXT_ULONG( p );
1812    FT_UInt32  idx    = (FT_ULong)( char_code - start );
1813
1814
1815    if ( idx < count )
1816    {
1817      p     += 2 * idx;
1818      result = TT_PEEK_USHORT( p );
1819    }
1820    return result;
1821  }
1822
1823
1824  FT_CALLBACK_DEF( FT_UInt )
1825  tt_cmap10_char_next( TT_CMap     cmap,
1826                       FT_UInt32  *pchar_code )
1827  {
1828    FT_Byte*   table     = cmap->data;
1829    FT_UInt32  char_code = *pchar_code + 1;
1830    FT_UInt    gindex    = 0;
1831    FT_Byte*   p         = table + 12;
1832    FT_UInt32  start     = TT_NEXT_ULONG( p );
1833    FT_UInt32  count     = TT_NEXT_ULONG( p );
1834    FT_UInt32  idx;
1835
1836
1837    if ( char_code < start )
1838      char_code = start;
1839
1840    idx = (FT_UInt32)( char_code - start );
1841    p  += 2 * idx;
1842
1843    for ( ; idx < count; idx++ )
1844    {
1845      gindex = TT_NEXT_USHORT( p );
1846      if ( gindex != 0 )
1847        break;
1848      char_code++;
1849    }
1850
1851    *pchar_code = char_code;
1852    return gindex;
1853  }
1854
1855
1856  FT_CALLBACK_DEF( FT_Error )
1857  tt_cmap10_get_info( TT_CMap       cmap,
1858                      TT_CMapInfo  *cmap_info )
1859  {
1860    FT_Byte*  p = cmap->data + 8;
1861
1862
1863    cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1864
1865    return SFNT_Err_Ok;
1866  }
1867
1868
1869  FT_CALLBACK_TABLE_DEF
1870  const TT_CMap_ClassRec  tt_cmap10_class_rec =
1871  {
1872    {
1873      sizeof ( TT_CMapRec ),
1874
1875      (FT_CMap_InitFunc)     tt_cmap_init,
1876      (FT_CMap_DoneFunc)     NULL,
1877      (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
1878      (FT_CMap_CharNextFunc) tt_cmap10_char_next
1879    },
1880    10,
1881    (TT_CMap_ValidateFunc)   tt_cmap10_validate,
1882    (TT_CMap_Info_GetFunc)   tt_cmap10_get_info
1883  };
1884
1885#endif /* TT_CONFIG_CMAP_FORMAT_10 */
1886
1887
1888  /*************************************************************************/
1889  /*************************************************************************/
1890  /*****                                                               *****/
1891  /*****                          FORMAT 12                            *****/
1892  /*****                                                               *****/
1893  /*************************************************************************/
1894  /*************************************************************************/
1895
1896  /*************************************************************************/
1897  /*                                                                       */
1898  /* TABLE OVERVIEW                                                        */
1899  /* --------------                                                        */
1900  /*                                                                       */
1901  /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
1902  /*                                                                       */
1903  /*   format      0          USHORT     must be 12                        */
1904  /*   reserved    2          USHORT     reserved                          */
1905  /*   length      4          ULONG      length in bytes                   */
1906  /*   language    8          ULONG      Mac language code                 */
1907  /*   count       12         ULONG      number of groups                  */
1908  /*               16                                                      */
1909  /*                                                                       */
1910  /* This header is followed by `count' groups of the following format:    */
1911  /*                                                                       */
1912  /*   start       0          ULONG      first charcode                    */
1913  /*   end         4          ULONG      last charcode                     */
1914  /*   startId     8          ULONG      start glyph id for the group      */
1915  /*                                                                       */
1916
1917#ifdef TT_CONFIG_CMAP_FORMAT_12
1918
1919  FT_CALLBACK_DEF( FT_Error )
1920  tt_cmap12_validate( FT_Byte*      table,
1921                      FT_Validator  valid )
1922  {
1923    FT_Byte*   p;
1924    FT_ULong   length;
1925    FT_ULong   num_groups;
1926
1927
1928    if ( table + 16 > valid->limit )
1929      FT_INVALID_TOO_SHORT;
1930
1931    p      = table + 4;
1932    length = TT_NEXT_ULONG( p );
1933
1934    p          = table + 12;
1935    num_groups = TT_NEXT_ULONG( p );
1936
1937    if ( table + length > valid->limit || length < 16 + 12 * num_groups )
1938      FT_INVALID_TOO_SHORT;
1939
1940    /* check groups, they must be in increasing order */
1941    {
1942      FT_ULong  n, start, end, start_id, last = 0;
1943
1944
1945      for ( n = 0; n < num_groups; n++ )
1946      {
1947        start    = TT_NEXT_ULONG( p );
1948        end      = TT_NEXT_ULONG( p );
1949        start_id = TT_NEXT_ULONG( p );
1950
1951        if ( start > end )
1952          FT_INVALID_DATA;
1953
1954        if ( n > 0 && start <= last )
1955          FT_INVALID_DATA;
1956
1957        if ( valid->level >= FT_VALIDATE_TIGHT )
1958        {
1959          if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
1960            FT_INVALID_GLYPH_ID;
1961        }
1962
1963        last = end;
1964      }
1965    }
1966
1967    return SFNT_Err_Ok;
1968  }
1969
1970
1971  FT_CALLBACK_DEF( FT_UInt )
1972  tt_cmap12_char_index( TT_CMap    cmap,
1973                        FT_UInt32  char_code )
1974  {
1975    FT_UInt    result     = 0;
1976    FT_Byte*   table      = cmap->data;
1977    FT_Byte*   p          = table + 12;
1978    FT_UInt32  num_groups = TT_NEXT_ULONG( p );
1979    FT_UInt32  start, end, start_id;
1980
1981
1982    for ( ; num_groups > 0; num_groups-- )
1983    {
1984      start    = TT_NEXT_ULONG( p );
1985      end      = TT_NEXT_ULONG( p );
1986      start_id = TT_NEXT_ULONG( p );
1987
1988      if ( char_code < start )
1989        break;
1990
1991      if ( char_code <= end )
1992      {
1993        result = (FT_UInt)( start_id + char_code - start );
1994        break;
1995      }
1996    }
1997    return result;
1998  }
1999
2000
2001  FT_CALLBACK_DEF( FT_UInt )
2002  tt_cmap12_char_next( TT_CMap     cmap,
2003                       FT_UInt32  *pchar_code )
2004  {
2005    FT_Byte*   table      = cmap->data;
2006    FT_UInt32  result     = 0;
2007    FT_UInt32  char_code  = *pchar_code + 1;
2008    FT_UInt    gindex     = 0;
2009    FT_Byte*   p          = table + 12;
2010    FT_UInt32  num_groups = TT_NEXT_ULONG( p );
2011    FT_UInt32  start, end, start_id;
2012
2013
2014    p = table + 16;
2015
2016    for ( ; num_groups > 0; num_groups-- )
2017    {
2018      start    = TT_NEXT_ULONG( p );
2019      end      = TT_NEXT_ULONG( p );
2020      start_id = TT_NEXT_ULONG( p );
2021
2022      if ( char_code < start )
2023        char_code = start;
2024
2025      if ( char_code <= end )
2026      {
2027        gindex = (FT_UInt)(char_code - start + start_id);
2028        if ( gindex != 0 )
2029        {
2030          result = char_code;
2031          goto Exit;
2032        }
2033      }
2034    }
2035
2036  Exit:
2037    *pchar_code = result;
2038    return gindex;
2039  }
2040
2041
2042  FT_CALLBACK_DEF( FT_Error )
2043  tt_cmap12_get_info( TT_CMap       cmap,
2044                      TT_CMapInfo  *cmap_info )
2045  {
2046    FT_Byte*  p = cmap->data + 8;
2047
2048
2049    cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2050
2051    return SFNT_Err_Ok;
2052  }
2053
2054
2055  FT_CALLBACK_TABLE_DEF
2056  const TT_CMap_ClassRec  tt_cmap12_class_rec =
2057  {
2058    {
2059      sizeof ( TT_CMapRec ),
2060
2061      (FT_CMap_InitFunc)     tt_cmap_init,
2062      (FT_CMap_DoneFunc)     NULL,
2063      (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
2064      (FT_CMap_CharNextFunc) tt_cmap12_char_next
2065    },
2066    12,
2067    (TT_CMap_ValidateFunc)   tt_cmap12_validate,
2068    (TT_CMap_Info_GetFunc)   tt_cmap12_get_info
2069  };
2070
2071
2072#endif /* TT_CONFIG_CMAP_FORMAT_12 */
2073
2074
2075  static const TT_CMap_Class  tt_cmap_classes[] =
2076  {
2077#ifdef TT_CONFIG_CMAP_FORMAT_0
2078    &tt_cmap0_class_rec,
2079#endif
2080
2081#ifdef TT_CONFIG_CMAP_FORMAT_2
2082    &tt_cmap2_class_rec,
2083#endif
2084
2085#ifdef TT_CONFIG_CMAP_FORMAT_4
2086    &tt_cmap4_class_rec,
2087#endif
2088
2089#ifdef TT_CONFIG_CMAP_FORMAT_6
2090    &tt_cmap6_class_rec,
2091#endif
2092
2093#ifdef TT_CONFIG_CMAP_FORMAT_8
2094    &tt_cmap8_class_rec,
2095#endif
2096
2097#ifdef TT_CONFIG_CMAP_FORMAT_10
2098    &tt_cmap10_class_rec,
2099#endif
2100
2101#ifdef TT_CONFIG_CMAP_FORMAT_12
2102    &tt_cmap12_class_rec,
2103#endif
2104
2105    NULL,
2106  };
2107
2108
2109  /* parse the `cmap' table and build the corresponding TT_CMap objects */
2110  /* in the current face                                                */
2111  /*                                                                    */
2112  FT_LOCAL_DEF( FT_Error )
2113  tt_face_build_cmaps( TT_Face  face )
2114  {
2115    FT_Byte*           table = face->cmap_table;
2116    FT_Byte*           limit = table + face->cmap_size;
2117    FT_UInt volatile   num_cmaps;
2118    FT_Byte* volatile  p     = table;
2119
2120
2121    if ( p + 4 > limit )
2122      return SFNT_Err_Invalid_Table;
2123
2124    /* only recognize format 0 */
2125    if ( TT_NEXT_USHORT( p ) != 0 )
2126    {
2127      p -= 2;
2128      FT_ERROR(( "tt_face_build_cmaps: unsupported `cmap' table format = %d\n",
2129                 TT_PEEK_USHORT( p ) ));
2130      return SFNT_Err_Invalid_Table;
2131    }
2132
2133    num_cmaps = TT_NEXT_USHORT( p );
2134
2135    for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
2136    {
2137      FT_CharMapRec  charmap;
2138      FT_UInt32      offset;
2139
2140
2141      charmap.platform_id = TT_NEXT_USHORT( p );
2142      charmap.encoding_id = TT_NEXT_USHORT( p );
2143      charmap.face        = FT_FACE( face );
2144      charmap.encoding    = FT_ENCODING_NONE;  /* will be filled later */
2145      offset              = TT_NEXT_ULONG( p );
2146
2147      if ( offset                     &&
2148           table + offset + 2 < limit &&
2149           table + offset >= table    )
2150      {
2151        FT_Byte*                       cmap   = table + offset;
2152        volatile FT_UInt               format = TT_PEEK_USHORT( cmap );
2153        const TT_CMap_Class* volatile  pclazz = tt_cmap_classes;
2154        TT_CMap_Class                  clazz;
2155
2156
2157        for ( ; *pclazz; pclazz++ )
2158        {
2159          clazz = *pclazz;
2160          if ( clazz->format == format )
2161          {
2162            volatile TT_ValidatorRec  valid;
2163            FT_Error                  error = SFNT_Err_Ok;
2164
2165
2166            ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
2167                               FT_VALIDATE_DEFAULT );
2168
2169            valid.num_glyphs = (FT_UInt)face->root.num_glyphs;
2170
2171            if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer ) == 0 )
2172            {
2173              /* validate this cmap sub-table */
2174              error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
2175            }
2176
2177            if ( valid.validator.error == 0 )
2178            {
2179              (void)FT_CMap_New( (FT_CMap_Class)clazz, cmap, &charmap, NULL );
2180
2181              /* it is simpler to directly set the `unsorted' flag instead */
2182              /* of adding a parameter to FT_CMap_New                      */
2183              ((TT_CMap)(face->root.charmaps
2184                          [face->root.num_charmaps - 1]))->unsorted =
2185                FT_BOOL( error );
2186            }
2187            else
2188            {
2189              FT_ERROR(( "tt_face_build_cmaps:" ));
2190              FT_ERROR(( " broken cmap sub-table ignored!\n" ));
2191            }
2192            break;
2193          }
2194        }
2195      }
2196    }
2197
2198    return SFNT_Err_Ok;
2199  }
2200
2201
2202  FT_LOCAL( FT_Error )
2203  tt_get_cmap_info( FT_CharMap    charmap,
2204                    TT_CMapInfo  *cmap_info )
2205  {
2206    FT_CMap        cmap  = (FT_CMap)charmap;
2207    TT_CMap_Class  clazz = (TT_CMap_Class)cmap->clazz;
2208
2209
2210    return clazz->get_cmap_info( charmap, cmap_info );
2211  }
2212
2213
2214/* END */
Note: See TracBrowser for help on using the repository browser.