- Italian translation by Daniele Forsi (dforsi at gmail dot com)
[reactos.git] / reactos / dll / 3rdparty / freetype / src / sfnt / ttcmap0.c
1 /***************************************************************************/
2 /* */
3 /* ttcmap0.c */
4 /* */
5 /* TrueType new character mapping table (cmap) support (body). */
6 /* */
7 /* Copyright 2002, 2003 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 #include FT_INTERNAL_OBJECTS_H
22 #include FT_INTERNAL_STREAM_H
23 #include "ttload.h"
24 #include "ttcmap0.h"
25
26 #include "sferrors.h"
27
28 /*************************************************************************/
29 /* */
30 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
31 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
32 /* messages during execution. */
33 /* */
34 #undef FT_COMPONENT
35 #define FT_COMPONENT trace_ttcmap
36
37
38 #define TT_PEEK_SHORT FT_PEEK_SHORT
39 #define TT_PEEK_USHORT FT_PEEK_USHORT
40 #define TT_PEEK_LONG FT_PEEK_LONG
41 #define TT_PEEK_ULONG FT_PEEK_ULONG
42
43 #define TT_NEXT_SHORT FT_NEXT_SHORT
44 #define TT_NEXT_USHORT FT_NEXT_USHORT
45 #define TT_NEXT_LONG FT_NEXT_LONG
46 #define TT_NEXT_ULONG FT_NEXT_ULONG
47
48
49 FT_CALLBACK_DEF( FT_Error )
50 tt_cmap_init( TT_CMap cmap,
51 FT_Byte* table )
52 {
53 cmap->data = table;
54 return 0;
55 }
56
57
58 /*************************************************************************/
59 /*************************************************************************/
60 /***** *****/
61 /***** FORMAT 0 *****/
62 /***** *****/
63 /*************************************************************************/
64 /*************************************************************************/
65
66 /*************************************************************************/
67 /* */
68 /* TABLE OVERVIEW */
69 /* -------------- */
70 /* */
71 /* NAME OFFSET TYPE DESCRIPTION */
72 /* */
73 /* format 0 USHORT must be 0 */
74 /* length 2 USHORT table length in bytes */
75 /* language 4 USHORT Mac language code */
76 /* glyph_ids 6 BYTE[256] array of glyph indices */
77 /* 262 */
78 /* */
79
80 #ifdef TT_CONFIG_CMAP_FORMAT_0
81
82 FT_CALLBACK_DEF( void )
83 tt_cmap0_validate( FT_Byte* table,
84 FT_Validator valid )
85 {
86 FT_Byte* p = table + 2;
87 FT_UInt length = TT_NEXT_USHORT( p );
88
89
90 if ( table + length > valid->limit || length < 262 )
91 FT_INVALID_TOO_SHORT;
92
93 /* check glyph indices whenever necessary */
94 if ( valid->level >= FT_VALIDATE_TIGHT )
95 {
96 FT_UInt n, idx;
97
98
99 p = table + 6;
100 for ( n = 0; n < 256; n++ )
101 {
102 idx = *p++;
103 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
104 FT_INVALID_GLYPH_ID;
105 }
106 }
107 }
108
109
110 FT_CALLBACK_DEF( FT_UInt )
111 tt_cmap0_char_index( TT_CMap cmap,
112 FT_UInt32 char_code )
113 {
114 FT_Byte* table = cmap->data;
115
116
117 return char_code < 256 ? table[6 + char_code] : 0;
118 }
119
120
121 FT_CALLBACK_DEF( FT_UInt )
122 tt_cmap0_char_next( TT_CMap cmap,
123 FT_UInt32 *pchar_code )
124 {
125 FT_Byte* table = cmap->data;
126 FT_UInt32 charcode = *pchar_code;
127 FT_UInt32 result = 0;
128 FT_UInt gindex = 0;
129
130
131 table += 6; /* go to glyph ids */
132 while ( ++charcode < 256 )
133 {
134 gindex = table[charcode];
135 if ( gindex != 0 )
136 {
137 result = charcode;
138 break;
139 }
140 }
141
142 *pchar_code = result;
143 return gindex;
144 }
145
146
147 FT_CALLBACK_DEF( FT_Error )
148 tt_cmap0_get_info( TT_CMap cmap,
149 TT_CMapInfo *cmap_info )
150 {
151 FT_Byte* p = cmap->data + 4;
152
153
154 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
155
156 return FT_Err_Ok;
157 }
158
159
160 FT_CALLBACK_TABLE_DEF
161 const TT_CMap_ClassRec tt_cmap0_class_rec =
162 {
163 {
164 sizeof( TT_CMapRec ),
165
166 (FT_CMap_InitFunc) tt_cmap_init,
167 (FT_CMap_DoneFunc) NULL,
168 (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
169 (FT_CMap_CharNextFunc) tt_cmap0_char_next
170 },
171 0,
172 (TT_CMap_ValidateFunc) tt_cmap0_validate,
173 (TT_CMap_Info_GetFunc) tt_cmap0_get_info
174 };
175
176 #endif /* TT_CONFIG_CMAP_FORMAT_0 */
177
178
179 /*************************************************************************/
180 /*************************************************************************/
181 /***** *****/
182 /***** FORMAT 2 *****/
183 /***** *****/
184 /***** This is used for certain CJK encodings that encode text in a *****/
185 /***** mixed 8/16 bits encoding along the following lines: *****/
186 /***** *****/
187 /***** * Certain byte values correspond to an 8-bit character code *****/
188 /***** (typically in the range 0..127 for ASCII compatibility). *****/
189 /***** *****/
190 /***** * Certain byte values signal the first byte of a 2-byte *****/
191 /***** character code (but these values are also valid as the *****/
192 /***** second byte of a 2-byte character). *****/
193 /***** *****/
194 /***** The following charmap lookup and iteration functions all *****/
195 /***** assume that the value "charcode" correspond to following: *****/
196 /***** *****/
197 /***** - For one byte characters, "charcode" is simply the *****/
198 /***** character code. *****/
199 /***** *****/
200 /***** - For two byte characters, "charcode" is the 2-byte *****/
201 /***** character code in big endian format. More exactly: *****/
202 /***** *****/
203 /***** (charcode >> 8) is the first byte value *****/
204 /***** (charcode & 0xFF) is the second byte value *****/
205 /***** *****/
206 /***** Note that not all values of "charcode" are valid according *****/
207 /***** to these rules, and the function moderately check the *****/
208 /***** arguments. *****/
209 /***** *****/
210 /*************************************************************************/
211 /*************************************************************************/
212
213 /*************************************************************************/
214 /* */
215 /* TABLE OVERVIEW */
216 /* -------------- */
217 /* */
218 /* NAME OFFSET TYPE DESCRIPTION */
219 /* */
220 /* format 0 USHORT must be 2 */
221 /* length 2 USHORT table length in bytes */
222 /* language 4 USHORT Mac language code */
223 /* keys 6 USHORT[256] sub-header keys */
224 /* subs 518 SUBHEAD[NSUBS] sub-headers array */
225 /* glyph_ids 518+NSUB*8 USHORT[] glyph id array */
226 /* */
227 /* The `keys' table is used to map charcode high-bytes to sub-headers. */
228 /* The value of `NSUBS' is the number of sub-headers defined in the */
229 /* table and is computed by finding the maximum of the `keys' table. */
230 /* */
231 /* Note that for any n, `keys[n]' is a byte offset within the `subs' */
232 /* table, i.e., it is the corresponding sub-header index multiplied */
233 /* by 8. */
234 /* */
235 /* Each sub-header has the following format: */
236 /* */
237 /* NAME OFFSET TYPE DESCRIPTION */
238 /* */
239 /* first 0 USHORT first valid low-byte */
240 /* count 2 USHORT number of valid low-bytes */
241 /* delta 4 SHORT see below */
242 /* offset 6 USHORT see below */
243 /* */
244 /* A sub-header defines, for each high-byte, the range of valid */
245 /* low-bytes within the charmap. Note that the range defined by `first' */
246 /* and `count' must be completely included in the interval [0..255] */
247 /* according to the specification. */
248 /* */
249 /* If a character code is contained within a given sub-header, then */
250 /* mapping it to a glyph index is done as follows: */
251 /* */
252 /* * The value of `offset' is read. This is a _byte_ distance from the */
253 /* location of the `offset' field itself into a slice of the */
254 /* `glyph_ids' table. Let's call it `slice' (it's a USHORT[] too). */
255 /* */
256 /* * The value `slice[char.lo - first]' is read. If it is 0, there is */
257 /* no glyph for the charcode. Otherwise, the value of `delta' is */
258 /* added to it (modulo 65536) to form a new glyph index. */
259 /* */
260 /* It is up to the validation routine to check that all offsets fall */
261 /* within the glyph ids table (and not within the `subs' table itself or */
262 /* outside of the CMap). */
263 /* */
264
265 #ifdef TT_CONFIG_CMAP_FORMAT_2
266
267 FT_CALLBACK_DEF( void )
268 tt_cmap2_validate( FT_Byte* table,
269 FT_Validator valid )
270 {
271 FT_Byte* p = table + 2; /* skip format */
272 FT_UInt length = TT_PEEK_USHORT( p );
273 FT_UInt n, max_subs;
274 FT_Byte* keys; /* keys table */
275 FT_Byte* subs; /* sub-headers */
276 FT_Byte* glyph_ids; /* glyph id array */
277
278
279 if ( table + length > valid->limit || length < 6 + 512 )
280 FT_INVALID_TOO_SHORT;
281
282 keys = table + 6;
283
284 /* parse keys to compute sub-headers count */
285 p = keys;
286 max_subs = 0;
287 for ( n = 0; n < 256; n++ )
288 {
289 FT_UInt idx = TT_NEXT_USHORT( p );
290
291
292 /* value must be multiple of 8 */
293 if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
294 FT_INVALID_DATA;
295
296 idx >>= 3;
297
298 if ( idx > max_subs )
299 max_subs = idx;
300 }
301
302 FT_ASSERT( p == table + 518 );
303
304 subs = p;
305 glyph_ids = subs + (max_subs + 1) * 8;
306 if ( glyph_ids > valid->limit )
307 FT_INVALID_TOO_SHORT;
308
309 /* parse sub-headers */
310 for ( n = 0; n <= max_subs; n++ )
311 {
312 FT_UInt first_code, code_count, offset;
313 FT_Int delta;
314 FT_Byte* ids;
315
316
317 first_code = TT_NEXT_USHORT( p );
318 code_count = TT_NEXT_USHORT( p );
319 delta = TT_NEXT_SHORT( p );
320 offset = TT_NEXT_USHORT( p );
321
322 /* check range within 0..255 */
323 if ( valid->level >= FT_VALIDATE_PARANOID )
324 {
325 if ( first_code >= 256 || first_code + code_count > 256 )
326 FT_INVALID_DATA;
327 }
328
329 /* check offset */
330 if ( offset != 0 )
331 {
332 ids = p - 2 + offset;
333 if ( ids < glyph_ids || ids + code_count*2 > table + length )
334 FT_INVALID_OFFSET;
335
336 /* check glyph ids */
337 if ( valid->level >= FT_VALIDATE_TIGHT )
338 {
339 FT_Byte* limit = p + code_count * 2;
340 FT_UInt idx;
341
342
343 for ( ; p < limit; )
344 {
345 idx = TT_NEXT_USHORT( p );
346 if ( idx != 0 )
347 {
348 idx = ( idx + delta ) & 0xFFFFU;
349 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
350 FT_INVALID_GLYPH_ID;
351 }
352 }
353 }
354 }
355 }
356 }
357
358
359 /* return sub header corresponding to a given character code */
360 /* NULL on invalid charcode */
361 static FT_Byte*
362 tt_cmap2_get_subheader( FT_Byte* table,
363 FT_UInt32 char_code )
364 {
365 FT_Byte* result = NULL;
366
367
368 if ( char_code < 0x10000UL )
369 {
370 FT_UInt char_lo = (FT_UInt)( char_code & 0xFF );
371 FT_UInt char_hi = (FT_UInt)( char_code >> 8 );
372 FT_Byte* p = table + 6; /* keys table */
373 FT_Byte* subs = table + 518; /* subheaders table */
374 FT_Byte* sub;
375
376
377 if ( char_hi == 0 )
378 {
379 /* an 8-bit character code -- we use subHeader 0 in this case */
380 /* to test whether the character code is in the charmap */
381 /* */
382 sub = subs; /* jump to first sub-header */
383
384 /* check that the sub-header for this byte is 0, which */
385 /* indicates that it's really a valid one-byte value */
386 /* Otherwise, return 0 */
387 /* */
388 p += char_lo * 2;
389 if ( TT_PEEK_USHORT( p ) != 0 )
390 goto Exit;
391 }
392 else
393 {
394 /* a 16-bit character code */
395
396 /* jump to key entry */
397 p += char_hi * 2;
398 /* jump to sub-header */
399 sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) );
400
401 /* check that the high byte isn't a valid one-byte value */
402 if ( sub == subs )
403 goto Exit;
404 }
405 result = sub;
406 }
407 Exit:
408 return result;
409 }
410
411
412 FT_CALLBACK_DEF( FT_UInt )
413 tt_cmap2_char_index( TT_CMap cmap,
414 FT_UInt32 char_code )
415 {
416 FT_Byte* table = cmap->data;
417 FT_UInt result = 0;
418 FT_Byte* subheader;
419
420
421 subheader = tt_cmap2_get_subheader( table, char_code );
422 if ( subheader )
423 {
424 FT_Byte* p = subheader;
425 FT_UInt idx = (FT_UInt)(char_code & 0xFF);
426 FT_UInt start, count;
427 FT_Int delta;
428 FT_UInt offset;
429
430
431 start = TT_NEXT_USHORT( p );
432 count = TT_NEXT_USHORT( p );
433 delta = TT_NEXT_SHORT ( p );
434 offset = TT_PEEK_USHORT( p );
435
436 idx -= start;
437 if ( idx < count && offset != 0 )
438 {
439 p += offset + 2 * idx;
440 idx = TT_PEEK_USHORT( p );
441
442 if ( idx != 0 )
443 result = (FT_UInt)( idx + delta ) & 0xFFFFU;
444 }
445 }
446 return result;
447 }
448
449
450 FT_CALLBACK_DEF( FT_UInt )
451 tt_cmap2_char_next( TT_CMap cmap,
452 FT_UInt32 *pcharcode )
453 {
454 FT_Byte* table = cmap->data;
455 FT_UInt gindex = 0;
456 FT_UInt32 result = 0;
457 FT_UInt32 charcode = *pcharcode + 1;
458 FT_Byte* subheader;
459
460
461 while ( charcode < 0x10000UL )
462 {
463 subheader = tt_cmap2_get_subheader( table, charcode );
464 if ( subheader )
465 {
466 FT_Byte* p = subheader;
467 FT_UInt start = TT_NEXT_USHORT( p );
468 FT_UInt count = TT_NEXT_USHORT( p );
469 FT_Int delta = TT_NEXT_SHORT ( p );
470 FT_UInt offset = TT_PEEK_USHORT( p );
471 FT_UInt char_lo = (FT_UInt)( charcode & 0xFF );
472 FT_UInt pos, idx;
473
474
475 if ( offset == 0 )
476 goto Next_SubHeader;
477
478 if ( char_lo < start )
479 {
480 char_lo = start;
481 pos = 0;
482 }
483 else
484 pos = (FT_UInt)( char_lo - start );
485
486 p += offset + pos * 2;
487 charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo;
488
489 for ( ; pos < count; pos++, charcode++ )
490 {
491 idx = TT_NEXT_USHORT( p );
492
493 if ( idx != 0 )
494 {
495 gindex = ( idx + delta ) & 0xFFFFU;
496 if ( gindex != 0 )
497 {
498 result = charcode;
499 goto Exit;
500 }
501 }
502 }
503 }
504
505 /* jump to next sub-header, i.e. higher byte value */
506 Next_SubHeader:
507 charcode = FT_PAD_FLOOR( charcode, 256 ) + 256;
508 }
509
510 Exit:
511 *pcharcode = result;
512
513 return gindex;
514 }
515
516
517 FT_CALLBACK_DEF( FT_Error )
518 tt_cmap2_get_info( TT_CMap cmap,
519 TT_CMapInfo *cmap_info )
520 {
521 FT_Byte* p = cmap->data + 4;
522
523
524 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
525
526 return FT_Err_Ok;
527 }
528
529
530 FT_CALLBACK_TABLE_DEF
531 const TT_CMap_ClassRec tt_cmap2_class_rec =
532 {
533 {
534 sizeof( TT_CMapRec ),
535
536 (FT_CMap_InitFunc) tt_cmap_init,
537 (FT_CMap_DoneFunc) NULL,
538 (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
539 (FT_CMap_CharNextFunc) tt_cmap2_char_next
540 },
541 2,
542 (TT_CMap_ValidateFunc) tt_cmap2_validate,
543 (TT_CMap_Info_GetFunc) tt_cmap2_get_info
544 };
545
546 #endif /* TT_CONFIG_CMAP_FORMAT_2 */
547
548
549 /*************************************************************************/
550 /*************************************************************************/
551 /***** *****/
552 /***** FORMAT 4 *****/
553 /***** *****/
554 /*************************************************************************/
555 /*************************************************************************/
556
557 /*************************************************************************/
558 /* */
559 /* TABLE OVERVIEW */
560 /* -------------- */
561 /* */
562 /* NAME OFFSET TYPE DESCRIPTION */
563 /* */
564 /* format 0 USHORT must be 4 */
565 /* length 2 USHORT table length */
566 /* in bytes */
567 /* language 4 USHORT Mac language code */
568 /* */
569 /* segCountX2 6 USHORT 2*NUM_SEGS */
570 /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */
571 /* entrySelector 10 USHORT LOG_SEGS */
572 /* rangeShift 12 USHORT segCountX2 - */
573 /* searchRange */
574 /* */
575 /* endCount 14 USHORT[NUM_SEGS] end charcode for */
576 /* each segment; last */
577 /* is 0xFFFF */
578 /* */
579 /* pad 14+NUM_SEGS*2 USHORT padding */
580 /* */
581 /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */
582 /* each segment */
583 /* */
584 /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */
585 /* segment */
586 /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */
587 /* each segment; can be */
588 /* zero */
589 /* */
590 /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph id */
591 /* ranges */
592 /* */
593 /* Character codes are modelled by a series of ordered (increasing) */
594 /* intervals called segments. Each segment has start and end codes, */
595 /* provided by the `startCount' and `endCount' arrays. Segments must */
596 /* not be overlapping and the last segment should always contain the */
597 /* `0xFFFF' endCount. */
598 /* */
599 /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
600 /* ignored (they are traces of over-engineering in the TrueType */
601 /* specification). */
602 /* */
603 /* Each segment also has a signed `delta', as well as an optional offset */
604 /* within the `glyphIds' table. */
605 /* */
606 /* If a segment's idOffset is 0, the glyph index corresponding to any */
607 /* charcode within the segment is obtained by adding the value of */
608 /* `idDelta' directly to the charcode, modulo 65536. */
609 /* */
610 /* Otherwise, a glyph index is taken from the glyph ids sub-array for */
611 /* the segment, and the value of `idDelta' is added to it. */
612 /* */
613 /* */
614 /* Finally, note that certain fonts contain invalid charmaps that */
615 /* contain end=0xFFFF, start=0xFFFF, delta=0x0001, offset=0xFFFF at the */
616 /* of their charmaps (e.g. opens___.ttf which comes with OpenOffice.org) */
617 /* we need special code to deal with them correctly... */
618 /* */
619
620 #ifdef TT_CONFIG_CMAP_FORMAT_4
621
622 FT_CALLBACK_DEF( void )
623 tt_cmap4_validate( FT_Byte* table,
624 FT_Validator valid )
625 {
626 FT_Byte* p = table + 2; /* skip format */
627 FT_UInt length = TT_NEXT_USHORT( p );
628 FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids;
629 FT_UInt num_segs;
630
631
632 /* in certain fonts, the `length' field is invalid and goes */
633 /* out of bound. We try to correct this here... */
634 if ( length < 16 )
635 FT_INVALID_TOO_SHORT;
636
637 if ( table + length > valid->limit )
638 {
639 if ( valid->level >= FT_VALIDATE_TIGHT )
640 FT_INVALID_TOO_SHORT;
641
642 length = (FT_UInt)( valid->limit - table );
643 }
644
645 p = table + 6;
646 num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */
647
648 if ( valid->level >= FT_VALIDATE_PARANOID )
649 {
650 /* check that we have an even value here */
651 if ( num_segs & 1 )
652 FT_INVALID_DATA;
653 }
654
655 num_segs /= 2;
656
657 /* check the search parameters - even though we never use them */
658 /* */
659 if ( valid->level >= FT_VALIDATE_PARANOID )
660 {
661 /* check the values of 'searchRange', 'entrySelector', 'rangeShift' */
662 FT_UInt search_range = TT_NEXT_USHORT( p );
663 FT_UInt entry_selector = TT_NEXT_USHORT( p );
664 FT_UInt range_shift = TT_NEXT_USHORT( p );
665
666
667 if ( ( search_range | range_shift ) & 1 ) /* must be even values */
668 FT_INVALID_DATA;
669
670 search_range /= 2;
671 range_shift /= 2;
672
673 /* `search range' is the greatest power of 2 that is <= num_segs */
674
675 if ( search_range > num_segs ||
676 search_range * 2 < num_segs ||
677 search_range + range_shift != num_segs ||
678 search_range != ( 1U << entry_selector ) )
679 FT_INVALID_DATA;
680 }
681
682 ends = table + 14;
683 starts = table + 16 + num_segs * 2;
684 deltas = starts + num_segs * 2;
685 offsets = deltas + num_segs * 2;
686 glyph_ids = offsets + num_segs * 2;
687
688 if ( glyph_ids > table + length )
689 FT_INVALID_TOO_SHORT;
690
691 /* check last segment, its end count must be FFFF */
692 if ( valid->level >= FT_VALIDATE_PARANOID )
693 {
694 p = ends + ( num_segs - 1 ) * 2;
695 if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
696 FT_INVALID_DATA;
697 }
698
699 /* check that segments are sorted in increasing order and do not */
700 /* overlap; check also the offsets */
701 {
702 FT_UInt start, end, last = 0, offset, n;
703 FT_Int delta;
704
705
706 for ( n = 0; n < num_segs; n++ )
707 {
708 p = starts + n * 2;
709 start = TT_PEEK_USHORT( p );
710 p = ends + n * 2;
711 end = TT_PEEK_USHORT( p );
712 p = deltas + n * 2;
713 delta = TT_PEEK_SHORT( p );
714 p = offsets + n * 2;
715 offset = TT_PEEK_USHORT( p );
716
717 if ( start > end )
718 FT_INVALID_DATA;
719
720 /* this test should be performed at default validation level; */
721 /* unfortunately, some popular Asian fonts present overlapping */
722 /* ranges in their charmaps */
723 /* */
724 if ( valid->level >= FT_VALIDATE_TIGHT )
725 {
726 if ( n > 0 && start <= last )
727 FT_INVALID_DATA;
728 }
729
730 if ( offset && offset != 0xFFFFU )
731 {
732 p += offset; /* start of glyph id array */
733
734 /* check that we point within the glyph ids table only */
735 if ( valid->level >= FT_VALIDATE_TIGHT )
736 {
737 if ( p < glyph_ids ||
738 p + ( end - start + 1 ) * 2 > table + length )
739 FT_INVALID_DATA;
740 }
741 else
742 {
743 if ( p < glyph_ids ||
744 p + ( end - start + 1 ) * 2 > valid->limit )
745 FT_INVALID_DATA;
746 }
747
748 /* check glyph indices within the segment range */
749 if ( valid->level >= FT_VALIDATE_TIGHT )
750 {
751 FT_UInt i, idx;
752
753
754 for ( i = start; i < end; i++ )
755 {
756 idx = FT_NEXT_USHORT( p );
757 if ( idx != 0 )
758 {
759 idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
760
761 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
762 FT_INVALID_GLYPH_ID;
763 }
764 }
765 }
766 }
767 else if ( offset == 0xFFFFU )
768 {
769 /* Some fonts (erroneously?) use a range offset of 0xFFFF */
770 /* to mean missing glyph in cmap table */
771 /* */
772 if ( valid->level >= FT_VALIDATE_PARANOID ||
773 n != num_segs - 1 ||
774 !( start == 0xFFFFU && end == 0xFFFFU && delta == 0x1U ) )
775 FT_INVALID_DATA;
776 }
777
778 last = end;
779 }
780 }
781 }
782
783
784 FT_CALLBACK_DEF( FT_UInt )
785 tt_cmap4_char_index( TT_CMap cmap,
786 FT_UInt32 char_code )
787 {
788 FT_Byte* table = cmap->data;
789 FT_UInt result = 0;
790
791
792 if ( char_code < 0x10000UL )
793 {
794 FT_UInt idx, num_segs2;
795 FT_Int delta;
796 FT_UInt code = (FT_UInt)char_code;
797 FT_Byte* p;
798
799
800 p = table + 6;
801 num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); /* be paranoid! */
802
803 #if 1
804 /* Some fonts have more than 170 segments in their charmaps! */
805 /* We changed this function to use a more efficient binary */
806 /* search for improving performance */
807 {
808 FT_UInt min = 0;
809 FT_UInt max = num_segs2 >> 1;
810 FT_UInt mid, start, end, offset;
811
812
813 while ( min < max )
814 {
815 mid = ( min + max ) >> 1;
816 p = table + 14 + mid * 2;
817 end = TT_NEXT_USHORT( p );
818 p += num_segs2;
819 start = TT_PEEK_USHORT( p);
820
821 if ( code < start )
822 max = mid;
823 else if ( code > end )
824 min = mid + 1;
825 else
826 {
827 /* we found the segment */
828 idx = code;
829
830 p += num_segs2;
831 delta = TT_PEEK_SHORT( p );
832
833 p += num_segs2;
834 offset = TT_PEEK_USHORT( p );
835
836 if ( offset == 0xFFFFU )
837 goto Exit;
838
839 if ( offset != 0 )
840 {
841 p += offset + 2 * ( idx - start );
842 idx = TT_PEEK_USHORT( p );
843 }
844
845 if ( idx != 0 )
846 result = (FT_UInt)( idx + delta ) & 0xFFFFU;
847
848 goto Exit;
849 }
850 }
851 }
852
853 #else /* 0 - old code */
854
855 {
856 FT_UInt n;
857 FT_Byte* q;
858
859
860 p = table + 14; /* ends table */
861 q = table + 16 + num_segs2; /* starts table */
862
863
864 for ( n = 0; n < num_segs2; n += 2 )
865 {
866 FT_UInt end = TT_NEXT_USHORT( p );
867 FT_UInt start = TT_NEXT_USHORT( q );
868 FT_UInt offset;
869
870
871 if ( code < start )
872 break;
873
874 if ( code <= end )
875 {
876 idx = code;
877
878 p = q + num_segs2 - 2;
879 delta = TT_PEEK_SHORT( p );
880 p += num_segs2;
881 offset = TT_PEEK_USHORT( p );
882
883 if ( offset == 0xFFFFU )
884 goto Exit;
885
886 if ( offset != 0 )
887 {
888 p += offset + 2 * ( idx - start );
889 idx = TT_PEEK_USHORT( p );
890 }
891
892 if ( idx != 0 )
893 result = (FT_UInt)( idx + delta ) & 0xFFFFU;
894 }
895 }
896 }
897
898 #endif /* 0 */
899
900 }
901
902 Exit:
903 return result;
904 }
905
906
907 FT_CALLBACK_DEF( FT_UInt )
908 tt_cmap4_char_next( TT_CMap cmap,
909 FT_UInt32 *pchar_code )
910 {
911 FT_Byte* table = cmap->data;
912 FT_UInt32 result = 0;
913 FT_UInt gindex = 0;
914 FT_UInt32 char_code = *pchar_code;
915 FT_Byte* p;
916 FT_UInt code, num_segs2;
917
918
919 if ( char_code >= 0xFFFFUL )
920 goto Exit;
921
922 code = (FT_UInt)char_code + 1;
923 p = table + 6;
924 num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT(p), 2 ); /* ensure even-ness */
925
926 #if 1
927
928 for (;;)
929 {
930 /* Some fonts have more than 170 segments in their charmaps! */
931 /* We changed this function to use a more efficient binary */
932 /* search */
933 FT_UInt offset;
934 FT_Int delta;
935 FT_UInt min = 0;
936 FT_UInt max = num_segs2 >> 1;
937 FT_UInt mid, start, end;
938 FT_UInt hi;
939
940
941 /* we begin by finding the segment which end is
942 closer to our code point */
943 hi = max + 1;
944 while ( min < max )
945 {
946 mid = ( min + max ) >> 1;
947 p = table + 14 + mid * 2;
948 end = TT_PEEK_USHORT( p );
949
950 if ( end < code )
951 min = mid + 1;
952 else
953 {
954 hi = mid;
955 max = mid;
956 }
957 }
958
959 if ( hi > max )
960 {
961 /* the point is behind the last segment;
962 we will exit right now */
963 goto Exit;
964 }
965
966 p = table + 14 + hi * 2;
967 end = TT_PEEK_USHORT( p );
968
969 p += 2 + num_segs2;
970 start = TT_PEEK_USHORT( p );
971
972 if ( code < start )
973 code = start;
974
975 p += num_segs2;
976 delta = TT_PEEK_USHORT( p );
977
978 p += num_segs2;
979 offset = TT_PEEK_USHORT( p );
980
981 if ( offset != 0 && offset != 0xFFFFU )
982 {
983 /* parse the glyph ids array for non-zero index */
984 p += offset + ( code - start ) * 2;
985 while ( code <= end )
986 {
987 gindex = TT_NEXT_USHORT( p );
988 if ( gindex != 0 )
989 {
990 gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
991 if ( gindex != 0 )
992 {
993 result = code;
994 goto Exit;
995 }
996 }
997 code++;
998 }
999 }
1000 else if ( offset == 0xFFFFU )
1001 {
1002 /* an offset of 0xFFFF means an empty glyph in certain fonts! */
1003 code = end + 1;
1004 }
1005 else /* offset == 0 */
1006 {
1007 gindex = (FT_UInt)( code + delta ) & 0xFFFFU;
1008 if ( gindex != 0 )
1009 {
1010 result = code;
1011 goto Exit;
1012 }
1013 code++;
1014 }
1015 }
1016
1017 #else /* old code -- kept for reference */
1018
1019 for ( ;; )
1020 {
1021 FT_UInt offset, n;
1022 FT_Int delta;
1023 FT_Byte* q;
1024
1025
1026 p = table + 14; /* ends table */
1027 q = table + 16 + num_segs2; /* starts table */
1028
1029 for ( n = 0; n < num_segs2; n += 2 )
1030 {
1031 FT_UInt end = TT_NEXT_USHORT( p );
1032 FT_UInt start = TT_NEXT_USHORT( q );
1033
1034
1035 if ( code < start )
1036 code = start;
1037
1038 if ( code <= end )
1039 {
1040 p = q + num_segs2 - 2;
1041 delta = TT_PEEK_SHORT( p );
1042 p += num_segs2;
1043 offset = TT_PEEK_USHORT( p );
1044
1045 if ( offset != 0 && offset != 0xFFFFU )
1046 {
1047 /* parse the glyph ids array for non-0 index */
1048 p += offset + ( code - start ) * 2;
1049 while ( code <= end )
1050 {
1051 gindex = TT_NEXT_USHORT( p );
1052 if ( gindex != 0 )
1053 {
1054 gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
1055 if ( gindex != 0 )
1056 break;
1057 }
1058 code++;
1059 }
1060 }
1061 else if ( offset == 0xFFFFU )
1062 {
1063 /* an offset of 0xFFFF means an empty glyph in certain fonts! */
1064 code = end;
1065 break;
1066 }
1067 else
1068 gindex = (FT_UInt)( code + delta ) & 0xFFFFU;
1069
1070 if ( gindex == 0 )
1071 break;
1072
1073 result = code;
1074 goto Exit;
1075 }
1076 }
1077 /* loop to next trial charcode */
1078 if ( code >= 0xFFFFU )
1079 break;
1080
1081 code++;
1082 }
1083
1084 #endif /* !1 */
1085
1086 Exit:
1087 *pchar_code = result;
1088 return gindex;
1089 }
1090
1091
1092 FT_CALLBACK_DEF( FT_Error )
1093 tt_cmap4_get_info( TT_CMap cmap,
1094 TT_CMapInfo *cmap_info )
1095 {
1096 FT_Byte* p = cmap->data + 4;
1097
1098
1099 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1100
1101 return FT_Err_Ok;
1102 }
1103
1104
1105 FT_CALLBACK_TABLE_DEF
1106 const TT_CMap_ClassRec tt_cmap4_class_rec =
1107 {
1108 {
1109 sizeof ( TT_CMapRec ),
1110
1111 (FT_CMap_InitFunc) tt_cmap_init,
1112 (FT_CMap_DoneFunc) NULL,
1113 (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
1114 (FT_CMap_CharNextFunc) tt_cmap4_char_next
1115 },
1116 4,
1117 (TT_CMap_ValidateFunc) tt_cmap4_validate,
1118 (TT_CMap_Info_GetFunc) tt_cmap4_get_info
1119 };
1120
1121 #endif /* TT_CONFIG_CMAP_FORMAT_4 */
1122
1123
1124 /*************************************************************************/
1125 /*************************************************************************/
1126 /***** *****/
1127 /***** FORMAT 6 *****/
1128 /***** *****/
1129 /*************************************************************************/
1130 /*************************************************************************/
1131
1132 /*************************************************************************/
1133 /* */
1134 /* TABLE OVERVIEW */
1135 /* -------------- */
1136 /* */
1137 /* NAME OFFSET TYPE DESCRIPTION */
1138 /* */
1139 /* format 0 USHORT must be 4 */
1140 /* length 2 USHORT table length in bytes */
1141 /* language 4 USHORT Mac language code */
1142 /* */
1143 /* first 6 USHORT first segment code */
1144 /* count 8 USHORT segment size in chars */
1145 /* glyphIds 10 USHORT[count] glyph ids */
1146 /* */
1147 /* A very simplified segment mapping. */
1148 /* */
1149
1150 #ifdef TT_CONFIG_CMAP_FORMAT_6
1151
1152 FT_CALLBACK_DEF( void )
1153 tt_cmap6_validate( FT_Byte* table,
1154 FT_Validator valid )
1155 {
1156 FT_Byte* p;
1157 FT_UInt length, count;
1158
1159
1160 if ( table + 10 > valid->limit )
1161 FT_INVALID_TOO_SHORT;
1162
1163 p = table + 2;
1164 length = TT_NEXT_USHORT( p );
1165
1166 p = table + 8; /* skip language and start index */
1167 count = TT_NEXT_USHORT( p );
1168
1169 if ( table + length > valid->limit || length < 10 + count * 2 )
1170 FT_INVALID_TOO_SHORT;
1171
1172 /* check glyph indices */
1173 if ( valid->level >= FT_VALIDATE_TIGHT )
1174 {
1175 FT_UInt gindex;
1176
1177
1178 for ( ; count > 0; count-- )
1179 {
1180 gindex = TT_NEXT_USHORT( p );
1181 if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1182 FT_INVALID_GLYPH_ID;
1183 }
1184 }
1185 }
1186
1187
1188 FT_CALLBACK_DEF( FT_UInt )
1189 tt_cmap6_char_index( TT_CMap cmap,
1190 FT_UInt32 char_code )
1191 {
1192 FT_Byte* table = cmap->data;
1193 FT_UInt result = 0;
1194 FT_Byte* p = table + 6;
1195 FT_UInt start = TT_NEXT_USHORT( p );
1196 FT_UInt count = TT_NEXT_USHORT( p );
1197 FT_UInt idx = (FT_UInt)( char_code - start );
1198
1199
1200 if ( idx < count )
1201 {
1202 p += 2 * idx;
1203 result = TT_PEEK_USHORT( p );
1204 }
1205 return result;
1206 }
1207
1208
1209 FT_CALLBACK_DEF( FT_UInt )
1210 tt_cmap6_char_next( TT_CMap cmap,
1211 FT_UInt32 *pchar_code )
1212 {
1213 FT_Byte* table = cmap->data;
1214 FT_UInt32 result = 0;
1215 FT_UInt32 char_code = *pchar_code + 1;
1216 FT_UInt gindex = 0;
1217
1218 FT_Byte* p = table + 6;
1219 FT_UInt start = TT_NEXT_USHORT( p );
1220 FT_UInt count = TT_NEXT_USHORT( p );
1221 FT_UInt idx;
1222
1223
1224 if ( char_code >= 0x10000UL )
1225 goto Exit;
1226
1227 if ( char_code < start )
1228 char_code = start;
1229
1230 idx = (FT_UInt)( char_code - start );
1231 p += 2 * idx;
1232
1233 for ( ; idx < count; idx++ )
1234 {
1235 gindex = TT_NEXT_USHORT( p );
1236 if ( gindex != 0 )
1237 {
1238 result = char_code;
1239 break;
1240 }
1241 char_code++;
1242 }
1243
1244 Exit:
1245 *pchar_code = result;
1246 return gindex;
1247 }
1248
1249
1250 FT_CALLBACK_DEF( FT_Error )
1251 tt_cmap6_get_info( TT_CMap cmap,
1252 TT_CMapInfo *cmap_info )
1253 {
1254 FT_Byte* p = cmap->data + 4;
1255
1256
1257 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1258
1259 return FT_Err_Ok;
1260 }
1261
1262
1263 FT_CALLBACK_TABLE_DEF
1264 const TT_CMap_ClassRec tt_cmap6_class_rec =
1265 {
1266 {
1267 sizeof ( TT_CMapRec ),
1268
1269 (FT_CMap_InitFunc) tt_cmap_init,
1270 (FT_CMap_DoneFunc) NULL,
1271 (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
1272 (FT_CMap_CharNextFunc) tt_cmap6_char_next
1273 },
1274 6,
1275 (TT_CMap_ValidateFunc) tt_cmap6_validate,
1276 (TT_CMap_Info_GetFunc) tt_cmap6_get_info
1277 };
1278
1279 #endif /* TT_CONFIG_CMAP_FORMAT_6 */
1280
1281
1282 /*************************************************************************/
1283 /*************************************************************************/
1284 /***** *****/
1285 /***** FORMAT 8 *****/
1286 /***** *****/
1287 /***** It's hard to completely understand what the OpenType spec *****/
1288 /***** says about this format, but here is my conclusion. *****/
1289 /***** *****/
1290 /***** The purpose of this format is to easily map UTF-16 text to *****/
1291 /***** glyph indices. Basically, the `char_code' must be in one of *****/
1292 /***** the following formats: *****/
1293 /***** *****/
1294 /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/
1295 /***** Area (i.e. U+D800-U+DFFF). *****/
1296 /***** *****/
1297 /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/
1298 /***** `char_code = (char_hi << 16) | char_lo', then both *****/
1299 /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/
1300 /***** Area. *****/
1301 /***** *****/
1302 /***** The 'is32' table embedded in the charmap indicates whether a *****/
1303 /***** given 16-bit value is in the surrogates area or not. *****/
1304 /***** *****/
1305 /***** So, for any given `char_code', we can assert the following: *****/
1306 /***** *****/
1307 /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/
1308 /***** *****/
1309 /***** If `char_hi != 0' then we must have both *****/
1310 /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/
1311 /***** *****/
1312 /*************************************************************************/
1313 /*************************************************************************/
1314
1315 /*************************************************************************/
1316 /* */
1317 /* TABLE OVERVIEW */
1318 /* -------------- */
1319 /* */
1320 /* NAME OFFSET TYPE DESCRIPTION */
1321 /* */
1322 /* format 0 USHORT must be 8 */
1323 /* reseved 2 USHORT reserved */
1324 /* length 4 ULONG length in bytes */
1325 /* language 8 ULONG Mac language code */
1326 /* is32 12 BYTE[8192] 32-bitness bitmap */
1327 /* count 8204 ULONG number of groups */
1328 /* */
1329 /* This header is followed by 'count' groups of the following format: */
1330 /* */
1331 /* start 0 ULONG first charcode */
1332 /* end 4 ULONG last charcode */
1333 /* startId 8 ULONG start glyph id for the group */
1334 /* */
1335
1336 #ifdef TT_CONFIG_CMAP_FORMAT_8
1337
1338 FT_CALLBACK_DEF( void )
1339 tt_cmap8_validate( FT_Byte* table,
1340 FT_Validator valid )
1341 {
1342 FT_Byte* p = table + 4;
1343 FT_Byte* is32;
1344 FT_UInt32 length;
1345 FT_UInt32 num_groups;
1346
1347
1348 if ( table + 16 + 8192 > valid->limit )
1349 FT_INVALID_TOO_SHORT;
1350
1351 length = TT_NEXT_ULONG( p );
1352 if ( table + length > valid->limit || length < 8208 )
1353 FT_INVALID_TOO_SHORT;
1354
1355 is32 = table + 12;
1356 p = is32 + 8192; /* skip `is32' array */
1357 num_groups = TT_NEXT_ULONG( p );
1358
1359 if ( p + num_groups * 12 > valid->limit )
1360 FT_INVALID_TOO_SHORT;
1361
1362 /* check groups, they must be in increasing order */
1363 {
1364 FT_UInt32 n, start, end, start_id, count, last = 0;
1365
1366
1367 for ( n = 0; n < num_groups; n++ )
1368 {
1369 FT_UInt hi, lo;
1370
1371
1372 start = TT_NEXT_ULONG( p );
1373 end = TT_NEXT_ULONG( p );
1374 start_id = TT_NEXT_ULONG( p );
1375
1376 if ( start > end )
1377 FT_INVALID_DATA;
1378
1379 if ( n > 0 && start <= last )
1380 FT_INVALID_DATA;
1381
1382 if ( valid->level >= FT_VALIDATE_TIGHT )
1383 {
1384 if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
1385 FT_INVALID_GLYPH_ID;
1386
1387 count = (FT_UInt32)( end - start + 1 );
1388
1389 if ( start & ~0xFFFFU )
1390 {
1391 /* start_hi != 0; check that is32[i] is 1 for each i in */
1392 /* the `hi' and `lo' of the range [start..end] */
1393 for ( ; count > 0; count--, start++ )
1394 {
1395 hi = (FT_UInt)( start >> 16 );
1396 lo = (FT_UInt)( start & 0xFFFFU );
1397
1398 if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
1399 FT_INVALID_DATA;
1400
1401 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
1402 FT_INVALID_DATA;
1403 }
1404 }
1405 else
1406 {
1407 /* start_hi == 0; check that is32[i] is 0 for each i in */
1408 /* the range [start..end] */
1409
1410 /* end_hi cannot be != 0! */
1411 if ( end & ~0xFFFFU )
1412 FT_INVALID_DATA;
1413
1414 for ( ; count > 0; count--, start++ )
1415 {
1416 lo = (FT_UInt)( start & 0xFFFFU );
1417
1418 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
1419 FT_INVALID_DATA;
1420 }
1421 }
1422 }
1423
1424 last = end;
1425 }
1426 }
1427 }
1428
1429
1430 FT_CALLBACK_DEF( FT_UInt )
1431 tt_cmap8_char_index( TT_CMap cmap,
1432 FT_UInt32 char_code )
1433 {
1434 FT_Byte* table = cmap->data;
1435 FT_UInt result = 0;
1436 FT_Byte* p = table + 8204;
1437 FT_UInt32 num_groups = TT_NEXT_ULONG( p );
1438 FT_UInt32 start, end, start_id;
1439
1440
1441 for ( ; num_groups > 0; num_groups-- )
1442 {
1443 start = TT_NEXT_ULONG( p );
1444 end = TT_NEXT_ULONG( p );
1445 start_id = TT_NEXT_ULONG( p );
1446
1447 if ( char_code < start )
1448 break;
1449
1450 if ( char_code <= end )
1451 {
1452 result = (FT_UInt)( start_id + char_code - start );
1453 break;
1454 }
1455 }
1456 return result;
1457 }
1458
1459
1460 FT_CALLBACK_DEF( FT_UInt )
1461 tt_cmap8_char_next( TT_CMap cmap,
1462 FT_UInt32 *pchar_code )
1463 {
1464 FT_UInt32 result = 0;
1465 FT_UInt32 char_code = *pchar_code + 1;
1466 FT_UInt gindex = 0;
1467 FT_Byte* table = cmap->data;
1468 FT_Byte* p = table + 8204;
1469 FT_UInt32 num_groups = TT_NEXT_ULONG( p );
1470 FT_UInt32 start, end, start_id;
1471
1472
1473 p = table + 8208;
1474
1475 for ( ; num_groups > 0; num_groups-- )
1476 {
1477 start = TT_NEXT_ULONG( p );
1478 end = TT_NEXT_ULONG( p );
1479 start_id = TT_NEXT_ULONG( p );
1480
1481 if ( char_code < start )
1482 char_code = start;
1483
1484 if ( char_code <= end )
1485 {
1486 gindex = (FT_UInt)( char_code - start + start_id );
1487 if ( gindex != 0 )
1488 {
1489 result = char_code;
1490 goto Exit;
1491 }
1492 }
1493 }
1494
1495 Exit:
1496 *pchar_code = result;
1497 return gindex;
1498 }
1499
1500
1501 FT_CALLBACK_DEF( FT_Error )
1502 tt_cmap8_get_info( TT_CMap cmap,
1503 TT_CMapInfo *cmap_info )
1504 {
1505 FT_Byte* p = cmap->data + 8;
1506
1507
1508 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1509 return FT_Err_Ok;
1510 }
1511
1512
1513 FT_CALLBACK_TABLE_DEF
1514 const TT_CMap_ClassRec tt_cmap8_class_rec =
1515 {
1516 {
1517 sizeof ( TT_CMapRec ),
1518
1519 (FT_CMap_InitFunc) tt_cmap_init,
1520 (FT_CMap_DoneFunc) NULL,
1521 (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
1522 (FT_CMap_CharNextFunc) tt_cmap8_char_next
1523 },
1524 8,
1525 (TT_CMap_ValidateFunc) tt_cmap8_validate,
1526 (TT_CMap_Info_GetFunc) tt_cmap8_get_info
1527 };
1528
1529 #endif /* TT_CONFIG_CMAP_FORMAT_8 */
1530
1531
1532 /*************************************************************************/
1533 /*************************************************************************/
1534 /***** *****/
1535 /***** FORMAT 10 *****/
1536 /***** *****/
1537 /*************************************************************************/
1538 /*************************************************************************/
1539
1540 /*************************************************************************/
1541 /* */
1542 /* TABLE OVERVIEW */
1543 /* -------------- */
1544 /* */
1545 /* NAME OFFSET TYPE DESCRIPTION */
1546 /* */
1547 /* format 0 USHORT must be 10 */
1548 /* reserved 2 USHORT reserved */
1549 /* length 4 ULONG length in bytes */
1550 /* language 8 ULONG Mac language code */
1551 /* */
1552 /* start 12 ULONG first char in range */
1553 /* count 16 ULONG number of chars in range */
1554 /* glyphIds 20 USHORT[count] glyph indices covered */
1555 /* */
1556
1557 #ifdef TT_CONFIG_CMAP_FORMAT_10
1558
1559 FT_CALLBACK_DEF( void )
1560 tt_cmap10_validate( FT_Byte* table,
1561 FT_Validator valid )
1562 {
1563 FT_Byte* p = table + 4;
1564 FT_ULong length, count;
1565
1566
1567 if ( table + 20 > valid->limit )
1568 FT_INVALID_TOO_SHORT;
1569
1570 length = TT_NEXT_ULONG( p );
1571 p = table + 16;
1572 count = TT_NEXT_ULONG( p );
1573
1574 if ( table + length > valid->limit || length < 20 + count * 2 )
1575 FT_INVALID_TOO_SHORT;
1576
1577 /* check glyph indices */
1578 if ( valid->level >= FT_VALIDATE_TIGHT )
1579 {
1580 FT_UInt gindex;
1581
1582
1583 for ( ; count > 0; count-- )
1584 {
1585 gindex = TT_NEXT_USHORT( p );
1586 if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1587 FT_INVALID_GLYPH_ID;
1588 }
1589 }
1590 }
1591
1592
1593 FT_CALLBACK_DEF( FT_UInt )
1594 tt_cmap10_char_index( TT_CMap cmap,
1595 FT_UInt32 char_code )
1596 {
1597 FT_Byte* table = cmap->data;
1598 FT_UInt result = 0;
1599 FT_Byte* p = table + 12;
1600 FT_UInt32 start = TT_NEXT_ULONG( p );
1601 FT_UInt32 count = TT_NEXT_ULONG( p );
1602 FT_UInt32 idx = (FT_ULong)( char_code - start );
1603
1604
1605 if ( idx < count )
1606 {
1607 p += 2 * idx;
1608 result = TT_PEEK_USHORT( p );
1609 }
1610 return result;
1611 }
1612
1613
1614 FT_CALLBACK_DEF( FT_UInt )
1615 tt_cmap10_char_next( TT_CMap cmap,
1616 FT_UInt32 *pchar_code )
1617 {
1618 FT_Byte* table = cmap->data;
1619 FT_UInt32 char_code = *pchar_code + 1;
1620 FT_UInt gindex = 0;
1621 FT_Byte* p = table + 12;
1622 FT_UInt32 start = TT_NEXT_ULONG( p );
1623 FT_UInt32 count = TT_NEXT_ULONG( p );
1624 FT_UInt32 idx;
1625
1626
1627 if ( char_code < start )
1628 char_code = start;
1629
1630 idx = (FT_UInt32)( char_code - start );
1631 p += 2 * idx;
1632
1633 for ( ; idx < count; idx++ )
1634 {
1635 gindex = TT_NEXT_USHORT( p );
1636 if ( gindex != 0 )
1637 break;
1638 char_code++;
1639 }
1640
1641 *pchar_code = char_code;
1642 return gindex;
1643 }
1644
1645
1646 FT_CALLBACK_DEF( FT_Error )
1647 tt_cmap10_get_info( TT_CMap cmap,
1648 TT_CMapInfo *cmap_info )
1649 {
1650 FT_Byte* p = cmap->data + 8;
1651
1652
1653 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1654
1655 return FT_Err_Ok;
1656 }
1657
1658
1659 FT_CALLBACK_TABLE_DEF
1660 const TT_CMap_ClassRec tt_cmap10_class_rec =
1661 {
1662 {
1663 sizeof ( TT_CMapRec ),
1664
1665 (FT_CMap_InitFunc) tt_cmap_init,
1666 (FT_CMap_DoneFunc) NULL,
1667 (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
1668 (FT_CMap_CharNextFunc) tt_cmap10_char_next
1669 },
1670 10,
1671 (TT_CMap_ValidateFunc) tt_cmap10_validate,
1672 (TT_CMap_Info_GetFunc) tt_cmap10_get_info
1673 };
1674
1675 #endif /* TT_CONFIG_CMAP_FORMAT_10 */
1676
1677
1678 /*************************************************************************/
1679 /*************************************************************************/
1680 /***** *****/
1681 /***** FORMAT 12 *****/
1682 /***** *****/
1683 /*************************************************************************/
1684 /*************************************************************************/
1685
1686 /*************************************************************************/
1687 /* */
1688 /* TABLE OVERVIEW */
1689 /* -------------- */
1690 /* */
1691 /* NAME OFFSET TYPE DESCRIPTION */
1692 /* */
1693 /* format 0 USHORT must be 12 */
1694 /* reserved 2 USHORT reserved */
1695 /* length 4 ULONG length in bytes */
1696 /* language 8 ULONG Mac language code */
1697 /* count 12 ULONG number of groups */
1698 /* 16 */
1699 /* */
1700 /* This header is followed by `count' groups of the following format: */
1701 /* */
1702 /* start 0 ULONG first charcode */
1703 /* end 4 ULONG last charcode */
1704 /* startId 8 ULONG start glyph id for the group */
1705 /* */
1706
1707 #ifdef TT_CONFIG_CMAP_FORMAT_12
1708
1709 FT_CALLBACK_DEF( void )
1710 tt_cmap12_validate( FT_Byte* table,
1711 FT_Validator valid )
1712 {
1713 FT_Byte* p;
1714 FT_ULong length;
1715 FT_ULong num_groups;
1716
1717
1718 if ( table + 16 > valid->limit )
1719 FT_INVALID_TOO_SHORT;
1720
1721 p = table + 4;
1722 length = TT_NEXT_ULONG( p );
1723
1724 p = table + 12;
1725 num_groups = TT_NEXT_ULONG( p );
1726
1727 if ( table + length > valid->limit || length < 16 + 12 * num_groups )
1728 FT_INVALID_TOO_SHORT;
1729
1730 /* check groups, they must be in increasing order */
1731 {
1732 FT_ULong n, start, end, start_id, last = 0;
1733
1734
1735 for ( n = 0; n < num_groups; n++ )
1736 {
1737 start = TT_NEXT_ULONG( p );
1738 end = TT_NEXT_ULONG( p );
1739 start_id = TT_NEXT_ULONG( p );
1740
1741 if ( start > end )
1742 FT_INVALID_DATA;
1743
1744 if ( n > 0 && start <= last )
1745 FT_INVALID_DATA;
1746
1747 if ( valid->level >= FT_VALIDATE_TIGHT )
1748 {
1749 if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
1750 FT_INVALID_GLYPH_ID;
1751 }
1752
1753 last = end;
1754 }
1755 }
1756 }
1757
1758
1759 FT_CALLBACK_DEF( FT_UInt )
1760 tt_cmap12_char_index( TT_CMap cmap,
1761 FT_UInt32 char_code )
1762 {
1763 FT_UInt result = 0;
1764 FT_Byte* table = cmap->data;
1765 FT_Byte* p = table + 12;
1766 FT_UInt32 num_groups = TT_NEXT_ULONG( p );
1767 FT_UInt32 start, end, start_id;
1768
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 break;
1778
1779 if ( char_code <= end )
1780 {
1781 result = (FT_UInt)( start_id + char_code - start );
1782 break;
1783 }
1784 }
1785 return result;
1786 }
1787
1788
1789 FT_CALLBACK_DEF( FT_UInt )
1790 tt_cmap12_char_next( TT_CMap cmap,
1791 FT_UInt32 *pchar_code )
1792 {
1793 FT_Byte* table = cmap->data;
1794 FT_UInt32 result = 0;
1795 FT_UInt32 char_code = *pchar_code + 1;
1796 FT_UInt gindex = 0;
1797 FT_Byte* p = table + 12;
1798 FT_UInt32 num_groups = TT_NEXT_ULONG( p );
1799 FT_UInt32 start, end, start_id;
1800
1801
1802 p = table + 16;
1803
1804 for ( ; num_groups > 0; num_groups-- )
1805 {
1806 start = TT_NEXT_ULONG( p );
1807 end = TT_NEXT_ULONG( p );
1808 start_id = TT_NEXT_ULONG( p );
1809
1810 if ( char_code < start )
1811 char_code = start;
1812
1813 if ( char_code <= end )
1814 {
1815 gindex = (FT_UInt)(char_code - start + start_id);
1816 if ( gindex != 0 )
1817 {
1818 result = char_code;
1819 goto Exit;
1820 }
1821 }
1822 }
1823
1824 Exit:
1825 *pchar_code = result;
1826 return gindex;
1827 }
1828
1829
1830 FT_CALLBACK_DEF( FT_Error )
1831 tt_cmap12_get_info( TT_CMap cmap,
1832 TT_CMapInfo *cmap_info )
1833 {
1834 FT_Byte* p = cmap->data + 8;
1835
1836
1837 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1838
1839 return FT_Err_Ok;
1840 }
1841
1842
1843 FT_CALLBACK_TABLE_DEF
1844 const TT_CMap_ClassRec tt_cmap12_class_rec =
1845 {
1846 {
1847 sizeof ( TT_CMapRec ),
1848
1849 (FT_CMap_InitFunc) tt_cmap_init,
1850 (FT_CMap_DoneFunc) NULL,
1851 (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
1852 (FT_CMap_CharNextFunc) tt_cmap12_char_next
1853 },
1854 12,
1855 (TT_CMap_ValidateFunc) tt_cmap12_validate,
1856 (TT_CMap_Info_GetFunc) tt_cmap12_get_info
1857 };
1858
1859
1860 #endif /* TT_CONFIG_CMAP_FORMAT_12 */
1861
1862
1863 static const TT_CMap_Class tt_cmap_classes[] =
1864 {
1865 #ifdef TT_CONFIG_CMAP_FORMAT_0
1866 &tt_cmap0_class_rec,
1867 #endif
1868
1869 #ifdef TT_CONFIG_CMAP_FORMAT_2
1870 &tt_cmap2_class_rec,
1871 #endif
1872
1873 #ifdef TT_CONFIG_CMAP_FORMAT_4
1874 &tt_cmap4_class_rec,
1875 #endif
1876
1877 #ifdef TT_CONFIG_CMAP_FORMAT_6
1878 &tt_cmap6_class_rec,
1879 #endif
1880
1881 #ifdef TT_CONFIG_CMAP_FORMAT_8
1882 &tt_cmap8_class_rec,
1883 #endif
1884
1885 #ifdef TT_CONFIG_CMAP_FORMAT_10
1886 &tt_cmap10_class_rec,
1887 #endif
1888
1889 #ifdef TT_CONFIG_CMAP_FORMAT_12
1890 &tt_cmap12_class_rec,
1891 #endif
1892
1893 NULL,
1894 };
1895
1896
1897 /* parse the `cmap' table and build the corresponding TT_CMap objects */
1898 /* in the current face */
1899 /* */
1900 FT_LOCAL_DEF( FT_Error )
1901 tt_face_build_cmaps( TT_Face face )
1902 {
1903 FT_Byte* table = face->cmap_table;
1904 FT_Byte* limit = table + face->cmap_size;
1905 FT_UInt volatile num_cmaps;
1906 FT_Byte* volatile p = table;
1907
1908
1909 if ( p + 4 > limit )
1910 return SFNT_Err_Invalid_Table;
1911
1912 /* only recognize format 0 */
1913 if ( TT_NEXT_USHORT( p ) != 0 )
1914 {
1915 p -= 2;
1916 FT_ERROR(( "tt_face_build_cmaps: unsupported `cmap' table format = %d\n",
1917 TT_PEEK_USHORT( p ) ));
1918 return SFNT_Err_Invalid_Table;
1919 }
1920
1921 num_cmaps = TT_NEXT_USHORT( p );
1922
1923 for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
1924 {
1925 FT_CharMapRec charmap;
1926 FT_UInt32 offset;
1927
1928
1929 charmap.platform_id = TT_NEXT_USHORT( p );
1930 charmap.encoding_id = TT_NEXT_USHORT( p );
1931 charmap.face = FT_FACE( face );
1932 charmap.encoding = FT_ENCODING_NONE; /* will be filled later */
1933 offset = TT_NEXT_ULONG( p );
1934
1935 if ( offset && table + offset + 2 < limit )
1936 {
1937 FT_Byte* cmap = table + offset;
1938 volatile FT_UInt format = TT_PEEK_USHORT( cmap );
1939 const TT_CMap_Class* volatile pclazz = tt_cmap_classes;
1940 TT_CMap_Class clazz;
1941
1942
1943 for ( ; *pclazz; pclazz++ )
1944 {
1945 clazz = *pclazz;
1946 if ( clazz->format == format )
1947 {
1948 volatile TT_ValidatorRec valid;
1949
1950
1951 ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
1952 FT_VALIDATE_DEFAULT );
1953
1954 valid.num_glyphs = (FT_UInt)face->root.num_glyphs;
1955
1956 if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer ) == 0 )
1957 {
1958 /* validate this cmap sub-table */
1959 clazz->validate( cmap, FT_VALIDATOR( &valid ) );
1960 }
1961
1962 if ( valid.validator.error == 0 )
1963 (void)FT_CMap_New( (FT_CMap_Class)clazz, cmap, &charmap, NULL );
1964 else
1965 {
1966 FT_ERROR(( "tt_face_build_cmaps:" ));
1967 FT_ERROR(( " broken cmap sub-table ignored!\n" ));
1968 }
1969 break;
1970 }
1971 }
1972 }
1973 }
1974
1975 return 0;
1976 }
1977
1978
1979 FT_LOCAL( FT_Error )
1980 tt_get_cmap_info( FT_CharMap charmap,
1981 TT_CMapInfo *cmap_info )
1982 {
1983 FT_CMap cmap = (FT_CMap)charmap;
1984 TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz;
1985
1986
1987 return clazz->get_cmap_info( charmap, cmap_info );
1988 }
1989
1990
1991 /* END */