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