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