Coverage Report

Created: 2021-08-22 09:07

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