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