1 /***************************************************************************/
5 /* TrueType character mapping table (cmap) support (body). */
7 /* Copyright 2002, 2003, 2004, 2005, 2006, 2007 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
22 #include "sferrors.h" /* must come before FT_INTERNAL_VALIDATE_H */
24 #include FT_INTERNAL_VALIDATE_H
25 #include FT_INTERNAL_STREAM_H
30 /*************************************************************************/
32 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
33 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
34 /* messages during execution. */
37 #define FT_COMPONENT trace_ttcmap
40 #define TT_PEEK_SHORT FT_PEEK_SHORT
41 #define TT_PEEK_USHORT FT_PEEK_USHORT
42 #define TT_PEEK_LONG FT_PEEK_LONG
43 #define TT_PEEK_ULONG FT_PEEK_ULONG
45 #define TT_NEXT_SHORT FT_NEXT_SHORT
46 #define TT_NEXT_USHORT FT_NEXT_USHORT
47 #define TT_NEXT_LONG FT_NEXT_LONG
48 #define TT_NEXT_ULONG FT_NEXT_ULONG
51 FT_CALLBACK_DEF( FT_Error
)
52 tt_cmap_init( TT_CMap cmap
,
60 /*************************************************************************/
61 /*************************************************************************/
63 /***** FORMAT 0 *****/
65 /*************************************************************************/
66 /*************************************************************************/
68 /*************************************************************************/
73 /* NAME OFFSET TYPE DESCRIPTION */
75 /* format 0 USHORT must be 0 */
76 /* length 2 USHORT table length in bytes */
77 /* language 4 USHORT Mac language code */
78 /* glyph_ids 6 BYTE[256] array of glyph indices */
82 #ifdef TT_CONFIG_CMAP_FORMAT_0
84 FT_CALLBACK_DEF( FT_Error
)
85 tt_cmap0_validate( FT_Byte
* table
,
88 FT_Byte
* p
= table
+ 2;
89 FT_UInt length
= TT_NEXT_USHORT( p
);
92 if ( table
+ length
> valid
->limit
|| length
< 262 )
95 /* check glyph indices whenever necessary */
96 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
102 for ( n
= 0; n
< 256; n
++ )
105 if ( idx
>= TT_VALID_GLYPH_COUNT( valid
) )
114 FT_CALLBACK_DEF( FT_UInt
)
115 tt_cmap0_char_index( TT_CMap cmap
,
116 FT_UInt32 char_code
)
118 FT_Byte
* table
= cmap
->data
;
121 return char_code
< 256 ? table
[6 + char_code
] : 0;
125 FT_CALLBACK_DEF( FT_UInt
)
126 tt_cmap0_char_next( TT_CMap cmap
,
127 FT_UInt32
*pchar_code
)
129 FT_Byte
* table
= cmap
->data
;
130 FT_UInt32 charcode
= *pchar_code
;
131 FT_UInt32 result
= 0;
135 table
+= 6; /* go to glyph ids */
136 while ( ++charcode
< 256 )
138 gindex
= table
[charcode
];
146 *pchar_code
= result
;
151 FT_CALLBACK_DEF( FT_Error
)
152 tt_cmap0_get_info( TT_CMap cmap
,
153 TT_CMapInfo
*cmap_info
)
155 FT_Byte
* p
= cmap
->data
+ 4;
158 cmap_info
->format
= 0;
159 cmap_info
->language
= (FT_ULong
)TT_PEEK_USHORT( p
);
165 FT_CALLBACK_TABLE_DEF
166 const TT_CMap_ClassRec tt_cmap0_class_rec
=
169 sizeof ( TT_CMapRec
),
171 (FT_CMap_InitFunc
) tt_cmap_init
,
172 (FT_CMap_DoneFunc
) NULL
,
173 (FT_CMap_CharIndexFunc
)tt_cmap0_char_index
,
174 (FT_CMap_CharNextFunc
) tt_cmap0_char_next
177 (TT_CMap_ValidateFunc
) tt_cmap0_validate
,
178 (TT_CMap_Info_GetFunc
) tt_cmap0_get_info
181 #endif /* TT_CONFIG_CMAP_FORMAT_0 */
184 /*************************************************************************/
185 /*************************************************************************/
187 /***** FORMAT 2 *****/
189 /***** This is used for certain CJK encodings that encode text in a *****/
190 /***** mixed 8/16 bits encoding along the following lines: *****/
192 /***** * Certain byte values correspond to an 8-bit character code *****/
193 /***** (typically in the range 0..127 for ASCII compatibility). *****/
195 /***** * Certain byte values signal the first byte of a 2-byte *****/
196 /***** character code (but these values are also valid as the *****/
197 /***** second byte of a 2-byte character). *****/
199 /***** The following charmap lookup and iteration functions all *****/
200 /***** assume that the value "charcode" correspond to following: *****/
202 /***** - For one byte characters, "charcode" is simply the *****/
203 /***** character code. *****/
205 /***** - For two byte characters, "charcode" is the 2-byte *****/
206 /***** character code in big endian format. More exactly: *****/
208 /***** (charcode >> 8) is the first byte value *****/
209 /***** (charcode & 0xFF) is the second byte value *****/
211 /***** Note that not all values of "charcode" are valid according *****/
212 /***** to these rules, and the function moderately check the *****/
213 /***** arguments. *****/
215 /*************************************************************************/
216 /*************************************************************************/
218 /*************************************************************************/
223 /* NAME OFFSET TYPE DESCRIPTION */
225 /* format 0 USHORT must be 2 */
226 /* length 2 USHORT table length in bytes */
227 /* language 4 USHORT Mac language code */
228 /* keys 6 USHORT[256] sub-header keys */
229 /* subs 518 SUBHEAD[NSUBS] sub-headers array */
230 /* glyph_ids 518+NSUB*8 USHORT[] glyph id array */
232 /* The `keys' table is used to map charcode high-bytes to sub-headers. */
233 /* The value of `NSUBS' is the number of sub-headers defined in the */
234 /* table and is computed by finding the maximum of the `keys' table. */
236 /* Note that for any n, `keys[n]' is a byte offset within the `subs' */
237 /* table, i.e., it is the corresponding sub-header index multiplied */
240 /* Each sub-header has the following format: */
242 /* NAME OFFSET TYPE DESCRIPTION */
244 /* first 0 USHORT first valid low-byte */
245 /* count 2 USHORT number of valid low-bytes */
246 /* delta 4 SHORT see below */
247 /* offset 6 USHORT see below */
249 /* A sub-header defines, for each high-byte, the range of valid */
250 /* low-bytes within the charmap. Note that the range defined by `first' */
251 /* and `count' must be completely included in the interval [0..255] */
252 /* according to the specification. */
254 /* If a character code is contained within a given sub-header, then */
255 /* mapping it to a glyph index is done as follows: */
257 /* * The value of `offset' is read. This is a _byte_ distance from the */
258 /* location of the `offset' field itself into a slice of the */
259 /* `glyph_ids' table. Let's call it `slice' (it's a USHORT[] too). */
261 /* * The value `slice[char.lo - first]' is read. If it is 0, there is */
262 /* no glyph for the charcode. Otherwise, the value of `delta' is */
263 /* added to it (modulo 65536) to form a new glyph index. */
265 /* It is up to the validation routine to check that all offsets fall */
266 /* within the glyph ids table (and not within the `subs' table itself or */
267 /* outside of the CMap). */
270 #ifdef TT_CONFIG_CMAP_FORMAT_2
272 FT_CALLBACK_DEF( FT_Error
)
273 tt_cmap2_validate( FT_Byte
* table
,
276 FT_Byte
* p
= table
+ 2; /* skip format */
277 FT_UInt length
= TT_PEEK_USHORT( p
);
279 FT_Byte
* keys
; /* keys table */
280 FT_Byte
* subs
; /* sub-headers */
281 FT_Byte
* glyph_ids
; /* glyph id array */
284 if ( table
+ length
> valid
->limit
|| length
< 6 + 512 )
285 FT_INVALID_TOO_SHORT
;
289 /* parse keys to compute sub-headers count */
292 for ( n
= 0; n
< 256; n
++ )
294 FT_UInt idx
= TT_NEXT_USHORT( p
);
297 /* value must be multiple of 8 */
298 if ( valid
->level
>= FT_VALIDATE_PARANOID
&& ( idx
& 7 ) != 0 )
303 if ( idx
> max_subs
)
307 FT_ASSERT( p
== table
+ 518 );
310 glyph_ids
= subs
+ (max_subs
+ 1) * 8;
311 if ( glyph_ids
> valid
->limit
)
312 FT_INVALID_TOO_SHORT
;
314 /* parse sub-headers */
315 for ( n
= 0; n
<= max_subs
; n
++ )
317 FT_UInt first_code
, code_count
, offset
;
322 first_code
= TT_NEXT_USHORT( p
);
323 code_count
= TT_NEXT_USHORT( p
);
324 delta
= TT_NEXT_SHORT( p
);
325 offset
= TT_NEXT_USHORT( p
);
327 /* check range within 0..255 */
328 if ( valid
->level
>= FT_VALIDATE_PARANOID
)
330 if ( first_code
>= 256 || first_code
+ code_count
> 256 )
337 ids
= p
- 2 + offset
;
338 if ( ids
< glyph_ids
|| ids
+ code_count
*2 > table
+ length
)
341 /* check glyph ids */
342 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
344 FT_Byte
* limit
= p
+ code_count
* 2;
350 idx
= TT_NEXT_USHORT( p
);
353 idx
= ( idx
+ delta
) & 0xFFFFU
;
354 if ( idx
>= TT_VALID_GLYPH_COUNT( valid
) )
366 /* return sub header corresponding to a given character code */
367 /* NULL on invalid charcode */
369 tt_cmap2_get_subheader( FT_Byte
* table
,
370 FT_UInt32 char_code
)
372 FT_Byte
* result
= NULL
;
375 if ( char_code
< 0x10000UL
)
377 FT_UInt char_lo
= (FT_UInt
)( char_code
& 0xFF );
378 FT_UInt char_hi
= (FT_UInt
)( char_code
>> 8 );
379 FT_Byte
* p
= table
+ 6; /* keys table */
380 FT_Byte
* subs
= table
+ 518; /* subheaders table */
386 /* an 8-bit character code -- we use subHeader 0 in this case */
387 /* to test whether the character code is in the charmap */
389 sub
= subs
; /* jump to first sub-header */
391 /* check that the sub-header for this byte is 0, which */
392 /* indicates that it's really a valid one-byte value */
393 /* Otherwise, return 0 */
396 if ( TT_PEEK_USHORT( p
) != 0 )
401 /* a 16-bit character code */
403 /* jump to key entry */
405 /* jump to sub-header */
406 sub
= subs
+ ( FT_PAD_FLOOR( TT_PEEK_USHORT( p
), 8 ) );
408 /* check that the high byte isn't a valid one-byte value */
419 FT_CALLBACK_DEF( FT_UInt
)
420 tt_cmap2_char_index( TT_CMap cmap
,
421 FT_UInt32 char_code
)
423 FT_Byte
* table
= cmap
->data
;
428 subheader
= tt_cmap2_get_subheader( table
, char_code
);
431 FT_Byte
* p
= subheader
;
432 FT_UInt idx
= (FT_UInt
)(char_code
& 0xFF);
433 FT_UInt start
, count
;
438 start
= TT_NEXT_USHORT( p
);
439 count
= TT_NEXT_USHORT( p
);
440 delta
= TT_NEXT_SHORT ( p
);
441 offset
= TT_PEEK_USHORT( p
);
444 if ( idx
< count
&& offset
!= 0 )
446 p
+= offset
+ 2 * idx
;
447 idx
= TT_PEEK_USHORT( p
);
450 result
= (FT_UInt
)( idx
+ delta
) & 0xFFFFU
;
457 FT_CALLBACK_DEF( FT_UInt
)
458 tt_cmap2_char_next( TT_CMap cmap
,
459 FT_UInt32
*pcharcode
)
461 FT_Byte
* table
= cmap
->data
;
463 FT_UInt32 result
= 0;
464 FT_UInt32 charcode
= *pcharcode
+ 1;
468 while ( charcode
< 0x10000UL
)
470 subheader
= tt_cmap2_get_subheader( table
, charcode
);
473 FT_Byte
* p
= subheader
;
474 FT_UInt start
= TT_NEXT_USHORT( p
);
475 FT_UInt count
= TT_NEXT_USHORT( p
);
476 FT_Int delta
= TT_NEXT_SHORT ( p
);
477 FT_UInt offset
= TT_PEEK_USHORT( p
);
478 FT_UInt char_lo
= (FT_UInt
)( charcode
& 0xFF );
485 if ( char_lo
< start
)
491 pos
= (FT_UInt
)( char_lo
- start
);
493 p
+= offset
+ pos
* 2;
494 charcode
= FT_PAD_FLOOR( charcode
, 256 ) + char_lo
;
496 for ( ; pos
< count
; pos
++, charcode
++ )
498 idx
= TT_NEXT_USHORT( p
);
502 gindex
= ( idx
+ delta
) & 0xFFFFU
;
512 /* jump to next sub-header, i.e. higher byte value */
514 charcode
= FT_PAD_FLOOR( charcode
, 256 ) + 256;
524 FT_CALLBACK_DEF( FT_Error
)
525 tt_cmap2_get_info( TT_CMap cmap
,
526 TT_CMapInfo
*cmap_info
)
528 FT_Byte
* p
= cmap
->data
+ 4;
531 cmap_info
->format
= 2;
532 cmap_info
->language
= (FT_ULong
)TT_PEEK_USHORT( p
);
538 FT_CALLBACK_TABLE_DEF
539 const TT_CMap_ClassRec tt_cmap2_class_rec
=
542 sizeof ( TT_CMapRec
),
544 (FT_CMap_InitFunc
) tt_cmap_init
,
545 (FT_CMap_DoneFunc
) NULL
,
546 (FT_CMap_CharIndexFunc
)tt_cmap2_char_index
,
547 (FT_CMap_CharNextFunc
) tt_cmap2_char_next
550 (TT_CMap_ValidateFunc
) tt_cmap2_validate
,
551 (TT_CMap_Info_GetFunc
) tt_cmap2_get_info
554 #endif /* TT_CONFIG_CMAP_FORMAT_2 */
557 /*************************************************************************/
558 /*************************************************************************/
560 /***** FORMAT 4 *****/
562 /*************************************************************************/
563 /*************************************************************************/
565 /*************************************************************************/
570 /* NAME OFFSET TYPE DESCRIPTION */
572 /* format 0 USHORT must be 4 */
573 /* length 2 USHORT table length */
575 /* language 4 USHORT Mac language code */
577 /* segCountX2 6 USHORT 2*NUM_SEGS */
578 /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */
579 /* entrySelector 10 USHORT LOG_SEGS */
580 /* rangeShift 12 USHORT segCountX2 - */
583 /* endCount 14 USHORT[NUM_SEGS] end charcode for */
584 /* each segment; last */
587 /* pad 14+NUM_SEGS*2 USHORT padding */
589 /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */
592 /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */
594 /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */
595 /* each segment; can be */
598 /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph id */
601 /* Character codes are modelled by a series of ordered (increasing) */
602 /* intervals called segments. Each segment has start and end codes, */
603 /* provided by the `startCount' and `endCount' arrays. Segments must */
604 /* not be overlapping and the last segment should always contain the */
605 /* `0xFFFF' endCount. */
607 /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
608 /* ignored (they are traces of over-engineering in the TrueType */
609 /* specification). */
611 /* Each segment also has a signed `delta', as well as an optional offset */
612 /* within the `glyphIds' table. */
614 /* If a segment's idOffset is 0, the glyph index corresponding to any */
615 /* charcode within the segment is obtained by adding the value of */
616 /* `idDelta' directly to the charcode, modulo 65536. */
618 /* Otherwise, a glyph index is taken from the glyph ids sub-array for */
619 /* the segment, and the value of `idDelta' is added to it. */
622 /* Finally, note that certain fonts contain invalid charmaps that */
623 /* contain end=0xFFFF, start=0xFFFF, delta=0x0001, offset=0xFFFF at the */
624 /* of their charmaps (e.g. opens___.ttf which comes with OpenOffice.org) */
625 /* we need special code to deal with them correctly... */
628 #ifdef TT_CONFIG_CMAP_FORMAT_4
630 typedef struct TT_CMap4Rec_
633 FT_UInt32 cur_charcode
; /* current charcode */
634 FT_UInt cur_gindex
; /* current glyph index */
643 } TT_CMap4Rec
, *TT_CMap4
;
646 FT_CALLBACK_DEF( FT_Error
)
647 tt_cmap4_init( TT_CMap4 cmap
,
653 cmap
->cmap
.data
= table
;
656 cmap
->num_ranges
= FT_PEEK_USHORT( p
) >> 1;
657 cmap
->cur_charcode
= 0xFFFFFFFFUL
;
658 cmap
->cur_gindex
= 0;
665 tt_cmap4_set_range( TT_CMap4 cmap
,
666 FT_UInt range_index
)
668 FT_Byte
* table
= cmap
->cmap
.data
;
670 FT_UInt num_ranges
= cmap
->num_ranges
;
673 while ( range_index
< num_ranges
)
678 p
= table
+ 14 + range_index
* 2;
679 cmap
->cur_end
= FT_PEEK_USHORT( p
);
681 p
+= 2 + num_ranges
* 2;
682 cmap
->cur_start
= FT_PEEK_USHORT( p
);
685 cmap
->cur_delta
= FT_PEEK_SHORT( p
);
688 offset
= FT_PEEK_USHORT( p
);
690 if ( offset
!= 0xFFFFU
)
692 cmap
->cur_values
= offset
? p
+ offset
: NULL
;
693 cmap
->cur_range
= range_index
;
697 /* we skip empty segments */
705 /* search the index of the charcode next to cmap->cur_charcode; */
706 /* caller should call tt_cmap4_set_range with proper range */
707 /* before calling this function */
710 tt_cmap4_next( TT_CMap4 cmap
)
715 if ( cmap
->cur_charcode
>= 0xFFFFUL
)
718 charcode
= cmap
->cur_charcode
+ 1;
720 if ( charcode
< cmap
->cur_start
)
721 charcode
= cmap
->cur_start
;
725 FT_Byte
* values
= cmap
->cur_values
;
726 FT_UInt end
= cmap
->cur_end
;
727 FT_Int delta
= cmap
->cur_delta
;
730 if ( charcode
<= end
)
734 FT_Byte
* p
= values
+ 2 * ( charcode
- cmap
->cur_start
);
739 FT_UInt gindex
= FT_NEXT_USHORT( p
);
744 gindex
= (FT_UInt
)( ( gindex
+ delta
) & 0xFFFFU
);
747 cmap
->cur_charcode
= charcode
;
748 cmap
->cur_gindex
= gindex
;
752 } while ( ++charcode
<= end
);
758 FT_UInt gindex
= (FT_UInt
)( ( charcode
+ delta
) & 0xFFFFU
);
763 cmap
->cur_charcode
= charcode
;
764 cmap
->cur_gindex
= gindex
;
767 } while ( ++charcode
<= end
);
771 /* we need to find another range */
772 if ( tt_cmap4_set_range( cmap
, cmap
->cur_range
+ 1 ) < 0 )
775 if ( charcode
< cmap
->cur_start
)
776 charcode
= cmap
->cur_start
;
780 cmap
->cur_charcode
= 0xFFFFFFFFUL
;
781 cmap
->cur_gindex
= 0;
785 FT_CALLBACK_DEF( FT_Error
)
786 tt_cmap4_validate( FT_Byte
* table
,
789 FT_Byte
* p
= table
+ 2; /* skip format */
790 FT_UInt length
= TT_NEXT_USHORT( p
);
791 FT_Byte
*ends
, *starts
, *offsets
, *deltas
, *glyph_ids
;
793 FT_Error error
= SFNT_Err_Ok
;
797 FT_INVALID_TOO_SHORT
;
799 /* in certain fonts, the `length' field is invalid and goes */
800 /* out of bound. We try to correct this here... */
801 if ( table
+ length
> valid
->limit
)
803 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
804 FT_INVALID_TOO_SHORT
;
806 length
= (FT_UInt
)( valid
->limit
- table
);
810 num_segs
= TT_NEXT_USHORT( p
); /* read segCountX2 */
812 if ( valid
->level
>= FT_VALIDATE_PARANOID
)
814 /* check that we have an even value here */
821 if ( length
< 16 + num_segs
* 2 * 4 )
822 FT_INVALID_TOO_SHORT
;
824 /* check the search parameters - even though we never use them */
826 if ( valid
->level
>= FT_VALIDATE_PARANOID
)
828 /* check the values of 'searchRange', 'entrySelector', 'rangeShift' */
829 FT_UInt search_range
= TT_NEXT_USHORT( p
);
830 FT_UInt entry_selector
= TT_NEXT_USHORT( p
);
831 FT_UInt range_shift
= TT_NEXT_USHORT( p
);
834 if ( ( search_range
| range_shift
) & 1 ) /* must be even values */
840 /* `search range' is the greatest power of 2 that is <= num_segs */
842 if ( search_range
> num_segs
||
843 search_range
* 2 < num_segs
||
844 search_range
+ range_shift
!= num_segs
||
845 search_range
!= ( 1U << entry_selector
) )
850 starts
= table
+ 16 + num_segs
* 2;
851 deltas
= starts
+ num_segs
* 2;
852 offsets
= deltas
+ num_segs
* 2;
853 glyph_ids
= offsets
+ num_segs
* 2;
855 /* check last segment, its end count must be FFFF */
856 if ( valid
->level
>= FT_VALIDATE_PARANOID
)
858 p
= ends
+ ( num_segs
- 1 ) * 2;
859 if ( TT_PEEK_USHORT( p
) != 0xFFFFU
)
864 FT_UInt start
, end
, offset
, n
;
865 FT_UInt last_start
= 0, last_end
= 0;
867 FT_Byte
* p_start
= starts
;
868 FT_Byte
* p_end
= ends
;
869 FT_Byte
* p_delta
= deltas
;
870 FT_Byte
* p_offset
= offsets
;
873 for ( n
= 0; n
< num_segs
; n
++ )
876 start
= TT_NEXT_USHORT( p_start
);
877 end
= TT_NEXT_USHORT( p_end
);
878 delta
= TT_NEXT_SHORT( p_delta
);
879 offset
= TT_NEXT_USHORT( p_offset
);
884 /* this test should be performed at default validation level; */
885 /* unfortunately, some popular Asian fonts present overlapping */
886 /* ranges in their charmaps */
888 if ( start
<= last_end
&& n
> 0 )
890 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
894 /* allow overlapping segments, provided their start points */
895 /* and end points, respectively, are in ascending order. */
897 if ( last_start
> start
|| last_end
> end
)
898 error
|= TT_CMAP_FLAG_UNSORTED
;
900 error
|= TT_CMAP_FLAG_OVERLAPPING
;
904 if ( offset
&& offset
!= 0xFFFFU
)
906 p
+= offset
; /* start of glyph id array */
908 /* check that we point within the glyph ids table only */
909 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
911 if ( p
< glyph_ids
||
912 p
+ ( end
- start
+ 1 ) * 2 > table
+ length
)
917 if ( p
< glyph_ids
||
918 p
+ ( end
- start
+ 1 ) * 2 > valid
->limit
)
922 /* check glyph indices within the segment range */
923 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
928 for ( i
= start
; i
< end
; i
++ )
930 idx
= FT_NEXT_USHORT( p
);
933 idx
= (FT_UInt
)( idx
+ delta
) & 0xFFFFU
;
935 if ( idx
>= TT_VALID_GLYPH_COUNT( valid
) )
941 else if ( offset
== 0xFFFFU
)
943 /* Some fonts (erroneously?) use a range offset of 0xFFFF */
944 /* to mean missing glyph in cmap table */
946 if ( valid
->level
>= FT_VALIDATE_PARANOID
||
948 !( start
== 0xFFFFU
&& end
== 0xFFFFU
&& delta
== 0x1U
) )
962 tt_cmap4_char_map_linear( TT_CMap cmap
,
966 FT_UInt num_segs2
, start
, end
, offset
;
969 FT_UInt32 charcode
= *pcharcode
;
975 num_segs2
= FT_PAD_FLOOR( TT_PEEK_USHORT( p
), 2 );
977 num_segs
= num_segs2
>> 1;
986 for ( ; charcode
<= 0xFFFFU
; charcode
++ )
991 p
= cmap
->data
+ 14; /* ends table */
992 q
= cmap
->data
+ 16 + num_segs2
; /* starts table */
994 for ( i
= 0; i
< num_segs
; i
++ )
996 end
= TT_NEXT_USHORT( p
);
997 start
= TT_NEXT_USHORT( q
);
999 if ( charcode
>= start
&& charcode
<= end
)
1001 p
= q
- 2 + num_segs2
;
1002 delta
= TT_PEEK_SHORT( p
);
1004 offset
= TT_PEEK_USHORT( p
);
1006 if ( offset
== 0xFFFFU
)
1011 p
+= offset
+ ( charcode
- start
) * 2;
1012 gindex
= TT_PEEK_USHORT( p
);
1014 gindex
= (FT_UInt
)( gindex
+ delta
) & 0xFFFFU
;
1017 gindex
= (FT_UInt
)( charcode
+ delta
) & 0xFFFFU
;
1023 if ( !next
|| gindex
)
1027 if ( next
&& gindex
)
1028 *pcharcode
= charcode
;
1035 tt_cmap4_char_map_binary( TT_CMap cmap
,
1039 FT_UInt num_segs2
, start
, end
, offset
;
1041 FT_UInt max
, min
, mid
, num_segs
;
1042 FT_UInt charcode
= *pcharcode
;
1048 num_segs2
= FT_PAD_FLOOR( TT_PEEK_USHORT( p
), 2 );
1053 num_segs
= num_segs2
>> 1;
1055 /* make compiler happy */
1068 mid
= ( min
+ max
) >> 1;
1069 p
= cmap
->data
+ 14 + mid
* 2;
1070 end
= TT_PEEK_USHORT( p
);
1072 start
= TT_PEEK_USHORT( p
);
1074 if ( charcode
< start
)
1076 else if ( charcode
> end
)
1081 delta
= TT_PEEK_SHORT( p
);
1083 offset
= TT_PEEK_USHORT( p
);
1085 /* search the first segment containing `charcode' */
1086 if ( cmap
->flags
& TT_CMAP_FLAG_OVERLAPPING
)
1091 /* call the current segment `max' */
1094 if ( offset
== 0xFFFFU
)
1097 /* search in segments before the current segment */
1098 for ( i
= max
; i
> 0; i
-- )
1105 p
= cmap
->data
+ 14 + ( i
- 1 ) * 2;
1106 prev_end
= TT_PEEK_USHORT( p
);
1108 if ( charcode
> prev_end
)
1116 start
= TT_PEEK_USHORT( p
);
1118 delta
= TT_PEEK_SHORT( p
);
1120 offset
= TT_PEEK_USHORT( p
);
1122 if ( offset
!= 0xFFFFU
)
1127 if ( mid
== max
+ 1 )
1131 p
= cmap
->data
+ 14 + max
* 2;
1132 end
= TT_PEEK_USHORT( p
);
1134 start
= TT_PEEK_USHORT( p
);
1136 delta
= TT_PEEK_SHORT( p
);
1138 offset
= TT_PEEK_USHORT( p
);
1143 /* search in segments after the current segment */
1144 for ( i
= max
+ 1; i
< num_segs
; i
++ )
1146 FT_UInt next_end
, next_start
;
1149 p
= cmap
->data
+ 14 + i
* 2;
1150 next_end
= TT_PEEK_USHORT( p
);
1152 next_start
= TT_PEEK_USHORT( p
);
1154 if ( charcode
< next_start
)
1160 delta
= TT_PEEK_SHORT( p
);
1162 offset
= TT_PEEK_USHORT( p
);
1164 if ( offset
!= 0xFFFFU
)
1178 /* end, start, delta, and offset are for the i'th segment */
1181 p
= cmap
->data
+ 14 + mid
* 2;
1182 end
= TT_PEEK_USHORT( p
);
1184 start
= TT_PEEK_USHORT( p
);
1186 delta
= TT_PEEK_SHORT( p
);
1188 offset
= TT_PEEK_USHORT( p
);
1193 if ( offset
== 0xFFFFU
)
1199 p
+= offset
+ ( charcode
- start
) * 2;
1200 gindex
= TT_PEEK_USHORT( p
);
1202 gindex
= (FT_UInt
)( gindex
+ delta
) & 0xFFFFU
;
1205 gindex
= (FT_UInt
)( charcode
+ delta
) & 0xFFFFU
;
1213 TT_CMap4 cmap4
= (TT_CMap4
)cmap
;
1216 /* if `charcode' is not in any segment, then `mid' is */
1217 /* the segment nearest to `charcode' */
1220 if ( charcode
> end
)
1223 if ( mid
== num_segs
)
1227 if ( tt_cmap4_set_range( cmap4
, mid
) )
1230 *pcharcode
= charcode
;
1234 cmap4
->cur_charcode
= charcode
;
1237 cmap4
->cur_gindex
= gindex
;
1240 cmap4
->cur_charcode
= charcode
;
1241 tt_cmap4_next( cmap4
);
1242 gindex
= cmap4
->cur_gindex
;
1246 *pcharcode
= cmap4
->cur_charcode
;
1254 FT_CALLBACK_DEF( FT_UInt
)
1255 tt_cmap4_char_index( TT_CMap cmap
,
1256 FT_UInt32 char_code
)
1258 if ( char_code
>= 0x10000UL
)
1261 if ( cmap
->flags
& TT_CMAP_FLAG_UNSORTED
)
1262 return tt_cmap4_char_map_linear( cmap
, &char_code
, 0 );
1264 return tt_cmap4_char_map_binary( cmap
, &char_code
, 0 );
1268 FT_CALLBACK_DEF( FT_UInt
)
1269 tt_cmap4_char_next( TT_CMap cmap
,
1270 FT_UInt32
*pchar_code
)
1275 if ( *pchar_code
>= 0xFFFFU
)
1278 if ( cmap
->flags
& TT_CMAP_FLAG_UNSORTED
)
1279 gindex
= tt_cmap4_char_map_linear( cmap
, pchar_code
, 1 );
1282 TT_CMap4 cmap4
= (TT_CMap4
)cmap
;
1285 /* no need to search */
1286 if ( *pchar_code
== cmap4
->cur_charcode
)
1288 tt_cmap4_next( cmap4
);
1289 gindex
= cmap4
->cur_gindex
;
1291 *pchar_code
= cmap4
->cur_charcode
;
1294 gindex
= tt_cmap4_char_map_binary( cmap
, pchar_code
, 1 );
1301 FT_CALLBACK_DEF( FT_Error
)
1302 tt_cmap4_get_info( TT_CMap cmap
,
1303 TT_CMapInfo
*cmap_info
)
1305 FT_Byte
* p
= cmap
->data
+ 4;
1308 cmap_info
->format
= 4;
1309 cmap_info
->language
= (FT_ULong
)TT_PEEK_USHORT( p
);
1315 FT_CALLBACK_TABLE_DEF
1316 const TT_CMap_ClassRec tt_cmap4_class_rec
=
1319 sizeof ( TT_CMap4Rec
),
1320 (FT_CMap_InitFunc
) tt_cmap4_init
,
1321 (FT_CMap_DoneFunc
) NULL
,
1322 (FT_CMap_CharIndexFunc
)tt_cmap4_char_index
,
1323 (FT_CMap_CharNextFunc
) tt_cmap4_char_next
1326 (TT_CMap_ValidateFunc
) tt_cmap4_validate
,
1327 (TT_CMap_Info_GetFunc
) tt_cmap4_get_info
1330 #endif /* TT_CONFIG_CMAP_FORMAT_4 */
1333 /*************************************************************************/
1334 /*************************************************************************/
1336 /***** FORMAT 6 *****/
1338 /*************************************************************************/
1339 /*************************************************************************/
1341 /*************************************************************************/
1343 /* TABLE OVERVIEW */
1344 /* -------------- */
1346 /* NAME OFFSET TYPE DESCRIPTION */
1348 /* format 0 USHORT must be 4 */
1349 /* length 2 USHORT table length in bytes */
1350 /* language 4 USHORT Mac language code */
1352 /* first 6 USHORT first segment code */
1353 /* count 8 USHORT segment size in chars */
1354 /* glyphIds 10 USHORT[count] glyph ids */
1356 /* A very simplified segment mapping. */
1359 #ifdef TT_CONFIG_CMAP_FORMAT_6
1361 FT_CALLBACK_DEF( FT_Error
)
1362 tt_cmap6_validate( FT_Byte
* table
,
1363 FT_Validator valid
)
1366 FT_UInt length
, count
;
1369 if ( table
+ 10 > valid
->limit
)
1370 FT_INVALID_TOO_SHORT
;
1373 length
= TT_NEXT_USHORT( p
);
1375 p
= table
+ 8; /* skip language and start index */
1376 count
= TT_NEXT_USHORT( p
);
1378 if ( table
+ length
> valid
->limit
|| length
< 10 + count
* 2 )
1379 FT_INVALID_TOO_SHORT
;
1381 /* check glyph indices */
1382 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
1387 for ( ; count
> 0; count
-- )
1389 gindex
= TT_NEXT_USHORT( p
);
1390 if ( gindex
>= TT_VALID_GLYPH_COUNT( valid
) )
1391 FT_INVALID_GLYPH_ID
;
1399 FT_CALLBACK_DEF( FT_UInt
)
1400 tt_cmap6_char_index( TT_CMap cmap
,
1401 FT_UInt32 char_code
)
1403 FT_Byte
* table
= cmap
->data
;
1405 FT_Byte
* p
= table
+ 6;
1406 FT_UInt start
= TT_NEXT_USHORT( p
);
1407 FT_UInt count
= TT_NEXT_USHORT( p
);
1408 FT_UInt idx
= (FT_UInt
)( char_code
- start
);
1414 result
= TT_PEEK_USHORT( p
);
1420 FT_CALLBACK_DEF( FT_UInt
)
1421 tt_cmap6_char_next( TT_CMap cmap
,
1422 FT_UInt32
*pchar_code
)
1424 FT_Byte
* table
= cmap
->data
;
1425 FT_UInt32 result
= 0;
1426 FT_UInt32 char_code
= *pchar_code
+ 1;
1429 FT_Byte
* p
= table
+ 6;
1430 FT_UInt start
= TT_NEXT_USHORT( p
);
1431 FT_UInt count
= TT_NEXT_USHORT( p
);
1435 if ( char_code
>= 0x10000UL
)
1438 if ( char_code
< start
)
1441 idx
= (FT_UInt
)( char_code
- start
);
1444 for ( ; idx
< count
; idx
++ )
1446 gindex
= TT_NEXT_USHORT( p
);
1456 *pchar_code
= result
;
1461 FT_CALLBACK_DEF( FT_Error
)
1462 tt_cmap6_get_info( TT_CMap cmap
,
1463 TT_CMapInfo
*cmap_info
)
1465 FT_Byte
* p
= cmap
->data
+ 4;
1468 cmap_info
->format
= 6;
1469 cmap_info
->language
= (FT_ULong
)TT_PEEK_USHORT( p
);
1475 FT_CALLBACK_TABLE_DEF
1476 const TT_CMap_ClassRec tt_cmap6_class_rec
=
1479 sizeof ( TT_CMapRec
),
1481 (FT_CMap_InitFunc
) tt_cmap_init
,
1482 (FT_CMap_DoneFunc
) NULL
,
1483 (FT_CMap_CharIndexFunc
)tt_cmap6_char_index
,
1484 (FT_CMap_CharNextFunc
) tt_cmap6_char_next
1487 (TT_CMap_ValidateFunc
) tt_cmap6_validate
,
1488 (TT_CMap_Info_GetFunc
) tt_cmap6_get_info
1491 #endif /* TT_CONFIG_CMAP_FORMAT_6 */
1494 /*************************************************************************/
1495 /*************************************************************************/
1497 /***** FORMAT 8 *****/
1499 /***** It's hard to completely understand what the OpenType spec *****/
1500 /***** says about this format, but here is my conclusion. *****/
1502 /***** The purpose of this format is to easily map UTF-16 text to *****/
1503 /***** glyph indices. Basically, the `char_code' must be in one of *****/
1504 /***** the following formats: *****/
1506 /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/
1507 /***** Area (i.e. U+D800-U+DFFF). *****/
1509 /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/
1510 /***** `char_code = (char_hi << 16) | char_lo', then both *****/
1511 /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/
1514 /***** The 'is32' table embedded in the charmap indicates whether a *****/
1515 /***** given 16-bit value is in the surrogates area or not. *****/
1517 /***** So, for any given `char_code', we can assert the following: *****/
1519 /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/
1521 /***** If `char_hi != 0' then we must have both *****/
1522 /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/
1524 /*************************************************************************/
1525 /*************************************************************************/
1527 /*************************************************************************/
1529 /* TABLE OVERVIEW */
1530 /* -------------- */
1532 /* NAME OFFSET TYPE DESCRIPTION */
1534 /* format 0 USHORT must be 8 */
1535 /* reserved 2 USHORT reserved */
1536 /* length 4 ULONG length in bytes */
1537 /* language 8 ULONG Mac language code */
1538 /* is32 12 BYTE[8192] 32-bitness bitmap */
1539 /* count 8204 ULONG number of groups */
1541 /* This header is followed by 'count' groups of the following format: */
1543 /* start 0 ULONG first charcode */
1544 /* end 4 ULONG last charcode */
1545 /* startId 8 ULONG start glyph id for the group */
1548 #ifdef TT_CONFIG_CMAP_FORMAT_8
1550 FT_CALLBACK_DEF( FT_Error
)
1551 tt_cmap8_validate( FT_Byte
* table
,
1552 FT_Validator valid
)
1554 FT_Byte
* p
= table
+ 4;
1557 FT_UInt32 num_groups
;
1560 if ( table
+ 16 + 8192 > valid
->limit
)
1561 FT_INVALID_TOO_SHORT
;
1563 length
= TT_NEXT_ULONG( p
);
1564 if ( table
+ length
> valid
->limit
|| length
< 8208 )
1565 FT_INVALID_TOO_SHORT
;
1568 p
= is32
+ 8192; /* skip `is32' array */
1569 num_groups
= TT_NEXT_ULONG( p
);
1571 if ( p
+ num_groups
* 12 > valid
->limit
)
1572 FT_INVALID_TOO_SHORT
;
1574 /* check groups, they must be in increasing order */
1576 FT_UInt32 n
, start
, end
, start_id
, count
, last
= 0;
1579 for ( n
= 0; n
< num_groups
; n
++ )
1584 start
= TT_NEXT_ULONG( p
);
1585 end
= TT_NEXT_ULONG( p
);
1586 start_id
= TT_NEXT_ULONG( p
);
1591 if ( n
> 0 && start
<= last
)
1594 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
1596 if ( start_id
+ end
- start
>= TT_VALID_GLYPH_COUNT( valid
) )
1597 FT_INVALID_GLYPH_ID
;
1599 count
= (FT_UInt32
)( end
- start
+ 1 );
1601 if ( start
& ~0xFFFFU
)
1603 /* start_hi != 0; check that is32[i] is 1 for each i in */
1604 /* the `hi' and `lo' of the range [start..end] */
1605 for ( ; count
> 0; count
--, start
++ )
1607 hi
= (FT_UInt
)( start
>> 16 );
1608 lo
= (FT_UInt
)( start
& 0xFFFFU
);
1610 if ( (is32
[hi
>> 3] & ( 0x80 >> ( hi
& 7 ) ) ) == 0 )
1613 if ( (is32
[lo
>> 3] & ( 0x80 >> ( lo
& 7 ) ) ) == 0 )
1619 /* start_hi == 0; check that is32[i] is 0 for each i in */
1620 /* the range [start..end] */
1622 /* end_hi cannot be != 0! */
1623 if ( end
& ~0xFFFFU
)
1626 for ( ; count
> 0; count
--, start
++ )
1628 lo
= (FT_UInt
)( start
& 0xFFFFU
);
1630 if ( (is32
[lo
>> 3] & ( 0x80 >> ( lo
& 7 ) ) ) != 0 )
1644 FT_CALLBACK_DEF( FT_UInt
)
1645 tt_cmap8_char_index( TT_CMap cmap
,
1646 FT_UInt32 char_code
)
1648 FT_Byte
* table
= cmap
->data
;
1650 FT_Byte
* p
= table
+ 8204;
1651 FT_UInt32 num_groups
= TT_NEXT_ULONG( p
);
1652 FT_UInt32 start
, end
, start_id
;
1655 for ( ; num_groups
> 0; num_groups
-- )
1657 start
= TT_NEXT_ULONG( p
);
1658 end
= TT_NEXT_ULONG( p
);
1659 start_id
= TT_NEXT_ULONG( p
);
1661 if ( char_code
< start
)
1664 if ( char_code
<= end
)
1666 result
= (FT_UInt
)( start_id
+ char_code
- start
);
1674 FT_CALLBACK_DEF( FT_UInt
)
1675 tt_cmap8_char_next( TT_CMap cmap
,
1676 FT_UInt32
*pchar_code
)
1678 FT_UInt32 result
= 0;
1679 FT_UInt32 char_code
= *pchar_code
+ 1;
1681 FT_Byte
* table
= cmap
->data
;
1682 FT_Byte
* p
= table
+ 8204;
1683 FT_UInt32 num_groups
= TT_NEXT_ULONG( p
);
1684 FT_UInt32 start
, end
, start_id
;
1689 for ( ; num_groups
> 0; num_groups
-- )
1691 start
= TT_NEXT_ULONG( p
);
1692 end
= TT_NEXT_ULONG( p
);
1693 start_id
= TT_NEXT_ULONG( p
);
1695 if ( char_code
< start
)
1698 if ( char_code
<= end
)
1700 gindex
= (FT_UInt
)( char_code
- start
+ start_id
);
1710 *pchar_code
= result
;
1715 FT_CALLBACK_DEF( FT_Error
)
1716 tt_cmap8_get_info( TT_CMap cmap
,
1717 TT_CMapInfo
*cmap_info
)
1719 FT_Byte
* p
= cmap
->data
+ 8;
1722 cmap_info
->format
= 8;
1723 cmap_info
->language
= (FT_ULong
)TT_PEEK_ULONG( p
);
1729 FT_CALLBACK_TABLE_DEF
1730 const TT_CMap_ClassRec tt_cmap8_class_rec
=
1733 sizeof ( TT_CMapRec
),
1735 (FT_CMap_InitFunc
) tt_cmap_init
,
1736 (FT_CMap_DoneFunc
) NULL
,
1737 (FT_CMap_CharIndexFunc
)tt_cmap8_char_index
,
1738 (FT_CMap_CharNextFunc
) tt_cmap8_char_next
1741 (TT_CMap_ValidateFunc
) tt_cmap8_validate
,
1742 (TT_CMap_Info_GetFunc
) tt_cmap8_get_info
1745 #endif /* TT_CONFIG_CMAP_FORMAT_8 */
1748 /*************************************************************************/
1749 /*************************************************************************/
1751 /***** FORMAT 10 *****/
1753 /*************************************************************************/
1754 /*************************************************************************/
1756 /*************************************************************************/
1758 /* TABLE OVERVIEW */
1759 /* -------------- */
1761 /* NAME OFFSET TYPE DESCRIPTION */
1763 /* format 0 USHORT must be 10 */
1764 /* reserved 2 USHORT reserved */
1765 /* length 4 ULONG length in bytes */
1766 /* language 8 ULONG Mac language code */
1768 /* start 12 ULONG first char in range */
1769 /* count 16 ULONG number of chars in range */
1770 /* glyphIds 20 USHORT[count] glyph indices covered */
1773 #ifdef TT_CONFIG_CMAP_FORMAT_10
1775 FT_CALLBACK_DEF( FT_Error
)
1776 tt_cmap10_validate( FT_Byte
* table
,
1777 FT_Validator valid
)
1779 FT_Byte
* p
= table
+ 4;
1780 FT_ULong length
, count
;
1783 if ( table
+ 20 > valid
->limit
)
1784 FT_INVALID_TOO_SHORT
;
1786 length
= TT_NEXT_ULONG( p
);
1788 count
= TT_NEXT_ULONG( p
);
1790 if ( table
+ length
> valid
->limit
|| length
< 20 + count
* 2 )
1791 FT_INVALID_TOO_SHORT
;
1793 /* check glyph indices */
1794 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
1799 for ( ; count
> 0; count
-- )
1801 gindex
= TT_NEXT_USHORT( p
);
1802 if ( gindex
>= TT_VALID_GLYPH_COUNT( valid
) )
1803 FT_INVALID_GLYPH_ID
;
1811 FT_CALLBACK_DEF( FT_UInt
)
1812 tt_cmap10_char_index( TT_CMap cmap
,
1813 FT_UInt32 char_code
)
1815 FT_Byte
* table
= cmap
->data
;
1817 FT_Byte
* p
= table
+ 12;
1818 FT_UInt32 start
= TT_NEXT_ULONG( p
);
1819 FT_UInt32 count
= TT_NEXT_ULONG( p
);
1820 FT_UInt32 idx
= (FT_ULong
)( char_code
- start
);
1826 result
= TT_PEEK_USHORT( p
);
1832 FT_CALLBACK_DEF( FT_UInt
)
1833 tt_cmap10_char_next( TT_CMap cmap
,
1834 FT_UInt32
*pchar_code
)
1836 FT_Byte
* table
= cmap
->data
;
1837 FT_UInt32 char_code
= *pchar_code
+ 1;
1839 FT_Byte
* p
= table
+ 12;
1840 FT_UInt32 start
= TT_NEXT_ULONG( p
);
1841 FT_UInt32 count
= TT_NEXT_ULONG( p
);
1845 if ( char_code
< start
)
1848 idx
= (FT_UInt32
)( char_code
- start
);
1851 for ( ; idx
< count
; idx
++ )
1853 gindex
= TT_NEXT_USHORT( p
);
1859 *pchar_code
= char_code
;
1864 FT_CALLBACK_DEF( FT_Error
)
1865 tt_cmap10_get_info( TT_CMap cmap
,
1866 TT_CMapInfo
*cmap_info
)
1868 FT_Byte
* p
= cmap
->data
+ 8;
1871 cmap_info
->format
= 10;
1872 cmap_info
->language
= (FT_ULong
)TT_PEEK_ULONG( p
);
1878 FT_CALLBACK_TABLE_DEF
1879 const TT_CMap_ClassRec tt_cmap10_class_rec
=
1882 sizeof ( TT_CMapRec
),
1884 (FT_CMap_InitFunc
) tt_cmap_init
,
1885 (FT_CMap_DoneFunc
) NULL
,
1886 (FT_CMap_CharIndexFunc
)tt_cmap10_char_index
,
1887 (FT_CMap_CharNextFunc
) tt_cmap10_char_next
1890 (TT_CMap_ValidateFunc
) tt_cmap10_validate
,
1891 (TT_CMap_Info_GetFunc
) tt_cmap10_get_info
1894 #endif /* TT_CONFIG_CMAP_FORMAT_10 */
1897 /*************************************************************************/
1898 /*************************************************************************/
1900 /***** FORMAT 12 *****/
1902 /*************************************************************************/
1903 /*************************************************************************/
1905 /*************************************************************************/
1907 /* TABLE OVERVIEW */
1908 /* -------------- */
1910 /* NAME OFFSET TYPE DESCRIPTION */
1912 /* format 0 USHORT must be 12 */
1913 /* reserved 2 USHORT reserved */
1914 /* length 4 ULONG length in bytes */
1915 /* language 8 ULONG Mac language code */
1916 /* count 12 ULONG number of groups */
1919 /* This header is followed by `count' groups of the following format: */
1921 /* start 0 ULONG first charcode */
1922 /* end 4 ULONG last charcode */
1923 /* startId 8 ULONG start glyph id for the group */
1926 #ifdef TT_CONFIG_CMAP_FORMAT_12
1928 typedef struct TT_CMap12Rec_
1932 FT_ULong cur_charcode
;
1935 FT_ULong num_groups
;
1937 } TT_CMap12Rec
, *TT_CMap12
;
1940 FT_CALLBACK_DEF( FT_Error
)
1941 tt_cmap12_init( TT_CMap12 cmap
,
1944 cmap
->cmap
.data
= table
;
1947 cmap
->num_groups
= FT_PEEK_ULONG( table
);
1955 FT_CALLBACK_DEF( FT_Error
)
1956 tt_cmap12_validate( FT_Byte
* table
,
1957 FT_Validator valid
)
1961 FT_ULong num_groups
;
1964 if ( table
+ 16 > valid
->limit
)
1965 FT_INVALID_TOO_SHORT
;
1968 length
= TT_NEXT_ULONG( p
);
1971 num_groups
= TT_NEXT_ULONG( p
);
1973 if ( table
+ length
> valid
->limit
|| length
< 16 + 12 * num_groups
)
1974 FT_INVALID_TOO_SHORT
;
1976 /* check groups, they must be in increasing order */
1978 FT_ULong n
, start
, end
, start_id
, last
= 0;
1981 for ( n
= 0; n
< num_groups
; n
++ )
1983 start
= TT_NEXT_ULONG( p
);
1984 end
= TT_NEXT_ULONG( p
);
1985 start_id
= TT_NEXT_ULONG( p
);
1990 if ( n
> 0 && start
<= last
)
1993 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
1995 if ( start_id
+ end
- start
>= TT_VALID_GLYPH_COUNT( valid
) )
1996 FT_INVALID_GLYPH_ID
;
2007 /* search the index of the charcode next to cmap->cur_charcode */
2008 /* cmap->cur_group should be set up properly by caller */
2011 tt_cmap12_next( TT_CMap12 cmap
)
2014 FT_ULong start
, end
, start_id
, char_code
;
2019 if ( cmap
->cur_charcode
>= 0xFFFFFFFFUL
)
2022 char_code
= cmap
->cur_charcode
+ 1;
2024 n
= cmap
->cur_group
;
2026 for ( n
= cmap
->cur_group
; n
< cmap
->num_groups
; n
++ )
2028 p
= cmap
->cmap
.data
+ 16 + 12 * n
;
2029 start
= TT_NEXT_ULONG( p
);
2030 end
= TT_NEXT_ULONG( p
);
2031 start_id
= TT_PEEK_ULONG( p
);
2033 if ( char_code
< start
)
2036 for ( ; char_code
<= end
; char_code
++ )
2038 gindex
= (FT_UInt
)( start_id
+ char_code
- start
);
2042 cmap
->cur_charcode
= char_code
;
2043 cmap
->cur_gindex
= gindex
;
2044 cmap
->cur_group
= n
;
2057 tt_cmap12_char_map_binary( TT_CMap cmap
,
2058 FT_UInt32
* pchar_code
,
2062 FT_Byte
* p
= cmap
->data
+ 12;
2063 FT_UInt32 num_groups
= TT_PEEK_ULONG( p
);
2064 FT_UInt32 char_code
= *pchar_code
;
2065 FT_UInt32 start
, end
, start_id
;
2066 FT_UInt32 max
, min
, mid
;
2072 /* make compiler happy */
2085 mid
= ( min
+ max
) >> 1;
2086 p
= cmap
->data
+ 16 + 12 * mid
;
2088 start
= TT_NEXT_ULONG( p
);
2089 end
= TT_NEXT_ULONG( p
);
2091 if ( char_code
< start
)
2093 else if ( char_code
> end
)
2097 start_id
= TT_PEEK_ULONG( p
);
2098 gindex
= (FT_UInt
)( start_id
+ char_code
- start
);
2106 TT_CMap12 cmap12
= (TT_CMap12
)cmap
;
2109 /* if `char_code' is not in any group, then `mid' is */
2110 /* the group nearest to `char_code' */
2113 if ( char_code
> end
)
2116 if ( mid
== num_groups
)
2121 cmap12
->cur_charcode
= char_code
;
2122 cmap12
->cur_group
= mid
;
2126 tt_cmap12_next( cmap12
);
2128 if ( cmap12
->valid
)
2129 gindex
= cmap12
->cur_gindex
;
2132 cmap12
->cur_gindex
= gindex
;
2135 *pchar_code
= cmap12
->cur_charcode
;
2142 FT_CALLBACK_DEF( FT_UInt
)
2143 tt_cmap12_char_index( TT_CMap cmap
,
2144 FT_UInt32 char_code
)
2146 return tt_cmap12_char_map_binary( cmap
, &char_code
, 0 );
2150 FT_CALLBACK_DEF( FT_UInt
)
2151 tt_cmap12_char_next( TT_CMap cmap
,
2152 FT_UInt32
*pchar_code
)
2154 TT_CMap12 cmap12
= (TT_CMap12
)cmap
;
2158 if ( cmap12
->cur_charcode
>= 0xFFFFFFFFUL
)
2161 /* no need to search */
2162 if ( cmap12
->valid
&& cmap12
->cur_charcode
== *pchar_code
)
2164 tt_cmap12_next( cmap12
);
2165 if ( cmap12
->valid
)
2167 gindex
= cmap12
->cur_gindex
;
2169 *pchar_code
= cmap12
->cur_charcode
;
2175 gindex
= tt_cmap12_char_map_binary( cmap
, pchar_code
, 1 );
2181 FT_CALLBACK_DEF( FT_Error
)
2182 tt_cmap12_get_info( TT_CMap cmap
,
2183 TT_CMapInfo
*cmap_info
)
2185 FT_Byte
* p
= cmap
->data
+ 8;
2188 cmap_info
->format
= 12;
2189 cmap_info
->language
= (FT_ULong
)TT_PEEK_ULONG( p
);
2195 FT_CALLBACK_TABLE_DEF
2196 const TT_CMap_ClassRec tt_cmap12_class_rec
=
2199 sizeof ( TT_CMap12Rec
),
2201 (FT_CMap_InitFunc
) tt_cmap12_init
,
2202 (FT_CMap_DoneFunc
) NULL
,
2203 (FT_CMap_CharIndexFunc
)tt_cmap12_char_index
,
2204 (FT_CMap_CharNextFunc
) tt_cmap12_char_next
2207 (TT_CMap_ValidateFunc
) tt_cmap12_validate
,
2208 (TT_CMap_Info_GetFunc
) tt_cmap12_get_info
2212 #endif /* TT_CONFIG_CMAP_FORMAT_12 */
2215 static const TT_CMap_Class tt_cmap_classes
[] =
2217 #ifdef TT_CONFIG_CMAP_FORMAT_0
2218 &tt_cmap0_class_rec
,
2221 #ifdef TT_CONFIG_CMAP_FORMAT_2
2222 &tt_cmap2_class_rec
,
2225 #ifdef TT_CONFIG_CMAP_FORMAT_4
2226 &tt_cmap4_class_rec
,
2229 #ifdef TT_CONFIG_CMAP_FORMAT_6
2230 &tt_cmap6_class_rec
,
2233 #ifdef TT_CONFIG_CMAP_FORMAT_8
2234 &tt_cmap8_class_rec
,
2237 #ifdef TT_CONFIG_CMAP_FORMAT_10
2238 &tt_cmap10_class_rec
,
2241 #ifdef TT_CONFIG_CMAP_FORMAT_12
2242 &tt_cmap12_class_rec
,
2249 /* parse the `cmap' table and build the corresponding TT_CMap objects */
2250 /* in the current face */
2252 FT_LOCAL_DEF( FT_Error
)
2253 tt_face_build_cmaps( TT_Face face
)
2255 FT_Byte
* table
= face
->cmap_table
;
2256 FT_Byte
* limit
= table
+ face
->cmap_size
;
2257 FT_UInt
volatile num_cmaps
;
2258 FT_Byte
* volatile p
= table
;
2261 if ( p
+ 4 > limit
)
2262 return SFNT_Err_Invalid_Table
;
2264 /* only recognize format 0 */
2265 if ( TT_NEXT_USHORT( p
) != 0 )
2268 FT_ERROR(( "tt_face_build_cmaps: unsupported `cmap' table format = %d\n",
2269 TT_PEEK_USHORT( p
) ));
2270 return SFNT_Err_Invalid_Table
;
2273 num_cmaps
= TT_NEXT_USHORT( p
);
2275 for ( ; num_cmaps
> 0 && p
+ 8 <= limit
; num_cmaps
-- )
2277 FT_CharMapRec charmap
;
2281 charmap
.platform_id
= TT_NEXT_USHORT( p
);
2282 charmap
.encoding_id
= TT_NEXT_USHORT( p
);
2283 charmap
.face
= FT_FACE( face
);
2284 charmap
.encoding
= FT_ENCODING_NONE
; /* will be filled later */
2285 offset
= TT_NEXT_ULONG( p
);
2287 if ( offset
&& offset
<= face
->cmap_size
- 2 )
2289 FT_Byte
* volatile cmap
= table
+ offset
;
2290 volatile FT_UInt format
= TT_PEEK_USHORT( cmap
);
2291 const TT_CMap_Class
* volatile pclazz
= tt_cmap_classes
;
2292 TT_CMap_Class
volatile clazz
;
2295 for ( ; *pclazz
; pclazz
++ )
2298 if ( clazz
->format
== format
)
2300 volatile TT_ValidatorRec valid
;
2301 volatile FT_Error error
= SFNT_Err_Ok
;
2304 ft_validator_init( FT_VALIDATOR( &valid
), cmap
, limit
,
2305 FT_VALIDATE_DEFAULT
);
2307 valid
.num_glyphs
= (FT_UInt
)face
->max_profile
.numGlyphs
;
2310 *((ft_jmp_buf
*)&FT_VALIDATOR( &valid
)->jump_buffer
) ) == 0 )
2312 /* validate this cmap sub-table */
2313 error
= clazz
->validate( cmap
, FT_VALIDATOR( &valid
) );
2316 if ( valid
.validator
.error
== 0 )
2321 if ( !FT_CMap_New( (FT_CMap_Class
)clazz
,
2322 cmap
, &charmap
, &ttcmap
) )
2324 /* it is simpler to directly set `flags' than adding */
2325 /* a parameter to FT_CMap_New */
2326 ((TT_CMap
)ttcmap
)->flags
= (FT_Int
)error
;
2331 FT_ERROR(( "tt_face_build_cmaps:" ));
2332 FT_ERROR(( " broken cmap sub-table ignored!\n" ));
2344 FT_LOCAL( FT_Error
)
2345 tt_get_cmap_info( FT_CharMap charmap
,
2346 TT_CMapInfo
*cmap_info
)
2348 FT_CMap cmap
= (FT_CMap
)charmap
;
2349 TT_CMap_Class clazz
= (TT_CMap_Class
)cmap
->clazz
;
2352 return clazz
->get_cmap_info( charmap
, cmap_info
);