1 /***************************************************************************/
5 /* TrueType new character mapping table (cmap) support (body). */
7 /* Copyright 2002, 2003 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
20 #include FT_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_OBJECTS_H
22 #include FT_INTERNAL_STREAM_H
28 /*************************************************************************/
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. */
35 #define FT_COMPONENT trace_ttcmap
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
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
49 FT_CALLBACK_DEF( FT_Error
)
50 tt_cmap_init( TT_CMap cmap
,
58 /*************************************************************************/
59 /*************************************************************************/
61 /***** FORMAT 0 *****/
63 /*************************************************************************/
64 /*************************************************************************/
66 /*************************************************************************/
71 /* NAME OFFSET TYPE DESCRIPTION */
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 */
80 #ifdef TT_CONFIG_CMAP_FORMAT_0
82 FT_CALLBACK_DEF( void )
83 tt_cmap0_validate( FT_Byte
* table
,
86 FT_Byte
* p
= table
+ 2;
87 FT_UInt length
= TT_NEXT_USHORT( p
);
90 if ( table
+ length
> valid
->limit
|| length
< 262 )
93 /* check glyph indices whenever necessary */
94 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
100 for ( n
= 0; n
< 256; n
++ )
103 if ( idx
>= TT_VALID_GLYPH_COUNT( valid
) )
110 FT_CALLBACK_DEF( FT_UInt
)
111 tt_cmap0_char_index( TT_CMap cmap
,
112 FT_UInt32 char_code
)
114 FT_Byte
* table
= cmap
->data
;
117 return char_code
< 256 ? table
[6 + char_code
] : 0;
121 FT_CALLBACK_DEF( FT_UInt
)
122 tt_cmap0_char_next( TT_CMap cmap
,
123 FT_UInt32
*pchar_code
)
125 FT_Byte
* table
= cmap
->data
;
126 FT_UInt32 charcode
= *pchar_code
;
127 FT_UInt32 result
= 0;
131 table
+= 6; /* go to glyph ids */
132 while ( ++charcode
< 256 )
134 gindex
= table
[charcode
];
142 *pchar_code
= result
;
147 FT_CALLBACK_DEF( FT_Error
)
148 tt_cmap0_get_info( TT_CMap cmap
,
149 TT_CMapInfo
*cmap_info
)
151 FT_Byte
* p
= cmap
->data
+ 4;
154 cmap_info
->language
= (FT_ULong
)TT_PEEK_USHORT( p
);
160 FT_CALLBACK_TABLE_DEF
161 const TT_CMap_ClassRec tt_cmap0_class_rec
=
164 sizeof( TT_CMapRec
),
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
172 (TT_CMap_ValidateFunc
) tt_cmap0_validate
,
173 (TT_CMap_Info_GetFunc
) tt_cmap0_get_info
176 #endif /* TT_CONFIG_CMAP_FORMAT_0 */
179 /*************************************************************************/
180 /*************************************************************************/
182 /***** FORMAT 2 *****/
184 /***** This is used for certain CJK encodings that encode text in a *****/
185 /***** mixed 8/16 bits encoding along the following lines: *****/
187 /***** * Certain byte values correspond to an 8-bit character code *****/
188 /***** (typically in the range 0..127 for ASCII compatibility). *****/
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). *****/
194 /***** The following charmap lookup and iteration functions all *****/
195 /***** assume that the value "charcode" correspond to following: *****/
197 /***** - For one byte characters, "charcode" is simply the *****/
198 /***** character code. *****/
200 /***** - For two byte characters, "charcode" is the 2-byte *****/
201 /***** character code in big endian format. More exactly: *****/
203 /***** (charcode >> 8) is the first byte value *****/
204 /***** (charcode & 0xFF) is the second byte value *****/
206 /***** Note that not all values of "charcode" are valid according *****/
207 /***** to these rules, and the function moderately check the *****/
208 /***** arguments. *****/
210 /*************************************************************************/
211 /*************************************************************************/
213 /*************************************************************************/
218 /* NAME OFFSET TYPE DESCRIPTION */
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 */
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. */
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 */
235 /* Each sub-header has the following format: */
237 /* NAME OFFSET TYPE DESCRIPTION */
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 */
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. */
249 /* If a character code is contained within a given sub-header, then */
250 /* mapping it to a glyph index is done as follows: */
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). */
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. */
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). */
265 #ifdef TT_CONFIG_CMAP_FORMAT_2
267 FT_CALLBACK_DEF( void )
268 tt_cmap2_validate( FT_Byte
* table
,
271 FT_Byte
* p
= table
+ 2; /* skip format */
272 FT_UInt length
= TT_PEEK_USHORT( p
);
274 FT_Byte
* keys
; /* keys table */
275 FT_Byte
* subs
; /* sub-headers */
276 FT_Byte
* glyph_ids
; /* glyph id array */
279 if ( table
+ length
> valid
->limit
|| length
< 6 + 512 )
280 FT_INVALID_TOO_SHORT
;
284 /* parse keys to compute sub-headers count */
287 for ( n
= 0; n
< 256; n
++ )
289 FT_UInt idx
= TT_NEXT_USHORT( p
);
292 /* value must be multiple of 8 */
293 if ( valid
->level
>= FT_VALIDATE_PARANOID
&& ( idx
& 7 ) != 0 )
298 if ( idx
> max_subs
)
302 FT_ASSERT( p
== table
+ 518 );
305 glyph_ids
= subs
+ (max_subs
+ 1) * 8;
306 if ( glyph_ids
> valid
->limit
)
307 FT_INVALID_TOO_SHORT
;
309 /* parse sub-headers */
310 for ( n
= 0; n
<= max_subs
; n
++ )
312 FT_UInt first_code
, code_count
, offset
;
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
);
322 /* check range within 0..255 */
323 if ( valid
->level
>= FT_VALIDATE_PARANOID
)
325 if ( first_code
>= 256 || first_code
+ code_count
> 256 )
332 ids
= p
- 2 + offset
;
333 if ( ids
< glyph_ids
|| ids
+ code_count
*2 > table
+ length
)
336 /* check glyph ids */
337 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
339 FT_Byte
* limit
= p
+ code_count
* 2;
345 idx
= TT_NEXT_USHORT( p
);
348 idx
= ( idx
+ delta
) & 0xFFFFU
;
349 if ( idx
>= TT_VALID_GLYPH_COUNT( valid
) )
359 /* return sub header corresponding to a given character code */
360 /* NULL on invalid charcode */
362 tt_cmap2_get_subheader( FT_Byte
* table
,
363 FT_UInt32 char_code
)
365 FT_Byte
* result
= NULL
;
368 if ( char_code
< 0x10000UL
)
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 */
379 /* an 8-bit character code -- we use subHeader 0 in this case */
380 /* to test whether the character code is in the charmap */
382 sub
= subs
; /* jump to first sub-header */
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 */
389 if ( TT_PEEK_USHORT( p
) != 0 )
394 /* a 16-bit character code */
396 /* jump to key entry */
398 /* jump to sub-header */
399 sub
= subs
+ ( FT_PAD_FLOOR( TT_PEEK_USHORT( p
), 8 ) );
401 /* check that the high byte isn't a valid one-byte value */
412 FT_CALLBACK_DEF( FT_UInt
)
413 tt_cmap2_char_index( TT_CMap cmap
,
414 FT_UInt32 char_code
)
416 FT_Byte
* table
= cmap
->data
;
421 subheader
= tt_cmap2_get_subheader( table
, char_code
);
424 FT_Byte
* p
= subheader
;
425 FT_UInt idx
= (FT_UInt
)(char_code
& 0xFF);
426 FT_UInt start
, count
;
431 start
= TT_NEXT_USHORT( p
);
432 count
= TT_NEXT_USHORT( p
);
433 delta
= TT_NEXT_SHORT ( p
);
434 offset
= TT_PEEK_USHORT( p
);
437 if ( idx
< count
&& offset
!= 0 )
439 p
+= offset
+ 2 * idx
;
440 idx
= TT_PEEK_USHORT( p
);
443 result
= (FT_UInt
)( idx
+ delta
) & 0xFFFFU
;
450 FT_CALLBACK_DEF( FT_UInt
)
451 tt_cmap2_char_next( TT_CMap cmap
,
452 FT_UInt32
*pcharcode
)
454 FT_Byte
* table
= cmap
->data
;
456 FT_UInt32 result
= 0;
457 FT_UInt32 charcode
= *pcharcode
+ 1;
461 while ( charcode
< 0x10000UL
)
463 subheader
= tt_cmap2_get_subheader( table
, charcode
);
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 );
478 if ( char_lo
< start
)
484 pos
= (FT_UInt
)( char_lo
- start
);
486 p
+= offset
+ pos
* 2;
487 charcode
= FT_PAD_FLOOR( charcode
, 256 ) + char_lo
;
489 for ( ; pos
< count
; pos
++, charcode
++ )
491 idx
= TT_NEXT_USHORT( p
);
495 gindex
= ( idx
+ delta
) & 0xFFFFU
;
505 /* jump to next sub-header, i.e. higher byte value */
507 charcode
= FT_PAD_FLOOR( charcode
, 256 ) + 256;
517 FT_CALLBACK_DEF( FT_Error
)
518 tt_cmap2_get_info( TT_CMap cmap
,
519 TT_CMapInfo
*cmap_info
)
521 FT_Byte
* p
= cmap
->data
+ 4;
524 cmap_info
->language
= (FT_ULong
)TT_PEEK_USHORT( p
);
530 FT_CALLBACK_TABLE_DEF
531 const TT_CMap_ClassRec tt_cmap2_class_rec
=
534 sizeof( TT_CMapRec
),
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
542 (TT_CMap_ValidateFunc
) tt_cmap2_validate
,
543 (TT_CMap_Info_GetFunc
) tt_cmap2_get_info
546 #endif /* TT_CONFIG_CMAP_FORMAT_2 */
549 /*************************************************************************/
550 /*************************************************************************/
552 /***** FORMAT 4 *****/
554 /*************************************************************************/
555 /*************************************************************************/
557 /*************************************************************************/
562 /* NAME OFFSET TYPE DESCRIPTION */
564 /* format 0 USHORT must be 4 */
565 /* length 2 USHORT table length */
567 /* language 4 USHORT Mac language code */
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 - */
575 /* endCount 14 USHORT[NUM_SEGS] end charcode for */
576 /* each segment; last */
579 /* pad 14+NUM_SEGS*2 USHORT padding */
581 /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */
584 /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */
586 /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */
587 /* each segment; can be */
590 /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph id */
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. */
599 /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
600 /* ignored (they are traces of over-engineering in the TrueType */
601 /* specification). */
603 /* Each segment also has a signed `delta', as well as an optional offset */
604 /* within the `glyphIds' table. */
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. */
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. */
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... */
620 #ifdef TT_CONFIG_CMAP_FORMAT_4
622 FT_CALLBACK_DEF( void )
623 tt_cmap4_validate( FT_Byte
* table
,
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
;
632 /* in certain fonts, the `length' field is invalid and goes */
633 /* out of bound. We try to correct this here... */
635 FT_INVALID_TOO_SHORT
;
637 if ( table
+ length
> valid
->limit
)
639 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
640 FT_INVALID_TOO_SHORT
;
642 length
= (FT_UInt
)( valid
->limit
- table
);
646 num_segs
= TT_NEXT_USHORT( p
); /* read segCountX2 */
648 if ( valid
->level
>= FT_VALIDATE_PARANOID
)
650 /* check that we have an even value here */
657 /* check the search parameters - even though we never use them */
659 if ( valid
->level
>= FT_VALIDATE_PARANOID
)
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
);
667 if ( ( search_range
| range_shift
) & 1 ) /* must be even values */
673 /* `search range' is the greatest power of 2 that is <= num_segs */
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
) )
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;
688 if ( glyph_ids
> table
+ length
)
689 FT_INVALID_TOO_SHORT
;
691 /* check last segment, its end count must be FFFF */
692 if ( valid
->level
>= FT_VALIDATE_PARANOID
)
694 p
= ends
+ ( num_segs
- 1 ) * 2;
695 if ( TT_PEEK_USHORT( p
) != 0xFFFFU
)
699 /* check that segments are sorted in increasing order and do not */
700 /* overlap; check also the offsets */
702 FT_UInt start
, end
, last
= 0, offset
, n
;
706 for ( n
= 0; n
< num_segs
; n
++ )
709 start
= TT_PEEK_USHORT( p
);
711 end
= TT_PEEK_USHORT( p
);
713 delta
= TT_PEEK_SHORT( p
);
715 offset
= TT_PEEK_USHORT( p
);
720 /* this test should be performed at default validation level; */
721 /* unfortunately, some popular Asian fonts present overlapping */
722 /* ranges in their charmaps */
724 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
726 if ( n
> 0 && start
<= last
)
730 if ( offset
&& offset
!= 0xFFFFU
)
732 p
+= offset
; /* start of glyph id array */
734 /* check that we point within the glyph ids table only */
735 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
737 if ( p
< glyph_ids
||
738 p
+ ( end
- start
+ 1 ) * 2 > table
+ length
)
743 if ( p
< glyph_ids
||
744 p
+ ( end
- start
+ 1 ) * 2 > valid
->limit
)
748 /* check glyph indices within the segment range */
749 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
754 for ( i
= start
; i
< end
; i
++ )
756 idx
= FT_NEXT_USHORT( p
);
759 idx
= (FT_UInt
)( idx
+ delta
) & 0xFFFFU
;
761 if ( idx
>= TT_VALID_GLYPH_COUNT( valid
) )
767 else if ( offset
== 0xFFFFU
)
769 /* Some fonts (erroneously?) use a range offset of 0xFFFF */
770 /* to mean missing glyph in cmap table */
772 if ( valid
->level
>= FT_VALIDATE_PARANOID
||
774 !( start
== 0xFFFFU
&& end
== 0xFFFFU
&& delta
== 0x1U
) )
784 FT_CALLBACK_DEF( FT_UInt
)
785 tt_cmap4_char_index( TT_CMap cmap
,
786 FT_UInt32 char_code
)
788 FT_Byte
* table
= cmap
->data
;
792 if ( char_code
< 0x10000UL
)
794 FT_UInt idx
, num_segs2
;
796 FT_UInt code
= (FT_UInt
)char_code
;
801 num_segs2
= FT_PAD_FLOOR( TT_PEEK_USHORT( p
), 2 ); /* be paranoid! */
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 */
809 FT_UInt max
= num_segs2
>> 1;
810 FT_UInt mid
, start
, end
, offset
;
815 mid
= ( min
+ max
) >> 1;
816 p
= table
+ 14 + mid
* 2;
817 end
= TT_NEXT_USHORT( p
);
819 start
= TT_PEEK_USHORT( p
);
823 else if ( code
> end
)
827 /* we found the segment */
831 delta
= TT_PEEK_SHORT( p
);
834 offset
= TT_PEEK_USHORT( p
);
836 if ( offset
== 0xFFFFU
)
841 p
+= offset
+ 2 * ( idx
- start
);
842 idx
= TT_PEEK_USHORT( p
);
846 result
= (FT_UInt
)( idx
+ delta
) & 0xFFFFU
;
853 #else /* 0 - old code */
860 p
= table
+ 14; /* ends table */
861 q
= table
+ 16 + num_segs2
; /* starts table */
864 for ( n
= 0; n
< num_segs2
; n
+= 2 )
866 FT_UInt end
= TT_NEXT_USHORT( p
);
867 FT_UInt start
= TT_NEXT_USHORT( q
);
878 p
= q
+ num_segs2
- 2;
879 delta
= TT_PEEK_SHORT( p
);
881 offset
= TT_PEEK_USHORT( p
);
883 if ( offset
== 0xFFFFU
)
888 p
+= offset
+ 2 * ( idx
- start
);
889 idx
= TT_PEEK_USHORT( p
);
893 result
= (FT_UInt
)( idx
+ delta
) & 0xFFFFU
;
907 FT_CALLBACK_DEF( FT_UInt
)
908 tt_cmap4_char_next( TT_CMap cmap
,
909 FT_UInt32
*pchar_code
)
911 FT_Byte
* table
= cmap
->data
;
912 FT_UInt32 result
= 0;
914 FT_UInt32 char_code
= *pchar_code
;
916 FT_UInt code
, num_segs2
;
919 if ( char_code
>= 0xFFFFUL
)
922 code
= (FT_UInt
)char_code
+ 1;
924 num_segs2
= FT_PAD_FLOOR( TT_PEEK_USHORT(p
), 2 ); /* ensure even-ness */
930 /* Some fonts have more than 170 segments in their charmaps! */
931 /* We changed this function to use a more efficient binary */
936 FT_UInt max
= num_segs2
>> 1;
937 FT_UInt mid
, start
, end
;
941 /* we begin by finding the segment which end is
942 closer to our code point */
946 mid
= ( min
+ max
) >> 1;
947 p
= table
+ 14 + mid
* 2;
948 end
= TT_PEEK_USHORT( p
);
961 /* the point is behind the last segment;
962 we will exit right now */
966 p
= table
+ 14 + hi
* 2;
967 end
= TT_PEEK_USHORT( p
);
970 start
= TT_PEEK_USHORT( p
);
976 delta
= TT_PEEK_USHORT( p
);
979 offset
= TT_PEEK_USHORT( p
);
981 if ( offset
!= 0 && offset
!= 0xFFFFU
)
983 /* parse the glyph ids array for non-zero index */
984 p
+= offset
+ ( code
- start
) * 2;
985 while ( code
<= end
)
987 gindex
= TT_NEXT_USHORT( p
);
990 gindex
= (FT_UInt
)( gindex
+ delta
) & 0xFFFFU
;
1000 else if ( offset
== 0xFFFFU
)
1002 /* an offset of 0xFFFF means an empty glyph in certain fonts! */
1005 else /* offset == 0 */
1007 gindex
= (FT_UInt
)( code
+ delta
) & 0xFFFFU
;
1017 #else /* old code -- kept for reference */
1026 p
= table
+ 14; /* ends table */
1027 q
= table
+ 16 + num_segs2
; /* starts table */
1029 for ( n
= 0; n
< num_segs2
; n
+= 2 )
1031 FT_UInt end
= TT_NEXT_USHORT( p
);
1032 FT_UInt start
= TT_NEXT_USHORT( q
);
1040 p
= q
+ num_segs2
- 2;
1041 delta
= TT_PEEK_SHORT( p
);
1043 offset
= TT_PEEK_USHORT( p
);
1045 if ( offset
!= 0 && offset
!= 0xFFFFU
)
1047 /* parse the glyph ids array for non-0 index */
1048 p
+= offset
+ ( code
- start
) * 2;
1049 while ( code
<= end
)
1051 gindex
= TT_NEXT_USHORT( p
);
1054 gindex
= (FT_UInt
)( gindex
+ delta
) & 0xFFFFU
;
1061 else if ( offset
== 0xFFFFU
)
1063 /* an offset of 0xFFFF means an empty glyph in certain fonts! */
1068 gindex
= (FT_UInt
)( code
+ delta
) & 0xFFFFU
;
1077 /* loop to next trial charcode */
1078 if ( code
>= 0xFFFFU
)
1087 *pchar_code
= result
;
1092 FT_CALLBACK_DEF( FT_Error
)
1093 tt_cmap4_get_info( TT_CMap cmap
,
1094 TT_CMapInfo
*cmap_info
)
1096 FT_Byte
* p
= cmap
->data
+ 4;
1099 cmap_info
->language
= (FT_ULong
)TT_PEEK_USHORT( p
);
1105 FT_CALLBACK_TABLE_DEF
1106 const TT_CMap_ClassRec tt_cmap4_class_rec
=
1109 sizeof ( TT_CMapRec
),
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
1117 (TT_CMap_ValidateFunc
) tt_cmap4_validate
,
1118 (TT_CMap_Info_GetFunc
) tt_cmap4_get_info
1121 #endif /* TT_CONFIG_CMAP_FORMAT_4 */
1124 /*************************************************************************/
1125 /*************************************************************************/
1127 /***** FORMAT 6 *****/
1129 /*************************************************************************/
1130 /*************************************************************************/
1132 /*************************************************************************/
1134 /* TABLE OVERVIEW */
1135 /* -------------- */
1137 /* NAME OFFSET TYPE DESCRIPTION */
1139 /* format 0 USHORT must be 4 */
1140 /* length 2 USHORT table length in bytes */
1141 /* language 4 USHORT Mac language code */
1143 /* first 6 USHORT first segment code */
1144 /* count 8 USHORT segment size in chars */
1145 /* glyphIds 10 USHORT[count] glyph ids */
1147 /* A very simplified segment mapping. */
1150 #ifdef TT_CONFIG_CMAP_FORMAT_6
1152 FT_CALLBACK_DEF( void )
1153 tt_cmap6_validate( FT_Byte
* table
,
1154 FT_Validator valid
)
1157 FT_UInt length
, count
;
1160 if ( table
+ 10 > valid
->limit
)
1161 FT_INVALID_TOO_SHORT
;
1164 length
= TT_NEXT_USHORT( p
);
1166 p
= table
+ 8; /* skip language and start index */
1167 count
= TT_NEXT_USHORT( p
);
1169 if ( table
+ length
> valid
->limit
|| length
< 10 + count
* 2 )
1170 FT_INVALID_TOO_SHORT
;
1172 /* check glyph indices */
1173 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
1178 for ( ; count
> 0; count
-- )
1180 gindex
= TT_NEXT_USHORT( p
);
1181 if ( gindex
>= TT_VALID_GLYPH_COUNT( valid
) )
1182 FT_INVALID_GLYPH_ID
;
1188 FT_CALLBACK_DEF( FT_UInt
)
1189 tt_cmap6_char_index( TT_CMap cmap
,
1190 FT_UInt32 char_code
)
1192 FT_Byte
* table
= cmap
->data
;
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
);
1203 result
= TT_PEEK_USHORT( p
);
1209 FT_CALLBACK_DEF( FT_UInt
)
1210 tt_cmap6_char_next( TT_CMap cmap
,
1211 FT_UInt32
*pchar_code
)
1213 FT_Byte
* table
= cmap
->data
;
1214 FT_UInt32 result
= 0;
1215 FT_UInt32 char_code
= *pchar_code
+ 1;
1218 FT_Byte
* p
= table
+ 6;
1219 FT_UInt start
= TT_NEXT_USHORT( p
);
1220 FT_UInt count
= TT_NEXT_USHORT( p
);
1224 if ( char_code
>= 0x10000UL
)
1227 if ( char_code
< start
)
1230 idx
= (FT_UInt
)( char_code
- start
);
1233 for ( ; idx
< count
; idx
++ )
1235 gindex
= TT_NEXT_USHORT( p
);
1245 *pchar_code
= result
;
1250 FT_CALLBACK_DEF( FT_Error
)
1251 tt_cmap6_get_info( TT_CMap cmap
,
1252 TT_CMapInfo
*cmap_info
)
1254 FT_Byte
* p
= cmap
->data
+ 4;
1257 cmap_info
->language
= (FT_ULong
)TT_PEEK_USHORT( p
);
1263 FT_CALLBACK_TABLE_DEF
1264 const TT_CMap_ClassRec tt_cmap6_class_rec
=
1267 sizeof ( TT_CMapRec
),
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
1275 (TT_CMap_ValidateFunc
) tt_cmap6_validate
,
1276 (TT_CMap_Info_GetFunc
) tt_cmap6_get_info
1279 #endif /* TT_CONFIG_CMAP_FORMAT_6 */
1282 /*************************************************************************/
1283 /*************************************************************************/
1285 /***** FORMAT 8 *****/
1287 /***** It's hard to completely understand what the OpenType spec *****/
1288 /***** says about this format, but here is my conclusion. *****/
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: *****/
1294 /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/
1295 /***** Area (i.e. U+D800-U+DFFF). *****/
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. *****/
1302 /***** The 'is32' table embedded in the charmap indicates whether a *****/
1303 /***** given 16-bit value is in the surrogates area or not. *****/
1305 /***** So, for any given `char_code', we can assert the following: *****/
1307 /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/
1309 /***** If `char_hi != 0' then we must have both *****/
1310 /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/
1312 /*************************************************************************/
1313 /*************************************************************************/
1315 /*************************************************************************/
1317 /* TABLE OVERVIEW */
1318 /* -------------- */
1320 /* NAME OFFSET TYPE DESCRIPTION */
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 */
1329 /* This header is followed by 'count' groups of the following format: */
1331 /* start 0 ULONG first charcode */
1332 /* end 4 ULONG last charcode */
1333 /* startId 8 ULONG start glyph id for the group */
1336 #ifdef TT_CONFIG_CMAP_FORMAT_8
1338 FT_CALLBACK_DEF( void )
1339 tt_cmap8_validate( FT_Byte
* table
,
1340 FT_Validator valid
)
1342 FT_Byte
* p
= table
+ 4;
1345 FT_UInt32 num_groups
;
1348 if ( table
+ 16 + 8192 > valid
->limit
)
1349 FT_INVALID_TOO_SHORT
;
1351 length
= TT_NEXT_ULONG( p
);
1352 if ( table
+ length
> valid
->limit
|| length
< 8208 )
1353 FT_INVALID_TOO_SHORT
;
1356 p
= is32
+ 8192; /* skip `is32' array */
1357 num_groups
= TT_NEXT_ULONG( p
);
1359 if ( p
+ num_groups
* 12 > valid
->limit
)
1360 FT_INVALID_TOO_SHORT
;
1362 /* check groups, they must be in increasing order */
1364 FT_UInt32 n
, start
, end
, start_id
, count
, last
= 0;
1367 for ( n
= 0; n
< num_groups
; n
++ )
1372 start
= TT_NEXT_ULONG( p
);
1373 end
= TT_NEXT_ULONG( p
);
1374 start_id
= TT_NEXT_ULONG( p
);
1379 if ( n
> 0 && start
<= last
)
1382 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
1384 if ( start_id
+ end
- start
>= TT_VALID_GLYPH_COUNT( valid
) )
1385 FT_INVALID_GLYPH_ID
;
1387 count
= (FT_UInt32
)( end
- start
+ 1 );
1389 if ( start
& ~0xFFFFU
)
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
++ )
1395 hi
= (FT_UInt
)( start
>> 16 );
1396 lo
= (FT_UInt
)( start
& 0xFFFFU
);
1398 if ( (is32
[hi
>> 3] & ( 0x80 >> ( hi
& 7 ) ) ) == 0 )
1401 if ( (is32
[lo
>> 3] & ( 0x80 >> ( lo
& 7 ) ) ) == 0 )
1407 /* start_hi == 0; check that is32[i] is 0 for each i in */
1408 /* the range [start..end] */
1410 /* end_hi cannot be != 0! */
1411 if ( end
& ~0xFFFFU
)
1414 for ( ; count
> 0; count
--, start
++ )
1416 lo
= (FT_UInt
)( start
& 0xFFFFU
);
1418 if ( (is32
[lo
>> 3] & ( 0x80 >> ( lo
& 7 ) ) ) != 0 )
1430 FT_CALLBACK_DEF( FT_UInt
)
1431 tt_cmap8_char_index( TT_CMap cmap
,
1432 FT_UInt32 char_code
)
1434 FT_Byte
* table
= cmap
->data
;
1436 FT_Byte
* p
= table
+ 8204;
1437 FT_UInt32 num_groups
= TT_NEXT_ULONG( p
);
1438 FT_UInt32 start
, end
, start_id
;
1441 for ( ; num_groups
> 0; num_groups
-- )
1443 start
= TT_NEXT_ULONG( p
);
1444 end
= TT_NEXT_ULONG( p
);
1445 start_id
= TT_NEXT_ULONG( p
);
1447 if ( char_code
< start
)
1450 if ( char_code
<= end
)
1452 result
= (FT_UInt
)( start_id
+ char_code
- start
);
1460 FT_CALLBACK_DEF( FT_UInt
)
1461 tt_cmap8_char_next( TT_CMap cmap
,
1462 FT_UInt32
*pchar_code
)
1464 FT_UInt32 result
= 0;
1465 FT_UInt32 char_code
= *pchar_code
+ 1;
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
;
1475 for ( ; num_groups
> 0; num_groups
-- )
1477 start
= TT_NEXT_ULONG( p
);
1478 end
= TT_NEXT_ULONG( p
);
1479 start_id
= TT_NEXT_ULONG( p
);
1481 if ( char_code
< start
)
1484 if ( char_code
<= end
)
1486 gindex
= (FT_UInt
)( char_code
- start
+ start_id
);
1496 *pchar_code
= result
;
1501 FT_CALLBACK_DEF( FT_Error
)
1502 tt_cmap8_get_info( TT_CMap cmap
,
1503 TT_CMapInfo
*cmap_info
)
1505 FT_Byte
* p
= cmap
->data
+ 8;
1508 cmap_info
->language
= (FT_ULong
)TT_PEEK_ULONG( p
);
1513 FT_CALLBACK_TABLE_DEF
1514 const TT_CMap_ClassRec tt_cmap8_class_rec
=
1517 sizeof ( TT_CMapRec
),
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
1525 (TT_CMap_ValidateFunc
) tt_cmap8_validate
,
1526 (TT_CMap_Info_GetFunc
) tt_cmap8_get_info
1529 #endif /* TT_CONFIG_CMAP_FORMAT_8 */
1532 /*************************************************************************/
1533 /*************************************************************************/
1535 /***** FORMAT 10 *****/
1537 /*************************************************************************/
1538 /*************************************************************************/
1540 /*************************************************************************/
1542 /* TABLE OVERVIEW */
1543 /* -------------- */
1545 /* NAME OFFSET TYPE DESCRIPTION */
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 */
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 */
1557 #ifdef TT_CONFIG_CMAP_FORMAT_10
1559 FT_CALLBACK_DEF( void )
1560 tt_cmap10_validate( FT_Byte
* table
,
1561 FT_Validator valid
)
1563 FT_Byte
* p
= table
+ 4;
1564 FT_ULong length
, count
;
1567 if ( table
+ 20 > valid
->limit
)
1568 FT_INVALID_TOO_SHORT
;
1570 length
= TT_NEXT_ULONG( p
);
1572 count
= TT_NEXT_ULONG( p
);
1574 if ( table
+ length
> valid
->limit
|| length
< 20 + count
* 2 )
1575 FT_INVALID_TOO_SHORT
;
1577 /* check glyph indices */
1578 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
1583 for ( ; count
> 0; count
-- )
1585 gindex
= TT_NEXT_USHORT( p
);
1586 if ( gindex
>= TT_VALID_GLYPH_COUNT( valid
) )
1587 FT_INVALID_GLYPH_ID
;
1593 FT_CALLBACK_DEF( FT_UInt
)
1594 tt_cmap10_char_index( TT_CMap cmap
,
1595 FT_UInt32 char_code
)
1597 FT_Byte
* table
= cmap
->data
;
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
);
1608 result
= TT_PEEK_USHORT( p
);
1614 FT_CALLBACK_DEF( FT_UInt
)
1615 tt_cmap10_char_next( TT_CMap cmap
,
1616 FT_UInt32
*pchar_code
)
1618 FT_Byte
* table
= cmap
->data
;
1619 FT_UInt32 char_code
= *pchar_code
+ 1;
1621 FT_Byte
* p
= table
+ 12;
1622 FT_UInt32 start
= TT_NEXT_ULONG( p
);
1623 FT_UInt32 count
= TT_NEXT_ULONG( p
);
1627 if ( char_code
< start
)
1630 idx
= (FT_UInt32
)( char_code
- start
);
1633 for ( ; idx
< count
; idx
++ )
1635 gindex
= TT_NEXT_USHORT( p
);
1641 *pchar_code
= char_code
;
1646 FT_CALLBACK_DEF( FT_Error
)
1647 tt_cmap10_get_info( TT_CMap cmap
,
1648 TT_CMapInfo
*cmap_info
)
1650 FT_Byte
* p
= cmap
->data
+ 8;
1653 cmap_info
->language
= (FT_ULong
)TT_PEEK_ULONG( p
);
1659 FT_CALLBACK_TABLE_DEF
1660 const TT_CMap_ClassRec tt_cmap10_class_rec
=
1663 sizeof ( TT_CMapRec
),
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
1671 (TT_CMap_ValidateFunc
) tt_cmap10_validate
,
1672 (TT_CMap_Info_GetFunc
) tt_cmap10_get_info
1675 #endif /* TT_CONFIG_CMAP_FORMAT_10 */
1678 /*************************************************************************/
1679 /*************************************************************************/
1681 /***** FORMAT 12 *****/
1683 /*************************************************************************/
1684 /*************************************************************************/
1686 /*************************************************************************/
1688 /* TABLE OVERVIEW */
1689 /* -------------- */
1691 /* NAME OFFSET TYPE DESCRIPTION */
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 */
1700 /* This header is followed by `count' groups of the following format: */
1702 /* start 0 ULONG first charcode */
1703 /* end 4 ULONG last charcode */
1704 /* startId 8 ULONG start glyph id for the group */
1707 #ifdef TT_CONFIG_CMAP_FORMAT_12
1709 FT_CALLBACK_DEF( void )
1710 tt_cmap12_validate( FT_Byte
* table
,
1711 FT_Validator valid
)
1715 FT_ULong num_groups
;
1718 if ( table
+ 16 > valid
->limit
)
1719 FT_INVALID_TOO_SHORT
;
1722 length
= TT_NEXT_ULONG( p
);
1725 num_groups
= TT_NEXT_ULONG( p
);
1727 if ( table
+ length
> valid
->limit
|| length
< 16 + 12 * num_groups
)
1728 FT_INVALID_TOO_SHORT
;
1730 /* check groups, they must be in increasing order */
1732 FT_ULong n
, start
, end
, start_id
, last
= 0;
1735 for ( n
= 0; n
< num_groups
; n
++ )
1737 start
= TT_NEXT_ULONG( p
);
1738 end
= TT_NEXT_ULONG( p
);
1739 start_id
= TT_NEXT_ULONG( p
);
1744 if ( n
> 0 && start
<= last
)
1747 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
1749 if ( start_id
+ end
- start
>= TT_VALID_GLYPH_COUNT( valid
) )
1750 FT_INVALID_GLYPH_ID
;
1759 FT_CALLBACK_DEF( FT_UInt
)
1760 tt_cmap12_char_index( TT_CMap cmap
,
1761 FT_UInt32 char_code
)
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
;
1770 for ( ; num_groups
> 0; num_groups
-- )
1772 start
= TT_NEXT_ULONG( p
);
1773 end
= TT_NEXT_ULONG( p
);
1774 start_id
= TT_NEXT_ULONG( p
);
1776 if ( char_code
< start
)
1779 if ( char_code
<= end
)
1781 result
= (FT_UInt
)( start_id
+ char_code
- start
);
1789 FT_CALLBACK_DEF( FT_UInt
)
1790 tt_cmap12_char_next( TT_CMap cmap
,
1791 FT_UInt32
*pchar_code
)
1793 FT_Byte
* table
= cmap
->data
;
1794 FT_UInt32 result
= 0;
1795 FT_UInt32 char_code
= *pchar_code
+ 1;
1797 FT_Byte
* p
= table
+ 12;
1798 FT_UInt32 num_groups
= TT_NEXT_ULONG( p
);
1799 FT_UInt32 start
, end
, start_id
;
1804 for ( ; num_groups
> 0; num_groups
-- )
1806 start
= TT_NEXT_ULONG( p
);
1807 end
= TT_NEXT_ULONG( p
);
1808 start_id
= TT_NEXT_ULONG( p
);
1810 if ( char_code
< start
)
1813 if ( char_code
<= end
)
1815 gindex
= (FT_UInt
)(char_code
- start
+ start_id
);
1825 *pchar_code
= result
;
1830 FT_CALLBACK_DEF( FT_Error
)
1831 tt_cmap12_get_info( TT_CMap cmap
,
1832 TT_CMapInfo
*cmap_info
)
1834 FT_Byte
* p
= cmap
->data
+ 8;
1837 cmap_info
->language
= (FT_ULong
)TT_PEEK_ULONG( p
);
1843 FT_CALLBACK_TABLE_DEF
1844 const TT_CMap_ClassRec tt_cmap12_class_rec
=
1847 sizeof ( TT_CMapRec
),
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
1855 (TT_CMap_ValidateFunc
) tt_cmap12_validate
,
1856 (TT_CMap_Info_GetFunc
) tt_cmap12_get_info
1860 #endif /* TT_CONFIG_CMAP_FORMAT_12 */
1863 static const TT_CMap_Class tt_cmap_classes
[] =
1865 #ifdef TT_CONFIG_CMAP_FORMAT_0
1866 &tt_cmap0_class_rec
,
1869 #ifdef TT_CONFIG_CMAP_FORMAT_2
1870 &tt_cmap2_class_rec
,
1873 #ifdef TT_CONFIG_CMAP_FORMAT_4
1874 &tt_cmap4_class_rec
,
1877 #ifdef TT_CONFIG_CMAP_FORMAT_6
1878 &tt_cmap6_class_rec
,
1881 #ifdef TT_CONFIG_CMAP_FORMAT_8
1882 &tt_cmap8_class_rec
,
1885 #ifdef TT_CONFIG_CMAP_FORMAT_10
1886 &tt_cmap10_class_rec
,
1889 #ifdef TT_CONFIG_CMAP_FORMAT_12
1890 &tt_cmap12_class_rec
,
1897 /* parse the `cmap' table and build the corresponding TT_CMap objects */
1898 /* in the current face */
1900 FT_LOCAL_DEF( FT_Error
)
1901 tt_face_build_cmaps( TT_Face face
)
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
;
1909 if ( p
+ 4 > limit
)
1910 return SFNT_Err_Invalid_Table
;
1912 /* only recognize format 0 */
1913 if ( TT_NEXT_USHORT( p
) != 0 )
1916 FT_ERROR(( "tt_face_build_cmaps: unsupported `cmap' table format = %d\n",
1917 TT_PEEK_USHORT( p
) ));
1918 return SFNT_Err_Invalid_Table
;
1921 num_cmaps
= TT_NEXT_USHORT( p
);
1923 for ( ; num_cmaps
> 0 && p
+ 8 <= limit
; num_cmaps
-- )
1925 FT_CharMapRec charmap
;
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
);
1935 if ( offset
&& table
+ offset
+ 2 < limit
)
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
;
1943 for ( ; *pclazz
; pclazz
++ )
1946 if ( clazz
->format
== format
)
1948 volatile TT_ValidatorRec valid
;
1951 ft_validator_init( FT_VALIDATOR( &valid
), cmap
, limit
,
1952 FT_VALIDATE_DEFAULT
);
1954 valid
.num_glyphs
= (FT_UInt
)face
->root
.num_glyphs
;
1956 if ( ft_setjmp( FT_VALIDATOR( &valid
)->jump_buffer
) == 0 )
1958 /* validate this cmap sub-table */
1959 clazz
->validate( cmap
, FT_VALIDATOR( &valid
) );
1962 if ( valid
.validator
.error
== 0 )
1963 (void)FT_CMap_New( (FT_CMap_Class
)clazz
, cmap
, &charmap
, NULL
);
1966 FT_ERROR(( "tt_face_build_cmaps:" ));
1967 FT_ERROR(( " broken cmap sub-table ignored!\n" ));
1979 FT_LOCAL( FT_Error
)
1980 tt_get_cmap_info( FT_CharMap charmap
,
1981 TT_CMapInfo
*cmap_info
)
1983 FT_CMap cmap
= (FT_CMap
)charmap
;
1984 TT_CMap_Class clazz
= (TT_CMap_Class
)cmap
->clazz
;
1987 return clazz
->get_cmap_info( charmap
, cmap_info
);