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