1 /***************************************************************************/
5 /* TrueType character mapping table (cmap) support (body). */
7 /* Copyright 2002-2016 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
31 /*************************************************************************/
33 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
34 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
35 /* messages during execution. */
38 #define FT_COMPONENT trace_ttcmap
41 #define TT_PEEK_SHORT FT_PEEK_SHORT
42 #define TT_PEEK_USHORT FT_PEEK_USHORT
43 #define TT_PEEK_UINT24 FT_PEEK_UOFF3
44 #define TT_PEEK_LONG FT_PEEK_LONG
45 #define TT_PEEK_ULONG FT_PEEK_ULONG
47 #define TT_NEXT_SHORT FT_NEXT_SHORT
48 #define TT_NEXT_USHORT FT_NEXT_USHORT
49 #define TT_NEXT_UINT24 FT_NEXT_UOFF3
50 #define TT_NEXT_LONG FT_NEXT_LONG
51 #define TT_NEXT_ULONG FT_NEXT_ULONG
54 /* Too large glyph index return values are caught in `FT_Get_Char_Index' */
55 /* and `FT_Get_Next_Char' (the latter calls the internal `next' function */
56 /* again in this case). To mark character code return values as invalid */
57 /* it is sufficient to set the corresponding glyph index return value to */
61 FT_CALLBACK_DEF( FT_Error
)
62 tt_cmap_init( TT_CMap cmap
,
70 /*************************************************************************/
71 /*************************************************************************/
73 /***** FORMAT 0 *****/
75 /*************************************************************************/
76 /*************************************************************************/
78 /*************************************************************************/
83 /* NAME OFFSET TYPE DESCRIPTION */
85 /* format 0 USHORT must be 0 */
86 /* length 2 USHORT table length in bytes */
87 /* language 4 USHORT Mac language code */
88 /* glyph_ids 6 BYTE[256] array of glyph indices */
92 #ifdef TT_CONFIG_CMAP_FORMAT_0
94 FT_CALLBACK_DEF( FT_Error
)
95 tt_cmap0_validate( FT_Byte
* table
,
102 if ( table
+ 2 + 2 > valid
->limit
)
103 FT_INVALID_TOO_SHORT
;
105 p
= table
+ 2; /* skip format */
106 length
= TT_NEXT_USHORT( p
);
108 if ( table
+ length
> valid
->limit
|| length
< 262 )
109 FT_INVALID_TOO_SHORT
;
111 /* check glyph indices whenever necessary */
112 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
118 for ( n
= 0; n
< 256; n
++ )
121 if ( idx
>= TT_VALID_GLYPH_COUNT( valid
) )
130 FT_CALLBACK_DEF( FT_UInt
)
131 tt_cmap0_char_index( TT_CMap cmap
,
132 FT_UInt32 char_code
)
134 FT_Byte
* table
= cmap
->data
;
137 return char_code
< 256 ? table
[6 + char_code
] : 0;
141 FT_CALLBACK_DEF( FT_UInt32
)
142 tt_cmap0_char_next( TT_CMap cmap
,
143 FT_UInt32
*pchar_code
)
145 FT_Byte
* table
= cmap
->data
;
146 FT_UInt32 charcode
= *pchar_code
;
147 FT_UInt32 result
= 0;
151 table
+= 6; /* go to glyph IDs */
152 while ( ++charcode
< 256 )
154 gindex
= table
[charcode
];
162 *pchar_code
= result
;
167 FT_CALLBACK_DEF( FT_Error
)
168 tt_cmap0_get_info( TT_CMap cmap
,
169 TT_CMapInfo
*cmap_info
)
171 FT_Byte
* p
= cmap
->data
+ 4;
174 cmap_info
->format
= 0;
175 cmap_info
->language
= (FT_ULong
)TT_PEEK_USHORT( p
);
184 sizeof ( TT_CMapRec
),
186 (FT_CMap_InitFunc
) tt_cmap_init
, /* init */
187 (FT_CMap_DoneFunc
) NULL
, /* done */
188 (FT_CMap_CharIndexFunc
)tt_cmap0_char_index
, /* char_index */
189 (FT_CMap_CharNextFunc
) tt_cmap0_char_next
, /* char_next */
191 (FT_CMap_CharVarIndexFunc
) NULL
, /* char_var_index */
192 (FT_CMap_CharVarIsDefaultFunc
)NULL
, /* char_var_default */
193 (FT_CMap_VariantListFunc
) NULL
, /* variant_list */
194 (FT_CMap_CharVariantListFunc
) NULL
, /* charvariant_list */
195 (FT_CMap_VariantCharListFunc
) NULL
, /* variantchar_list */
198 (TT_CMap_ValidateFunc
)tt_cmap0_validate
, /* validate */
199 (TT_CMap_Info_GetFunc
)tt_cmap0_get_info
/* get_cmap_info */
202 #endif /* TT_CONFIG_CMAP_FORMAT_0 */
205 /*************************************************************************/
206 /*************************************************************************/
208 /***** FORMAT 2 *****/
210 /***** This is used for certain CJK encodings that encode text in a *****/
211 /***** mixed 8/16 bits encoding along the following lines. *****/
213 /***** * Certain byte values correspond to an 8-bit character code *****/
214 /***** (typically in the range 0..127 for ASCII compatibility). *****/
216 /***** * Certain byte values signal the first byte of a 2-byte *****/
217 /***** character code (but these values are also valid as the *****/
218 /***** second byte of a 2-byte character). *****/
220 /***** The following charmap lookup and iteration functions all *****/
221 /***** assume that the value `charcode' fulfills the following. *****/
223 /***** - For one byte characters, `charcode' is simply the *****/
224 /***** character code. *****/
226 /***** - For two byte characters, `charcode' is the 2-byte *****/
227 /***** character code in big endian format. More precisely: *****/
229 /***** (charcode >> 8) is the first byte value *****/
230 /***** (charcode & 0xFF) is the second byte value *****/
232 /***** Note that not all values of `charcode' are valid according *****/
233 /***** to these rules, and the function moderately checks the *****/
234 /***** arguments. *****/
236 /*************************************************************************/
237 /*************************************************************************/
239 /*************************************************************************/
244 /* NAME OFFSET TYPE DESCRIPTION */
246 /* format 0 USHORT must be 2 */
247 /* length 2 USHORT table length in bytes */
248 /* language 4 USHORT Mac language code */
249 /* keys 6 USHORT[256] sub-header keys */
250 /* subs 518 SUBHEAD[NSUBS] sub-headers array */
251 /* glyph_ids 518+NSUB*8 USHORT[] glyph ID array */
253 /* The `keys' table is used to map charcode high-bytes to sub-headers. */
254 /* The value of `NSUBS' is the number of sub-headers defined in the */
255 /* table and is computed by finding the maximum of the `keys' table. */
257 /* Note that for any n, `keys[n]' is a byte offset within the `subs' */
258 /* table, i.e., it is the corresponding sub-header index multiplied */
261 /* Each sub-header has the following format. */
263 /* NAME OFFSET TYPE DESCRIPTION */
265 /* first 0 USHORT first valid low-byte */
266 /* count 2 USHORT number of valid low-bytes */
267 /* delta 4 SHORT see below */
268 /* offset 6 USHORT see below */
270 /* A sub-header defines, for each high-byte, the range of valid */
271 /* low-bytes within the charmap. Note that the range defined by `first' */
272 /* and `count' must be completely included in the interval [0..255] */
273 /* according to the specification. */
275 /* If a character code is contained within a given sub-header, then */
276 /* mapping it to a glyph index is done as follows. */
278 /* * The value of `offset' is read. This is a _byte_ distance from the */
279 /* location of the `offset' field itself into a slice of the */
280 /* `glyph_ids' table. Let's call it `slice' (it is a USHORT[], too). */
282 /* * The value `slice[char.lo - first]' is read. If it is 0, there is */
283 /* no glyph for the charcode. Otherwise, the value of `delta' is */
284 /* added to it (modulo 65536) to form a new glyph index. */
286 /* It is up to the validation routine to check that all offsets fall */
287 /* within the glyph IDs table (and not within the `subs' table itself or */
288 /* outside of the CMap). */
291 #ifdef TT_CONFIG_CMAP_FORMAT_2
293 FT_CALLBACK_DEF( FT_Error
)
294 tt_cmap2_validate( FT_Byte
* table
,
301 FT_Byte
* keys
; /* keys table */
302 FT_Byte
* subs
; /* sub-headers */
303 FT_Byte
* glyph_ids
; /* glyph ID array */
306 if ( table
+ 2 + 2 > valid
->limit
)
307 FT_INVALID_TOO_SHORT
;
309 p
= table
+ 2; /* skip format */
310 length
= TT_NEXT_USHORT( p
);
312 if ( table
+ length
> valid
->limit
|| length
< 6 + 512 )
313 FT_INVALID_TOO_SHORT
;
317 /* parse keys to compute sub-headers count */
320 for ( n
= 0; n
< 256; n
++ )
322 FT_UInt idx
= TT_NEXT_USHORT( p
);
325 /* value must be multiple of 8 */
326 if ( valid
->level
>= FT_VALIDATE_PARANOID
&& ( idx
& 7 ) != 0 )
331 if ( idx
> max_subs
)
335 FT_ASSERT( p
== table
+ 518 );
338 glyph_ids
= subs
+ ( max_subs
+ 1 ) * 8;
339 if ( glyph_ids
> valid
->limit
)
340 FT_INVALID_TOO_SHORT
;
342 /* parse sub-headers */
343 for ( n
= 0; n
<= max_subs
; n
++ )
345 FT_UInt first_code
, code_count
, offset
;
349 first_code
= TT_NEXT_USHORT( p
);
350 code_count
= TT_NEXT_USHORT( p
);
351 delta
= TT_NEXT_SHORT( p
);
352 offset
= TT_NEXT_USHORT( p
);
354 /* many Dynalab fonts have empty sub-headers */
355 if ( code_count
== 0 )
358 /* check range within 0..255 */
359 if ( valid
->level
>= FT_VALIDATE_PARANOID
)
361 if ( first_code
>= 256 || first_code
+ code_count
> 256 )
371 ids
= p
- 2 + offset
;
372 if ( ids
< glyph_ids
|| ids
+ code_count
* 2 > table
+ length
)
375 /* check glyph IDs */
376 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
378 FT_Byte
* limit
= p
+ code_count
* 2;
384 idx
= TT_NEXT_USHORT( p
);
387 idx
= (FT_UInt
)( (FT_Int
)idx
+ delta
) & 0xFFFFU
;
388 if ( idx
>= TT_VALID_GLYPH_COUNT( valid
) )
400 /* return sub header corresponding to a given character code */
401 /* NULL on invalid charcode */
403 tt_cmap2_get_subheader( FT_Byte
* table
,
404 FT_UInt32 char_code
)
406 FT_Byte
* result
= NULL
;
409 if ( char_code
< 0x10000UL
)
411 FT_UInt char_lo
= (FT_UInt
)( char_code
& 0xFF );
412 FT_UInt char_hi
= (FT_UInt
)( char_code
>> 8 );
413 FT_Byte
* p
= table
+ 6; /* keys table */
414 FT_Byte
* subs
= table
+ 518; /* subheaders table */
420 /* an 8-bit character code -- we use subHeader 0 in this case */
421 /* to test whether the character code is in the charmap */
423 sub
= subs
; /* jump to first sub-header */
425 /* check that the sub-header for this byte is 0, which */
426 /* indicates that it is really a valid one-byte value */
427 /* Otherwise, return 0 */
430 if ( TT_PEEK_USHORT( p
) != 0 )
435 /* a 16-bit character code */
437 /* jump to key entry */
439 /* jump to sub-header */
440 sub
= subs
+ ( FT_PAD_FLOOR( TT_PEEK_USHORT( p
), 8 ) );
442 /* check that the high byte isn't a valid one-byte value */
454 FT_CALLBACK_DEF( FT_UInt
)
455 tt_cmap2_char_index( TT_CMap cmap
,
456 FT_UInt32 char_code
)
458 FT_Byte
* table
= cmap
->data
;
463 subheader
= tt_cmap2_get_subheader( table
, char_code
);
466 FT_Byte
* p
= subheader
;
467 FT_UInt idx
= (FT_UInt
)(char_code
& 0xFF);
468 FT_UInt start
, count
;
473 start
= TT_NEXT_USHORT( p
);
474 count
= TT_NEXT_USHORT( p
);
475 delta
= TT_NEXT_SHORT ( p
);
476 offset
= TT_PEEK_USHORT( p
);
479 if ( idx
< count
&& offset
!= 0 )
481 p
+= offset
+ 2 * idx
;
482 idx
= TT_PEEK_USHORT( p
);
485 result
= (FT_UInt
)( (FT_Int
)idx
+ delta
) & 0xFFFFU
;
493 FT_CALLBACK_DEF( FT_UInt32
)
494 tt_cmap2_char_next( TT_CMap cmap
,
495 FT_UInt32
*pcharcode
)
497 FT_Byte
* table
= cmap
->data
;
499 FT_UInt32 result
= 0;
500 FT_UInt32 charcode
= *pcharcode
+ 1;
504 while ( charcode
< 0x10000UL
)
506 subheader
= tt_cmap2_get_subheader( table
, charcode
);
509 FT_Byte
* p
= subheader
;
510 FT_UInt start
= TT_NEXT_USHORT( p
);
511 FT_UInt count
= TT_NEXT_USHORT( p
);
512 FT_Int delta
= TT_NEXT_SHORT ( p
);
513 FT_UInt offset
= TT_PEEK_USHORT( p
);
514 FT_UInt char_lo
= (FT_UInt
)( charcode
& 0xFF );
521 if ( char_lo
< start
)
527 pos
= (FT_UInt
)( char_lo
- start
);
529 p
+= offset
+ pos
* 2;
530 charcode
= FT_PAD_FLOOR( charcode
, 256 ) + char_lo
;
532 for ( ; pos
< count
; pos
++, charcode
++ )
534 idx
= TT_NEXT_USHORT( p
);
538 gindex
= (FT_UInt
)( (FT_Int
)idx
+ delta
) & 0xFFFFU
;
548 /* jump to next sub-header, i.e. higher byte value */
550 charcode
= FT_PAD_FLOOR( charcode
, 256 ) + 256;
560 FT_CALLBACK_DEF( FT_Error
)
561 tt_cmap2_get_info( TT_CMap cmap
,
562 TT_CMapInfo
*cmap_info
)
564 FT_Byte
* p
= cmap
->data
+ 4;
567 cmap_info
->format
= 2;
568 cmap_info
->language
= (FT_ULong
)TT_PEEK_USHORT( p
);
577 sizeof ( TT_CMapRec
),
579 (FT_CMap_InitFunc
) tt_cmap_init
, /* init */
580 (FT_CMap_DoneFunc
) NULL
, /* done */
581 (FT_CMap_CharIndexFunc
)tt_cmap2_char_index
, /* char_index */
582 (FT_CMap_CharNextFunc
) tt_cmap2_char_next
, /* char_next */
584 (FT_CMap_CharVarIndexFunc
) NULL
, /* char_var_index */
585 (FT_CMap_CharVarIsDefaultFunc
)NULL
, /* char_var_default */
586 (FT_CMap_VariantListFunc
) NULL
, /* variant_list */
587 (FT_CMap_CharVariantListFunc
) NULL
, /* charvariant_list */
588 (FT_CMap_VariantCharListFunc
) NULL
, /* variantchar_list */
591 (TT_CMap_ValidateFunc
)tt_cmap2_validate
, /* validate */
592 (TT_CMap_Info_GetFunc
)tt_cmap2_get_info
/* get_cmap_info */
595 #endif /* TT_CONFIG_CMAP_FORMAT_2 */
598 /*************************************************************************/
599 /*************************************************************************/
601 /***** FORMAT 4 *****/
603 /*************************************************************************/
604 /*************************************************************************/
606 /*************************************************************************/
611 /* NAME OFFSET TYPE DESCRIPTION */
613 /* format 0 USHORT must be 4 */
614 /* length 2 USHORT table length */
616 /* language 4 USHORT Mac language code */
618 /* segCountX2 6 USHORT 2*NUM_SEGS */
619 /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */
620 /* entrySelector 10 USHORT LOG_SEGS */
621 /* rangeShift 12 USHORT segCountX2 - */
624 /* endCount 14 USHORT[NUM_SEGS] end charcode for */
625 /* each segment; last */
628 /* pad 14+NUM_SEGS*2 USHORT padding */
630 /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */
633 /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */
635 /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */
636 /* each segment; can be */
639 /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph ID */
642 /* Character codes are modelled by a series of ordered (increasing) */
643 /* intervals called segments. Each segment has start and end codes, */
644 /* provided by the `startCount' and `endCount' arrays. Segments must */
645 /* not overlap, and the last segment should always contain the value */
646 /* 0xFFFF for `endCount'. */
648 /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
649 /* ignored (they are traces of over-engineering in the TrueType */
650 /* specification). */
652 /* Each segment also has a signed `delta', as well as an optional offset */
653 /* within the `glyphIds' table. */
655 /* If a segment's idOffset is 0, the glyph index corresponding to any */
656 /* charcode within the segment is obtained by adding the value of */
657 /* `idDelta' directly to the charcode, modulo 65536. */
659 /* Otherwise, a glyph index is taken from the glyph IDs sub-array for */
660 /* the segment, and the value of `idDelta' is added to it. */
663 /* Finally, note that a lot of fonts contain an invalid last segment, */
664 /* where `start' and `end' are correctly set to 0xFFFF but both `delta' */
665 /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with */
666 /* OpenOffice.org). We need special code to deal with them correctly. */
669 #ifdef TT_CONFIG_CMAP_FORMAT_4
671 typedef struct TT_CMap4Rec_
674 FT_UInt32 cur_charcode
; /* current charcode */
675 FT_UInt cur_gindex
; /* current glyph index */
684 } TT_CMap4Rec
, *TT_CMap4
;
687 FT_CALLBACK_DEF( FT_Error
)
688 tt_cmap4_init( TT_CMap4 cmap
,
694 cmap
->cmap
.data
= table
;
697 cmap
->num_ranges
= FT_PEEK_USHORT( p
) >> 1;
698 cmap
->cur_charcode
= (FT_UInt32
)0xFFFFFFFFUL
;
699 cmap
->cur_gindex
= 0;
706 tt_cmap4_set_range( TT_CMap4 cmap
,
707 FT_UInt range_index
)
709 FT_Byte
* table
= cmap
->cmap
.data
;
711 FT_UInt num_ranges
= cmap
->num_ranges
;
714 while ( range_index
< num_ranges
)
719 p
= table
+ 14 + range_index
* 2;
720 cmap
->cur_end
= FT_PEEK_USHORT( p
);
722 p
+= 2 + num_ranges
* 2;
723 cmap
->cur_start
= FT_PEEK_USHORT( p
);
726 cmap
->cur_delta
= FT_PEEK_SHORT( p
);
729 offset
= FT_PEEK_USHORT( p
);
731 /* some fonts have an incorrect last segment; */
732 /* we have to catch it */
733 if ( range_index
>= num_ranges
- 1 &&
734 cmap
->cur_start
== 0xFFFFU
&&
735 cmap
->cur_end
== 0xFFFFU
)
737 TT_Face face
= (TT_Face
)cmap
->cmap
.cmap
.charmap
.face
;
738 FT_Byte
* limit
= face
->cmap_table
+ face
->cmap_size
;
741 if ( offset
&& p
+ offset
+ 2 > limit
)
748 if ( offset
!= 0xFFFFU
)
750 cmap
->cur_values
= offset
? p
+ offset
: NULL
;
751 cmap
->cur_range
= range_index
;
755 /* we skip empty segments */
763 /* search the index of the charcode next to cmap->cur_charcode; */
764 /* caller should call tt_cmap4_set_range with proper range */
765 /* before calling this function */
768 tt_cmap4_next( TT_CMap4 cmap
)
770 TT_Face face
= (TT_Face
)cmap
->cmap
.cmap
.charmap
.face
;
771 FT_Byte
* limit
= face
->cmap_table
+ face
->cmap_size
;
776 if ( cmap
->cur_charcode
>= 0xFFFFUL
)
779 charcode
= (FT_UInt
)cmap
->cur_charcode
+ 1;
781 if ( charcode
< cmap
->cur_start
)
782 charcode
= cmap
->cur_start
;
786 FT_Byte
* values
= cmap
->cur_values
;
787 FT_UInt end
= cmap
->cur_end
;
788 FT_Int delta
= cmap
->cur_delta
;
791 if ( charcode
<= end
)
795 FT_Byte
* p
= values
+ 2 * ( charcode
- cmap
->cur_start
);
798 /* if p > limit, the whole segment is invalid */
804 FT_UInt gindex
= FT_NEXT_USHORT( p
);
809 gindex
= (FT_UInt
)( (FT_Int
)gindex
+ delta
) & 0xFFFFU
;
812 cmap
->cur_charcode
= charcode
;
813 cmap
->cur_gindex
= gindex
;
817 } while ( ++charcode
<= end
);
823 FT_UInt gindex
= (FT_UInt
)( (FT_Int
)charcode
+ delta
) & 0xFFFFU
;
826 if ( gindex
>= (FT_UInt
)face
->root
.num_glyphs
)
828 /* we have an invalid glyph index; if there is an overflow, */
829 /* we can adjust `charcode', otherwise the whole segment is */
833 if ( (FT_Int
)charcode
+ delta
< 0 &&
834 (FT_Int
)end
+ delta
>= 0 )
835 charcode
= (FT_UInt
)( -delta
);
837 else if ( (FT_Int
)charcode
+ delta
< 0x10000L
&&
838 (FT_Int
)end
+ delta
>= 0x10000L
)
839 charcode
= (FT_UInt
)( 0x10000L
- delta
);
847 cmap
->cur_charcode
= charcode
;
848 cmap
->cur_gindex
= gindex
;
851 } while ( ++charcode
<= end
);
856 /* we need to find another range */
857 if ( tt_cmap4_set_range( cmap
, cmap
->cur_range
+ 1 ) < 0 )
860 if ( charcode
< cmap
->cur_start
)
861 charcode
= cmap
->cur_start
;
865 cmap
->cur_charcode
= (FT_UInt32
)0xFFFFFFFFUL
;
866 cmap
->cur_gindex
= 0;
870 FT_CALLBACK_DEF( FT_Error
)
871 tt_cmap4_validate( FT_Byte
* table
,
877 FT_Byte
*ends
, *starts
, *offsets
, *deltas
, *glyph_ids
;
879 FT_Error error
= FT_Err_Ok
;
882 if ( table
+ 2 + 2 > valid
->limit
)
883 FT_INVALID_TOO_SHORT
;
885 p
= table
+ 2; /* skip format */
886 length
= TT_NEXT_USHORT( p
);
888 /* in certain fonts, the `length' field is invalid and goes */
889 /* out of bound. We try to correct this here... */
890 if ( table
+ length
> valid
->limit
)
892 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
893 FT_INVALID_TOO_SHORT
;
895 length
= (FT_UInt
)( valid
->limit
- table
);
899 FT_INVALID_TOO_SHORT
;
902 num_segs
= TT_NEXT_USHORT( p
); /* read segCountX2 */
904 if ( valid
->level
>= FT_VALIDATE_PARANOID
)
906 /* check that we have an even value here */
913 if ( length
< 16 + num_segs
* 2 * 4 )
914 FT_INVALID_TOO_SHORT
;
916 /* check the search parameters - even though we never use them */
918 if ( valid
->level
>= FT_VALIDATE_PARANOID
)
920 /* check the values of `searchRange', `entrySelector', `rangeShift' */
921 FT_UInt search_range
= TT_NEXT_USHORT( p
);
922 FT_UInt entry_selector
= TT_NEXT_USHORT( p
);
923 FT_UInt range_shift
= TT_NEXT_USHORT( p
);
926 if ( ( search_range
| range_shift
) & 1 ) /* must be even values */
932 /* `search range' is the greatest power of 2 that is <= num_segs */
934 if ( search_range
> num_segs
||
935 search_range
* 2 < num_segs
||
936 search_range
+ range_shift
!= num_segs
||
937 search_range
!= ( 1U << entry_selector
) )
942 starts
= table
+ 16 + num_segs
* 2;
943 deltas
= starts
+ num_segs
* 2;
944 offsets
= deltas
+ num_segs
* 2;
945 glyph_ids
= offsets
+ num_segs
* 2;
947 /* check last segment; its end count value must be 0xFFFF */
948 if ( valid
->level
>= FT_VALIDATE_PARANOID
)
950 p
= ends
+ ( num_segs
- 1 ) * 2;
951 if ( TT_PEEK_USHORT( p
) != 0xFFFFU
)
956 FT_UInt start
, end
, offset
, n
;
957 FT_UInt last_start
= 0, last_end
= 0;
959 FT_Byte
* p_start
= starts
;
960 FT_Byte
* p_end
= ends
;
961 FT_Byte
* p_delta
= deltas
;
962 FT_Byte
* p_offset
= offsets
;
965 for ( n
= 0; n
< num_segs
; n
++ )
968 start
= TT_NEXT_USHORT( p_start
);
969 end
= TT_NEXT_USHORT( p_end
);
970 delta
= TT_NEXT_SHORT( p_delta
);
971 offset
= TT_NEXT_USHORT( p_offset
);
976 /* this test should be performed at default validation level; */
977 /* unfortunately, some popular Asian fonts have overlapping */
978 /* ranges in their charmaps */
980 if ( start
<= last_end
&& n
> 0 )
982 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
986 /* allow overlapping segments, provided their start points */
987 /* and end points, respectively, are in ascending order */
989 if ( last_start
> start
|| last_end
> end
)
990 error
|= TT_CMAP_FLAG_UNSORTED
;
992 error
|= TT_CMAP_FLAG_OVERLAPPING
;
996 if ( offset
&& offset
!= 0xFFFFU
)
998 p
+= offset
; /* start of glyph ID array */
1000 /* check that we point within the glyph IDs table only */
1001 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
1003 if ( p
< glyph_ids
||
1004 p
+ ( end
- start
+ 1 ) * 2 > table
+ length
)
1007 /* Some fonts handle the last segment incorrectly. In */
1008 /* theory, 0xFFFF might point to an ordinary glyph -- */
1009 /* a cmap 4 is versatile and could be used for any */
1010 /* encoding, not only Unicode. However, reality shows */
1011 /* that far too many fonts are sloppy and incorrectly */
1012 /* set all fields but `start' and `end' for the last */
1013 /* segment if it contains only a single character. */
1015 /* We thus omit the test here, delaying it to the */
1016 /* routines that actually access the cmap. */
1017 else if ( n
!= num_segs
- 1 ||
1018 !( start
== 0xFFFFU
&& end
== 0xFFFFU
) )
1020 if ( p
< glyph_ids
||
1021 p
+ ( end
- start
+ 1 ) * 2 > valid
->limit
)
1025 /* check glyph indices within the segment range */
1026 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
1031 for ( i
= start
; i
< end
; i
++ )
1033 idx
= FT_NEXT_USHORT( p
);
1036 idx
= (FT_UInt
)( (FT_Int
)idx
+ delta
) & 0xFFFFU
;
1038 if ( idx
>= TT_VALID_GLYPH_COUNT( valid
) )
1039 FT_INVALID_GLYPH_ID
;
1044 else if ( offset
== 0xFFFFU
)
1046 /* some fonts (erroneously?) use a range offset of 0xFFFF */
1047 /* to mean missing glyph in cmap table */
1049 if ( valid
->level
>= FT_VALIDATE_PARANOID
||
1050 n
!= num_segs
- 1 ||
1051 !( start
== 0xFFFFU
&& end
== 0xFFFFU
) )
1065 tt_cmap4_char_map_linear( TT_CMap cmap
,
1066 FT_UInt32
* pcharcode
,
1069 TT_Face face
= (TT_Face
)cmap
->cmap
.charmap
.face
;
1070 FT_Byte
* limit
= face
->cmap_table
+ face
->cmap_size
;
1073 FT_UInt num_segs2
, start
, end
, offset
;
1075 FT_UInt i
, num_segs
;
1076 FT_UInt32 charcode
= *pcharcode
;
1083 num_segs2
= FT_PAD_FLOOR( TT_PEEK_USHORT( p
), 2 );
1085 num_segs
= num_segs2
>> 1;
1093 if ( charcode
> 0xFFFFU
)
1097 p
= cmap
->data
+ 14; /* ends table */
1098 q
= cmap
->data
+ 16 + num_segs2
; /* starts table */
1100 for ( i
= 0; i
< num_segs
; i
++ )
1102 end
= TT_NEXT_USHORT( p
);
1103 start
= TT_NEXT_USHORT( q
);
1105 if ( charcode
< start
)
1114 if ( charcode
<= end
)
1119 r
= q
- 2 + num_segs2
;
1120 delta
= TT_PEEK_SHORT( r
);
1122 offset
= TT_PEEK_USHORT( r
);
1124 /* some fonts have an incorrect last segment; */
1125 /* we have to catch it */
1126 if ( i
>= num_segs
- 1 &&
1127 start
== 0xFFFFU
&& end
== 0xFFFFU
)
1129 if ( offset
&& r
+ offset
+ 2 > limit
)
1136 if ( offset
== 0xFFFFU
)
1141 r
+= offset
+ ( charcode
- start
) * 2;
1143 /* if r > limit, the whole segment is invalid */
1144 if ( next
&& r
> limit
)
1147 gindex
= TT_PEEK_USHORT( r
);
1150 gindex
= (FT_UInt
)( (FT_Int
)gindex
+ delta
) & 0xFFFFU
;
1151 if ( gindex
>= (FT_UInt
)face
->root
.num_glyphs
)
1157 gindex
= (FT_UInt
)( (FT_Int
)charcode
+ delta
) & 0xFFFFU
;
1159 if ( next
&& gindex
>= (FT_UInt
)face
->root
.num_glyphs
)
1161 /* we have an invalid glyph index; if there is an overflow, */
1162 /* we can adjust `charcode', otherwise the whole segment is */
1166 if ( (FT_Int
)charcode
+ delta
< 0 &&
1167 (FT_Int
)end
+ delta
>= 0 )
1168 charcode
= (FT_UInt
)( -delta
);
1170 else if ( (FT_Int
)charcode
+ delta
< 0x10000L
&&
1171 (FT_Int
)end
+ delta
>= 0x10000L
)
1172 charcode
= (FT_UInt
)( 0x10000L
- delta
);
1179 if ( next
&& !gindex
)
1181 if ( charcode
>= 0xFFFFU
)
1193 *pcharcode
= charcode
;
1200 tt_cmap4_char_map_binary( TT_CMap cmap
,
1201 FT_UInt32
* pcharcode
,
1204 TT_Face face
= (TT_Face
)cmap
->cmap
.charmap
.face
;
1205 FT_Byte
* limit
= face
->cmap_table
+ face
->cmap_size
;
1207 FT_UInt num_segs2
, start
, end
, offset
;
1209 FT_UInt max
, min
, mid
, num_segs
;
1210 FT_UInt charcode
= (FT_UInt
)*pcharcode
;
1216 num_segs2
= FT_PAD_FLOOR( TT_PEEK_USHORT( p
), 2 );
1221 num_segs
= num_segs2
>> 1;
1223 /* make compiler happy */
1236 mid
= ( min
+ max
) >> 1;
1237 p
= cmap
->data
+ 14 + mid
* 2;
1238 end
= TT_PEEK_USHORT( p
);
1240 start
= TT_PEEK_USHORT( p
);
1242 if ( charcode
< start
)
1244 else if ( charcode
> end
)
1249 delta
= TT_PEEK_SHORT( p
);
1251 offset
= TT_PEEK_USHORT( p
);
1253 /* some fonts have an incorrect last segment; */
1254 /* we have to catch it */
1255 if ( mid
>= num_segs
- 1 &&
1256 start
== 0xFFFFU
&& end
== 0xFFFFU
)
1258 if ( offset
&& p
+ offset
+ 2 > limit
)
1265 /* search the first segment containing `charcode' */
1266 if ( cmap
->flags
& TT_CMAP_FLAG_OVERLAPPING
)
1271 /* call the current segment `max' */
1274 if ( offset
== 0xFFFFU
)
1277 /* search in segments before the current segment */
1278 for ( i
= max
; i
> 0; i
-- )
1285 p
= cmap
->data
+ 14 + ( i
- 1 ) * 2;
1286 prev_end
= TT_PEEK_USHORT( p
);
1288 if ( charcode
> prev_end
)
1296 start
= TT_PEEK_USHORT( p
);
1298 delta
= TT_PEEK_SHORT( p
);
1300 offset
= TT_PEEK_USHORT( p
);
1302 if ( offset
!= 0xFFFFU
)
1307 if ( mid
== max
+ 1 )
1311 p
= cmap
->data
+ 14 + max
* 2;
1312 end
= TT_PEEK_USHORT( p
);
1314 start
= TT_PEEK_USHORT( p
);
1316 delta
= TT_PEEK_SHORT( p
);
1318 offset
= TT_PEEK_USHORT( p
);
1323 /* search in segments after the current segment */
1324 for ( i
= max
+ 1; i
< num_segs
; i
++ )
1326 FT_UInt next_end
, next_start
;
1329 p
= cmap
->data
+ 14 + i
* 2;
1330 next_end
= TT_PEEK_USHORT( p
);
1332 next_start
= TT_PEEK_USHORT( p
);
1334 if ( charcode
< next_start
)
1340 delta
= TT_PEEK_SHORT( p
);
1342 offset
= TT_PEEK_USHORT( p
);
1344 if ( offset
!= 0xFFFFU
)
1358 /* end, start, delta, and offset are for the i'th segment */
1361 p
= cmap
->data
+ 14 + mid
* 2;
1362 end
= TT_PEEK_USHORT( p
);
1364 start
= TT_PEEK_USHORT( p
);
1366 delta
= TT_PEEK_SHORT( p
);
1368 offset
= TT_PEEK_USHORT( p
);
1373 if ( offset
== 0xFFFFU
)
1379 p
+= offset
+ ( charcode
- start
) * 2;
1381 /* if p > limit, the whole segment is invalid */
1382 if ( next
&& p
> limit
)
1385 gindex
= TT_PEEK_USHORT( p
);
1388 gindex
= (FT_UInt
)( (FT_Int
)gindex
+ delta
) & 0xFFFFU
;
1389 if ( gindex
>= (FT_UInt
)face
->root
.num_glyphs
)
1395 gindex
= (FT_UInt
)( (FT_Int
)charcode
+ delta
) & 0xFFFFU
;
1397 if ( next
&& gindex
>= (FT_UInt
)face
->root
.num_glyphs
)
1399 /* we have an invalid glyph index; if there is an overflow, */
1400 /* we can adjust `charcode', otherwise the whole segment is */
1404 if ( (FT_Int
)charcode
+ delta
< 0 &&
1405 (FT_Int
)end
+ delta
>= 0 )
1406 charcode
= (FT_UInt
)( -delta
);
1408 else if ( (FT_Int
)charcode
+ delta
< 0x10000L
&&
1409 (FT_Int
)end
+ delta
>= 0x10000L
)
1410 charcode
= (FT_UInt
)( 0x10000L
- delta
);
1420 TT_CMap4 cmap4
= (TT_CMap4
)cmap
;
1423 /* if `charcode' is not in any segment, then `mid' is */
1424 /* the segment nearest to `charcode' */
1426 if ( charcode
> end
)
1429 if ( mid
== num_segs
)
1433 if ( tt_cmap4_set_range( cmap4
, mid
) )
1436 *pcharcode
= charcode
;
1440 cmap4
->cur_charcode
= charcode
;
1443 cmap4
->cur_gindex
= gindex
;
1446 cmap4
->cur_charcode
= charcode
;
1447 tt_cmap4_next( cmap4
);
1448 gindex
= cmap4
->cur_gindex
;
1452 *pcharcode
= cmap4
->cur_charcode
;
1460 FT_CALLBACK_DEF( FT_UInt
)
1461 tt_cmap4_char_index( TT_CMap cmap
,
1462 FT_UInt32 char_code
)
1464 if ( char_code
>= 0x10000UL
)
1467 if ( cmap
->flags
& TT_CMAP_FLAG_UNSORTED
)
1468 return tt_cmap4_char_map_linear( cmap
, &char_code
, 0 );
1470 return tt_cmap4_char_map_binary( cmap
, &char_code
, 0 );
1474 FT_CALLBACK_DEF( FT_UInt32
)
1475 tt_cmap4_char_next( TT_CMap cmap
,
1476 FT_UInt32
*pchar_code
)
1481 if ( *pchar_code
>= 0xFFFFU
)
1484 if ( cmap
->flags
& TT_CMAP_FLAG_UNSORTED
)
1485 gindex
= tt_cmap4_char_map_linear( cmap
, pchar_code
, 1 );
1488 TT_CMap4 cmap4
= (TT_CMap4
)cmap
;
1491 /* no need to search */
1492 if ( *pchar_code
== cmap4
->cur_charcode
)
1494 tt_cmap4_next( cmap4
);
1495 gindex
= cmap4
->cur_gindex
;
1497 *pchar_code
= cmap4
->cur_charcode
;
1500 gindex
= tt_cmap4_char_map_binary( cmap
, pchar_code
, 1 );
1507 FT_CALLBACK_DEF( FT_Error
)
1508 tt_cmap4_get_info( TT_CMap cmap
,
1509 TT_CMapInfo
*cmap_info
)
1511 FT_Byte
* p
= cmap
->data
+ 4;
1514 cmap_info
->format
= 4;
1515 cmap_info
->language
= (FT_ULong
)TT_PEEK_USHORT( p
);
1524 sizeof ( TT_CMap4Rec
),
1526 (FT_CMap_InitFunc
) tt_cmap4_init
, /* init */
1527 (FT_CMap_DoneFunc
) NULL
, /* done */
1528 (FT_CMap_CharIndexFunc
)tt_cmap4_char_index
, /* char_index */
1529 (FT_CMap_CharNextFunc
) tt_cmap4_char_next
, /* char_next */
1531 (FT_CMap_CharVarIndexFunc
) NULL
, /* char_var_index */
1532 (FT_CMap_CharVarIsDefaultFunc
)NULL
, /* char_var_default */
1533 (FT_CMap_VariantListFunc
) NULL
, /* variant_list */
1534 (FT_CMap_CharVariantListFunc
) NULL
, /* charvariant_list */
1535 (FT_CMap_VariantCharListFunc
) NULL
, /* variantchar_list */
1538 (TT_CMap_ValidateFunc
)tt_cmap4_validate
, /* validate */
1539 (TT_CMap_Info_GetFunc
)tt_cmap4_get_info
/* get_cmap_info */
1542 #endif /* TT_CONFIG_CMAP_FORMAT_4 */
1545 /*************************************************************************/
1546 /*************************************************************************/
1548 /***** FORMAT 6 *****/
1550 /*************************************************************************/
1551 /*************************************************************************/
1553 /*************************************************************************/
1555 /* TABLE OVERVIEW */
1556 /* -------------- */
1558 /* NAME OFFSET TYPE DESCRIPTION */
1560 /* format 0 USHORT must be 6 */
1561 /* length 2 USHORT table length in bytes */
1562 /* language 4 USHORT Mac language code */
1564 /* first 6 USHORT first segment code */
1565 /* count 8 USHORT segment size in chars */
1566 /* glyphIds 10 USHORT[count] glyph IDs */
1568 /* A very simplified segment mapping. */
1571 #ifdef TT_CONFIG_CMAP_FORMAT_6
1573 FT_CALLBACK_DEF( FT_Error
)
1574 tt_cmap6_validate( FT_Byte
* table
,
1575 FT_Validator valid
)
1578 FT_UInt length
, count
;
1581 if ( table
+ 10 > valid
->limit
)
1582 FT_INVALID_TOO_SHORT
;
1585 length
= TT_NEXT_USHORT( p
);
1587 p
= table
+ 8; /* skip language and start index */
1588 count
= TT_NEXT_USHORT( p
);
1590 if ( table
+ length
> valid
->limit
|| length
< 10 + count
* 2 )
1591 FT_INVALID_TOO_SHORT
;
1593 /* check glyph indices */
1594 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
1599 for ( ; count
> 0; count
-- )
1601 gindex
= TT_NEXT_USHORT( p
);
1602 if ( gindex
>= TT_VALID_GLYPH_COUNT( valid
) )
1603 FT_INVALID_GLYPH_ID
;
1611 FT_CALLBACK_DEF( FT_UInt
)
1612 tt_cmap6_char_index( TT_CMap cmap
,
1613 FT_UInt32 char_code
)
1615 FT_Byte
* table
= cmap
->data
;
1617 FT_Byte
* p
= table
+ 6;
1618 FT_UInt start
= TT_NEXT_USHORT( p
);
1619 FT_UInt count
= TT_NEXT_USHORT( p
);
1620 FT_UInt idx
= (FT_UInt
)( char_code
- start
);
1626 result
= TT_PEEK_USHORT( p
);
1633 FT_CALLBACK_DEF( FT_UInt32
)
1634 tt_cmap6_char_next( TT_CMap cmap
,
1635 FT_UInt32
*pchar_code
)
1637 FT_Byte
* table
= cmap
->data
;
1638 FT_UInt32 result
= 0;
1639 FT_UInt32 char_code
= *pchar_code
+ 1;
1642 FT_Byte
* p
= table
+ 6;
1643 FT_UInt start
= TT_NEXT_USHORT( p
);
1644 FT_UInt count
= TT_NEXT_USHORT( p
);
1648 if ( char_code
>= 0x10000UL
)
1651 if ( char_code
< start
)
1654 idx
= (FT_UInt
)( char_code
- start
);
1657 for ( ; idx
< count
; idx
++ )
1659 gindex
= TT_NEXT_USHORT( p
);
1666 if ( char_code
>= 0xFFFFU
)
1672 *pchar_code
= result
;
1677 FT_CALLBACK_DEF( FT_Error
)
1678 tt_cmap6_get_info( TT_CMap cmap
,
1679 TT_CMapInfo
*cmap_info
)
1681 FT_Byte
* p
= cmap
->data
+ 4;
1684 cmap_info
->format
= 6;
1685 cmap_info
->language
= (FT_ULong
)TT_PEEK_USHORT( p
);
1694 sizeof ( TT_CMapRec
),
1696 (FT_CMap_InitFunc
) tt_cmap_init
, /* init */
1697 (FT_CMap_DoneFunc
) NULL
, /* done */
1698 (FT_CMap_CharIndexFunc
)tt_cmap6_char_index
, /* char_index */
1699 (FT_CMap_CharNextFunc
) tt_cmap6_char_next
, /* char_next */
1701 (FT_CMap_CharVarIndexFunc
) NULL
, /* char_var_index */
1702 (FT_CMap_CharVarIsDefaultFunc
)NULL
, /* char_var_default */
1703 (FT_CMap_VariantListFunc
) NULL
, /* variant_list */
1704 (FT_CMap_CharVariantListFunc
) NULL
, /* charvariant_list */
1705 (FT_CMap_VariantCharListFunc
) NULL
, /* variantchar_list */
1708 (TT_CMap_ValidateFunc
)tt_cmap6_validate
, /* validate */
1709 (TT_CMap_Info_GetFunc
)tt_cmap6_get_info
/* get_cmap_info */
1712 #endif /* TT_CONFIG_CMAP_FORMAT_6 */
1715 /*************************************************************************/
1716 /*************************************************************************/
1718 /***** FORMAT 8 *****/
1720 /***** It is hard to completely understand what the OpenType spec *****/
1721 /***** says about this format, but here is my conclusion. *****/
1723 /***** The purpose of this format is to easily map UTF-16 text to *****/
1724 /***** glyph indices. Basically, the `char_code' must be in one of *****/
1725 /***** the following formats. *****/
1727 /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/
1728 /***** Area (i.e. U+D800-U+DFFF). *****/
1730 /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/
1731 /***** `char_code = (char_hi << 16) | char_lo', then both *****/
1732 /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/
1735 /***** The `is32' table embedded in the charmap indicates whether a *****/
1736 /***** given 16-bit value is in the surrogates area or not. *****/
1738 /***** So, for any given `char_code', we can assert the following. *****/
1740 /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/
1742 /***** If `char_hi != 0' then we must have both *****/
1743 /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/
1745 /*************************************************************************/
1746 /*************************************************************************/
1748 /*************************************************************************/
1750 /* TABLE OVERVIEW */
1751 /* -------------- */
1753 /* NAME OFFSET TYPE DESCRIPTION */
1755 /* format 0 USHORT must be 8 */
1756 /* reserved 2 USHORT reserved */
1757 /* length 4 ULONG length in bytes */
1758 /* language 8 ULONG Mac language code */
1759 /* is32 12 BYTE[8192] 32-bitness bitmap */
1760 /* count 8204 ULONG number of groups */
1762 /* This header is followed by `count' groups of the following format: */
1764 /* start 0 ULONG first charcode */
1765 /* end 4 ULONG last charcode */
1766 /* startId 8 ULONG start glyph ID for the group */
1769 #ifdef TT_CONFIG_CMAP_FORMAT_8
1771 FT_CALLBACK_DEF( FT_Error
)
1772 tt_cmap8_validate( FT_Byte
* table
,
1773 FT_Validator valid
)
1775 FT_Byte
* p
= table
+ 4;
1778 FT_UInt32 num_groups
;
1781 if ( table
+ 16 + 8192 > valid
->limit
)
1782 FT_INVALID_TOO_SHORT
;
1784 length
= TT_NEXT_ULONG( p
);
1785 if ( length
> (FT_UInt32
)( valid
->limit
- table
) || length
< 8192 + 16 )
1786 FT_INVALID_TOO_SHORT
;
1789 p
= is32
+ 8192; /* skip `is32' array */
1790 num_groups
= TT_NEXT_ULONG( p
);
1792 /* p + num_groups * 12 > valid->limit ? */
1793 if ( num_groups
> (FT_UInt32
)( valid
->limit
- p
) / 12 )
1794 FT_INVALID_TOO_SHORT
;
1796 /* check groups, they must be in increasing order */
1798 FT_UInt32 n
, start
, end
, start_id
, count
, last
= 0;
1801 for ( n
= 0; n
< num_groups
; n
++ )
1806 start
= TT_NEXT_ULONG( p
);
1807 end
= TT_NEXT_ULONG( p
);
1808 start_id
= TT_NEXT_ULONG( p
);
1813 if ( n
> 0 && start
<= last
)
1816 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
1818 FT_UInt32 d
= end
- start
;
1821 /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
1822 if ( d
> TT_VALID_GLYPH_COUNT( valid
) ||
1823 start_id
>= TT_VALID_GLYPH_COUNT( valid
) - d
)
1824 FT_INVALID_GLYPH_ID
;
1826 count
= (FT_UInt32
)( end
- start
+ 1 );
1828 if ( start
& ~0xFFFFU
)
1830 /* start_hi != 0; check that is32[i] is 1 for each i in */
1831 /* the `hi' and `lo' of the range [start..end] */
1832 for ( ; count
> 0; count
--, start
++ )
1834 hi
= (FT_UInt
)( start
>> 16 );
1835 lo
= (FT_UInt
)( start
& 0xFFFFU
);
1837 if ( (is32
[hi
>> 3] & ( 0x80 >> ( hi
& 7 ) ) ) == 0 )
1840 if ( (is32
[lo
>> 3] & ( 0x80 >> ( lo
& 7 ) ) ) == 0 )
1846 /* start_hi == 0; check that is32[i] is 0 for each i in */
1847 /* the range [start..end] */
1849 /* end_hi cannot be != 0! */
1850 if ( end
& ~0xFFFFU
)
1853 for ( ; count
> 0; count
--, start
++ )
1855 lo
= (FT_UInt
)( start
& 0xFFFFU
);
1857 if ( (is32
[lo
>> 3] & ( 0x80 >> ( lo
& 7 ) ) ) != 0 )
1871 FT_CALLBACK_DEF( FT_UInt
)
1872 tt_cmap8_char_index( TT_CMap cmap
,
1873 FT_UInt32 char_code
)
1875 FT_Byte
* table
= cmap
->data
;
1877 FT_Byte
* p
= table
+ 8204;
1878 FT_UInt32 num_groups
= TT_NEXT_ULONG( p
);
1879 FT_UInt32 start
, end
, start_id
;
1882 for ( ; num_groups
> 0; num_groups
-- )
1884 start
= TT_NEXT_ULONG( p
);
1885 end
= TT_NEXT_ULONG( p
);
1886 start_id
= TT_NEXT_ULONG( p
);
1888 if ( char_code
< start
)
1891 if ( char_code
<= end
)
1893 if ( start_id
> 0xFFFFFFFFUL
- ( char_code
- start
) )
1896 result
= (FT_UInt
)( start_id
+ ( char_code
- start
) );
1904 FT_CALLBACK_DEF( FT_UInt32
)
1905 tt_cmap8_char_next( TT_CMap cmap
,
1906 FT_UInt32
*pchar_code
)
1908 FT_Face face
= cmap
->cmap
.charmap
.face
;
1909 FT_UInt32 result
= 0;
1910 FT_UInt32 char_code
;
1912 FT_Byte
* table
= cmap
->data
;
1913 FT_Byte
* p
= table
+ 8204;
1914 FT_UInt32 num_groups
= TT_NEXT_ULONG( p
);
1915 FT_UInt32 start
, end
, start_id
;
1918 if ( *pchar_code
>= 0xFFFFFFFFUL
)
1921 char_code
= *pchar_code
+ 1;
1925 for ( ; num_groups
> 0; num_groups
-- )
1927 start
= TT_NEXT_ULONG( p
);
1928 end
= TT_NEXT_ULONG( p
);
1929 start_id
= TT_NEXT_ULONG( p
);
1931 if ( char_code
< start
)
1935 if ( char_code
<= end
)
1937 /* ignore invalid group */
1938 if ( start_id
> 0xFFFFFFFFUL
- ( char_code
- start
) )
1941 gindex
= (FT_UInt
)( start_id
+ ( char_code
- start
) );
1943 /* does first element of group point to `.notdef' glyph? */
1946 if ( char_code
>= 0xFFFFFFFFUL
)
1953 /* if `gindex' is invalid, the remaining values */
1954 /* in this group are invalid, too */
1955 if ( gindex
>= (FT_UInt
)face
->num_glyphs
)
1966 *pchar_code
= result
;
1971 FT_CALLBACK_DEF( FT_Error
)
1972 tt_cmap8_get_info( TT_CMap cmap
,
1973 TT_CMapInfo
*cmap_info
)
1975 FT_Byte
* p
= cmap
->data
+ 8;
1978 cmap_info
->format
= 8;
1979 cmap_info
->language
= (FT_ULong
)TT_PEEK_ULONG( p
);
1988 sizeof ( TT_CMapRec
),
1990 (FT_CMap_InitFunc
) tt_cmap_init
, /* init */
1991 (FT_CMap_DoneFunc
) NULL
, /* done */
1992 (FT_CMap_CharIndexFunc
)tt_cmap8_char_index
, /* char_index */
1993 (FT_CMap_CharNextFunc
) tt_cmap8_char_next
, /* char_next */
1995 (FT_CMap_CharVarIndexFunc
) NULL
, /* char_var_index */
1996 (FT_CMap_CharVarIsDefaultFunc
)NULL
, /* char_var_default */
1997 (FT_CMap_VariantListFunc
) NULL
, /* variant_list */
1998 (FT_CMap_CharVariantListFunc
) NULL
, /* charvariant_list */
1999 (FT_CMap_VariantCharListFunc
) NULL
, /* variantchar_list */
2002 (TT_CMap_ValidateFunc
)tt_cmap8_validate
, /* validate */
2003 (TT_CMap_Info_GetFunc
)tt_cmap8_get_info
/* get_cmap_info */
2006 #endif /* TT_CONFIG_CMAP_FORMAT_8 */
2009 /*************************************************************************/
2010 /*************************************************************************/
2012 /***** FORMAT 10 *****/
2014 /*************************************************************************/
2015 /*************************************************************************/
2017 /*************************************************************************/
2019 /* TABLE OVERVIEW */
2020 /* -------------- */
2022 /* NAME OFFSET TYPE DESCRIPTION */
2024 /* format 0 USHORT must be 10 */
2025 /* reserved 2 USHORT reserved */
2026 /* length 4 ULONG length in bytes */
2027 /* language 8 ULONG Mac language code */
2029 /* start 12 ULONG first char in range */
2030 /* count 16 ULONG number of chars in range */
2031 /* glyphIds 20 USHORT[count] glyph indices covered */
2034 #ifdef TT_CONFIG_CMAP_FORMAT_10
2036 FT_CALLBACK_DEF( FT_Error
)
2037 tt_cmap10_validate( FT_Byte
* table
,
2038 FT_Validator valid
)
2040 FT_Byte
* p
= table
+ 4;
2041 FT_ULong length
, count
;
2044 if ( table
+ 20 > valid
->limit
)
2045 FT_INVALID_TOO_SHORT
;
2047 length
= TT_NEXT_ULONG( p
);
2049 count
= TT_NEXT_ULONG( p
);
2051 if ( length
> (FT_ULong
)( valid
->limit
- table
) ||
2052 /* length < 20 + count * 2 ? */
2054 ( length
- 20 ) / 2 < count
)
2055 FT_INVALID_TOO_SHORT
;
2057 /* check glyph indices */
2058 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
2063 for ( ; count
> 0; count
-- )
2065 gindex
= TT_NEXT_USHORT( p
);
2066 if ( gindex
>= TT_VALID_GLYPH_COUNT( valid
) )
2067 FT_INVALID_GLYPH_ID
;
2075 FT_CALLBACK_DEF( FT_UInt
)
2076 tt_cmap10_char_index( TT_CMap cmap
,
2077 FT_UInt32 char_code
)
2079 FT_Byte
* table
= cmap
->data
;
2081 FT_Byte
* p
= table
+ 12;
2082 FT_UInt32 start
= TT_NEXT_ULONG( p
);
2083 FT_UInt32 count
= TT_NEXT_ULONG( p
);
2087 if ( char_code
< start
)
2090 idx
= char_code
- start
;
2095 result
= TT_PEEK_USHORT( p
);
2102 FT_CALLBACK_DEF( FT_UInt32
)
2103 tt_cmap10_char_next( TT_CMap cmap
,
2104 FT_UInt32
*pchar_code
)
2106 FT_Byte
* table
= cmap
->data
;
2107 FT_UInt32 char_code
;
2109 FT_Byte
* p
= table
+ 12;
2110 FT_UInt32 start
= TT_NEXT_ULONG( p
);
2111 FT_UInt32 count
= TT_NEXT_ULONG( p
);
2115 if ( *pchar_code
>= 0xFFFFFFFFUL
)
2118 char_code
= *pchar_code
+ 1;
2120 if ( char_code
< start
)
2123 idx
= char_code
- start
;
2126 for ( ; idx
< count
; idx
++ )
2128 gindex
= TT_NEXT_USHORT( p
);
2132 if ( char_code
>= 0xFFFFFFFFUL
)
2138 *pchar_code
= char_code
;
2143 FT_CALLBACK_DEF( FT_Error
)
2144 tt_cmap10_get_info( TT_CMap cmap
,
2145 TT_CMapInfo
*cmap_info
)
2147 FT_Byte
* p
= cmap
->data
+ 8;
2150 cmap_info
->format
= 10;
2151 cmap_info
->language
= (FT_ULong
)TT_PEEK_ULONG( p
);
2158 tt_cmap10_class_rec
,
2160 sizeof ( TT_CMapRec
),
2162 (FT_CMap_InitFunc
) tt_cmap_init
, /* init */
2163 (FT_CMap_DoneFunc
) NULL
, /* done */
2164 (FT_CMap_CharIndexFunc
)tt_cmap10_char_index
, /* char_index */
2165 (FT_CMap_CharNextFunc
) tt_cmap10_char_next
, /* char_next */
2167 (FT_CMap_CharVarIndexFunc
) NULL
, /* char_var_index */
2168 (FT_CMap_CharVarIsDefaultFunc
)NULL
, /* char_var_default */
2169 (FT_CMap_VariantListFunc
) NULL
, /* variant_list */
2170 (FT_CMap_CharVariantListFunc
) NULL
, /* charvariant_list */
2171 (FT_CMap_VariantCharListFunc
) NULL
, /* variantchar_list */
2174 (TT_CMap_ValidateFunc
)tt_cmap10_validate
, /* validate */
2175 (TT_CMap_Info_GetFunc
)tt_cmap10_get_info
/* get_cmap_info */
2178 #endif /* TT_CONFIG_CMAP_FORMAT_10 */
2181 /*************************************************************************/
2182 /*************************************************************************/
2184 /***** FORMAT 12 *****/
2186 /*************************************************************************/
2187 /*************************************************************************/
2189 /*************************************************************************/
2191 /* TABLE OVERVIEW */
2192 /* -------------- */
2194 /* NAME OFFSET TYPE DESCRIPTION */
2196 /* format 0 USHORT must be 12 */
2197 /* reserved 2 USHORT reserved */
2198 /* length 4 ULONG length in bytes */
2199 /* language 8 ULONG Mac language code */
2200 /* count 12 ULONG number of groups */
2203 /* This header is followed by `count' groups of the following format: */
2205 /* start 0 ULONG first charcode */
2206 /* end 4 ULONG last charcode */
2207 /* startId 8 ULONG start glyph ID for the group */
2210 #ifdef TT_CONFIG_CMAP_FORMAT_12
2212 typedef struct TT_CMap12Rec_
2216 FT_ULong cur_charcode
;
2219 FT_ULong num_groups
;
2221 } TT_CMap12Rec
, *TT_CMap12
;
2224 FT_CALLBACK_DEF( FT_Error
)
2225 tt_cmap12_init( TT_CMap12 cmap
,
2228 cmap
->cmap
.data
= table
;
2231 cmap
->num_groups
= FT_PEEK_ULONG( table
);
2239 FT_CALLBACK_DEF( FT_Error
)
2240 tt_cmap12_validate( FT_Byte
* table
,
2241 FT_Validator valid
)
2245 FT_ULong num_groups
;
2248 if ( table
+ 16 > valid
->limit
)
2249 FT_INVALID_TOO_SHORT
;
2252 length
= TT_NEXT_ULONG( p
);
2255 num_groups
= TT_NEXT_ULONG( p
);
2257 if ( length
> (FT_ULong
)( valid
->limit
- table
) ||
2258 /* length < 16 + 12 * num_groups ? */
2260 ( length
- 16 ) / 12 < num_groups
)
2261 FT_INVALID_TOO_SHORT
;
2263 /* check groups, they must be in increasing order */
2265 FT_ULong n
, start
, end
, start_id
, last
= 0;
2268 for ( n
= 0; n
< num_groups
; n
++ )
2270 start
= TT_NEXT_ULONG( p
);
2271 end
= TT_NEXT_ULONG( p
);
2272 start_id
= TT_NEXT_ULONG( p
);
2277 if ( n
> 0 && start
<= last
)
2280 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
2282 FT_UInt32 d
= end
- start
;
2285 /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
2286 if ( d
> TT_VALID_GLYPH_COUNT( valid
) ||
2287 start_id
>= TT_VALID_GLYPH_COUNT( valid
) - d
)
2288 FT_INVALID_GLYPH_ID
;
2299 /* search the index of the charcode next to cmap->cur_charcode */
2300 /* cmap->cur_group should be set up properly by caller */
2303 tt_cmap12_next( TT_CMap12 cmap
)
2305 FT_Face face
= cmap
->cmap
.cmap
.charmap
.face
;
2307 FT_ULong start
, end
, start_id
, char_code
;
2312 if ( cmap
->cur_charcode
>= 0xFFFFFFFFUL
)
2315 char_code
= cmap
->cur_charcode
+ 1;
2317 for ( n
= cmap
->cur_group
; n
< cmap
->num_groups
; n
++ )
2319 p
= cmap
->cmap
.data
+ 16 + 12 * n
;
2320 start
= TT_NEXT_ULONG( p
);
2321 end
= TT_NEXT_ULONG( p
);
2322 start_id
= TT_PEEK_ULONG( p
);
2324 if ( char_code
< start
)
2328 if ( char_code
<= end
)
2330 /* ignore invalid group */
2331 if ( start_id
> 0xFFFFFFFFUL
- ( char_code
- start
) )
2334 gindex
= (FT_UInt
)( start_id
+ ( char_code
- start
) );
2336 /* does first element of group point to `.notdef' glyph? */
2339 if ( char_code
>= 0xFFFFFFFFUL
)
2346 /* if `gindex' is invalid, the remaining values */
2347 /* in this group are invalid, too */
2348 if ( gindex
>= (FT_UInt
)face
->num_glyphs
)
2354 cmap
->cur_charcode
= char_code
;
2355 cmap
->cur_gindex
= gindex
;
2356 cmap
->cur_group
= n
;
2368 tt_cmap12_char_map_binary( TT_CMap cmap
,
2369 FT_UInt32
* pchar_code
,
2373 FT_Byte
* p
= cmap
->data
+ 12;
2374 FT_UInt32 num_groups
= TT_PEEK_ULONG( p
);
2375 FT_UInt32 char_code
= *pchar_code
;
2376 FT_UInt32 start
, end
, start_id
;
2377 FT_UInt32 max
, min
, mid
;
2383 /* make compiler happy */
2389 if ( char_code
>= 0xFFFFFFFFUL
)
2401 mid
= ( min
+ max
) >> 1;
2402 p
= cmap
->data
+ 16 + 12 * mid
;
2404 start
= TT_NEXT_ULONG( p
);
2405 end
= TT_NEXT_ULONG( p
);
2407 if ( char_code
< start
)
2409 else if ( char_code
> end
)
2413 start_id
= TT_PEEK_ULONG( p
);
2415 /* reject invalid glyph index */
2416 if ( start_id
> 0xFFFFFFFFUL
- ( char_code
- start
) )
2419 gindex
= (FT_UInt
)( start_id
+ ( char_code
- start
) );
2426 FT_Face face
= cmap
->cmap
.charmap
.face
;
2427 TT_CMap12 cmap12
= (TT_CMap12
)cmap
;
2430 /* if `char_code' is not in any group, then `mid' is */
2431 /* the group nearest to `char_code' */
2433 if ( char_code
> end
)
2436 if ( mid
== num_groups
)
2441 cmap12
->cur_charcode
= char_code
;
2442 cmap12
->cur_group
= mid
;
2444 if ( gindex
>= (FT_UInt
)face
->num_glyphs
)
2449 tt_cmap12_next( cmap12
);
2451 if ( cmap12
->valid
)
2452 gindex
= cmap12
->cur_gindex
;
2455 cmap12
->cur_gindex
= gindex
;
2457 *pchar_code
= cmap12
->cur_charcode
;
2464 FT_CALLBACK_DEF( FT_UInt
)
2465 tt_cmap12_char_index( TT_CMap cmap
,
2466 FT_UInt32 char_code
)
2468 return tt_cmap12_char_map_binary( cmap
, &char_code
, 0 );
2472 FT_CALLBACK_DEF( FT_UInt32
)
2473 tt_cmap12_char_next( TT_CMap cmap
,
2474 FT_UInt32
*pchar_code
)
2476 TT_CMap12 cmap12
= (TT_CMap12
)cmap
;
2480 /* no need to search */
2481 if ( cmap12
->valid
&& cmap12
->cur_charcode
== *pchar_code
)
2483 tt_cmap12_next( cmap12
);
2484 if ( cmap12
->valid
)
2486 gindex
= cmap12
->cur_gindex
;
2487 *pchar_code
= (FT_UInt32
)cmap12
->cur_charcode
;
2493 gindex
= tt_cmap12_char_map_binary( cmap
, pchar_code
, 1 );
2499 FT_CALLBACK_DEF( FT_Error
)
2500 tt_cmap12_get_info( TT_CMap cmap
,
2501 TT_CMapInfo
*cmap_info
)
2503 FT_Byte
* p
= cmap
->data
+ 8;
2506 cmap_info
->format
= 12;
2507 cmap_info
->language
= (FT_ULong
)TT_PEEK_ULONG( p
);
2514 tt_cmap12_class_rec
,
2516 sizeof ( TT_CMap12Rec
),
2518 (FT_CMap_InitFunc
) tt_cmap12_init
, /* init */
2519 (FT_CMap_DoneFunc
) NULL
, /* done */
2520 (FT_CMap_CharIndexFunc
)tt_cmap12_char_index
, /* char_index */
2521 (FT_CMap_CharNextFunc
) tt_cmap12_char_next
, /* char_next */
2523 (FT_CMap_CharVarIndexFunc
) NULL
, /* char_var_index */
2524 (FT_CMap_CharVarIsDefaultFunc
)NULL
, /* char_var_default */
2525 (FT_CMap_VariantListFunc
) NULL
, /* variant_list */
2526 (FT_CMap_CharVariantListFunc
) NULL
, /* charvariant_list */
2527 (FT_CMap_VariantCharListFunc
) NULL
, /* variantchar_list */
2530 (TT_CMap_ValidateFunc
)tt_cmap12_validate
, /* validate */
2531 (TT_CMap_Info_GetFunc
)tt_cmap12_get_info
/* get_cmap_info */
2534 #endif /* TT_CONFIG_CMAP_FORMAT_12 */
2537 /*************************************************************************/
2538 /*************************************************************************/
2540 /***** FORMAT 13 *****/
2542 /*************************************************************************/
2543 /*************************************************************************/
2545 /*************************************************************************/
2547 /* TABLE OVERVIEW */
2548 /* -------------- */
2550 /* NAME OFFSET TYPE DESCRIPTION */
2552 /* format 0 USHORT must be 13 */
2553 /* reserved 2 USHORT reserved */
2554 /* length 4 ULONG length in bytes */
2555 /* language 8 ULONG Mac language code */
2556 /* count 12 ULONG number of groups */
2559 /* This header is followed by `count' groups of the following format: */
2561 /* start 0 ULONG first charcode */
2562 /* end 4 ULONG last charcode */
2563 /* glyphId 8 ULONG glyph ID for the whole group */
2566 #ifdef TT_CONFIG_CMAP_FORMAT_13
2568 typedef struct TT_CMap13Rec_
2572 FT_ULong cur_charcode
;
2575 FT_ULong num_groups
;
2577 } TT_CMap13Rec
, *TT_CMap13
;
2580 FT_CALLBACK_DEF( FT_Error
)
2581 tt_cmap13_init( TT_CMap13 cmap
,
2584 cmap
->cmap
.data
= table
;
2587 cmap
->num_groups
= FT_PEEK_ULONG( table
);
2595 FT_CALLBACK_DEF( FT_Error
)
2596 tt_cmap13_validate( FT_Byte
* table
,
2597 FT_Validator valid
)
2601 FT_ULong num_groups
;
2604 if ( table
+ 16 > valid
->limit
)
2605 FT_INVALID_TOO_SHORT
;
2608 length
= TT_NEXT_ULONG( p
);
2611 num_groups
= TT_NEXT_ULONG( p
);
2613 if ( length
> (FT_ULong
)( valid
->limit
- table
) ||
2614 /* length < 16 + 12 * num_groups ? */
2616 ( length
- 16 ) / 12 < num_groups
)
2617 FT_INVALID_TOO_SHORT
;
2619 /* check groups, they must be in increasing order */
2621 FT_ULong n
, start
, end
, glyph_id
, last
= 0;
2624 for ( n
= 0; n
< num_groups
; n
++ )
2626 start
= TT_NEXT_ULONG( p
);
2627 end
= TT_NEXT_ULONG( p
);
2628 glyph_id
= TT_NEXT_ULONG( p
);
2633 if ( n
> 0 && start
<= last
)
2636 if ( valid
->level
>= FT_VALIDATE_TIGHT
)
2638 if ( glyph_id
>= TT_VALID_GLYPH_COUNT( valid
) )
2639 FT_INVALID_GLYPH_ID
;
2650 /* search the index of the charcode next to cmap->cur_charcode */
2651 /* cmap->cur_group should be set up properly by caller */
2654 tt_cmap13_next( TT_CMap13 cmap
)
2656 FT_Face face
= cmap
->cmap
.cmap
.charmap
.face
;
2658 FT_ULong start
, end
, glyph_id
, char_code
;
2663 if ( cmap
->cur_charcode
>= 0xFFFFFFFFUL
)
2666 char_code
= cmap
->cur_charcode
+ 1;
2668 for ( n
= cmap
->cur_group
; n
< cmap
->num_groups
; n
++ )
2670 p
= cmap
->cmap
.data
+ 16 + 12 * n
;
2671 start
= TT_NEXT_ULONG( p
);
2672 end
= TT_NEXT_ULONG( p
);
2673 glyph_id
= TT_PEEK_ULONG( p
);
2675 if ( char_code
< start
)
2678 if ( char_code
<= end
)
2680 gindex
= (FT_UInt
)glyph_id
;
2682 if ( gindex
&& gindex
< (FT_UInt
)face
->num_glyphs
)
2684 cmap
->cur_charcode
= char_code
;
2685 cmap
->cur_gindex
= gindex
;
2686 cmap
->cur_group
= n
;
2699 tt_cmap13_char_map_binary( TT_CMap cmap
,
2700 FT_UInt32
* pchar_code
,
2704 FT_Byte
* p
= cmap
->data
+ 12;
2705 FT_UInt32 num_groups
= TT_PEEK_ULONG( p
);
2706 FT_UInt32 char_code
= *pchar_code
;
2707 FT_UInt32 start
, end
;
2708 FT_UInt32 max
, min
, mid
;
2714 /* make compiler happy */
2720 if ( char_code
>= 0xFFFFFFFFUL
)
2732 mid
= ( min
+ max
) >> 1;
2733 p
= cmap
->data
+ 16 + 12 * mid
;
2735 start
= TT_NEXT_ULONG( p
);
2736 end
= TT_NEXT_ULONG( p
);
2738 if ( char_code
< start
)
2740 else if ( char_code
> end
)
2744 gindex
= (FT_UInt
)TT_PEEK_ULONG( p
);
2752 FT_Face face
= cmap
->cmap
.charmap
.face
;
2753 TT_CMap13 cmap13
= (TT_CMap13
)cmap
;
2756 /* if `char_code' is not in any group, then `mid' is */
2757 /* the group nearest to `char_code' */
2759 if ( char_code
> end
)
2762 if ( mid
== num_groups
)
2767 cmap13
->cur_charcode
= char_code
;
2768 cmap13
->cur_group
= mid
;
2770 if ( gindex
>= (FT_UInt
)face
->num_glyphs
)
2775 tt_cmap13_next( cmap13
);
2777 if ( cmap13
->valid
)
2778 gindex
= cmap13
->cur_gindex
;
2781 cmap13
->cur_gindex
= gindex
;
2783 *pchar_code
= cmap13
->cur_charcode
;
2790 FT_CALLBACK_DEF( FT_UInt
)
2791 tt_cmap13_char_index( TT_CMap cmap
,
2792 FT_UInt32 char_code
)
2794 return tt_cmap13_char_map_binary( cmap
, &char_code
, 0 );
2798 FT_CALLBACK_DEF( FT_UInt32
)
2799 tt_cmap13_char_next( TT_CMap cmap
,
2800 FT_UInt32
*pchar_code
)
2802 TT_CMap13 cmap13
= (TT_CMap13
)cmap
;
2806 /* no need to search */
2807 if ( cmap13
->valid
&& cmap13
->cur_charcode
== *pchar_code
)
2809 tt_cmap13_next( cmap13
);
2810 if ( cmap13
->valid
)
2812 gindex
= cmap13
->cur_gindex
;
2813 *pchar_code
= cmap13
->cur_charcode
;
2819 gindex
= tt_cmap13_char_map_binary( cmap
, pchar_code
, 1 );
2825 FT_CALLBACK_DEF( FT_Error
)
2826 tt_cmap13_get_info( TT_CMap cmap
,
2827 TT_CMapInfo
*cmap_info
)
2829 FT_Byte
* p
= cmap
->data
+ 8;
2832 cmap_info
->format
= 13;
2833 cmap_info
->language
= (FT_ULong
)TT_PEEK_ULONG( p
);
2840 tt_cmap13_class_rec
,
2842 sizeof ( TT_CMap13Rec
),
2844 (FT_CMap_InitFunc
) tt_cmap13_init
, /* init */
2845 (FT_CMap_DoneFunc
) NULL
, /* done */
2846 (FT_CMap_CharIndexFunc
)tt_cmap13_char_index
, /* char_index */
2847 (FT_CMap_CharNextFunc
) tt_cmap13_char_next
, /* char_next */
2849 (FT_CMap_CharVarIndexFunc
) NULL
, /* char_var_index */
2850 (FT_CMap_CharVarIsDefaultFunc
)NULL
, /* char_var_default */
2851 (FT_CMap_VariantListFunc
) NULL
, /* variant_list */
2852 (FT_CMap_CharVariantListFunc
) NULL
, /* charvariant_list */
2853 (FT_CMap_VariantCharListFunc
) NULL
, /* variantchar_list */
2856 (TT_CMap_ValidateFunc
)tt_cmap13_validate
, /* validate */
2857 (TT_CMap_Info_GetFunc
)tt_cmap13_get_info
/* get_cmap_info */
2860 #endif /* TT_CONFIG_CMAP_FORMAT_13 */
2863 /*************************************************************************/
2864 /*************************************************************************/
2866 /***** FORMAT 14 *****/
2868 /*************************************************************************/
2869 /*************************************************************************/
2871 /*************************************************************************/
2873 /* TABLE OVERVIEW */
2874 /* -------------- */
2876 /* NAME OFFSET TYPE DESCRIPTION */
2878 /* format 0 USHORT must be 14 */
2879 /* length 2 ULONG table length in bytes */
2880 /* numSelector 6 ULONG number of variation sel. records */
2882 /* Followed by numSelector records, each of which looks like */
2884 /* varSelector 0 UINT24 Unicode codepoint of sel. */
2885 /* defaultOff 3 ULONG offset to a default UVS table */
2886 /* describing any variants to be found in */
2887 /* the normal Unicode subtable. */
2888 /* nonDefOff 7 ULONG offset to a non-default UVS table */
2889 /* describing any variants not in the */
2890 /* standard cmap, with GIDs here */
2891 /* (either offset may be 0 NULL) */
2893 /* Selectors are sorted by code point. */
2895 /* A default Unicode Variation Selector (UVS) subtable is just a list of */
2896 /* ranges of code points which are to be found in the standard cmap. No */
2897 /* glyph IDs (GIDs) here. */
2899 /* numRanges 0 ULONG number of ranges following */
2901 /* A range looks like */
2903 /* uniStart 0 UINT24 code point of the first character in */
2905 /* additionalCnt 3 UBYTE count of additional characters in this */
2906 /* range (zero means a range of a single */
2909 /* Ranges are sorted by `uniStart'. */
2911 /* A non-default Unicode Variation Selector (UVS) subtable is a list of */
2912 /* mappings from codepoint to GID. */
2914 /* numMappings 0 ULONG number of mappings */
2916 /* A range looks like */
2918 /* uniStart 0 UINT24 code point of the first character in */
2920 /* GID 3 USHORT and its GID */
2922 /* Ranges are sorted by `uniStart'. */
2924 #ifdef TT_CONFIG_CMAP_FORMAT_14
2926 typedef struct TT_CMap14Rec_
2929 FT_ULong num_selectors
;
2931 /* This array is used to store the results of various
2932 * cmap 14 query functions. The data is overwritten
2933 * on each call to these functions.
2935 FT_UInt32 max_results
;
2939 } TT_CMap14Rec
, *TT_CMap14
;
2942 FT_CALLBACK_DEF( void )
2943 tt_cmap14_done( TT_CMap14 cmap
)
2945 FT_Memory memory
= cmap
->memory
;
2948 cmap
->max_results
= 0;
2949 if ( memory
&& cmap
->results
)
2950 FT_FREE( cmap
->results
);
2955 tt_cmap14_ensure( TT_CMap14 cmap
,
2956 FT_UInt32 num_results
,
2959 FT_UInt32 old_max
= cmap
->max_results
;
2960 FT_Error error
= FT_Err_Ok
;
2963 if ( num_results
> cmap
->max_results
)
2965 cmap
->memory
= memory
;
2967 if ( FT_QRENEW_ARRAY( cmap
->results
, old_max
, num_results
) )
2970 cmap
->max_results
= num_results
;
2977 FT_CALLBACK_DEF( FT_Error
)
2978 tt_cmap14_init( TT_CMap14 cmap
,
2981 cmap
->cmap
.data
= table
;
2984 cmap
->num_selectors
= FT_PEEK_ULONG( table
);
2985 cmap
->max_results
= 0;
2986 cmap
->results
= NULL
;
2992 FT_CALLBACK_DEF( FT_Error
)
2993 tt_cmap14_validate( FT_Byte
* table
,
2994 FT_Validator valid
)
2998 FT_ULong num_selectors
;
3001 if ( table
+ 2 + 4 + 4 > valid
->limit
)
3002 FT_INVALID_TOO_SHORT
;
3005 length
= TT_NEXT_ULONG( p
);
3006 num_selectors
= TT_NEXT_ULONG( p
);
3008 if ( length
> (FT_ULong
)( valid
->limit
- table
) ||
3009 /* length < 10 + 11 * num_selectors ? */
3011 ( length
- 10 ) / 11 < num_selectors
)
3012 FT_INVALID_TOO_SHORT
;
3014 /* check selectors, they must be in increasing order */
3016 /* we start lastVarSel at 1 because a variant selector value of 0
3019 FT_ULong n
, lastVarSel
= 1;
3022 for ( n
= 0; n
< num_selectors
; n
++ )
3024 FT_ULong varSel
= TT_NEXT_UINT24( p
);
3025 FT_ULong defOff
= TT_NEXT_ULONG( p
);
3026 FT_ULong nondefOff
= TT_NEXT_ULONG( p
);
3029 if ( defOff
>= length
|| nondefOff
>= length
)
3030 FT_INVALID_TOO_SHORT
;
3032 if ( varSel
< lastVarSel
)
3035 lastVarSel
= varSel
+ 1;
3037 /* check the default table (these glyphs should be reached */
3038 /* through the normal Unicode cmap, no GIDs, just check order) */
3041 FT_Byte
* defp
= table
+ defOff
;
3044 FT_ULong lastBase
= 0;
3047 if ( defp
+ 4 > valid
->limit
)
3048 FT_INVALID_TOO_SHORT
;
3050 numRanges
= TT_NEXT_ULONG( defp
);
3052 /* defp + numRanges * 4 > valid->limit ? */
3053 if ( numRanges
> (FT_ULong
)( valid
->limit
- defp
) / 4 )
3054 FT_INVALID_TOO_SHORT
;
3056 for ( i
= 0; i
< numRanges
; i
++ )
3058 FT_ULong base
= TT_NEXT_UINT24( defp
);
3059 FT_ULong cnt
= FT_NEXT_BYTE( defp
);
3062 if ( base
+ cnt
>= 0x110000UL
) /* end of Unicode */
3065 if ( base
< lastBase
)
3068 lastBase
= base
+ cnt
+ 1U;
3072 /* and the non-default table (these glyphs are specified here) */
3073 if ( nondefOff
!= 0 )
3075 FT_Byte
* ndp
= table
+ nondefOff
;
3076 FT_ULong numMappings
;
3077 FT_ULong i
, lastUni
= 0;
3080 if ( ndp
+ 4 > valid
->limit
)
3081 FT_INVALID_TOO_SHORT
;
3083 numMappings
= TT_NEXT_ULONG( ndp
);
3085 /* numMappings * 5 > (FT_ULong)( valid->limit - ndp ) ? */
3086 if ( numMappings
> ( (FT_ULong
)( valid
->limit
- ndp
) ) / 5 )
3087 FT_INVALID_TOO_SHORT
;
3089 for ( i
= 0; i
< numMappings
; i
++ )
3091 FT_ULong uni
= TT_NEXT_UINT24( ndp
);
3092 FT_ULong gid
= TT_NEXT_USHORT( ndp
);
3095 if ( uni
>= 0x110000UL
) /* end of Unicode */
3098 if ( uni
< lastUni
)
3103 if ( valid
->level
>= FT_VALIDATE_TIGHT
&&
3104 gid
>= TT_VALID_GLYPH_COUNT( valid
) )
3105 FT_INVALID_GLYPH_ID
;
3115 FT_CALLBACK_DEF( FT_UInt
)
3116 tt_cmap14_char_index( TT_CMap cmap
,
3117 FT_UInt32 char_code
)
3120 FT_UNUSED( char_code
);
3122 /* This can't happen */
3127 FT_CALLBACK_DEF( FT_UInt32
)
3128 tt_cmap14_char_next( TT_CMap cmap
,
3129 FT_UInt32
*pchar_code
)
3133 /* This can't happen */
3139 FT_CALLBACK_DEF( FT_Error
)
3140 tt_cmap14_get_info( TT_CMap cmap
,
3141 TT_CMapInfo
*cmap_info
)
3145 cmap_info
->format
= 14;
3146 /* subtable 14 does not define a language field */
3147 cmap_info
->language
= 0xFFFFFFFFUL
;
3154 tt_cmap14_char_map_def_binary( FT_Byte
*base
,
3155 FT_UInt32 char_code
)
3157 FT_UInt32 numRanges
= TT_PEEK_ULONG( base
);
3169 FT_UInt32 mid
= ( min
+ max
) >> 1;
3170 FT_Byte
* p
= base
+ 4 * mid
;
3171 FT_ULong start
= TT_NEXT_UINT24( p
);
3172 FT_UInt cnt
= FT_NEXT_BYTE( p
);
3175 if ( char_code
< start
)
3177 else if ( char_code
> start
+ cnt
)
3188 tt_cmap14_char_map_nondef_binary( FT_Byte
*base
,
3189 FT_UInt32 char_code
)
3191 FT_UInt32 numMappings
= TT_PEEK_ULONG( base
);
3203 FT_UInt32 mid
= ( min
+ max
) >> 1;
3204 FT_Byte
* p
= base
+ 5 * mid
;
3205 FT_UInt32 uni
= (FT_UInt32
)TT_NEXT_UINT24( p
);
3208 if ( char_code
< uni
)
3210 else if ( char_code
> uni
)
3213 return TT_PEEK_USHORT( p
);
3221 tt_cmap14_find_variant( FT_Byte
*base
,
3222 FT_UInt32 variantCode
)
3224 FT_UInt32 numVar
= TT_PEEK_ULONG( base
);
3236 FT_UInt32 mid
= ( min
+ max
) >> 1;
3237 FT_Byte
* p
= base
+ 11 * mid
;
3238 FT_ULong varSel
= TT_NEXT_UINT24( p
);
3241 if ( variantCode
< varSel
)
3243 else if ( variantCode
> varSel
)
3253 FT_CALLBACK_DEF( FT_UInt
)
3254 tt_cmap14_char_var_index( TT_CMap cmap
,
3257 FT_UInt32 variantSelector
)
3259 FT_Byte
* p
= tt_cmap14_find_variant( cmap
->data
+ 6, variantSelector
);
3267 defOff
= TT_NEXT_ULONG( p
);
3268 nondefOff
= TT_PEEK_ULONG( p
);
3271 tt_cmap14_char_map_def_binary( cmap
->data
+ defOff
, charcode
) )
3273 /* This is the default variant of this charcode. GID not stored */
3274 /* here; stored in the normal Unicode charmap instead. */
3275 return ucmap
->cmap
.clazz
->char_index( &ucmap
->cmap
, charcode
);
3278 if ( nondefOff
!= 0 )
3279 return tt_cmap14_char_map_nondef_binary( cmap
->data
+ nondefOff
,
3286 FT_CALLBACK_DEF( FT_Int
)
3287 tt_cmap14_char_var_isdefault( TT_CMap cmap
,
3289 FT_UInt32 variantSelector
)
3291 FT_Byte
* p
= tt_cmap14_find_variant( cmap
->data
+ 6, variantSelector
);
3299 defOff
= TT_NEXT_ULONG( p
);
3300 nondefOff
= TT_NEXT_ULONG( p
);
3303 tt_cmap14_char_map_def_binary( cmap
->data
+ defOff
, charcode
) )
3306 if ( nondefOff
!= 0 &&
3307 tt_cmap14_char_map_nondef_binary( cmap
->data
+ nondefOff
,
3315 FT_CALLBACK_DEF( FT_UInt32
* )
3316 tt_cmap14_variants( TT_CMap cmap
,
3319 TT_CMap14 cmap14
= (TT_CMap14
)cmap
;
3320 FT_UInt32 count
= cmap14
->num_selectors
;
3321 FT_Byte
* p
= cmap
->data
+ 10;
3326 if ( tt_cmap14_ensure( cmap14
, ( count
+ 1 ), memory
) )
3329 result
= cmap14
->results
;
3330 for ( i
= 0; i
< count
; i
++ )
3332 result
[i
] = (FT_UInt32
)TT_NEXT_UINT24( p
);
3341 FT_CALLBACK_DEF( FT_UInt32
* )
3342 tt_cmap14_char_variants( TT_CMap cmap
,
3344 FT_UInt32 charCode
)
3346 TT_CMap14 cmap14
= (TT_CMap14
) cmap
;
3347 FT_UInt32 count
= cmap14
->num_selectors
;
3348 FT_Byte
* p
= cmap
->data
+ 10;
3352 if ( tt_cmap14_ensure( cmap14
, ( count
+ 1 ), memory
) )
3355 for ( q
= cmap14
->results
; count
> 0; count
-- )
3357 FT_UInt32 varSel
= TT_NEXT_UINT24( p
);
3358 FT_ULong defOff
= TT_NEXT_ULONG( p
);
3359 FT_ULong nondefOff
= TT_NEXT_ULONG( p
);
3362 if ( ( defOff
!= 0 &&
3363 tt_cmap14_char_map_def_binary( cmap
->data
+ defOff
,
3366 tt_cmap14_char_map_nondef_binary( cmap
->data
+ nondefOff
,
3375 return cmap14
->results
;
3380 tt_cmap14_def_char_count( FT_Byte
*p
)
3382 FT_UInt32 numRanges
= (FT_UInt32
)TT_NEXT_ULONG( p
);
3386 p
+= 3; /* point to the first `cnt' field */
3387 for ( ; numRanges
> 0; numRanges
-- )
3398 tt_cmap14_get_def_chars( TT_CMap cmap
,
3402 TT_CMap14 cmap14
= (TT_CMap14
) cmap
;
3403 FT_UInt32 numRanges
;
3408 cnt
= tt_cmap14_def_char_count( p
);
3409 numRanges
= (FT_UInt32
)TT_NEXT_ULONG( p
);
3411 if ( tt_cmap14_ensure( cmap14
, ( cnt
+ 1 ), memory
) )
3414 for ( q
= cmap14
->results
; numRanges
> 0; numRanges
-- )
3416 FT_UInt32 uni
= (FT_UInt32
)TT_NEXT_UINT24( p
);
3419 cnt
= FT_NEXT_BYTE( p
) + 1;
3426 } while ( --cnt
!= 0 );
3430 return cmap14
->results
;
3435 tt_cmap14_get_nondef_chars( TT_CMap cmap
,
3439 TT_CMap14 cmap14
= (TT_CMap14
) cmap
;
3440 FT_UInt32 numMappings
;
3445 numMappings
= (FT_UInt32
)TT_NEXT_ULONG( p
);
3447 if ( tt_cmap14_ensure( cmap14
, ( numMappings
+ 1 ), memory
) )
3450 ret
= cmap14
->results
;
3451 for ( i
= 0; i
< numMappings
; i
++ )
3453 ret
[i
] = (FT_UInt32
)TT_NEXT_UINT24( p
);
3462 FT_CALLBACK_DEF( FT_UInt32
* )
3463 tt_cmap14_variant_chars( TT_CMap cmap
,
3465 FT_UInt32 variantSelector
)
3467 FT_Byte
*p
= tt_cmap14_find_variant( cmap
->data
+ 6,
3477 defOff
= TT_NEXT_ULONG( p
);
3478 nondefOff
= TT_NEXT_ULONG( p
);
3480 if ( defOff
== 0 && nondefOff
== 0 )
3484 return tt_cmap14_get_nondef_chars( cmap
, cmap
->data
+ nondefOff
,
3486 else if ( nondefOff
== 0 )
3487 return tt_cmap14_get_def_chars( cmap
, cmap
->data
+ defOff
,
3491 /* Both a default and a non-default glyph set? That's probably not */
3492 /* good font design, but the spec allows for it... */
3493 TT_CMap14 cmap14
= (TT_CMap14
) cmap
;
3494 FT_UInt32 numRanges
;
3495 FT_UInt32 numMappings
;
3505 p
= cmap
->data
+ nondefOff
;
3506 dp
= cmap
->data
+ defOff
;
3508 numMappings
= (FT_UInt32
)TT_NEXT_ULONG( p
);
3509 dcnt
= tt_cmap14_def_char_count( dp
);
3510 numRanges
= (FT_UInt32
)TT_NEXT_ULONG( dp
);
3512 if ( numMappings
== 0 )
3513 return tt_cmap14_get_def_chars( cmap
, cmap
->data
+ defOff
,
3516 return tt_cmap14_get_nondef_chars( cmap
, cmap
->data
+ nondefOff
,
3519 if ( tt_cmap14_ensure( cmap14
, ( dcnt
+ numMappings
+ 1 ), memory
) )
3522 ret
= cmap14
->results
;
3523 duni
= (FT_UInt32
)TT_NEXT_UINT24( dp
);
3524 dcnt
= FT_NEXT_BYTE( dp
);
3526 nuni
= (FT_UInt32
)TT_NEXT_UINT24( p
);
3533 if ( nuni
> duni
+ dcnt
)
3535 for ( k
= 0; k
<= dcnt
; k
++ )
3536 ret
[i
++] = duni
+ k
;
3540 if ( di
> numRanges
)
3543 duni
= (FT_UInt32
)TT_NEXT_UINT24( dp
);
3544 dcnt
= FT_NEXT_BYTE( dp
);
3550 /* If it is within the default range then ignore it -- */
3551 /* that should not have happened */
3553 if ( ni
> numMappings
)
3556 nuni
= (FT_UInt32
)TT_NEXT_UINT24( p
);
3561 if ( ni
<= numMappings
)
3563 /* If we get here then we have run out of all default ranges. */
3564 /* We have read one non-default mapping which we haven't stored */
3565 /* and there may be others that need to be read. */
3567 while ( ni
< numMappings
)
3569 ret
[i
++] = (FT_UInt32
)TT_NEXT_UINT24( p
);
3574 else if ( di
<= numRanges
)
3576 /* If we get here then we have run out of all non-default */
3577 /* mappings. We have read one default range which we haven't */
3578 /* stored and there may be others that need to be read. */
3579 for ( k
= 0; k
<= dcnt
; k
++ )
3580 ret
[i
++] = duni
+ k
;
3582 while ( di
< numRanges
)
3584 duni
= (FT_UInt32
)TT_NEXT_UINT24( dp
);
3585 dcnt
= FT_NEXT_BYTE( dp
);
3587 for ( k
= 0; k
<= dcnt
; k
++ )
3588 ret
[i
++] = duni
+ k
;
3601 tt_cmap14_class_rec
,
3603 sizeof ( TT_CMap14Rec
),
3605 (FT_CMap_InitFunc
) tt_cmap14_init
, /* init */
3606 (FT_CMap_DoneFunc
) tt_cmap14_done
, /* done */
3607 (FT_CMap_CharIndexFunc
)tt_cmap14_char_index
, /* char_index */
3608 (FT_CMap_CharNextFunc
) tt_cmap14_char_next
, /* char_next */
3610 /* Format 14 extension functions */
3611 (FT_CMap_CharVarIndexFunc
) tt_cmap14_char_var_index
,
3612 (FT_CMap_CharVarIsDefaultFunc
)tt_cmap14_char_var_isdefault
,
3613 (FT_CMap_VariantListFunc
) tt_cmap14_variants
,
3614 (FT_CMap_CharVariantListFunc
) tt_cmap14_char_variants
,
3615 (FT_CMap_VariantCharListFunc
) tt_cmap14_variant_chars
,
3618 (TT_CMap_ValidateFunc
)tt_cmap14_validate
, /* validate */
3619 (TT_CMap_Info_GetFunc
)tt_cmap14_get_info
/* get_cmap_info */
3622 #endif /* TT_CONFIG_CMAP_FORMAT_14 */
3625 #ifndef FT_CONFIG_OPTION_PIC
3627 static const TT_CMap_Class tt_cmap_classes
[] =
3629 #define TTCMAPCITEM( a ) &a,
3630 #include "ttcmapc.h"
3634 #else /*FT_CONFIG_OPTION_PIC*/
3637 FT_Destroy_Class_tt_cmap_classes( FT_Library library
,
3638 TT_CMap_Class
* clazz
)
3640 FT_Memory memory
= library
->memory
;
3649 FT_Create_Class_tt_cmap_classes( FT_Library library
,
3650 TT_CMap_Class
** output_class
)
3652 TT_CMap_Class
* clazz
= NULL
;
3653 TT_CMap_ClassRec
* recs
;
3655 FT_Memory memory
= library
->memory
;
3660 #define TTCMAPCITEM( a ) i++;
3661 #include "ttcmapc.h"
3663 /* allocate enough space for both the pointers */
3664 /* plus terminator and the class instances */
3665 if ( FT_ALLOC( clazz
, sizeof ( *clazz
) * ( i
+ 1 ) +
3666 sizeof ( TT_CMap_ClassRec
) * i
) )
3669 /* the location of the class instances follows the array of pointers */
3670 recs
= (TT_CMap_ClassRec
*)( (char*)clazz
+
3671 sizeof ( *clazz
) * ( i
+ 1 ) );
3675 #define TTCMAPCITEM( a ) \
3676 FT_Init_Class_ ## a( &recs[i] ); \
3677 clazz[i] = &recs[i]; \
3679 #include "ttcmapc.h"
3683 *output_class
= clazz
;
3687 #endif /*FT_CONFIG_OPTION_PIC*/
3690 /* parse the `cmap' table and build the corresponding TT_CMap objects */
3691 /* in the current face */
3693 FT_LOCAL_DEF( FT_Error
)
3694 tt_face_build_cmaps( TT_Face face
)
3696 FT_Byte
* table
= face
->cmap_table
;
3697 FT_Byte
* limit
= table
+ face
->cmap_size
;
3698 FT_UInt
volatile num_cmaps
;
3699 FT_Byte
* volatile p
= table
;
3700 FT_Library library
= FT_FACE_LIBRARY( face
);
3702 FT_UNUSED( library
);
3705 if ( !p
|| p
+ 4 > limit
)
3706 return FT_THROW( Invalid_Table
);
3708 /* only recognize format 0 */
3709 if ( TT_NEXT_USHORT( p
) != 0 )
3711 FT_ERROR(( "tt_face_build_cmaps:"
3712 " unsupported `cmap' table format = %d\n",
3713 TT_PEEK_USHORT( p
- 2 ) ));
3714 return FT_THROW( Invalid_Table
);
3717 num_cmaps
= TT_NEXT_USHORT( p
);
3719 for ( ; num_cmaps
> 0 && p
+ 8 <= limit
; num_cmaps
-- )
3721 FT_CharMapRec charmap
;
3725 charmap
.platform_id
= TT_NEXT_USHORT( p
);
3726 charmap
.encoding_id
= TT_NEXT_USHORT( p
);
3727 charmap
.face
= FT_FACE( face
);
3728 charmap
.encoding
= FT_ENCODING_NONE
; /* will be filled later */
3729 offset
= TT_NEXT_ULONG( p
);
3731 if ( offset
&& offset
<= face
->cmap_size
- 2 )
3733 FT_Byte
* volatile cmap
= table
+ offset
;
3734 volatile FT_UInt format
= TT_PEEK_USHORT( cmap
);
3735 const TT_CMap_Class
* volatile pclazz
= TT_CMAP_CLASSES_GET
;
3736 TT_CMap_Class
volatile clazz
;
3739 for ( ; *pclazz
; pclazz
++ )
3742 if ( clazz
->format
== format
)
3744 volatile TT_ValidatorRec valid
;
3745 volatile FT_Error error
= FT_Err_Ok
;
3748 ft_validator_init( FT_VALIDATOR( &valid
), cmap
, limit
,
3749 FT_VALIDATE_DEFAULT
);
3751 valid
.num_glyphs
= (FT_UInt
)face
->max_profile
.numGlyphs
;
3753 if ( ft_setjmp( FT_VALIDATOR( &valid
)->jump_buffer
) == 0 )
3755 /* validate this cmap sub-table */
3756 error
= clazz
->validate( cmap
, FT_VALIDATOR( &valid
) );
3759 if ( !valid
.validator
.error
)
3764 /* It might make sense to store the single variation */
3765 /* selector cmap somewhere special. But it would have to be */
3766 /* in the public FT_FaceRec, and we can't change that. */
3768 if ( !FT_CMap_New( (FT_CMap_Class
)clazz
,
3769 cmap
, &charmap
, &ttcmap
) )
3771 /* it is simpler to directly set `flags' than adding */
3772 /* a parameter to FT_CMap_New */
3773 ((TT_CMap
)ttcmap
)->flags
= (FT_Int
)error
;
3778 FT_TRACE0(( "tt_face_build_cmaps:"
3779 " broken cmap sub-table ignored\n" ));
3787 FT_TRACE0(( "tt_face_build_cmaps:"
3788 " unsupported cmap sub-table ignored\n" ));
3797 FT_LOCAL( FT_Error
)
3798 tt_get_cmap_info( FT_CharMap charmap
,
3799 TT_CMapInfo
*cmap_info
)
3801 FT_CMap cmap
= (FT_CMap
)charmap
;
3802 TT_CMap_Class clazz
= (TT_CMap_Class
)cmap
->clazz
;
3805 return clazz
->get_cmap_info( charmap
, cmap_info
);