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