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