~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/extras/freetype2/src/sfnt/ttcmap0.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************/
 
2
/*                                                                         */
 
3
/*  ttcmap0.c                                                              */
 
4
/*                                                                         */
 
5
/*    TrueType new character mapping table (cmap) support (body).          */
 
6
/*                                                                         */
 
7
/*  Copyright 2002 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
#include FT_INTERNAL_OBJECTS_H
 
22
#include FT_INTERNAL_STREAM_H
 
23
#include "ttload.h"
 
24
#include "ttcmap0.h"
 
25
 
 
26
#include "sferrors.h"
 
27
 
 
28
  /*************************************************************************/
 
29
  /*                                                                       */
 
30
  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
 
31
  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
 
32
  /* messages during execution.                                            */
 
33
  /*                                                                       */
 
34
#undef  FT_COMPONENT
 
35
#define FT_COMPONENT  trace_ttcmap
 
36
 
 
37
 
 
38
#define TT_PEEK_SHORT   FT_PEEK_SHORT
 
39
#define TT_PEEK_USHORT  FT_PEEK_USHORT
 
40
#define TT_PEEK_LONG    FT_PEEK_LONG
 
41
#define TT_PEEK_ULONG   FT_PEEK_ULONG
 
42
 
 
43
#define TT_NEXT_SHORT   FT_NEXT_SHORT
 
44
#define TT_NEXT_USHORT  FT_NEXT_USHORT
 
45
#define TT_NEXT_LONG    FT_NEXT_LONG
 
46
#define TT_NEXT_ULONG   FT_NEXT_ULONG
 
47
 
 
48
 
 
49
  FT_CALLBACK_DEF( FT_Error )
 
50
  tt_cmap_init( TT_CMap   cmap,
 
51
                FT_Byte*  table )
 
52
  {
 
53
    cmap->data = table;
 
54
    return 0;
 
55
  }
 
56
 
 
57
 
 
58
  /*************************************************************************/
 
59
  /*************************************************************************/
 
60
  /*****                                                               *****/
 
61
  /*****                           FORMAT 0                            *****/
 
62
  /*****                                                               *****/
 
63
  /*************************************************************************/
 
64
  /*************************************************************************/
 
65
 
 
66
  /*************************************************************************/
 
67
  /*                                                                       */
 
68
  /* TABLE OVERVIEW                                                        */
 
69
  /* --------------                                                        */
 
70
  /*                                                                       */
 
71
  /*   NAME        OFFSET         TYPE          DESCRIPTION                */
 
72
  /*                                                                       */
 
73
  /*   format      0              USHORT        must be 0                  */
 
74
  /*   length      2              USHORT        table length in bytes      */
 
75
  /*   language    4              USHORT        Mac language code          */
 
76
  /*   glyph_ids   6              BYTE[256]     array of glyph indices     */
 
77
  /*               262                                                     */
 
78
  /*                                                                       */
 
79
 
 
80
#ifdef TT_CONFIG_CMAP_FORMAT_0
 
81
 
 
82
  FT_CALLBACK_DEF( void )
 
83
  tt_cmap0_validate( FT_Byte*      table,
 
84
                     FT_Validator  valid )
 
85
  {
 
86
    FT_Byte*  p      = table + 2;
 
87
    FT_UInt   length = TT_NEXT_USHORT( p );
 
88
 
 
89
 
 
90
    if ( table + length > valid->limit || length < 262 )
 
91
      FT_INVALID_TOO_SHORT;
 
92
 
 
93
    /* check glyph indices whenever necessary */
 
94
    if ( valid->level >= FT_VALIDATE_TIGHT )
 
95
    {
 
96
      FT_UInt  n, idx;
 
97
 
 
98
 
 
99
      p = table + 6;
 
100
      for ( n = 0; n < 256; n++ )
 
101
      {
 
102
        idx = *p++;
 
103
        if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
 
104
          FT_INVALID_GLYPH_ID;
 
105
      }
 
106
    }
 
107
  }
 
108
 
 
109
 
 
110
  FT_CALLBACK_DEF( FT_UInt )
 
111
  tt_cmap0_char_index( TT_CMap    cmap,
 
112
                       FT_UInt32  char_code )
 
113
  {
 
114
    FT_Byte*  table = cmap->data;
 
115
 
 
116
 
 
117
    return char_code < 256 ? table[6 + char_code] : 0;
 
118
  }
 
119
 
 
120
 
 
121
  FT_CALLBACK_DEF( FT_UInt )
 
122
  tt_cmap0_char_next( TT_CMap     cmap,
 
123
                      FT_UInt32  *pchar_code )
 
124
  {
 
125
    FT_Byte*   table    = cmap->data;
 
126
    FT_UInt32  charcode = *pchar_code;
 
127
    FT_UInt32  result   = 0;
 
128
    FT_UInt    gindex   = 0;
 
129
 
 
130
 
 
131
    table += 6;  /* go to glyph ids */
 
132
    while ( ++charcode < 256 )
 
133
    {
 
134
      gindex = table[charcode];
 
135
      if ( gindex != 0 )
 
136
      {
 
137
        result = charcode;
 
138
        break;
 
139
      }
 
140
    }
 
141
 
 
142
    *pchar_code = result;
 
143
    return gindex;
 
144
  }
 
145
 
 
146
 
 
147
  FT_CALLBACK_TABLE_DEF
 
148
  const TT_CMap_ClassRec  tt_cmap0_class_rec =
 
149
  {
 
150
    {
 
151
      sizeof( TT_CMapRec ),
 
152
 
 
153
      (FT_CMap_InitFunc)     tt_cmap_init,
 
154
      (FT_CMap_DoneFunc)     NULL,
 
155
      (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
 
156
      (FT_CMap_CharNextFunc) tt_cmap0_char_next
 
157
    },
 
158
    0,
 
159
    (TT_CMap_ValidateFunc)   tt_cmap0_validate
 
160
  };
 
161
 
 
162
#endif /* TT_CONFIG_CMAP_FORMAT_0 */
 
163
 
 
164
 
 
165
  /*************************************************************************/
 
166
  /*************************************************************************/
 
167
  /*****                                                               *****/
 
168
  /*****                          FORMAT 2                             *****/
 
169
  /*****                                                               *****/
 
170
  /***** This is used for certain CJK encodings that encode text in a  *****/
 
171
  /***** mixed 8/16 bits encoding along the following lines:           *****/
 
172
  /*****                                                               *****/
 
173
  /***** * Certain byte values correspond to an 8-bit character code   *****/
 
174
  /*****   (typically in the range 0..127 for ASCII compatibility).    *****/
 
175
  /*****                                                               *****/
 
176
  /***** * Certain byte values signal the first byte of a 2-byte       *****/
 
177
  /*****   character code (but these values are also valid as the      *****/
 
178
  /*****   second byte of a 2-byte character).                         *****/
 
179
  /*****                                                               *****/
 
180
  /***** The following charmap lookup and iteration functions all      *****/
 
181
  /***** assume that the value "charcode" correspond to following:     *****/
 
182
  /*****                                                               *****/
 
183
  /*****   - For one byte characters, "charcode" is simply the         *****/
 
184
  /*****     character code.                                           *****/
 
185
  /*****                                                               *****/
 
186
  /*****   - For two byte characters, "charcode" is the 2-byte         *****/
 
187
  /*****     character code in big endian format.  More exactly:       *****/
 
188
  /*****                                                               *****/
 
189
  /*****       (charcode >> 8)    is the first byte value              *****/
 
190
  /*****       (charcode & 0xFF)  is the second byte value             *****/
 
191
  /*****                                                               *****/
 
192
  /***** Note that not all values of "charcode" are valid according    *****/
 
193
  /***** to these rules, and the function moderately check the         *****/
 
194
  /***** arguments.                                                    *****/
 
195
  /*****                                                               *****/
 
196
  /*************************************************************************/
 
197
  /*************************************************************************/
 
198
 
 
199
  /*************************************************************************/
 
200
  /*                                                                       */
 
201
  /* TABLE OVERVIEW                                                        */
 
202
  /* --------------                                                        */
 
203
  /*                                                                       */
 
204
  /*   NAME        OFFSET         TYPE            DESCRIPTION              */
 
205
  /*                                                                       */
 
206
  /*   format      0              USHORT          must be 2                */
 
207
  /*   length      2              USHORT          table length in bytes    */
 
208
  /*   language    4              USHORT          Mac language code        */
 
209
  /*   keys        6              USHORT[256]     sub-header keys          */
 
210
  /*   subs        518            SUBHEAD[NSUBS]  sub-headers array        */
 
211
  /*   glyph_ids   518+NSUB*8     USHORT[]        glyph id array           */
 
212
  /*                                                                       */
 
213
  /* The `keys' table is used to map charcode high-bytes to sub-headers.   */
 
214
  /* The value of `NSUBS' is the number of sub-headers defined in the      */
 
215
  /* table and is computed by finding the maximum of the `keys' table.     */
 
216
  /*                                                                       */
 
217
  /* Note that for any n, `keys[n]' is a byte offset within the `subs'     */
 
218
  /* table, i.e., it is the corresponding sub-header index multiplied      */
 
219
  /* by 8.                                                                 */
 
220
  /*                                                                       */
 
221
  /* Each sub-header has the following format:                             */
 
222
  /*                                                                       */
 
223
  /*   NAME        OFFSET      TYPE            DESCRIPTION                 */
 
224
  /*                                                                       */
 
225
  /*   first       0           USHORT          first valid low-byte        */
 
226
  /*   count       2           USHORT          number of valid low-bytes   */
 
227
  /*   delta       4           SHORT           see below                   */
 
228
  /*   offset      6           USHORT          see below                   */
 
229
  /*                                                                       */
 
230
  /* A sub-header defines, for each high-byte, the range of valid          */
 
231
  /* low-bytes within the charmap.  Note that the range defined by `first' */
 
232
  /* and `count' must be completely included in the interval [0..255]      */
 
233
  /* according to the specification.                                       */
 
234
  /*                                                                       */
 
235
  /* If a character code is contained within a given sub-header, then      */
 
236
  /* mapping it to a glyph index is done as follows:                       */
 
237
  /*                                                                       */
 
238
  /* * The value of `offset' is read.  This is a _byte_ distance from the  */
 
239
  /*   location of the `offset' field itself into a slice of the           */
 
240
  /*   `glyph_ids' table.  Let's call it `slice' (it's a USHORT[] too).    */
 
241
  /*                                                                       */
 
242
  /* * The value `slice[char.lo - first]' is read.  If it is 0, there is   */
 
243
  /*   no glyph for the charcode.  Otherwise, the value of `delta' is      */
 
244
  /*   added to it (modulo 65536) to form a new glyph index.               */
 
245
  /*                                                                       */
 
246
  /* It is up to the validation routine to check that all offsets fall     */
 
247
  /* within the glyph ids table (and not within the `subs' table itself or */
 
248
  /* outside of the CMap).                                                 */
 
249
  /*                                                                       */
 
250
 
 
251
#ifdef TT_CONFIG_CMAP_FORMAT_2
 
252
 
 
253
  FT_CALLBACK_DEF( void )
 
254
  tt_cmap2_validate( FT_Byte*      table,
 
255
                     FT_Validator  valid )
 
256
  {
 
257
    FT_Byte*  p      = table + 2;           /* skip format */
 
258
    FT_UInt   length = TT_PEEK_USHORT( p );
 
259
    FT_UInt   n, max_subs;
 
260
    FT_Byte*  keys;                         /* keys table */
 
261
    FT_Byte*  subs;                         /* sub-headers */
 
262
    FT_Byte*  glyph_ids;                    /* glyph id array */
 
263
 
 
264
 
 
265
    if ( table + length > valid->limit || length < 6 + 512 )
 
266
      FT_INVALID_TOO_SHORT;
 
267
 
 
268
    keys = table + 6;
 
269
 
 
270
    /* parse keys to compute sub-headers count */
 
271
    p        = keys;
 
272
    max_subs = 0;
 
273
    for ( n = 0; n < 256; n++ )
 
274
    {
 
275
      FT_UInt  idx = TT_NEXT_USHORT( p );
 
276
 
 
277
 
 
278
      /* value must be multiple of 8 */
 
279
      if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
 
280
        FT_INVALID_DATA;
 
281
 
 
282
      idx >>= 3;
 
283
 
 
284
      if ( idx > max_subs )
 
285
        max_subs = idx;
 
286
    }
 
287
 
 
288
    FT_ASSERT( p == table + 518 );
 
289
 
 
290
    subs      = p;
 
291
    glyph_ids = subs + (max_subs + 1) * 8;
 
292
    if ( glyph_ids > valid->limit )
 
293
      FT_INVALID_TOO_SHORT;
 
294
 
 
295
    /* parse sub-headers */
 
296
    for ( n = 0; n <= max_subs; n++ )
 
297
    {
 
298
      FT_UInt   first_code, code_count, offset;
 
299
      FT_Int    delta;
 
300
      FT_Byte*  ids;
 
301
 
 
302
 
 
303
      first_code = TT_NEXT_USHORT( p );
 
304
      code_count = TT_NEXT_USHORT( p );
 
305
      delta      = TT_NEXT_SHORT( p );
 
306
      offset     = TT_NEXT_USHORT( p );
 
307
 
 
308
      /* check range within 0..255 */
 
309
      if ( valid->level >= FT_VALIDATE_PARANOID )
 
310
      {
 
311
        if ( first_code >= 256 || first_code + code_count > 256 )
 
312
          FT_INVALID_DATA;
 
313
      }
 
314
 
 
315
      /* check offset */
 
316
      if ( offset != 0 )
 
317
      {
 
318
        ids = p - 2 + offset;
 
319
        if ( ids < glyph_ids || ids + code_count*2 > table + length )
 
320
          FT_INVALID_OFFSET;
 
321
 
 
322
        /* check glyph ids */
 
323
        if ( valid->level >= FT_VALIDATE_TIGHT )
 
324
        {
 
325
          FT_Byte*  limit = p + code_count * 2;
 
326
          FT_UInt   idx;
 
327
 
 
328
 
 
329
          for ( ; p < limit; )
 
330
          {
 
331
            idx = TT_NEXT_USHORT( p );
 
332
            if ( idx != 0 )
 
333
            {
 
334
              idx = ( idx + delta ) & 0xFFFFU;
 
335
              if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
 
336
                FT_INVALID_GLYPH_ID;
 
337
            }
 
338
          }
 
339
        }
 
340
      }
 
341
    }
 
342
  }
 
343
 
 
344
 
 
345
  /* return sub header corresponding to a given character code */
 
346
  /* NULL on invalid charcode                                  */
 
347
  static FT_Byte*
 
348
  tt_cmap2_get_subheader( FT_Byte*   table,
 
349
                          FT_UInt32  char_code )
 
350
  {
 
351
    FT_Byte*  result = NULL;
 
352
 
 
353
 
 
354
    if ( char_code < 0x10000UL )
 
355
    {
 
356
      FT_UInt   char_lo = (FT_UInt)( char_code & 0xFF );
 
357
      FT_UInt   char_hi = (FT_UInt)( char_code >> 8 );
 
358
      FT_Byte*  p       = table + 6;    /* keys table */
 
359
      FT_Byte*  subs    = table + 518;  /* subheaders table */
 
360
      FT_Byte*  sub;
 
361
 
 
362
 
 
363
      if ( char_hi == 0 )
 
364
      {
 
365
        /* an 8-bit character code -- we use subHeader 0 in this case */
 
366
        /* to test whether the character code is in the charmap       */
 
367
        /*                                                            */
 
368
        sub = subs;  /* jump to first sub-header */
 
369
 
 
370
        /* check that the sub-header for this byte is 0, which */
 
371
        /* indicates that it's really a valid one-byte value   */
 
372
        /* Otherwise, return 0                                 */
 
373
        /*                                                     */
 
374
        p += char_lo * 2;
 
375
        if ( TT_PEEK_USHORT( p ) != 0 )
 
376
          goto Exit;
 
377
      }
 
378
      else
 
379
      {
 
380
        /* a 16-bit character code */
 
381
        p  += char_hi * 2;                          /* jump to key entry  */
 
382
        sub = subs + ( TT_PEEK_USHORT( p ) & -8 );  /* jump to sub-header */
 
383
 
 
384
        /* check that the hi byte isn't a valid one-byte value */
 
385
        if ( sub == subs )
 
386
          goto Exit;
 
387
      }
 
388
      result = sub;
 
389
    }
 
390
  Exit:
 
391
    return result;
 
392
  }
 
393
 
 
394
 
 
395
  FT_CALLBACK_DEF( FT_UInt )
 
396
  tt_cmap2_char_index( TT_CMap    cmap,
 
397
                       FT_UInt32  char_code )
 
398
  {
 
399
    FT_Byte*  table   = cmap->data;
 
400
    FT_UInt   result  = 0;
 
401
    FT_Byte*  subheader;
 
402
 
 
403
 
 
404
    subheader = tt_cmap2_get_subheader( table, char_code );
 
405
    if ( subheader )
 
406
    {
 
407
      FT_Byte*  p   = subheader;
 
408
      FT_UInt   idx = (FT_UInt)(char_code & 0xFF);
 
409
      FT_UInt   start, count;
 
410
      FT_Int    delta;
 
411
      FT_UInt   offset;
 
412
 
 
413
 
 
414
      start  = TT_NEXT_USHORT( p );
 
415
      count  = TT_NEXT_USHORT( p );
 
416
      delta  = TT_NEXT_SHORT ( p );
 
417
      offset = TT_PEEK_USHORT( p );
 
418
 
 
419
      idx -= start;
 
420
      if ( idx < count && offset != 0 )
 
421
      {
 
422
        p  += offset + 2 * idx;
 
423
        idx = TT_PEEK_USHORT( p );
 
424
 
 
425
        if ( idx != 0 )
 
426
          result = (FT_UInt)( idx + delta ) & 0xFFFFU;
 
427
      }
 
428
    }
 
429
    return result;
 
430
  }
 
431
 
 
432
 
 
433
  FT_CALLBACK_DEF( FT_UInt )
 
434
  tt_cmap2_char_next( TT_CMap     cmap,
 
435
                      FT_UInt32  *pcharcode )
 
436
  {
 
437
    FT_Byte*   table    = cmap->data;
 
438
    FT_UInt    gindex   = 0;
 
439
    FT_UInt32  result   = 0;
 
440
    FT_UInt32  charcode = *pcharcode + 1;
 
441
    FT_Byte*   subheader;
 
442
 
 
443
 
 
444
    while ( charcode < 0x10000UL )
 
445
    {
 
446
      subheader = tt_cmap2_get_subheader( table, charcode );
 
447
      if ( subheader )
 
448
      {
 
449
        FT_Byte*  p       = subheader;
 
450
        FT_UInt   start   = TT_NEXT_USHORT( p );
 
451
        FT_UInt   count   = TT_NEXT_USHORT( p );
 
452
        FT_Int    delta   = TT_NEXT_SHORT ( p );
 
453
        FT_UInt   offset  = TT_PEEK_USHORT( p );
 
454
        FT_UInt   char_lo = (FT_UInt)( charcode & 0xFF );
 
455
        FT_UInt   pos, idx;
 
456
 
 
457
 
 
458
        if ( offset == 0 )
 
459
          goto Next_SubHeader;
 
460
 
 
461
        if ( char_lo < start )
 
462
        {
 
463
          char_lo = start;
 
464
          pos     = 0;
 
465
        }
 
466
        else
 
467
          pos = (FT_UInt)( char_lo - start );
 
468
 
 
469
        p       += offset + pos * 2;
 
470
        charcode = ( charcode & -256 ) + char_lo;
 
471
 
 
472
        for ( ; pos < count; pos++, charcode++ )
 
473
        {
 
474
          idx = TT_NEXT_USHORT( p );
 
475
 
 
476
          if ( idx != 0 )
 
477
          {
 
478
            gindex = ( idx + delta ) & 0xFFFFU;
 
479
            if ( gindex != 0 )
 
480
            {
 
481
              result = charcode;
 
482
              goto Exit;
 
483
            }
 
484
          }
 
485
        }
 
486
      }
 
487
 
 
488
      /* jump to next sub-header, i.e. higher byte value */
 
489
    Next_SubHeader:
 
490
      charcode = ( charcode & -256 ) + 256;
 
491
    }
 
492
 
 
493
  Exit:
 
494
    *pcharcode = result;
 
495
 
 
496
    return gindex;
 
497
  }
 
498
 
 
499
 
 
500
  FT_CALLBACK_TABLE_DEF
 
501
  const TT_CMap_ClassRec  tt_cmap2_class_rec =
 
502
  {
 
503
    {
 
504
      sizeof( TT_CMapRec ),
 
505
 
 
506
      (FT_CMap_InitFunc)     tt_cmap_init,
 
507
      (FT_CMap_DoneFunc)     NULL,
 
508
      (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
 
509
      (FT_CMap_CharNextFunc) tt_cmap2_char_next
 
510
    },
 
511
    2,
 
512
    (TT_CMap_ValidateFunc)   tt_cmap2_validate
 
513
  };
 
514
 
 
515
#endif /* TT_CONFIG_CMAP_FORMAT_2 */
 
516
 
 
517
 
 
518
  /*************************************************************************/
 
519
  /*************************************************************************/
 
520
  /*****                                                               *****/
 
521
  /*****                           FORMAT 4                            *****/
 
522
  /*****                                                               *****/
 
523
  /*************************************************************************/
 
524
  /*************************************************************************/
 
525
 
 
526
  /*************************************************************************/
 
527
  /*                                                                       */
 
528
  /* TABLE OVERVIEW                                                        */
 
529
  /* --------------                                                        */
 
530
  /*                                                                       */
 
531
  /*   NAME          OFFSET         TYPE              DESCRIPTION          */
 
532
  /*                                                                       */
 
533
  /*   format        0              USHORT            must be 4            */
 
534
  /*   length        2              USHORT            table length         */
 
535
  /*                                                  in bytes             */
 
536
  /*   language      4              USHORT            Mac language code    */
 
537
  /*                                                                       */
 
538
  /*   segCountX2    6              USHORT            2*NUM_SEGS           */
 
539
  /*   searchRange   8              USHORT            2*(1 << LOG_SEGS)    */
 
540
  /*   entrySelector 10             USHORT            LOG_SEGS             */
 
541
  /*   rangeShift    12             USHORT            segCountX2 -         */
 
542
  /*                                                    searchRange        */
 
543
  /*                                                                       */
 
544
  /*   endCount      14             USHORT[NUM_SEGS]  end charcode for     */
 
545
  /*                                                  each segment; last   */
 
546
  /*                                                  is 0xFFFF            */
 
547
  /*                                                                       */
 
548
  /*   pad           14+NUM_SEGS*2  USHORT            padding              */
 
549
  /*                                                                       */
 
550
  /*   startCount    16+NUM_SEGS*2  USHORT[NUM_SEGS]  first charcode for   */
 
551
  /*                                                  each segment         */
 
552
  /*                                                                       */
 
553
  /*   idDelta       16+NUM_SEGS*4  SHORT[NUM_SEGS]   delta for each       */
 
554
  /*                                                  segment              */
 
555
  /*   idOffset      16+NUM_SEGS*6  SHORT[NUM_SEGS]   range offset for     */
 
556
  /*                                                  each segment; can be */
 
557
  /*                                                  zero                 */
 
558
  /*                                                                       */
 
559
  /*   glyphIds      16+NUM_SEGS*8  USHORT[]          array of glyph id    */
 
560
  /*                                                  ranges               */
 
561
  /*                                                                       */
 
562
  /* Character codes are modelled by a series of ordered (increasing)      */
 
563
  /* intervals called segments.  Each segment has start and end codes,     */
 
564
  /* provided by the `startCount' and `endCount' arrays.  Segments must    */
 
565
  /* not be overlapping and the last segment should always contain the     */
 
566
  /* `0xFFFF' endCount.                                                    */
 
567
  /*                                                                       */
 
568
  /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
 
569
  /* ignored (they are traces of over-engineering in the TrueType          */
 
570
  /* specification).                                                       */
 
571
  /*                                                                       */
 
572
  /* Each segment also has a signed `delta', as well as an optional offset */
 
573
  /* within the `glyphIds' table.                                          */
 
574
  /*                                                                       */
 
575
  /* If a segment's idOffset is 0, the glyph index corresponding to any    */
 
576
  /* charcode within the segment is obtained by adding the value of        */
 
577
  /* `idDelta' directly to the charcode, modulo 65536.                     */
 
578
  /*                                                                       */
 
579
  /* Otherwise, a glyph index is taken from the glyph ids sub-array for    */
 
580
  /* the segment, and the value of `idDelta' is added to it.               */
 
581
  /*                                                                       */
 
582
 
 
583
#ifdef TT_CONFIG_CMAP_FORMAT_4
 
584
 
 
585
  FT_CALLBACK_DEF( void )
 
586
  tt_cmap4_validate( FT_Byte*      table,
 
587
                     FT_Validator  valid )
 
588
  {
 
589
    FT_Byte*  p      = table + 2;               /* skip format */
 
590
    FT_UInt   length = TT_NEXT_USHORT( p );
 
591
    FT_Byte   *ends, *starts, *offsets, *deltas, *glyph_ids;
 
592
    FT_UInt   num_segs;
 
593
 
 
594
 
 
595
    if ( table + length > valid->limit || length < 16 )
 
596
      FT_INVALID_TOO_SHORT;
 
597
 
 
598
    p        = table + 6;
 
599
    num_segs = TT_NEXT_USHORT( p );   /* read segCountX2 */
 
600
 
 
601
    if ( valid->level >= FT_VALIDATE_PARANOID )
 
602
    {
 
603
      /* check that we have an even value here */
 
604
      if ( num_segs & 1 )
 
605
        FT_INVALID_DATA;
 
606
    }
 
607
 
 
608
    num_segs /= 2;
 
609
 
 
610
    /* check the search parameters - even though we never use them */
 
611
    /*                                                             */
 
612
    if ( valid->level >= FT_VALIDATE_PARANOID )
 
613
    {
 
614
      /* check the values of 'searchRange', 'entrySelector', 'rangeShift' */
 
615
      FT_UInt  search_range   = TT_NEXT_USHORT( p );
 
616
      FT_UInt  entry_selector = TT_NEXT_USHORT( p );
 
617
      FT_UInt  range_shift    = TT_NEXT_USHORT( p );
 
618
 
 
619
 
 
620
      if ( ( search_range | range_shift ) & 1 )  /* must be even values */
 
621
        FT_INVALID_DATA;
 
622
 
 
623
      search_range /= 2;
 
624
      range_shift  /= 2;
 
625
 
 
626
      /* `search range' is the greatest power of 2 that is <= num_segs */
 
627
 
 
628
      if ( search_range                > num_segs                 ||
 
629
           search_range * 2            < num_segs                 ||
 
630
           search_range + range_shift != num_segs                 ||
 
631
           search_range               != ( 1U << entry_selector ) )
 
632
        FT_INVALID_DATA;
 
633
    }
 
634
 
 
635
    ends      = table   + 14;
 
636
    starts    = table   + 16 + num_segs * 2;
 
637
    deltas    = starts  + num_segs * 2;
 
638
    offsets   = deltas  + num_segs * 2;
 
639
    glyph_ids = offsets + num_segs * 2;
 
640
 
 
641
    if ( glyph_ids > table + length )
 
642
      FT_INVALID_TOO_SHORT;
 
643
 
 
644
    /* check last segment, its end count must be FFFF */
 
645
    if ( valid->level >= FT_VALIDATE_PARANOID )
 
646
    {
 
647
      p = ends + ( num_segs - 1 ) * 2;
 
648
      if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
 
649
        FT_INVALID_DATA;
 
650
    }
 
651
 
 
652
    /* check that segments are sorted in increasing order and do not */
 
653
    /* overlap; check also the offsets                               */
 
654
    {
 
655
      FT_UInt  start, end, last = 0, offset, n;
 
656
      FT_Int   delta;
 
657
 
 
658
 
 
659
      for ( n = 0; n < num_segs; n++ )
 
660
      {
 
661
        p = starts + n * 2;
 
662
        start = TT_PEEK_USHORT( p );
 
663
        p = ends + n * 2;
 
664
        end = TT_PEEK_USHORT( p );
 
665
        p = deltas + n * 2;
 
666
        delta = TT_PEEK_SHORT( p );
 
667
        p = offsets + n * 2;
 
668
        offset = TT_PEEK_USHORT( p );
 
669
 
 
670
        if ( start > end )
 
671
          FT_INVALID_DATA;
 
672
 
 
673
        /* this test should be performed at default validation level;  */
 
674
        /* unfortunately, some popular Asian fonts present overlapping */
 
675
        /* ranges in their charmaps                                    */
 
676
        /*                                                             */
 
677
        if ( valid->level >= FT_VALIDATE_TIGHT )
 
678
        {
 
679
          if ( n > 0 && start <= last )
 
680
            FT_INVALID_DATA;
 
681
        }
 
682
 
 
683
        if ( offset )
 
684
        {
 
685
          p += offset;  /* start of glyph id array */
 
686
 
 
687
          /* check that we point within the glyph ids table only */
 
688
          if ( p < glyph_ids                                ||
 
689
               p + ( end - start + 1 ) * 2 > table + length )
 
690
            FT_INVALID_DATA;
 
691
 
 
692
          /* check glyph indices within the segment range */
 
693
          if ( valid->level >= FT_VALIDATE_TIGHT )
 
694
          {
 
695
            FT_UInt  idx;
 
696
 
 
697
 
 
698
            for ( ; start < end; )
 
699
            {
 
700
              idx = FT_NEXT_USHORT( p );
 
701
              if ( idx != 0 )
 
702
              {
 
703
                idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
 
704
 
 
705
                if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
 
706
                  FT_INVALID_GLYPH_ID;
 
707
              }
 
708
            }
 
709
          }
 
710
        }
 
711
 
 
712
        last = end;
 
713
      }
 
714
    }
 
715
  }
 
716
 
 
717
 
 
718
  FT_CALLBACK_DEF( FT_UInt )
 
719
  tt_cmap4_char_index( TT_CMap    cmap,
 
720
                       FT_UInt32  char_code )
 
721
  {
 
722
    FT_Byte*  table  = cmap->data;
 
723
    FT_UInt   result = 0;
 
724
 
 
725
 
 
726
    if ( char_code < 0x10000UL )
 
727
    {
 
728
      FT_UInt   idx, num_segs2;
 
729
      FT_Int    delta;
 
730
      FT_UInt   code = (FT_UInt)char_code;
 
731
      FT_Byte*  p;
 
732
 
 
733
 
 
734
      p         = table + 6;
 
735
      num_segs2 = TT_PEEK_USHORT( p ) & -2;  /* be paranoid! */
 
736
 
 
737
#if 1
 
738
      /* Some fonts have more than 170 segments in their charmaps! */
 
739
      /* We changed this function to use a more efficient binary   */
 
740
      /* search for improving performance                          */
 
741
      {
 
742
        FT_UInt  min = 0;
 
743
        FT_UInt  max = num_segs2 >> 1;
 
744
        FT_UInt  mid, start, end, offset;
 
745
 
 
746
 
 
747
        while ( min < max )
 
748
        {
 
749
          mid   = ( min + max ) >> 1;
 
750
          p     = table + 14 + mid * 2;
 
751
          end   = TT_NEXT_USHORT( p );
 
752
          p    += num_segs2;
 
753
          start = TT_PEEK_USHORT( p);
 
754
 
 
755
          if ( code < start )
 
756
            max = mid;
 
757
 
 
758
          else if ( code > end )
 
759
            min = mid + 1;
 
760
 
 
761
          else
 
762
          {
 
763
            /* we found the segment */
 
764
            idx = code;
 
765
 
 
766
            p += num_segs2;
 
767
            delta = TT_PEEK_SHORT( p );
 
768
 
 
769
            p += num_segs2;
 
770
            offset = TT_PEEK_USHORT( p );
 
771
 
 
772
            if ( offset != 0 )
 
773
            {
 
774
              p  += offset + 2 * ( idx - start );
 
775
              idx = TT_PEEK_USHORT( p );
 
776
            }
 
777
 
 
778
            if ( idx != 0 )
 
779
              result = (FT_UInt)( idx + delta ) & 0xFFFFU;
 
780
 
 
781
            goto Exit;
 
782
          }
 
783
        }
 
784
      }
 
785
 
 
786
#else /* 0 - old code */
 
787
 
 
788
      {
 
789
        FT_UInt   n;
 
790
        FT_Byte*  q;
 
791
 
 
792
 
 
793
        p = table + 14;               /* ends table   */
 
794
        q = table + 16 + num_segs2;   /* starts table */
 
795
 
 
796
 
 
797
        for ( n = 0; n < num_segs2; n += 2 )
 
798
        {
 
799
          FT_UInt  end   = TT_NEXT_USHORT( p );
 
800
          FT_UInt  start = TT_NEXT_USHORT( q );
 
801
          FT_UInt  offset;
 
802
 
 
803
 
 
804
          if ( code < start )
 
805
            break;
 
806
 
 
807
          if ( code <= end )
 
808
          {
 
809
            idx = code;
 
810
 
 
811
            p = q + num_segs2 - 2;
 
812
            delta = TT_PEEK_SHORT( p );
 
813
            p += num_segs2;
 
814
            offset = TT_PEEK_USHORT( p );
 
815
 
 
816
            if ( offset != 0 )
 
817
            {
 
818
              p  += offset + 2 * ( idx - start );
 
819
              idx = TT_PEEK_USHORT( p );
 
820
            }
 
821
 
 
822
            if ( idx != 0 )
 
823
              result = (FT_UInt)( idx + delta ) & 0xFFFFU;
 
824
          }
 
825
        }
 
826
      }
 
827
 
 
828
#endif /* 0 */
 
829
 
 
830
    }
 
831
 
 
832
  Exit:
 
833
    return result;
 
834
  }
 
835
 
 
836
 
 
837
  FT_CALLBACK_DEF( FT_UInt )
 
838
  tt_cmap4_char_next( TT_CMap     cmap,
 
839
                      FT_UInt32  *pchar_code )
 
840
  {
 
841
    FT_Byte*   table     = cmap->data;
 
842
    FT_UInt32  result    = 0;
 
843
    FT_UInt32  char_code = *pchar_code + 1;
 
844
    FT_UInt    gindex    = 0;
 
845
    FT_Byte*   p;
 
846
    FT_Byte*   q;
 
847
    FT_UInt    code, num_segs2;
 
848
 
 
849
 
 
850
    if ( char_code >= 0x10000UL )
 
851
      goto Exit;
 
852
 
 
853
    code      = (FT_UInt)char_code;
 
854
    p         = table + 6;
 
855
    num_segs2 = TT_PEEK_USHORT(p) & -2;  /* ensure even-ness */
 
856
 
 
857
    for (;;)
 
858
    {
 
859
      FT_UInt  offset, n;
 
860
      FT_Int   delta;
 
861
 
 
862
 
 
863
      p = table + 14;              /* ends table  */
 
864
      q = table + 16 + num_segs2;  /* starts table */
 
865
 
 
866
      for ( n = 0; n < num_segs2; n += 2 )
 
867
      {
 
868
        FT_UInt  end   = TT_NEXT_USHORT( p );
 
869
        FT_UInt  start = TT_NEXT_USHORT( q );
 
870
 
 
871
 
 
872
        if ( code < start )
 
873
          code = start;
 
874
 
 
875
        if ( code <= end )
 
876
        {
 
877
          p = q + num_segs2 - 2;
 
878
          delta = TT_PEEK_SHORT( p );
 
879
          p += num_segs2;
 
880
          offset = TT_PEEK_USHORT( p );
 
881
 
 
882
          if ( offset != 0 )
 
883
          {
 
884
            /* parse the glyph ids array for non-0 index */
 
885
            p += offset + ( code - start ) * 2;
 
886
            while ( code <= end )
 
887
            {
 
888
              gindex = TT_NEXT_USHORT( p );
 
889
              if ( gindex != 0 )
 
890
              {
 
891
                gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
 
892
                if ( gindex != 0 )
 
893
                  break;
 
894
              }
 
895
              code++;
 
896
            }
 
897
          }
 
898
          else
 
899
            gindex = (FT_UInt)( code + delta ) & 0xFFFFU;
 
900
 
 
901
          if ( gindex == 0 )
 
902
            break;
 
903
 
 
904
          result = code;
 
905
          goto Exit;
 
906
        }
 
907
      }
 
908
 
 
909
      /* loop to next trial charcode */
 
910
      if ( code >= 0xFFFFU )
 
911
        break;
 
912
 
 
913
      code++;
 
914
    }
 
915
    return result;
 
916
 
 
917
  Exit:
 
918
    *pchar_code = result;
 
919
    return gindex;
 
920
  }
 
921
 
 
922
 
 
923
  FT_CALLBACK_TABLE_DEF
 
924
  const TT_CMap_ClassRec  tt_cmap4_class_rec =
 
925
  {
 
926
    {
 
927
      sizeof ( TT_CMapRec ),
 
928
 
 
929
      (FT_CMap_InitFunc)     tt_cmap_init,
 
930
      (FT_CMap_DoneFunc)     NULL,
 
931
      (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
 
932
      (FT_CMap_CharNextFunc) tt_cmap4_char_next
 
933
    },
 
934
    4,
 
935
    (TT_CMap_ValidateFunc)   tt_cmap4_validate
 
936
  };
 
937
 
 
938
#endif /* TT_CONFIG_CMAP_FORMAT_4 */
 
939
 
 
940
 
 
941
  /*************************************************************************/
 
942
  /*************************************************************************/
 
943
  /*****                                                               *****/
 
944
  /*****                          FORMAT 6                             *****/
 
945
  /*****                                                               *****/
 
946
  /*************************************************************************/
 
947
  /*************************************************************************/
 
948
 
 
949
  /*************************************************************************/
 
950
  /*                                                                       */
 
951
  /* TABLE OVERVIEW                                                        */
 
952
  /* --------------                                                        */
 
953
  /*                                                                       */
 
954
  /*   NAME        OFFSET          TYPE             DESCRIPTION            */
 
955
  /*                                                                       */
 
956
  /*   format       0              USHORT           must be 4              */
 
957
  /*   length       2              USHORT           table length in bytes  */
 
958
  /*   language     4              USHORT           Mac language code      */
 
959
  /*                                                                       */
 
960
  /*   first        6              USHORT           first segment code     */
 
961
  /*   count        8              USHORT           segment size in chars  */
 
962
  /*   glyphIds     10             USHORT[count]    glyph ids              */
 
963
  /*                                                                       */
 
964
  /* A very simplified segment mapping.                                    */
 
965
  /*                                                                       */
 
966
 
 
967
#ifdef TT_CONFIG_CMAP_FORMAT_6
 
968
 
 
969
  FT_CALLBACK_DEF( void )
 
970
  tt_cmap6_validate( FT_Byte*      table,
 
971
                     FT_Validator  valid )
 
972
  {
 
973
    FT_Byte*  p;
 
974
    FT_UInt   length, start, count;
 
975
 
 
976
 
 
977
    if ( table + 10 > valid->limit )
 
978
      FT_INVALID_TOO_SHORT;
 
979
 
 
980
    p      = table + 2;
 
981
    length = TT_NEXT_USHORT( p );
 
982
 
 
983
    p      = table + 6;             /* skip language */
 
984
    start  = TT_NEXT_USHORT( p );
 
985
    count  = TT_NEXT_USHORT( p );
 
986
 
 
987
    if ( table + length > valid->limit || length < 10 + count * 2 )
 
988
      FT_INVALID_TOO_SHORT;
 
989
 
 
990
    /* check glyph indices */
 
991
    if ( valid->level >= FT_VALIDATE_TIGHT )
 
992
    {
 
993
      FT_UInt  gindex;
 
994
 
 
995
 
 
996
      for ( ; count > 0; count-- )
 
997
      {
 
998
        gindex = TT_NEXT_USHORT( p );
 
999
        if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
 
1000
          FT_INVALID_GLYPH_ID;
 
1001
      }
 
1002
    }
 
1003
  }
 
1004
 
 
1005
 
 
1006
  FT_CALLBACK_DEF( FT_UInt )
 
1007
  tt_cmap6_char_index( TT_CMap    cmap,
 
1008
                       FT_UInt32  char_code )
 
1009
  {
 
1010
    FT_Byte*  table  = cmap->data;
 
1011
    FT_UInt   result = 0;
 
1012
    FT_Byte*  p      = table + 6;
 
1013
    FT_UInt   start  = TT_NEXT_USHORT( p );
 
1014
    FT_UInt   count  = TT_NEXT_USHORT( p );
 
1015
    FT_UInt   idx    = (FT_UInt)( char_code - start );
 
1016
 
 
1017
 
 
1018
    if ( idx < count )
 
1019
    {
 
1020
      p += 2 * idx;
 
1021
      result = TT_PEEK_USHORT( p );
 
1022
    }
 
1023
    return result;
 
1024
  }
 
1025
 
 
1026
 
 
1027
  FT_CALLBACK_DEF( FT_UInt )
 
1028
  tt_cmap6_char_next( TT_CMap     cmap,
 
1029
                      FT_UInt32  *pchar_code )
 
1030
  {
 
1031
    FT_Byte*   table     = cmap->data;
 
1032
    FT_UInt32  result    = 0;
 
1033
    FT_UInt32  char_code = *pchar_code + 1;
 
1034
    FT_UInt    gindex    = 0;
 
1035
 
 
1036
    FT_Byte*   p         = table + 6;
 
1037
    FT_UInt    start     = TT_NEXT_USHORT( p );
 
1038
    FT_UInt    count     = TT_NEXT_USHORT( p );
 
1039
    FT_UInt    idx;
 
1040
 
 
1041
 
 
1042
    if ( char_code >= 0x10000UL )
 
1043
      goto Exit;
 
1044
 
 
1045
    if ( char_code < start )
 
1046
      char_code = start;
 
1047
 
 
1048
    idx = (FT_UInt)( char_code - start );
 
1049
    p  += 2 * idx;
 
1050
 
 
1051
    for ( ; idx < count; idx++ )
 
1052
    {
 
1053
      gindex = TT_NEXT_USHORT( p );
 
1054
      if ( gindex != 0 )
 
1055
      {
 
1056
        result = char_code;
 
1057
        break;
 
1058
      }
 
1059
      char_code++;
 
1060
    }
 
1061
 
 
1062
  Exit:
 
1063
    *pchar_code = result;
 
1064
    return gindex;
 
1065
  }
 
1066
 
 
1067
 
 
1068
  FT_CALLBACK_TABLE_DEF
 
1069
  const TT_CMap_ClassRec  tt_cmap6_class_rec =
 
1070
  {
 
1071
    {
 
1072
      sizeof ( TT_CMapRec ),
 
1073
 
 
1074
      (FT_CMap_InitFunc)     tt_cmap_init,
 
1075
      (FT_CMap_DoneFunc)     NULL,
 
1076
      (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
 
1077
      (FT_CMap_CharNextFunc) tt_cmap6_char_next
 
1078
    },
 
1079
    6,
 
1080
    (TT_CMap_ValidateFunc)   tt_cmap6_validate
 
1081
  };
 
1082
 
 
1083
#endif /* TT_CONFIG_CMAP_FORMAT_6 */
 
1084
 
 
1085
 
 
1086
  /*************************************************************************/
 
1087
  /*************************************************************************/
 
1088
  /*****                                                               *****/
 
1089
  /*****                          FORMAT 8                             *****/
 
1090
  /*****                                                               *****/
 
1091
  /***** It's hard to completely understand what the OpenType spec     *****/
 
1092
  /***** says about this format, but here is my conclusion.            *****/
 
1093
  /*****                                                               *****/
 
1094
  /***** The purpose of this format is to easily map UTF-16 text to    *****/
 
1095
  /***** glyph indices.  Basically, the `char_code' must be in one of  *****/
 
1096
  /***** the following formats:                                        *****/
 
1097
  /*****                                                               *****/
 
1098
  /*****   - A 16-bit value that isn't part of the Unicode Surrogates  *****/
 
1099
  /*****     Area (i.e. U+D800-U+DFFF).                                *****/
 
1100
  /*****                                                               *****/
 
1101
  /*****   - A 32-bit value, made of two surrogate values, i.e.. if    *****/
 
1102
  /*****     `char_code = (char_hi << 16) | char_lo', then both        *****/
 
1103
  /*****     `char_hi' and `char_lo' must be in the Surrogates Area.   *****/
 
1104
  /*****      Area.                                                    *****/
 
1105
  /*****                                                               *****/
 
1106
  /***** The 'is32' table embedded in the charmap indicates whether a  *****/
 
1107
  /***** given 16-bit value is in the surrogates area or not.          *****/
 
1108
  /*****                                                               *****/
 
1109
  /***** So, for any given `char_code', we can assert the following:   *****/
 
1110
  /*****                                                               *****/
 
1111
  /*****   If `char_hi == 0' then we must have `is32[char_lo] == 0'.   *****/
 
1112
  /*****                                                               *****/
 
1113
  /*****   If `char_hi != 0' then we must have both                    *****/
 
1114
  /*****   `is32[char_hi] != 0' and `is32[char_lo] != 0'.              *****/
 
1115
  /*****                                                               *****/
 
1116
  /*************************************************************************/
 
1117
  /*************************************************************************/
 
1118
 
 
1119
  /*************************************************************************/
 
1120
  /*                                                                       */
 
1121
  /* TABLE OVERVIEW                                                        */
 
1122
  /* --------------                                                        */
 
1123
  /*                                                                       */
 
1124
  /*   NAME        OFFSET         TYPE        DESCRIPTION                  */
 
1125
  /*                                                                       */
 
1126
  /*   format      0              USHORT      must be 8                    */
 
1127
  /*   reseved     2              USHORT      reserved                     */
 
1128
  /*   length      4              ULONG       length in bytes              */
 
1129
  /*   language    8              ULONG       Mac language code            */
 
1130
  /*   is32        12             BYTE[8192]  32-bitness bitmap            */
 
1131
  /*   count       8204           ULONG       number of groups             */
 
1132
  /*                                                                       */
 
1133
  /* This header is followed by 'count' groups of the following format:    */
 
1134
  /*                                                                       */
 
1135
  /*   start       0              ULONG       first charcode               */
 
1136
  /*   end         4              ULONG       last charcode                */
 
1137
  /*   startId     8              ULONG       start glyph id for the group */
 
1138
  /*                                                                       */
 
1139
 
 
1140
#ifdef TT_CONFIG_CMAP_FORMAT_8
 
1141
 
 
1142
  FT_CALLBACK_DEF( void )
 
1143
  tt_cmap8_validate( FT_Byte*      table,
 
1144
                     FT_Validator  valid )
 
1145
  {
 
1146
    FT_Byte*   p = table + 4;
 
1147
    FT_Byte*   is32;
 
1148
    FT_UInt32  length;
 
1149
    FT_UInt32  num_groups;
 
1150
 
 
1151
 
 
1152
    if ( table + 16 + 8192 > valid->limit )
 
1153
      FT_INVALID_TOO_SHORT;
 
1154
 
 
1155
    length = TT_NEXT_ULONG( p );
 
1156
    if ( table + length > valid->limit || length < 8208 )
 
1157
      FT_INVALID_TOO_SHORT;
 
1158
 
 
1159
    is32       = table + 12;
 
1160
    p          = is32  + 8192;          /* skip `is32' array */
 
1161
    num_groups = TT_NEXT_ULONG( p );
 
1162
 
 
1163
    if ( p + num_groups * 12 > valid->limit )
 
1164
      FT_INVALID_TOO_SHORT;
 
1165
 
 
1166
    /* check groups, they must be in increasing order */
 
1167
    {
 
1168
      FT_UInt32  n, start, end, start_id, count, last = 0;
 
1169
 
 
1170
 
 
1171
      for ( n = 0; n < num_groups; n++ )
 
1172
      {
 
1173
        FT_UInt   hi, lo;
 
1174
 
 
1175
 
 
1176
        start    = TT_NEXT_ULONG( p );
 
1177
        end      = TT_NEXT_ULONG( p );
 
1178
        start_id = TT_NEXT_ULONG( p );
 
1179
 
 
1180
        if ( start > end )
 
1181
          FT_INVALID_DATA;
 
1182
 
 
1183
        if ( n > 0 && start <= last )
 
1184
          FT_INVALID_DATA;
 
1185
 
 
1186
        if ( valid->level >= FT_VALIDATE_TIGHT )
 
1187
        {
 
1188
          if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
 
1189
            FT_INVALID_GLYPH_ID;
 
1190
 
 
1191
          count = (FT_UInt32)( end - start + 1 );
 
1192
 
 
1193
          if ( start & ~0xFFFFU )
 
1194
          {
 
1195
            /* start_hi != 0; check that is32[i] is 1 for each i in */
 
1196
            /* the `hi' and `lo' of the range [start..end]          */
 
1197
            for ( ; count > 0; count--, start++ )
 
1198
            {
 
1199
              hi = (FT_UInt)( start >> 16 );
 
1200
              lo = (FT_UInt)( start & 0xFFFFU );
 
1201
 
 
1202
              if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
 
1203
                FT_INVALID_DATA;
 
1204
 
 
1205
              if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
 
1206
                FT_INVALID_DATA;
 
1207
            }
 
1208
          }
 
1209
          else
 
1210
          {
 
1211
            /* start_hi == 0; check that is32[i] is 0 for each i in */
 
1212
            /* the range [start..end]                               */
 
1213
 
 
1214
            /* end_hi cannot be != 0! */
 
1215
            if ( end & ~0xFFFFU )
 
1216
              FT_INVALID_DATA;
 
1217
 
 
1218
            for ( ; count > 0; count--, start++ )
 
1219
            {
 
1220
              lo = (FT_UInt)( start & 0xFFFFU );
 
1221
 
 
1222
              if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
 
1223
                FT_INVALID_DATA;
 
1224
            }
 
1225
          }
 
1226
        }
 
1227
 
 
1228
        last = end;
 
1229
      }
 
1230
    }
 
1231
  }
 
1232
 
 
1233
 
 
1234
  FT_CALLBACK_DEF( FT_UInt )
 
1235
  tt_cmap8_char_index( TT_CMap    cmap,
 
1236
                       FT_UInt32  char_code )
 
1237
  {
 
1238
    FT_Byte*   table      = cmap->data;
 
1239
    FT_UInt    result     = 0;
 
1240
    FT_Byte*   p          = table + 8204;
 
1241
    FT_UInt32  num_groups = TT_NEXT_ULONG( p );
 
1242
    FT_UInt32  start, end, start_id;
 
1243
 
 
1244
 
 
1245
    for ( ; num_groups > 0; num_groups-- )
 
1246
    {
 
1247
      start    = TT_NEXT_ULONG( p );
 
1248
      end      = TT_NEXT_ULONG( p );
 
1249
      start_id = TT_NEXT_ULONG( p );
 
1250
 
 
1251
      if ( char_code < start )
 
1252
        break;
 
1253
 
 
1254
      if ( char_code <= end )
 
1255
      {
 
1256
        result = start_id + char_code - start;
 
1257
        break;
 
1258
      }
 
1259
    }
 
1260
    return result;
 
1261
  }
 
1262
 
 
1263
 
 
1264
  FT_CALLBACK_DEF( FT_UInt )
 
1265
  tt_cmap8_char_next( TT_CMap     cmap,
 
1266
                      FT_UInt32  *pchar_code )
 
1267
  {
 
1268
    FT_UInt32  result     = 0;
 
1269
    FT_UInt32  char_code  = *pchar_code + 1;
 
1270
    FT_UInt    gindex     = 0;
 
1271
    FT_Byte*   table      = cmap->data;
 
1272
    FT_Byte*   p          = table + 8204;
 
1273
    FT_UInt32  num_groups = TT_NEXT_ULONG( p );
 
1274
    FT_UInt32  start, end, start_id;
 
1275
 
 
1276
 
 
1277
    p = table + 8208;
 
1278
 
 
1279
    for ( ; num_groups > 0; num_groups-- )
 
1280
    {
 
1281
      start    = TT_NEXT_ULONG( p );
 
1282
      end      = TT_NEXT_ULONG( p );
 
1283
      start_id = TT_NEXT_ULONG( p );
 
1284
 
 
1285
      if ( char_code < start )
 
1286
        char_code = start;
 
1287
 
 
1288
      if ( char_code <= end )
 
1289
      {
 
1290
        gindex = (FT_UInt)( char_code - start + start_id );
 
1291
        if ( gindex != 0 )
 
1292
        {
 
1293
          result = char_code;
 
1294
          goto Exit;
 
1295
        }
 
1296
      }
 
1297
    }
 
1298
 
 
1299
  Exit:
 
1300
    *pchar_code = result;
 
1301
    return gindex;
 
1302
  }
 
1303
 
 
1304
 
 
1305
  FT_CALLBACK_TABLE_DEF
 
1306
  const TT_CMap_ClassRec  tt_cmap8_class_rec =
 
1307
  {
 
1308
    {
 
1309
      sizeof ( TT_CMapRec ),
 
1310
 
 
1311
      (FT_CMap_InitFunc)     tt_cmap_init,
 
1312
      (FT_CMap_DoneFunc)     NULL,
 
1313
      (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
 
1314
      (FT_CMap_CharNextFunc) tt_cmap8_char_next
 
1315
    },
 
1316
    8,
 
1317
    (TT_CMap_ValidateFunc)   tt_cmap8_validate
 
1318
  };
 
1319
 
 
1320
#endif /* TT_CONFIG_CMAP_FORMAT_8 */
 
1321
 
 
1322
 
 
1323
  /*************************************************************************/
 
1324
  /*************************************************************************/
 
1325
  /*****                                                               *****/
 
1326
  /*****                          FORMAT 10                            *****/
 
1327
  /*****                                                               *****/
 
1328
  /*************************************************************************/
 
1329
  /*************************************************************************/
 
1330
 
 
1331
  /*************************************************************************/
 
1332
  /*                                                                       */
 
1333
  /* TABLE OVERVIEW                                                        */
 
1334
  /* --------------                                                        */
 
1335
  /*                                                                       */
 
1336
  /*   NAME      OFFSET  TYPE               DESCRIPTION                    */
 
1337
  /*                                                                       */
 
1338
  /*   format     0      USHORT             must be 10                     */
 
1339
  /*   reserved   2      USHORT             reserved                       */
 
1340
  /*   length     4      ULONG              length in bytes                */
 
1341
  /*   language   8      ULONG              Mac language code              */
 
1342
  /*                                                                       */
 
1343
  /*   start     12      ULONG              first char in range            */
 
1344
  /*   count     16      ULONG              number of chars in range       */
 
1345
  /*   glyphIds  20      USHORT[count]      glyph indices covered          */
 
1346
  /*                                                                       */
 
1347
 
 
1348
#ifdef TT_CONFIG_CMAP_FORMAT_10
 
1349
 
 
1350
  FT_CALLBACK_DEF( void )
 
1351
  tt_cmap10_validate( FT_Byte*      table,
 
1352
                      FT_Validator  valid )
 
1353
  {
 
1354
    FT_Byte*  p = table + 4;
 
1355
    FT_ULong  length, start, count;
 
1356
 
 
1357
 
 
1358
    if ( table + 20 > valid->limit )
 
1359
      FT_INVALID_TOO_SHORT;
 
1360
 
 
1361
    length = TT_NEXT_ULONG( p );
 
1362
    p      = table + 12;
 
1363
    start  = TT_NEXT_ULONG( p );
 
1364
    count  = TT_NEXT_ULONG( p );
 
1365
 
 
1366
    if ( table + length > valid->limit || length < 20 + count * 2 )
 
1367
      FT_INVALID_TOO_SHORT;
 
1368
 
 
1369
    /* check glyph indices */
 
1370
    if ( valid->level >= FT_VALIDATE_TIGHT )
 
1371
    {
 
1372
      FT_UInt  gindex;
 
1373
 
 
1374
 
 
1375
      for ( ; count > 0; count-- )
 
1376
      {
 
1377
        gindex = TT_NEXT_USHORT( p );
 
1378
        if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
 
1379
          FT_INVALID_GLYPH_ID;
 
1380
      }
 
1381
    }
 
1382
  }
 
1383
 
 
1384
 
 
1385
  FT_CALLBACK_DEF( FT_UInt )
 
1386
  tt_cmap10_char_index( TT_CMap    cmap,
 
1387
                        FT_UInt32  char_code )
 
1388
  {
 
1389
    FT_Byte*   table  = cmap->data;
 
1390
    FT_UInt    result = 0;
 
1391
    FT_Byte*   p      = table + 12;
 
1392
    FT_UInt32  start  = TT_NEXT_ULONG( p );
 
1393
    FT_UInt32  count  = TT_NEXT_ULONG( p );
 
1394
    FT_UInt32  idx    = (FT_ULong)( char_code - start );
 
1395
 
 
1396
 
 
1397
    if ( idx < count )
 
1398
    {
 
1399
      p     += 2 * idx;
 
1400
      result = TT_PEEK_USHORT( p );
 
1401
    }
 
1402
    return result;
 
1403
  }
 
1404
 
 
1405
 
 
1406
  FT_CALLBACK_DEF( FT_UInt )
 
1407
  tt_cmap10_char_next( TT_CMap     cmap,
 
1408
                       FT_UInt32  *pchar_code )
 
1409
  {
 
1410
    FT_Byte*   table     = cmap->data;
 
1411
    FT_UInt32  result    = 0;
 
1412
    FT_UInt32  char_code = *pchar_code + 1;
 
1413
    FT_UInt    gindex    = 0;
 
1414
    FT_Byte*   p         = table + 12;
 
1415
    FT_UInt32  start     = TT_NEXT_ULONG( p );
 
1416
    FT_UInt32  count     = TT_NEXT_ULONG( p );
 
1417
    FT_UInt32  idx;
 
1418
 
 
1419
 
 
1420
    if ( char_code < start )
 
1421
      char_code = start;
 
1422
 
 
1423
    idx = (FT_UInt32)( char_code - start );
 
1424
    p  += 2 * idx;
 
1425
 
 
1426
    for ( ; idx < count; idx++ )
 
1427
    {
 
1428
      gindex = TT_NEXT_USHORT( p );
 
1429
      if ( gindex != 0 )
 
1430
      {
 
1431
        result = char_code;
 
1432
        break;
 
1433
      }
 
1434
      char_code++;
 
1435
    }
 
1436
 
 
1437
    *pchar_code = char_code;
 
1438
    return gindex;
 
1439
  }
 
1440
 
 
1441
 
 
1442
  FT_CALLBACK_TABLE_DEF
 
1443
  const TT_CMap_ClassRec  tt_cmap10_class_rec =
 
1444
  {
 
1445
    {
 
1446
      sizeof ( TT_CMapRec ),
 
1447
 
 
1448
      (FT_CMap_InitFunc)     tt_cmap_init,
 
1449
      (FT_CMap_DoneFunc)     NULL,
 
1450
      (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
 
1451
      (FT_CMap_CharNextFunc) tt_cmap10_char_next
 
1452
    },
 
1453
    10,
 
1454
    (TT_CMap_ValidateFunc)   tt_cmap10_validate
 
1455
  };
 
1456
 
 
1457
#endif /* TT_CONFIG_CMAP_FORMAT_10 */
 
1458
 
 
1459
 
 
1460
  /*************************************************************************/
 
1461
  /*************************************************************************/
 
1462
  /*****                                                               *****/
 
1463
  /*****                          FORMAT 12                            *****/
 
1464
  /*****                                                               *****/
 
1465
  /*************************************************************************/
 
1466
  /*************************************************************************/
 
1467
 
 
1468
  /*************************************************************************/
 
1469
  /*                                                                       */
 
1470
  /* TABLE OVERVIEW                                                        */
 
1471
  /* --------------                                                        */
 
1472
  /*                                                                       */
 
1473
  /*   NAME        OFFSET     TYPE       DESCRIPTION                       */
 
1474
  /*                                                                       */
 
1475
  /*   format      0          USHORT     must be 12                        */
 
1476
  /*   reserved    2          USHORT     reserved                          */
 
1477
  /*   length      4          ULONG      length in bytes                   */
 
1478
  /*   language    8          ULONG      Mac language code                 */
 
1479
  /*   count       12         ULONG      number of groups                  */
 
1480
  /*               16                                                      */
 
1481
  /*                                                                       */
 
1482
  /* This header is followed by `count' groups of the following format:    */
 
1483
  /*                                                                       */
 
1484
  /*   start       0          ULONG      first charcode                    */
 
1485
  /*   end         4          ULONG      last charcode                     */
 
1486
  /*   startId     8          ULONG      start glyph id for the group      */
 
1487
  /*                                                                       */
 
1488
 
 
1489
#ifdef TT_CONFIG_CMAP_FORMAT_12
 
1490
 
 
1491
  FT_CALLBACK_DEF( void )
 
1492
  tt_cmap12_validate( FT_Byte*      table,
 
1493
                      FT_Validator  valid )
 
1494
  {
 
1495
    FT_Byte*   p;
 
1496
    FT_ULong   length;
 
1497
    FT_ULong   num_groups;
 
1498
 
 
1499
 
 
1500
    if ( table + 16 > valid->limit )
 
1501
      FT_INVALID_TOO_SHORT;
 
1502
 
 
1503
    p      = table + 4;
 
1504
    length = TT_NEXT_ULONG( p );
 
1505
 
 
1506
    p          = table + 12;
 
1507
    num_groups = TT_NEXT_ULONG( p );
 
1508
 
 
1509
    if ( table + length > valid->limit || length < 16 + 12 * num_groups )
 
1510
      FT_INVALID_TOO_SHORT;
 
1511
 
 
1512
    /* check groups, they must be in increasing order */
 
1513
    {
 
1514
      FT_ULong  n, start, end, start_id, last = 0;
 
1515
 
 
1516
 
 
1517
      for ( n = 0; n < num_groups; n++ )
 
1518
      {
 
1519
        start    = TT_NEXT_ULONG( p );
 
1520
        end      = TT_NEXT_ULONG( p );
 
1521
        start_id = TT_NEXT_ULONG( p );
 
1522
 
 
1523
        if ( start > end )
 
1524
          FT_INVALID_DATA;
 
1525
 
 
1526
        if ( n > 0 && start <= last )
 
1527
          FT_INVALID_DATA;
 
1528
 
 
1529
        if ( valid->level >= FT_VALIDATE_TIGHT )
 
1530
        {
 
1531
          if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
 
1532
            FT_INVALID_GLYPH_ID;
 
1533
        }
 
1534
 
 
1535
        last = end;
 
1536
      }
 
1537
    }
 
1538
  }
 
1539
 
 
1540
 
 
1541
  FT_CALLBACK_DEF( FT_UInt )
 
1542
  tt_cmap12_char_index( TT_CMap    cmap,
 
1543
                        FT_UInt32  char_code )
 
1544
  {
 
1545
    FT_UInt    result     = 0;
 
1546
    FT_Byte*   table      = cmap->data;
 
1547
    FT_Byte*   p          = table + 12;
 
1548
    FT_UInt32  num_groups = TT_NEXT_ULONG( p );
 
1549
    FT_UInt32  start, end, start_id;
 
1550
 
 
1551
 
 
1552
    for ( ; num_groups > 0; num_groups-- )
 
1553
    {
 
1554
      start    = TT_NEXT_ULONG( p );
 
1555
      end      = TT_NEXT_ULONG( p );
 
1556
      start_id = TT_NEXT_ULONG( p );
 
1557
 
 
1558
      if ( char_code < start )
 
1559
        break;
 
1560
 
 
1561
      if ( char_code <= end )
 
1562
      {
 
1563
        result = start_id + char_code - start;
 
1564
        break;
 
1565
      }
 
1566
    }
 
1567
    return result;
 
1568
  }
 
1569
 
 
1570
 
 
1571
  FT_CALLBACK_DEF( FT_UInt )
 
1572
  tt_cmap12_char_next( TT_CMap     cmap,
 
1573
                       FT_UInt32  *pchar_code )
 
1574
  {
 
1575
    FT_Byte*   table      = cmap->data;
 
1576
    FT_UInt32  result     = 0;
 
1577
    FT_UInt32  char_code  = *pchar_code + 1;
 
1578
    FT_UInt    gindex     = 0;
 
1579
    FT_Byte*   p          = table + 12;
 
1580
    FT_UInt32  num_groups = TT_NEXT_ULONG( p );
 
1581
    FT_UInt32  start, end, start_id;
 
1582
 
 
1583
 
 
1584
    p = table + 16;
 
1585
 
 
1586
    for ( ; num_groups > 0; num_groups-- )
 
1587
    {
 
1588
      start    = TT_NEXT_ULONG( p );
 
1589
      end      = TT_NEXT_ULONG( p );
 
1590
      start_id = TT_NEXT_ULONG( p );
 
1591
 
 
1592
      if ( char_code < start )
 
1593
        char_code = start;
 
1594
 
 
1595
      if ( char_code <= end )
 
1596
      {
 
1597
        gindex = (FT_UInt)(char_code - start + start_id);
 
1598
        if ( gindex != 0 )
 
1599
        {
 
1600
          result = char_code;
 
1601
          goto Exit;
 
1602
        }
 
1603
      }
 
1604
    }
 
1605
 
 
1606
  Exit:
 
1607
    *pchar_code = result;
 
1608
    return gindex;
 
1609
  }
 
1610
 
 
1611
 
 
1612
  FT_CALLBACK_TABLE_DEF
 
1613
  const TT_CMap_ClassRec  tt_cmap12_class_rec =
 
1614
  {
 
1615
    {
 
1616
      sizeof ( TT_CMapRec ),
 
1617
 
 
1618
      (FT_CMap_InitFunc)     tt_cmap_init,
 
1619
      (FT_CMap_DoneFunc)     NULL,
 
1620
      (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
 
1621
      (FT_CMap_CharNextFunc) tt_cmap12_char_next
 
1622
    },
 
1623
    12,
 
1624
    (TT_CMap_ValidateFunc)   tt_cmap12_validate
 
1625
  };
 
1626
 
 
1627
 
 
1628
#endif /* TT_CONFIG_CMAP_FORMAT_12 */
 
1629
 
 
1630
 
 
1631
#ifdef FT_CONFIG_OPTION_USE_CMAPS
 
1632
 
 
1633
  static const TT_CMap_Class  tt_cmap_classes[] =
 
1634
  {
 
1635
#ifdef TT_CONFIG_CMAP_FORMAT_0
 
1636
    &tt_cmap0_class_rec,
 
1637
#endif
 
1638
 
 
1639
#ifdef TT_CONFIG_CMAP_FORMAT_2
 
1640
    &tt_cmap2_class_rec,
 
1641
#endif
 
1642
 
 
1643
#ifdef TT_CONFIG_CMAP_FORMAT_4
 
1644
    &tt_cmap4_class_rec,
 
1645
#endif
 
1646
 
 
1647
#ifdef TT_CONFIG_CMAP_FORMAT_6
 
1648
    &tt_cmap6_class_rec,
 
1649
#endif
 
1650
 
 
1651
#ifdef TT_CONFIG_CMAP_FORMAT_8
 
1652
    &tt_cmap8_class_rec,
 
1653
#endif
 
1654
 
 
1655
#ifdef TT_CONFIG_CMAP_FORMAT_10
 
1656
    &tt_cmap10_class_rec,
 
1657
#endif
 
1658
 
 
1659
#ifdef TT_CONFIG_CMAP_FORMAT_12
 
1660
    &tt_cmap12_class_rec,
 
1661
#endif
 
1662
 
 
1663
    NULL,
 
1664
  };
 
1665
 
 
1666
 
 
1667
  /* parse the `cmap' table and build the corresponding TT_CMap objects */
 
1668
  /* in the current face                                                */
 
1669
  /*                                                                    */
 
1670
  FT_LOCAL_DEF( FT_Error )
 
1671
  TT_Build_CMaps( TT_Face  face )
 
1672
  {
 
1673
    FT_Byte*           table = face->cmap_table;
 
1674
    FT_Byte*           limit = table + face->cmap_size;
 
1675
    volatile FT_UInt   num_cmaps;
 
1676
    volatile FT_Byte*  p     = table;
 
1677
 
 
1678
 
 
1679
    if ( p + 4 > limit )
 
1680
      return FT_Err_Invalid_Table;
 
1681
 
 
1682
    /* only recognize format 0 */
 
1683
    if ( TT_NEXT_USHORT( p ) != 0 )
 
1684
    {
 
1685
      p -= 2;
 
1686
      FT_ERROR(( "TT_Build_CMaps: unsupported `cmap' table format = %d\n",
 
1687
                 TT_PEEK_USHORT( p ) ));
 
1688
      return FT_Err_Invalid_Table;
 
1689
    }
 
1690
 
 
1691
    num_cmaps = TT_NEXT_USHORT( p );
 
1692
 
 
1693
    for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
 
1694
    {
 
1695
      FT_CharMapRec  charmap;
 
1696
      FT_UInt32      offset;
 
1697
 
 
1698
 
 
1699
      charmap.platform_id = TT_NEXT_USHORT( p );
 
1700
      charmap.encoding_id = TT_NEXT_USHORT( p );
 
1701
      charmap.face        = FT_FACE( face );
 
1702
      charmap.encoding    = ft_encoding_none;  /* will be filled later */
 
1703
      offset              = TT_NEXT_ULONG( p );
 
1704
 
 
1705
      if ( offset && table + offset + 2 < limit )
 
1706
      {
 
1707
        FT_Byte*                       cmap   = table + offset;
 
1708
        FT_UInt                        format = TT_PEEK_USHORT( cmap );
 
1709
        volatile const TT_CMap_Class*  pclazz = tt_cmap_classes;
 
1710
        TT_CMap_Class                  clazz;
 
1711
 
 
1712
 
 
1713
        for ( ; *pclazz; pclazz++ )
 
1714
        {
 
1715
          clazz = *pclazz;
 
1716
          if ( clazz->format == format )
 
1717
          {
 
1718
            volatile TT_ValidatorRec  valid;
 
1719
 
 
1720
 
 
1721
            ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
 
1722
                               FT_VALIDATE_DEFAULT );
 
1723
 
 
1724
            valid.num_glyphs = face->root.num_glyphs;
 
1725
 
 
1726
            if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer ) == 0 )
 
1727
            {
 
1728
              /* validate this cmap sub-table */
 
1729
              clazz->validate( cmap, FT_VALIDATOR( &valid ) );
 
1730
            }
 
1731
 
 
1732
            if ( valid.validator.error == 0 )
 
1733
              (void)FT_CMap_New( (FT_CMap_Class)clazz, cmap, &charmap, NULL );
 
1734
            else
 
1735
            {
 
1736
              FT_ERROR(( "TT_Build_CMaps:" ));
 
1737
              FT_ERROR(( " broken cmap sub-table ignored!\n" ));
 
1738
            }
 
1739
          }
 
1740
        }
 
1741
      }
 
1742
    }
 
1743
 
 
1744
    return 0;
 
1745
  }
 
1746
 
 
1747
#endif /* FT_CONFIG_OPTION_USE_CMAPS */
 
1748
 
 
1749
 
 
1750
/* END */