Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(628)

Side by Side Diff: core/src/fxge/fx_freetype/fxft2.5.01/src/sfnt/ttcmap.c

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

Powered by Google App Engine
This is Rietveld 408576698