1 /***************************************************************************/
5 /* TrueType character mapping table (cmap) support (body). */
7 /* Copyright 2002-2010, 2012-2014 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 FT_CALLBACK_DEF( FT_Error )
55 tt_cmap_init( TT_CMap cmap,
63 /*************************************************************************/
64 /*************************************************************************/
66 /***** FORMAT 0 *****/
68 /*************************************************************************/
69 /*************************************************************************/
71 /*************************************************************************/
76 /* NAME OFFSET TYPE DESCRIPTION */
78 /* format 0 USHORT must be 0 */
79 /* length 2 USHORT table length in bytes */
80 /* language 4 USHORT Mac language code */
81 /* glyph_ids 6 BYTE[256] array of glyph indices */
85 #ifdef TT_CONFIG_CMAP_FORMAT_0
87 FT_CALLBACK_DEF( FT_Error )
88 tt_cmap0_validate( FT_Byte* table,
95 if ( table + 2 + 2 > valid->limit )
98 p = table + 2; /* skip format */
99 length = TT_NEXT_USHORT( p );
101 if ( table + length > valid->limit || length < 262 )
102 FT_INVALID_TOO_SHORT;
104 /* check glyph indices whenever necessary */
105 if ( valid->level >= FT_VALIDATE_TIGHT )
111 for ( n = 0; n < 256; n++ )
114 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
123 FT_CALLBACK_DEF( FT_UInt )
124 tt_cmap0_char_index( TT_CMap cmap,
125 FT_UInt32 char_code )
127 FT_Byte* table = cmap->data;
130 return char_code < 256 ? table[6 + char_code] : 0;
134 FT_CALLBACK_DEF( FT_UInt32 )
135 tt_cmap0_char_next( TT_CMap cmap,
136 FT_UInt32 *pchar_code )
138 FT_Byte* table = cmap->data;
139 FT_UInt32 charcode = *pchar_code;
140 FT_UInt32 result = 0;
144 table += 6; /* go to glyph IDs */
145 while ( ++charcode < 256 )
147 gindex = table[charcode];
155 *pchar_code = result;
160 FT_CALLBACK_DEF( FT_Error )
161 tt_cmap0_get_info( TT_CMap cmap,
162 TT_CMapInfo *cmap_info )
164 FT_Byte* p = cmap->data + 4;
167 cmap_info->format = 0;
168 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
176 sizeof ( TT_CMapRec ),
178 (FT_CMap_InitFunc) tt_cmap_init,
179 (FT_CMap_DoneFunc) NULL,
180 (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
181 (FT_CMap_CharNextFunc) tt_cmap0_char_next,
190 (TT_CMap_ValidateFunc)tt_cmap0_validate,
191 (TT_CMap_Info_GetFunc)tt_cmap0_get_info )
193 #endif /* TT_CONFIG_CMAP_FORMAT_0 */
196 /*************************************************************************/
197 /*************************************************************************/
199 /***** FORMAT 2 *****/
201 /***** This is used for certain CJK encodings that encode text in a *****/
202 /***** mixed 8/16 bits encoding along the following lines: *****/
204 /***** * Certain byte values correspond to an 8-bit character code *****/
205 /***** (typically in the range 0..127 for ASCII compatibility). *****/
207 /***** * Certain byte values signal the first byte of a 2-byte *****/
208 /***** character code (but these values are also valid as the *****/
209 /***** second byte of a 2-byte character). *****/
211 /***** The following charmap lookup and iteration functions all *****/
212 /***** assume that the value "charcode" correspond to following: *****/
214 /***** - For one byte characters, "charcode" is simply the *****/
215 /***** character code. *****/
217 /***** - For two byte characters, "charcode" is the 2-byte *****/
218 /***** character code in big endian format. More exactly: *****/
220 /***** (charcode >> 8) is the first byte value *****/
221 /***** (charcode & 0xFF) is the second byte value *****/
223 /***** Note that not all values of "charcode" are valid according *****/
224 /***** to these rules, and the function moderately check the *****/
225 /***** arguments. *****/
227 /*************************************************************************/
228 /*************************************************************************/
230 /*************************************************************************/
235 /* NAME OFFSET TYPE DESCRIPTION */
237 /* format 0 USHORT must be 2 */
238 /* length 2 USHORT table length in bytes */
239 /* language 4 USHORT Mac language code */
240 /* keys 6 USHORT[256] sub-header keys */
241 /* subs 518 SUBHEAD[NSUBS] sub-headers array */
242 /* glyph_ids 518+NSUB*8 USHORT[] glyph ID array */
244 /* The `keys' table is used to map charcode high-bytes to sub-headers. */
245 /* The value of `NSUBS' is the number of sub-headers defined in the */
246 /* table and is computed by finding the maximum of the `keys' table. */
248 /* Note that for any n, `keys[n]' is a byte offset within the `subs' */
249 /* table, i.e., it is the corresponding sub-header index multiplied */
252 /* Each sub-header has the following format: */
254 /* NAME OFFSET TYPE DESCRIPTION */
256 /* first 0 USHORT first valid low-byte */
257 /* count 2 USHORT number of valid low-bytes */
258 /* delta 4 SHORT see below */
259 /* offset 6 USHORT see below */
261 /* A sub-header defines, for each high-byte, the range of valid */
262 /* low-bytes within the charmap. Note that the range defined by `first' */
263 /* and `count' must be completely included in the interval [0..255] */
264 /* according to the specification. */
266 /* If a character code is contained within a given sub-header, then */
267 /* mapping it to a glyph index is done as follows: */
269 /* * The value of `offset' is read. This is a _byte_ distance from the */
270 /* location of the `offset' field itself into a slice of the */
271 /* `glyph_ids' table. Let's call it `slice' (it is a USHORT[] too). */
273 /* * The value `slice[char.lo - first]' is read. If it is 0, there is */
274 /* no glyph for the charcode. Otherwise, the value of `delta' is */
275 /* added to it (modulo 65536) to form a new glyph index. */
277 /* It is up to the validation routine to check that all offsets fall */
278 /* within the glyph IDs table (and not within the `subs' table itself or */
279 /* outside of the CMap). */
282 #ifdef TT_CONFIG_CMAP_FORMAT_2
284 FT_CALLBACK_DEF( FT_Error )
285 tt_cmap2_validate( FT_Byte* table,
292 FT_Byte* keys; /* keys table */
293 FT_Byte* subs; /* sub-headers */
294 FT_Byte* glyph_ids; /* glyph ID array */
297 if ( table + 2 + 2 > valid->limit )
298 FT_INVALID_TOO_SHORT;
300 p = table + 2; /* skip format */
301 length = TT_NEXT_USHORT( p );
303 if ( table + length > valid->limit || length < 6 + 512 )
304 FT_INVALID_TOO_SHORT;
308 /* parse keys to compute sub-headers count */
311 for ( n = 0; n < 256; n++ )
313 FT_UInt idx = TT_NEXT_USHORT( p );
316 /* value must be multiple of 8 */
317 if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
322 if ( idx > max_subs )
326 FT_ASSERT( p == table + 518 );
329 glyph_ids = subs + (max_subs + 1) * 8;
330 if ( glyph_ids > valid->limit )
331 FT_INVALID_TOO_SHORT;
333 /* parse sub-headers */
334 for ( n = 0; n <= max_subs; n++ )
336 FT_UInt first_code, code_count, offset;
340 first_code = TT_NEXT_USHORT( p );
341 code_count = TT_NEXT_USHORT( p );
342 delta = TT_NEXT_SHORT( p );
343 offset = TT_NEXT_USHORT( p );
345 /* many Dynalab fonts have empty sub-headers */
346 if ( code_count == 0 )
349 /* check range within 0..255 */
350 if ( valid->level >= FT_VALIDATE_PARANOID )
352 if ( first_code >= 256 || first_code + code_count > 256 )
362 ids = p - 2 + offset;
363 if ( ids < glyph_ids || ids + code_count*2 > table + length )
366 /* check glyph IDs */
367 if ( valid->level >= FT_VALIDATE_TIGHT )
369 FT_Byte* limit = p + code_count * 2;
375 idx = TT_NEXT_USHORT( p );
378 idx = ( idx + delta ) & 0xFFFFU;
379 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
391 /* return sub header corresponding to a given character code */
392 /* NULL on invalid charcode */
394 tt_cmap2_get_subheader( FT_Byte* table,
395 FT_UInt32 char_code )
397 FT_Byte* result = NULL;
400 if ( char_code < 0x10000UL )
402 FT_UInt char_lo = (FT_UInt)( char_code & 0xFF );
403 FT_UInt char_hi = (FT_UInt)( char_code >> 8 );
404 FT_Byte* p = table + 6; /* keys table */
405 FT_Byte* subs = table + 518; /* subheaders table */
411 /* an 8-bit character code -- we use subHeader 0 in this case */
412 /* to test whether the character code is in the charmap */
414 sub = subs; /* jump to first sub-header */
416 /* check that the sub-header for this byte is 0, which */
417 /* indicates that it is really a valid one-byte value */
418 /* Otherwise, return 0 */
421 if ( TT_PEEK_USHORT( p ) != 0 )
426 /* a 16-bit character code */
428 /* jump to key entry */
430 /* jump to sub-header */
431 sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) );
433 /* check that the high byte isn't a valid one-byte value */
444 FT_CALLBACK_DEF( FT_UInt )
445 tt_cmap2_char_index( TT_CMap cmap,
446 FT_UInt32 char_code )
448 FT_Byte* table = cmap->data;
453 subheader = tt_cmap2_get_subheader( table, char_code );
456 FT_Byte* p = subheader;
457 FT_UInt idx = (FT_UInt)(char_code & 0xFF);
458 FT_UInt start, count;
463 start = TT_NEXT_USHORT( p );
464 count = TT_NEXT_USHORT( p );
465 delta = TT_NEXT_SHORT ( p );
466 offset = TT_PEEK_USHORT( p );
469 if ( idx < count && offset != 0 )
471 p += offset + 2 * idx;
472 idx = TT_PEEK_USHORT( p );
475 result = (FT_UInt)( idx + delta ) & 0xFFFFU;
482 FT_CALLBACK_DEF( FT_UInt32 )
483 tt_cmap2_char_next( TT_CMap cmap,
484 FT_UInt32 *pcharcode )
486 FT_Byte* table = cmap->data;
488 FT_UInt32 result = 0;
489 FT_UInt32 charcode = *pcharcode + 1;
493 while ( charcode < 0x10000UL )
495 subheader = tt_cmap2_get_subheader( table, charcode );
498 FT_Byte* p = subheader;
499 FT_UInt start = TT_NEXT_USHORT( p );
500 FT_UInt count = TT_NEXT_USHORT( p );
501 FT_Int delta = TT_NEXT_SHORT ( p );
502 FT_UInt offset = TT_PEEK_USHORT( p );
503 FT_UInt char_lo = (FT_UInt)( charcode & 0xFF );
510 if ( char_lo < start )
516 pos = (FT_UInt)( char_lo - start );
518 p += offset + pos * 2;
519 charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo;
521 for ( ; pos < count; pos++, charcode++ )
523 idx = TT_NEXT_USHORT( p );
527 gindex = ( idx + delta ) & 0xFFFFU;
537 /* jump to next sub-header, i.e. higher byte value */
539 charcode = FT_PAD_FLOOR( charcode, 256 ) + 256;
549 FT_CALLBACK_DEF( FT_Error )
550 tt_cmap2_get_info( TT_CMap cmap,
551 TT_CMapInfo *cmap_info )
553 FT_Byte* p = cmap->data + 4;
556 cmap_info->format = 2;
557 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
565 sizeof ( TT_CMapRec ),
567 (FT_CMap_InitFunc) tt_cmap_init,
568 (FT_CMap_DoneFunc) NULL,
569 (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
570 (FT_CMap_CharNextFunc) tt_cmap2_char_next,
579 (TT_CMap_ValidateFunc)tt_cmap2_validate,
580 (TT_CMap_Info_GetFunc)tt_cmap2_get_info )
582 #endif /* TT_CONFIG_CMAP_FORMAT_2 */
585 /*************************************************************************/
586 /*************************************************************************/
588 /***** FORMAT 4 *****/
590 /*************************************************************************/
591 /*************************************************************************/
593 /*************************************************************************/
598 /* NAME OFFSET TYPE DESCRIPTION */
600 /* format 0 USHORT must be 4 */
601 /* length 2 USHORT table length */
603 /* language 4 USHORT Mac language code */
605 /* segCountX2 6 USHORT 2*NUM_SEGS */
606 /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */
607 /* entrySelector 10 USHORT LOG_SEGS */
608 /* rangeShift 12 USHORT segCountX2 - */
611 /* endCount 14 USHORT[NUM_SEGS] end charcode for */
612 /* each segment; last */
615 /* pad 14+NUM_SEGS*2 USHORT padding */
617 /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */
620 /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */
622 /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */
623 /* each segment; can be */
626 /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph ID */
629 /* Character codes are modelled by a series of ordered (increasing) */
630 /* intervals called segments. Each segment has start and end codes, */
631 /* provided by the `startCount' and `endCount' arrays. Segments must */
632 /* not overlap, and the last segment should always contain the value */
633 /* 0xFFFF for `endCount'. */
635 /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
636 /* ignored (they are traces of over-engineering in the TrueType */
637 /* specification). */
639 /* Each segment also has a signed `delta', as well as an optional offset */
640 /* within the `glyphIds' table. */
642 /* If a segment's idOffset is 0, the glyph index corresponding to any */
643 /* charcode within the segment is obtained by adding the value of */
644 /* `idDelta' directly to the charcode, modulo 65536. */
646 /* Otherwise, a glyph index is taken from the glyph IDs sub-array for */
647 /* the segment, and the value of `idDelta' is added to it. */
650 /* Finally, note that a lot of fonts contain an invalid last segment, */
651 /* where `start' and `end' are correctly set to 0xFFFF but both `delta' */
652 /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with */
653 /* OpenOffice.org). We need special code to deal with them correctly. */
656 #ifdef TT_CONFIG_CMAP_FORMAT_4
658 typedef struct TT_CMap4Rec_
661 FT_UInt32 cur_charcode; /* current charcode */
662 FT_UInt cur_gindex; /* current glyph index */
671 } TT_CMap4Rec, *TT_CMap4;
674 FT_CALLBACK_DEF( FT_Error )
675 tt_cmap4_init( TT_CMap4 cmap,
681 cmap->cmap.data = table;
684 cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1;
685 cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
686 cmap->cur_gindex = 0;
693 tt_cmap4_set_range( TT_CMap4 cmap,
694 FT_UInt range_index )
696 FT_Byte* table = cmap->cmap.data;
698 FT_UInt num_ranges = cmap->num_ranges;
701 while ( range_index < num_ranges )
706 p = table + 14 + range_index * 2;
707 cmap->cur_end = FT_PEEK_USHORT( p );
709 p += 2 + num_ranges * 2;
710 cmap->cur_start = FT_PEEK_USHORT( p );
713 cmap->cur_delta = FT_PEEK_SHORT( p );
716 offset = FT_PEEK_USHORT( p );
718 /* some fonts have an incorrect last segment; */
719 /* we have to catch it */
720 if ( range_index >= num_ranges - 1 &&
721 cmap->cur_start == 0xFFFFU &&
722 cmap->cur_end == 0xFFFFU )
724 TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face;
725 FT_Byte* limit = face->cmap_table + face->cmap_size;
728 if ( offset && p + offset + 2 > limit )
735 if ( offset != 0xFFFFU )
737 cmap->cur_values = offset ? p + offset : NULL;
738 cmap->cur_range = range_index;
742 /* we skip empty segments */
750 /* search the index of the charcode next to cmap->cur_charcode; */
751 /* caller should call tt_cmap4_set_range with proper range */
752 /* before calling this function */
755 tt_cmap4_next( TT_CMap4 cmap )
760 if ( cmap->cur_charcode >= 0xFFFFUL )
763 charcode = (FT_UInt)cmap->cur_charcode + 1;
765 if ( charcode < cmap->cur_start )
766 charcode = cmap->cur_start;
770 FT_Byte* values = cmap->cur_values;
771 FT_UInt end = cmap->cur_end;
772 FT_Int delta = cmap->cur_delta;
775 if ( charcode <= end )
779 FT_Byte* p = values + 2 * ( charcode - cmap->cur_start );
784 FT_UInt gindex = FT_NEXT_USHORT( p );
789 gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU );
792 cmap->cur_charcode = charcode;
793 cmap->cur_gindex = gindex;
797 } while ( ++charcode <= end );
803 FT_UInt gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU );
808 cmap->cur_charcode = charcode;
809 cmap->cur_gindex = gindex;
812 } while ( ++charcode <= end );
816 /* we need to find another range */
817 if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )
820 if ( charcode < cmap->cur_start )
821 charcode = cmap->cur_start;
825 cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
826 cmap->cur_gindex = 0;
830 FT_CALLBACK_DEF( FT_Error )
831 tt_cmap4_validate( FT_Byte* table,
837 FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids;
839 FT_Error error = FT_Err_Ok;
842 if ( table + 2 + 2 > valid->limit )
843 FT_INVALID_TOO_SHORT;
845 p = table + 2; /* skip format */
846 length = TT_NEXT_USHORT( p );
848 /* in certain fonts, the `length' field is invalid and goes */
849 /* out of bound. We try to correct this here... */
850 if ( table + length > valid->limit )
852 if ( valid->level >= FT_VALIDATE_TIGHT )
853 FT_INVALID_TOO_SHORT;
855 length = (FT_UInt)( valid->limit - table );
859 FT_INVALID_TOO_SHORT;
862 num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */
864 if ( valid->level >= FT_VALIDATE_PARANOID )
866 /* check that we have an even value here */
873 if ( length < 16 + num_segs * 2 * 4 )
874 FT_INVALID_TOO_SHORT;
876 /* check the search parameters - even though we never use them */
878 if ( valid->level >= FT_VALIDATE_PARANOID )
880 /* check the values of `searchRange', `entrySelector', `rangeShift' */
881 FT_UInt search_range = TT_NEXT_USHORT( p );
882 FT_UInt entry_selector = TT_NEXT_USHORT( p );
883 FT_UInt range_shift = TT_NEXT_USHORT( p );
886 if ( ( search_range | range_shift ) & 1 ) /* must be even values */
892 /* `search range' is the greatest power of 2 that is <= num_segs */
894 if ( search_range > num_segs ||
895 search_range * 2 < num_segs ||
896 search_range + range_shift != num_segs ||
897 search_range != ( 1U << entry_selector ) )
902 starts = table + 16 + num_segs * 2;
903 deltas = starts + num_segs * 2;
904 offsets = deltas + num_segs * 2;
905 glyph_ids = offsets + num_segs * 2;
907 /* check last segment; its end count value must be 0xFFFF */
908 if ( valid->level >= FT_VALIDATE_PARANOID )
910 p = ends + ( num_segs - 1 ) * 2;
911 if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
916 FT_UInt start, end, offset, n;
917 FT_UInt last_start = 0, last_end = 0;
919 FT_Byte* p_start = starts;
920 FT_Byte* p_end = ends;
921 FT_Byte* p_delta = deltas;
922 FT_Byte* p_offset = offsets;
925 for ( n = 0; n < num_segs; n++ )
928 start = TT_NEXT_USHORT( p_start );
929 end = TT_NEXT_USHORT( p_end );
930 delta = TT_NEXT_SHORT( p_delta );
931 offset = TT_NEXT_USHORT( p_offset );
936 /* this test should be performed at default validation level; */
937 /* unfortunately, some popular Asian fonts have overlapping */
938 /* ranges in their charmaps */
940 if ( start <= last_end && n > 0 )
942 if ( valid->level >= FT_VALIDATE_TIGHT )
946 /* allow overlapping segments, provided their start points */
947 /* and end points, respectively, are in ascending order */
949 if ( last_start > start || last_end > end )
950 error |= TT_CMAP_FLAG_UNSORTED;
952 error |= TT_CMAP_FLAG_OVERLAPPING;
956 if ( offset && offset != 0xFFFFU )
958 p += offset; /* start of glyph ID array */
960 /* check that we point within the glyph IDs table only */
961 if ( valid->level >= FT_VALIDATE_TIGHT )
963 if ( p < glyph_ids ||
964 p + ( end - start + 1 ) * 2 > table + length )
967 /* Some fonts handle the last segment incorrectly. In */
968 /* theory, 0xFFFF might point to an ordinary glyph -- */
969 /* a cmap 4 is versatile and could be used for any */
970 /* encoding, not only Unicode. However, reality shows */
971 /* that far too many fonts are sloppy and incorrectly */
972 /* set all fields but `start' and `end' for the last */
973 /* segment if it contains only a single character. */
975 /* We thus omit the test here, delaying it to the */
976 /* routines which actually access the cmap. */
977 else if ( n != num_segs - 1 ||
978 !( start == 0xFFFFU && end == 0xFFFFU ) )
980 if ( p < glyph_ids ||
981 p + ( end - start + 1 ) * 2 > valid->limit )
985 /* check glyph indices within the segment range */
986 if ( valid->level >= FT_VALIDATE_TIGHT )
991 for ( i = start; i < end; i++ )
993 idx = FT_NEXT_USHORT( p );
996 idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
998 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
1004 else if ( offset == 0xFFFFU )
1006 /* some fonts (erroneously?) use a range offset of 0xFFFF */
1007 /* to mean missing glyph in cmap table */
1009 if ( valid->level >= FT_VALIDATE_PARANOID ||
1010 n != num_segs - 1 ||
1011 !( start == 0xFFFFU && end == 0xFFFFU ) )
1025 tt_cmap4_char_map_linear( TT_CMap cmap,
1026 FT_UInt32* pcharcode,
1029 FT_UInt num_segs2, start, end, offset;
1031 FT_UInt i, num_segs;
1032 FT_UInt32 charcode = *pcharcode;
1038 num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
1040 num_segs = num_segs2 >> 1;
1049 for ( ; charcode <= 0xFFFFU; charcode++ )
1054 p = cmap->data + 14; /* ends table */
1055 q = cmap->data + 16 + num_segs2; /* starts table */
1057 for ( i = 0; i < num_segs; i++ )
1059 end = TT_NEXT_USHORT( p );
1060 start = TT_NEXT_USHORT( q );
1062 if ( charcode >= start && charcode <= end )
1064 p = q - 2 + num_segs2;
1065 delta = TT_PEEK_SHORT( p );
1067 offset = TT_PEEK_USHORT( p );
1069 /* some fonts have an incorrect last segment; */
1070 /* we have to catch it */
1071 if ( i >= num_segs - 1 &&
1072 start == 0xFFFFU && end == 0xFFFFU )
1074 TT_Face face = (TT_Face)cmap->cmap.charmap.face;
1075 FT_Byte* limit = face->cmap_table + face->cmap_size;
1078 if ( offset && p + offset + 2 > limit )
1085 if ( offset == 0xFFFFU )
1090 p += offset + ( charcode - start ) * 2;
1091 gindex = TT_PEEK_USHORT( p );
1093 gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
1096 gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
1102 if ( !next || gindex )
1106 if ( next && gindex )
1107 *pcharcode = charcode;
1114 tt_cmap4_char_map_binary( TT_CMap cmap,
1115 FT_UInt32* pcharcode,
1118 FT_UInt num_segs2, start, end, offset;
1120 FT_UInt max, min, mid, num_segs;
1121 FT_UInt charcode = (FT_UInt)*pcharcode;
1127 num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
1132 num_segs = num_segs2 >> 1;
1134 /* make compiler happy */
1147 mid = ( min + max ) >> 1;
1148 p = cmap->data + 14 + mid * 2;
1149 end = TT_PEEK_USHORT( p );
1151 start = TT_PEEK_USHORT( p );
1153 if ( charcode < start )
1155 else if ( charcode > end )
1160 delta = TT_PEEK_SHORT( p );
1162 offset = TT_PEEK_USHORT( p );
1164 /* some fonts have an incorrect last segment; */
1165 /* we have to catch it */
1166 if ( mid >= num_segs - 1 &&
1167 start == 0xFFFFU && end == 0xFFFFU )
1169 TT_Face face = (TT_Face)cmap->cmap.charmap.face;
1170 FT_Byte* limit = face->cmap_table + face->cmap_size;
1173 if ( offset && p + offset + 2 > limit )
1180 /* search the first segment containing `charcode' */
1181 if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING )
1186 /* call the current segment `max' */
1189 if ( offset == 0xFFFFU )
1192 /* search in segments before the current segment */
1193 for ( i = max ; i > 0; i-- )
1200 p = cmap->data + 14 + ( i - 1 ) * 2;
1201 prev_end = TT_PEEK_USHORT( p );
1203 if ( charcode > prev_end )
1211 start = TT_PEEK_USHORT( p );
1213 delta = TT_PEEK_SHORT( p );
1215 offset = TT_PEEK_USHORT( p );
1217 if ( offset != 0xFFFFU )
1222 if ( mid == max + 1 )
1226 p = cmap->data + 14 + max * 2;
1227 end = TT_PEEK_USHORT( p );
1229 start = TT_PEEK_USHORT( p );
1231 delta = TT_PEEK_SHORT( p );
1233 offset = TT_PEEK_USHORT( p );
1238 /* search in segments after the current segment */
1239 for ( i = max + 1; i < num_segs; i++ )
1241 FT_UInt next_end, next_start;
1244 p = cmap->data + 14 + i * 2;
1245 next_end = TT_PEEK_USHORT( p );
1247 next_start = TT_PEEK_USHORT( p );
1249 if ( charcode < next_start )
1255 delta = TT_PEEK_SHORT( p );
1257 offset = TT_PEEK_USHORT( p );
1259 if ( offset != 0xFFFFU )
1273 /* end, start, delta, and offset are for the i'th segment */
1276 p = cmap->data + 14 + mid * 2;
1277 end = TT_PEEK_USHORT( p );
1279 start = TT_PEEK_USHORT( p );
1281 delta = TT_PEEK_SHORT( p );
1283 offset = TT_PEEK_USHORT( p );
1288 if ( offset == 0xFFFFU )
1294 p += offset + ( charcode - start ) * 2;
1295 gindex = TT_PEEK_USHORT( p );
1297 gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
1300 gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
1308 TT_CMap4 cmap4 = (TT_CMap4)cmap;
1311 /* if `charcode' is not in any segment, then `mid' is */
1312 /* the segment nearest to `charcode' */
1315 if ( charcode > end )
1318 if ( mid == num_segs )
1322 if ( tt_cmap4_set_range( cmap4, mid ) )
1325 *pcharcode = charcode;
1329 cmap4->cur_charcode = charcode;
1332 cmap4->cur_gindex = gindex;
1335 cmap4->cur_charcode = charcode;
1336 tt_cmap4_next( cmap4 );
1337 gindex = cmap4->cur_gindex;
1341 *pcharcode = cmap4->cur_charcode;
1349 FT_CALLBACK_DEF( FT_UInt )
1350 tt_cmap4_char_index( TT_CMap cmap,
1351 FT_UInt32 char_code )
1353 if ( char_code >= 0x10000UL )
1356 if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
1357 return tt_cmap4_char_map_linear( cmap, &char_code, 0 );
1359 return tt_cmap4_char_map_binary( cmap, &char_code, 0 );
1363 FT_CALLBACK_DEF( FT_UInt32 )
1364 tt_cmap4_char_next( TT_CMap cmap,
1365 FT_UInt32 *pchar_code )
1370 if ( *pchar_code >= 0xFFFFU )
1373 if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
1374 gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 );
1377 TT_CMap4 cmap4 = (TT_CMap4)cmap;
1380 /* no need to search */
1381 if ( *pchar_code == cmap4->cur_charcode )
1383 tt_cmap4_next( cmap4 );
1384 gindex = cmap4->cur_gindex;
1386 *pchar_code = cmap4->cur_charcode;
1389 gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 );
1396 FT_CALLBACK_DEF( FT_Error )
1397 tt_cmap4_get_info( TT_CMap cmap,
1398 TT_CMapInfo *cmap_info )
1400 FT_Byte* p = cmap->data + 4;
1403 cmap_info->format = 4;
1404 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1412 sizeof ( TT_CMap4Rec ),
1413 (FT_CMap_InitFunc) tt_cmap4_init,
1414 (FT_CMap_DoneFunc) NULL,
1415 (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
1416 (FT_CMap_CharNextFunc) tt_cmap4_char_next,
1425 (TT_CMap_ValidateFunc)tt_cmap4_validate,
1426 (TT_CMap_Info_GetFunc)tt_cmap4_get_info )
1428 #endif /* TT_CONFIG_CMAP_FORMAT_4 */
1431 /*************************************************************************/
1432 /*************************************************************************/
1434 /***** FORMAT 6 *****/
1436 /*************************************************************************/
1437 /*************************************************************************/
1439 /*************************************************************************/
1441 /* TABLE OVERVIEW */
1442 /* -------------- */
1444 /* NAME OFFSET TYPE DESCRIPTION */
1446 /* format 0 USHORT must be 4 */
1447 /* length 2 USHORT table length in bytes */
1448 /* language 4 USHORT Mac language code */
1450 /* first 6 USHORT first segment code */
1451 /* count 8 USHORT segment size in chars */
1452 /* glyphIds 10 USHORT[count] glyph IDs */
1454 /* A very simplified segment mapping. */
1457 #ifdef TT_CONFIG_CMAP_FORMAT_6
1459 FT_CALLBACK_DEF( FT_Error )
1460 tt_cmap6_validate( FT_Byte* table,
1461 FT_Validator valid )
1464 FT_UInt length, count;
1467 if ( table + 10 > valid->limit )
1468 FT_INVALID_TOO_SHORT;
1471 length = TT_NEXT_USHORT( p );
1473 p = table + 8; /* skip language and start index */
1474 count = TT_NEXT_USHORT( p );
1476 if ( table + length > valid->limit || length < 10 + count * 2 )
1477 FT_INVALID_TOO_SHORT;
1479 /* check glyph indices */
1480 if ( valid->level >= FT_VALIDATE_TIGHT )
1485 for ( ; count > 0; count-- )
1487 gindex = TT_NEXT_USHORT( p );
1488 if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1489 FT_INVALID_GLYPH_ID;
1497 FT_CALLBACK_DEF( FT_UInt )
1498 tt_cmap6_char_index( TT_CMap cmap,
1499 FT_UInt32 char_code )
1501 FT_Byte* table = cmap->data;
1503 FT_Byte* p = table + 6;
1504 FT_UInt start = TT_NEXT_USHORT( p );
1505 FT_UInt count = TT_NEXT_USHORT( p );
1506 FT_UInt idx = (FT_UInt)( char_code - start );
1512 result = TT_PEEK_USHORT( p );
1518 FT_CALLBACK_DEF( FT_UInt32 )
1519 tt_cmap6_char_next( TT_CMap cmap,
1520 FT_UInt32 *pchar_code )
1522 FT_Byte* table = cmap->data;
1523 FT_UInt32 result = 0;
1524 FT_UInt32 char_code = *pchar_code + 1;
1527 FT_Byte* p = table + 6;
1528 FT_UInt start = TT_NEXT_USHORT( p );
1529 FT_UInt count = TT_NEXT_USHORT( p );
1533 if ( char_code >= 0x10000UL )
1536 if ( char_code < start )
1539 idx = (FT_UInt)( char_code - start );
1542 for ( ; idx < count; idx++ )
1544 gindex = TT_NEXT_USHORT( p );
1554 *pchar_code = result;
1559 FT_CALLBACK_DEF( FT_Error )
1560 tt_cmap6_get_info( TT_CMap cmap,
1561 TT_CMapInfo *cmap_info )
1563 FT_Byte* p = cmap->data + 4;
1566 cmap_info->format = 6;
1567 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1575 sizeof ( TT_CMapRec ),
1577 (FT_CMap_InitFunc) tt_cmap_init,
1578 (FT_CMap_DoneFunc) NULL,
1579 (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
1580 (FT_CMap_CharNextFunc) tt_cmap6_char_next,
1589 (TT_CMap_ValidateFunc)tt_cmap6_validate,
1590 (TT_CMap_Info_GetFunc)tt_cmap6_get_info )
1592 #endif /* TT_CONFIG_CMAP_FORMAT_6 */
1595 /*************************************************************************/
1596 /*************************************************************************/
1598 /***** FORMAT 8 *****/
1600 /***** It is hard to completely understand what the OpenType spec *****/
1601 /***** says about this format, but here is my conclusion. *****/
1603 /***** The purpose of this format is to easily map UTF-16 text to *****/
1604 /***** glyph indices. Basically, the `char_code' must be in one of *****/
1605 /***** the following formats: *****/
1607 /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/
1608 /***** Area (i.e. U+D800-U+DFFF). *****/
1610 /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/
1611 /***** `char_code = (char_hi << 16) | char_lo', then both *****/
1612 /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/
1615 /***** The `is32' table embedded in the charmap indicates whether a *****/
1616 /***** given 16-bit value is in the surrogates area or not. *****/
1618 /***** So, for any given `char_code', we can assert the following: *****/
1620 /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/
1622 /***** If `char_hi != 0' then we must have both *****/
1623 /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/
1625 /*************************************************************************/
1626 /*************************************************************************/
1628 /*************************************************************************/
1630 /* TABLE OVERVIEW */
1631 /* -------------- */
1633 /* NAME OFFSET TYPE DESCRIPTION */
1635 /* format 0 USHORT must be 8 */
1636 /* reserved 2 USHORT reserved */
1637 /* length 4 ULONG length in bytes */
1638 /* language 8 ULONG Mac language code */
1639 /* is32 12 BYTE[8192] 32-bitness bitmap */
1640 /* count 8204 ULONG number of groups */
1642 /* This header is followed by `count' groups of the following format: */
1644 /* start 0 ULONG first charcode */
1645 /* end 4 ULONG last charcode */
1646 /* startId 8 ULONG start glyph ID for the group */
1649 #ifdef TT_CONFIG_CMAP_FORMAT_8
1651 FT_CALLBACK_DEF( FT_Error )
1652 tt_cmap8_validate( FT_Byte* table,
1653 FT_Validator valid )
1655 FT_Byte* p = table + 4;
1658 FT_UInt32 num_groups;
1661 if ( table + 16 + 8192 > valid->limit )
1662 FT_INVALID_TOO_SHORT;
1664 length = TT_NEXT_ULONG( p );
1665 if ( length > (FT_UInt32)( valid->limit - table ) || length < 8192 + 16 )
1666 FT_INVALID_TOO_SHORT;
1669 p = is32 + 8192; /* skip `is32' array */
1670 num_groups = TT_NEXT_ULONG( p );
1672 /* p + num_groups * 12 > valid->limit ? */
1673 if ( num_groups > (FT_UInt32)( valid->limit - p ) / 12 )
1674 FT_INVALID_TOO_SHORT;
1676 /* check groups, they must be in increasing order */
1678 FT_UInt32 n, start, end, start_id, count, last = 0;
1681 for ( n = 0; n < num_groups; n++ )
1686 start = TT_NEXT_ULONG( p );
1687 end = TT_NEXT_ULONG( p );
1688 start_id = TT_NEXT_ULONG( p );
1693 if ( n > 0 && start <= last )
1696 if ( valid->level >= FT_VALIDATE_TIGHT )
1698 FT_UInt32 d = end - start;
1701 /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
1702 if ( d > TT_VALID_GLYPH_COUNT( valid ) ||
1703 start_id >= TT_VALID_GLYPH_COUNT( valid ) - d )
1704 FT_INVALID_GLYPH_ID;
1706 count = (FT_UInt32)( end - start + 1 );
1708 if ( start & ~0xFFFFU )
1710 /* start_hi != 0; check that is32[i] is 1 for each i in */
1711 /* the `hi' and `lo' of the range [start..end] */
1712 for ( ; count > 0; count--, start++ )
1714 hi = (FT_UInt)( start >> 16 );
1715 lo = (FT_UInt)( start & 0xFFFFU );
1717 if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
1720 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
1726 /* start_hi == 0; check that is32[i] is 0 for each i in */
1727 /* the range [start..end] */
1729 /* end_hi cannot be != 0! */
1730 if ( end & ~0xFFFFU )
1733 for ( ; count > 0; count--, start++ )
1735 lo = (FT_UInt)( start & 0xFFFFU );
1737 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
1751 FT_CALLBACK_DEF( FT_UInt )
1752 tt_cmap8_char_index( TT_CMap cmap,
1753 FT_UInt32 char_code )
1755 FT_Byte* table = cmap->data;
1757 FT_Byte* p = table + 8204;
1758 FT_UInt32 num_groups = TT_NEXT_ULONG( p );
1759 FT_UInt32 start, end, start_id;
1762 for ( ; num_groups > 0; num_groups-- )
1764 start = TT_NEXT_ULONG( p );
1765 end = TT_NEXT_ULONG( p );
1766 start_id = TT_NEXT_ULONG( p );
1768 if ( char_code < start )
1771 if ( char_code <= end )
1773 result = (FT_UInt)( start_id + char_code - start );
1781 FT_CALLBACK_DEF( FT_UInt32 )
1782 tt_cmap8_char_next( TT_CMap cmap,
1783 FT_UInt32 *pchar_code )
1785 FT_UInt32 result = 0;
1786 FT_UInt32 char_code = *pchar_code + 1;
1788 FT_Byte* table = cmap->data;
1789 FT_Byte* p = table + 8204;
1790 FT_UInt32 num_groups = TT_NEXT_ULONG( p );
1791 FT_UInt32 start, end, start_id;
1796 for ( ; num_groups > 0; num_groups-- )
1798 start = TT_NEXT_ULONG( p );
1799 end = TT_NEXT_ULONG( p );
1800 start_id = TT_NEXT_ULONG( p );
1802 if ( char_code < start )
1805 if ( char_code <= end )
1807 gindex = (FT_UInt)( char_code - start + start_id );
1817 *pchar_code = result;
1822 FT_CALLBACK_DEF( FT_Error )
1823 tt_cmap8_get_info( TT_CMap cmap,
1824 TT_CMapInfo *cmap_info )
1826 FT_Byte* p = cmap->data + 8;
1829 cmap_info->format = 8;
1830 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1838 sizeof ( TT_CMapRec ),
1840 (FT_CMap_InitFunc) tt_cmap_init,
1841 (FT_CMap_DoneFunc) NULL,
1842 (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
1843 (FT_CMap_CharNextFunc) tt_cmap8_char_next,
1852 (TT_CMap_ValidateFunc)tt_cmap8_validate,
1853 (TT_CMap_Info_GetFunc)tt_cmap8_get_info )
1855 #endif /* TT_CONFIG_CMAP_FORMAT_8 */
1858 /*************************************************************************/
1859 /*************************************************************************/
1861 /***** FORMAT 10 *****/
1863 /*************************************************************************/
1864 /*************************************************************************/
1866 /*************************************************************************/
1868 /* TABLE OVERVIEW */
1869 /* -------------- */
1871 /* NAME OFFSET TYPE DESCRIPTION */
1873 /* format 0 USHORT must be 10 */
1874 /* reserved 2 USHORT reserved */
1875 /* length 4 ULONG length in bytes */
1876 /* language 8 ULONG Mac language code */
1878 /* start 12 ULONG first char in range */
1879 /* count 16 ULONG number of chars in range */
1880 /* glyphIds 20 USHORT[count] glyph indices covered */
1883 #ifdef TT_CONFIG_CMAP_FORMAT_10
1885 FT_CALLBACK_DEF( FT_Error )
1886 tt_cmap10_validate( FT_Byte* table,
1887 FT_Validator valid )
1889 FT_Byte* p = table + 4;
1890 FT_ULong length, count;
1893 if ( table + 20 > valid->limit )
1894 FT_INVALID_TOO_SHORT;
1896 length = TT_NEXT_ULONG( p );
1898 count = TT_NEXT_ULONG( p );
1900 if ( length > (FT_ULong)( valid->limit - table ) ||
1901 /* length < 20 + count * 2 ? */
1903 ( length - 20 ) / 2 < count )
1904 FT_INVALID_TOO_SHORT;
1906 /* check glyph indices */
1907 if ( valid->level >= FT_VALIDATE_TIGHT )
1912 for ( ; count > 0; count-- )
1914 gindex = TT_NEXT_USHORT( p );
1915 if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1916 FT_INVALID_GLYPH_ID;
1924 FT_CALLBACK_DEF( FT_UInt )
1925 tt_cmap10_char_index( TT_CMap cmap,
1926 FT_UInt32 char_code )
1928 FT_Byte* table = cmap->data;
1930 FT_Byte* p = table + 12;
1931 FT_UInt32 start = TT_NEXT_ULONG( p );
1932 FT_UInt32 count = TT_NEXT_ULONG( p );
1933 FT_UInt32 idx = (FT_ULong)( char_code - start );
1939 result = TT_PEEK_USHORT( p );
1945 FT_CALLBACK_DEF( FT_UInt32 )
1946 tt_cmap10_char_next( TT_CMap cmap,
1947 FT_UInt32 *pchar_code )
1949 FT_Byte* table = cmap->data;
1950 FT_UInt32 char_code = *pchar_code + 1;
1952 FT_Byte* p = table + 12;
1953 FT_UInt32 start = TT_NEXT_ULONG( p );
1954 FT_UInt32 count = TT_NEXT_ULONG( p );
1958 if ( char_code < start )
1961 idx = (FT_UInt32)( char_code - start );
1964 for ( ; idx < count; idx++ )
1966 gindex = TT_NEXT_USHORT( p );
1972 *pchar_code = char_code;
1977 FT_CALLBACK_DEF( FT_Error )
1978 tt_cmap10_get_info( TT_CMap cmap,
1979 TT_CMapInfo *cmap_info )
1981 FT_Byte* p = cmap->data + 8;
1984 cmap_info->format = 10;
1985 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1992 tt_cmap10_class_rec,
1993 sizeof ( TT_CMapRec ),
1995 (FT_CMap_InitFunc) tt_cmap_init,
1996 (FT_CMap_DoneFunc) NULL,
1997 (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
1998 (FT_CMap_CharNextFunc) tt_cmap10_char_next,
2007 (TT_CMap_ValidateFunc)tt_cmap10_validate,
2008 (TT_CMap_Info_GetFunc)tt_cmap10_get_info )
2010 #endif /* TT_CONFIG_CMAP_FORMAT_10 */
2013 /*************************************************************************/
2014 /*************************************************************************/
2016 /***** FORMAT 12 *****/
2018 /*************************************************************************/
2019 /*************************************************************************/
2021 /*************************************************************************/
2023 /* TABLE OVERVIEW */
2024 /* -------------- */
2026 /* NAME OFFSET TYPE DESCRIPTION */
2028 /* format 0 USHORT must be 12 */
2029 /* reserved 2 USHORT reserved */
2030 /* length 4 ULONG length in bytes */
2031 /* language 8 ULONG Mac language code */
2032 /* count 12 ULONG number of groups */
2035 /* This header is followed by `count' groups of the following format: */
2037 /* start 0 ULONG first charcode */
2038 /* end 4 ULONG last charcode */
2039 /* startId 8 ULONG start glyph ID for the group */
2042 #ifdef TT_CONFIG_CMAP_FORMAT_12
2044 typedef struct TT_CMap12Rec_
2048 FT_ULong cur_charcode;
2051 FT_ULong num_groups;
2053 } TT_CMap12Rec, *TT_CMap12;
2056 FT_CALLBACK_DEF( FT_Error )
2057 tt_cmap12_init( TT_CMap12 cmap,
2060 cmap->cmap.data = table;
2063 cmap->num_groups = FT_PEEK_ULONG( table );
2071 FT_CALLBACK_DEF( FT_Error )
2072 tt_cmap12_validate( FT_Byte* table,
2073 FT_Validator valid )
2077 FT_ULong num_groups;
2080 if ( table + 16 > valid->limit )
2081 FT_INVALID_TOO_SHORT;
2084 length = TT_NEXT_ULONG( p );
2087 num_groups = TT_NEXT_ULONG( p );
2089 if ( length > (FT_ULong)( valid->limit - table ) ||
2090 /* length < 16 + 12 * num_groups ? */
2092 ( length - 16 ) / 12 < num_groups )
2093 FT_INVALID_TOO_SHORT;
2095 /* check groups, they must be in increasing order */
2097 FT_ULong n, start, end, start_id, last = 0;
2100 for ( n = 0; n < num_groups; n++ )
2102 start = TT_NEXT_ULONG( p );
2103 end = TT_NEXT_ULONG( p );
2104 start_id = TT_NEXT_ULONG( p );
2109 if ( n > 0 && start <= last )
2112 if ( valid->level >= FT_VALIDATE_TIGHT )
2114 FT_UInt32 d = end - start;
2117 /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
2118 if ( d > TT_VALID_GLYPH_COUNT( valid ) ||
2119 start_id >= TT_VALID_GLYPH_COUNT( valid ) - d )
2120 FT_INVALID_GLYPH_ID;
2131 /* search the index of the charcode next to cmap->cur_charcode */
2132 /* cmap->cur_group should be set up properly by caller */
2135 tt_cmap12_next( TT_CMap12 cmap )
2138 FT_ULong start, end, start_id, char_code;
2143 if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
2146 char_code = cmap->cur_charcode + 1;
2148 for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
2150 p = cmap->cmap.data + 16 + 12 * n;
2151 start = TT_NEXT_ULONG( p );
2152 end = TT_NEXT_ULONG( p );
2153 start_id = TT_PEEK_ULONG( p );
2155 if ( char_code < start )
2158 for ( ; char_code <= end; char_code++ )
2160 gindex = (FT_UInt)( start_id + char_code - start );
2164 cmap->cur_charcode = char_code;;
2165 cmap->cur_gindex = gindex;
2166 cmap->cur_group = n;
2179 tt_cmap12_char_map_binary( TT_CMap cmap,
2180 FT_UInt32* pchar_code,
2184 FT_Byte* p = cmap->data + 12;
2185 FT_UInt32 num_groups = TT_PEEK_ULONG( p );
2186 FT_UInt32 char_code = *pchar_code;
2187 FT_UInt32 start, end, start_id;
2188 FT_UInt32 max, min, mid;
2194 /* make compiler happy */
2207 mid = ( min + max ) >> 1;
2208 p = cmap->data + 16 + 12 * mid;
2210 start = TT_NEXT_ULONG( p );
2211 end = TT_NEXT_ULONG( p );
2213 if ( char_code < start )
2215 else if ( char_code > end )
2219 start_id = TT_PEEK_ULONG( p );
2220 gindex = (FT_UInt)( start_id + char_code - start );
2228 TT_CMap12 cmap12 = (TT_CMap12)cmap;
2231 /* if `char_code' is not in any group, then `mid' is */
2232 /* the group nearest to `char_code' */
2235 if ( char_code > end )
2238 if ( mid == num_groups )
2243 cmap12->cur_charcode = char_code;
2244 cmap12->cur_group = mid;
2248 tt_cmap12_next( cmap12 );
2250 if ( cmap12->valid )
2251 gindex = cmap12->cur_gindex;
2254 cmap12->cur_gindex = gindex;
2257 *pchar_code = cmap12->cur_charcode;
2264 FT_CALLBACK_DEF( FT_UInt )
2265 tt_cmap12_char_index( TT_CMap cmap,
2266 FT_UInt32 char_code )
2268 return tt_cmap12_char_map_binary( cmap, &char_code, 0 );
2272 FT_CALLBACK_DEF( FT_UInt32 )
2273 tt_cmap12_char_next( TT_CMap cmap,
2274 FT_UInt32 *pchar_code )
2276 TT_CMap12 cmap12 = (TT_CMap12)cmap;
2280 if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )
2283 /* no need to search */
2284 if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
2286 tt_cmap12_next( cmap12 );
2287 if ( cmap12->valid )
2289 gindex = cmap12->cur_gindex;
2291 /* XXX: check cur_charcode overflow is expected */
2293 *pchar_code = (FT_UInt32)cmap12->cur_charcode;
2299 gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
2301 /* XXX: check gindex overflow is expected */
2302 return (FT_UInt32)gindex;
2306 FT_CALLBACK_DEF( FT_Error )
2307 tt_cmap12_get_info( TT_CMap cmap,
2308 TT_CMapInfo *cmap_info )
2310 FT_Byte* p = cmap->data + 8;
2313 cmap_info->format = 12;
2314 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2321 tt_cmap12_class_rec,
2322 sizeof ( TT_CMap12Rec ),
2324 (FT_CMap_InitFunc) tt_cmap12_init,
2325 (FT_CMap_DoneFunc) NULL,
2326 (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
2327 (FT_CMap_CharNextFunc) tt_cmap12_char_next,
2336 (TT_CMap_ValidateFunc)tt_cmap12_validate,
2337 (TT_CMap_Info_GetFunc)tt_cmap12_get_info )
2339 #endif /* TT_CONFIG_CMAP_FORMAT_12 */
2342 /*************************************************************************/
2343 /*************************************************************************/
2345 /***** FORMAT 13 *****/
2347 /*************************************************************************/
2348 /*************************************************************************/
2350 /*************************************************************************/
2352 /* TABLE OVERVIEW */
2353 /* -------------- */
2355 /* NAME OFFSET TYPE DESCRIPTION */
2357 /* format 0 USHORT must be 13 */
2358 /* reserved 2 USHORT reserved */
2359 /* length 4 ULONG length in bytes */
2360 /* language 8 ULONG Mac language code */
2361 /* count 12 ULONG number of groups */
2364 /* This header is followed by `count' groups of the following format: */
2366 /* start 0 ULONG first charcode */
2367 /* end 4 ULONG last charcode */
2368 /* glyphId 8 ULONG glyph ID for the whole group */
2371 #ifdef TT_CONFIG_CMAP_FORMAT_13
2373 typedef struct TT_CMap13Rec_
2377 FT_ULong cur_charcode;
2380 FT_ULong num_groups;
2382 } TT_CMap13Rec, *TT_CMap13;
2385 FT_CALLBACK_DEF( FT_Error )
2386 tt_cmap13_init( TT_CMap13 cmap,
2389 cmap->cmap.data = table;
2392 cmap->num_groups = FT_PEEK_ULONG( table );
2400 FT_CALLBACK_DEF( FT_Error )
2401 tt_cmap13_validate( FT_Byte* table,
2402 FT_Validator valid )
2406 FT_ULong num_groups;
2409 if ( table + 16 > valid->limit )
2410 FT_INVALID_TOO_SHORT;
2413 length = TT_NEXT_ULONG( p );
2416 num_groups = TT_NEXT_ULONG( p );
2418 if ( length > (FT_ULong)( valid->limit - table ) ||
2419 /* length < 16 + 12 * num_groups ? */
2421 ( length - 16 ) / 12 < num_groups )
2422 FT_INVALID_TOO_SHORT;
2424 /* check groups, they must be in increasing order */
2426 FT_ULong n, start, end, glyph_id, last = 0;
2429 for ( n = 0; n < num_groups; n++ )
2431 start = TT_NEXT_ULONG( p );
2432 end = TT_NEXT_ULONG( p );
2433 glyph_id = TT_NEXT_ULONG( p );
2438 if ( n > 0 && start <= last )
2441 if ( valid->level >= FT_VALIDATE_TIGHT )
2443 if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) )
2444 FT_INVALID_GLYPH_ID;
2455 /* search the index of the charcode next to cmap->cur_charcode */
2456 /* cmap->cur_group should be set up properly by caller */
2459 tt_cmap13_next( TT_CMap13 cmap )
2462 FT_ULong start, end, glyph_id, char_code;
2467 if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
2470 char_code = cmap->cur_charcode + 1;
2472 for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
2474 p = cmap->cmap.data + 16 + 12 * n;
2475 start = TT_NEXT_ULONG( p );
2476 end = TT_NEXT_ULONG( p );
2477 glyph_id = TT_PEEK_ULONG( p );
2479 if ( char_code < start )
2482 if ( char_code <= end )
2484 gindex = (FT_UInt)glyph_id;
2488 cmap->cur_charcode = char_code;;
2489 cmap->cur_gindex = gindex;
2490 cmap->cur_group = n;
2503 tt_cmap13_char_map_binary( TT_CMap cmap,
2504 FT_UInt32* pchar_code,
2508 FT_Byte* p = cmap->data + 12;
2509 FT_UInt32 num_groups = TT_PEEK_ULONG( p );
2510 FT_UInt32 char_code = *pchar_code;
2511 FT_UInt32 start, end;
2512 FT_UInt32 max, min, mid;
2518 /* make compiler happy */
2531 mid = ( min + max ) >> 1;
2532 p = cmap->data + 16 + 12 * mid;
2534 start = TT_NEXT_ULONG( p );
2535 end = TT_NEXT_ULONG( p );
2537 if ( char_code < start )
2539 else if ( char_code > end )
2543 gindex = (FT_UInt)TT_PEEK_ULONG( p );
2551 TT_CMap13 cmap13 = (TT_CMap13)cmap;
2554 /* if `char_code' is not in any group, then `mid' is */
2555 /* the group nearest to `char_code' */
2557 if ( char_code > end )
2560 if ( mid == num_groups )
2565 cmap13->cur_charcode = char_code;
2566 cmap13->cur_group = mid;
2570 tt_cmap13_next( cmap13 );
2572 if ( cmap13->valid )
2573 gindex = cmap13->cur_gindex;
2576 cmap13->cur_gindex = gindex;
2579 *pchar_code = cmap13->cur_charcode;
2586 FT_CALLBACK_DEF( FT_UInt )
2587 tt_cmap13_char_index( TT_CMap cmap,
2588 FT_UInt32 char_code )
2590 return tt_cmap13_char_map_binary( cmap, &char_code, 0 );
2594 FT_CALLBACK_DEF( FT_UInt32 )
2595 tt_cmap13_char_next( TT_CMap cmap,
2596 FT_UInt32 *pchar_code )
2598 TT_CMap13 cmap13 = (TT_CMap13)cmap;
2602 if ( cmap13->cur_charcode >= 0xFFFFFFFFUL )
2605 /* no need to search */
2606 if ( cmap13->valid && cmap13->cur_charcode == *pchar_code )
2608 tt_cmap13_next( cmap13 );
2609 if ( cmap13->valid )
2611 gindex = cmap13->cur_gindex;
2613 *pchar_code = cmap13->cur_charcode;
2619 gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 );
2625 FT_CALLBACK_DEF( FT_Error )
2626 tt_cmap13_get_info( TT_CMap cmap,
2627 TT_CMapInfo *cmap_info )
2629 FT_Byte* p = cmap->data + 8;
2632 cmap_info->format = 13;
2633 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2640 tt_cmap13_class_rec,
2641 sizeof ( TT_CMap13Rec ),
2643 (FT_CMap_InitFunc) tt_cmap13_init,
2644 (FT_CMap_DoneFunc) NULL,
2645 (FT_CMap_CharIndexFunc)tt_cmap13_char_index,
2646 (FT_CMap_CharNextFunc) tt_cmap13_char_next,
2655 (TT_CMap_ValidateFunc)tt_cmap13_validate,
2656 (TT_CMap_Info_GetFunc)tt_cmap13_get_info )
2658 #endif /* TT_CONFIG_CMAP_FORMAT_13 */
2661 /*************************************************************************/
2662 /*************************************************************************/
2664 /***** FORMAT 14 *****/
2666 /*************************************************************************/
2667 /*************************************************************************/
2669 /*************************************************************************/
2671 /* TABLE OVERVIEW */
2672 /* -------------- */
2674 /* NAME OFFSET TYPE DESCRIPTION */
2676 /* format 0 USHORT must be 14 */
2677 /* length 2 ULONG table length in bytes */
2678 /* numSelector 6 ULONG number of variation sel. records */
2680 /* Followed by numSelector records, each of which looks like */
2682 /* varSelector 0 UINT24 Unicode codepoint of sel. */
2683 /* defaultOff 3 ULONG offset to a default UVS table */
2684 /* describing any variants to be found in */
2685 /* the normal Unicode subtable. */
2686 /* nonDefOff 7 ULONG offset to a non-default UVS table */
2687 /* describing any variants not in the */
2688 /* standard cmap, with GIDs here */
2689 /* (either offset may be 0 NULL) */
2691 /* Selectors are sorted by code point. */
2693 /* A default Unicode Variation Selector (UVS) subtable is just a list of */
2694 /* ranges of code points which are to be found in the standard cmap. No */
2695 /* glyph IDs (GIDs) here. */
2697 /* numRanges 0 ULONG number of ranges following */
2699 /* A range looks like */
2701 /* uniStart 0 UINT24 code point of the first character in */
2703 /* additionalCnt 3 UBYTE count of additional characters in this */
2704 /* range (zero means a range of a single */
2707 /* Ranges are sorted by `uniStart'. */
2709 /* A non-default Unicode Variation Selector (UVS) subtable is a list of */
2710 /* mappings from codepoint to GID. */
2712 /* numMappings 0 ULONG number of mappings */
2714 /* A range looks like */
2716 /* uniStart 0 UINT24 code point of the first character in */
2718 /* GID 3 USHORT and its GID */
2720 /* Ranges are sorted by `uniStart'. */
2722 #ifdef TT_CONFIG_CMAP_FORMAT_14
2724 typedef struct TT_CMap14Rec_
2727 FT_ULong num_selectors;
2729 /* This array is used to store the results of various
2730 * cmap 14 query functions. The data is overwritten
2731 * on each call to these functions.
2733 FT_UInt32 max_results;
2737 } TT_CMap14Rec, *TT_CMap14;
2740 FT_CALLBACK_DEF( void )
2741 tt_cmap14_done( TT_CMap14 cmap )
2743 FT_Memory memory = cmap->memory;
2746 cmap->max_results = 0;
2747 if ( memory != NULL && cmap->results != NULL )
2748 FT_FREE( cmap->results );
2753 tt_cmap14_ensure( TT_CMap14 cmap,
2754 FT_UInt32 num_results,
2757 FT_UInt32 old_max = cmap->max_results;
2758 FT_Error error = FT_Err_Ok;
2761 if ( num_results > cmap->max_results )
2763 cmap->memory = memory;
2765 if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) )
2768 cmap->max_results = num_results;
2775 FT_CALLBACK_DEF( FT_Error )
2776 tt_cmap14_init( TT_CMap14 cmap,
2779 cmap->cmap.data = table;
2782 cmap->num_selectors = FT_PEEK_ULONG( table );
2783 cmap->max_results = 0;
2784 cmap->results = NULL;
2790 FT_CALLBACK_DEF( FT_Error )
2791 tt_cmap14_validate( FT_Byte* table,
2792 FT_Validator valid )
2796 FT_ULong num_selectors;
2799 if ( table + 2 + 4 + 4 > valid->limit )
2800 FT_INVALID_TOO_SHORT;
2803 length = TT_NEXT_ULONG( p );
2804 num_selectors = TT_NEXT_ULONG( p );
2806 if ( length > (FT_ULong)( valid->limit - table ) ||
2807 /* length < 10 + 11 * num_selectors ? */
2809 ( length - 10 ) / 11 < num_selectors )
2810 FT_INVALID_TOO_SHORT;
2812 /* check selectors, they must be in increasing order */
2814 /* we start lastVarSel at 1 because a variant selector value of 0
2817 FT_ULong n, lastVarSel = 1;
2820 for ( n = 0; n < num_selectors; n++ )
2822 FT_ULong varSel = TT_NEXT_UINT24( p );
2823 FT_ULong defOff = TT_NEXT_ULONG( p );
2824 FT_ULong nondefOff = TT_NEXT_ULONG( p );
2827 if ( defOff >= length || nondefOff >= length )
2828 FT_INVALID_TOO_SHORT;
2830 if ( varSel < lastVarSel )
2833 lastVarSel = varSel + 1;
2835 /* check the default table (these glyphs should be reached */
2836 /* through the normal Unicode cmap, no GIDs, just check order) */
2839 FT_Byte* defp = table + defOff;
2840 FT_ULong numRanges = TT_NEXT_ULONG( defp );
2842 FT_ULong lastBase = 0;
2845 /* defp + numRanges * 4 > valid->limit ? */
2846 if ( numRanges > (FT_ULong)( valid->limit - defp ) / 4 )
2847 FT_INVALID_TOO_SHORT;
2849 for ( i = 0; i < numRanges; ++i )
2851 FT_ULong base = TT_NEXT_UINT24( defp );
2852 FT_ULong cnt = FT_NEXT_BYTE( defp );
2855 if ( base + cnt >= 0x110000UL ) /* end of Unicode */
2858 if ( base < lastBase )
2861 lastBase = base + cnt + 1U;
2865 /* and the non-default table (these glyphs are specified here) */
2866 if ( nondefOff != 0 )
2868 FT_Byte* ndp = table + nondefOff;
2869 FT_ULong numMappings = TT_NEXT_ULONG( ndp );
2870 FT_ULong i, lastUni = 0;
2873 /* numMappings * 4 > (FT_ULong)( valid->limit - ndp ) ? */
2874 if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 4 )
2875 FT_INVALID_TOO_SHORT;
2877 for ( i = 0; i < numMappings; ++i )
2879 FT_ULong uni = TT_NEXT_UINT24( ndp );
2880 FT_ULong gid = TT_NEXT_USHORT( ndp );
2883 if ( uni >= 0x110000UL ) /* end of Unicode */
2886 if ( uni < lastUni )
2891 if ( valid->level >= FT_VALIDATE_TIGHT &&
2892 gid >= TT_VALID_GLYPH_COUNT( valid ) )
2893 FT_INVALID_GLYPH_ID;
2903 FT_CALLBACK_DEF( FT_UInt )
2904 tt_cmap14_char_index( TT_CMap cmap,
2905 FT_UInt32 char_code )
2908 FT_UNUSED( char_code );
2910 /* This can't happen */
2915 FT_CALLBACK_DEF( FT_UInt32 )
2916 tt_cmap14_char_next( TT_CMap cmap,
2917 FT_UInt32 *pchar_code )
2921 /* This can't happen */
2927 FT_CALLBACK_DEF( FT_Error )
2928 tt_cmap14_get_info( TT_CMap cmap,
2929 TT_CMapInfo *cmap_info )
2933 cmap_info->format = 14;
2934 /* subtable 14 does not define a language field */
2935 cmap_info->language = 0xFFFFFFFFUL;
2942 tt_cmap14_char_map_def_binary( FT_Byte *base,
2943 FT_UInt32 char_code )
2945 FT_UInt32 numRanges = TT_PEEK_ULONG( base );
2957 FT_UInt32 mid = ( min + max ) >> 1;
2958 FT_Byte* p = base + 4 * mid;
2959 FT_ULong start = TT_NEXT_UINT24( p );
2960 FT_UInt cnt = FT_NEXT_BYTE( p );
2963 if ( char_code < start )
2965 else if ( char_code > start+cnt )
2976 tt_cmap14_char_map_nondef_binary( FT_Byte *base,
2977 FT_UInt32 char_code )
2979 FT_UInt32 numMappings = TT_PEEK_ULONG( base );
2991 FT_UInt32 mid = ( min + max ) >> 1;
2992 FT_Byte* p = base + 5 * mid;
2993 FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p );
2996 if ( char_code < uni )
2998 else if ( char_code > uni )
3001 return TT_PEEK_USHORT( p );
3009 tt_cmap14_find_variant( FT_Byte *base,
3010 FT_UInt32 variantCode )
3012 FT_UInt32 numVar = TT_PEEK_ULONG( base );
3024 FT_UInt32 mid = ( min + max ) >> 1;
3025 FT_Byte* p = base + 11 * mid;
3026 FT_ULong varSel = TT_NEXT_UINT24( p );
3029 if ( variantCode < varSel )
3031 else if ( variantCode > varSel )
3041 FT_CALLBACK_DEF( FT_UInt )
3042 tt_cmap14_char_var_index( TT_CMap cmap,
3045 FT_UInt32 variantSelector )
3047 FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
3055 defOff = TT_NEXT_ULONG( p );
3056 nondefOff = TT_PEEK_ULONG( p );
3059 tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
3061 /* This is the default variant of this charcode. GID not stored */
3062 /* here; stored in the normal Unicode charmap instead. */
3063 return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode );
3066 if ( nondefOff != 0 )
3067 return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3074 FT_CALLBACK_DEF( FT_Int )
3075 tt_cmap14_char_var_isdefault( TT_CMap cmap,
3077 FT_UInt32 variantSelector )
3079 FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
3087 defOff = TT_NEXT_ULONG( p );
3088 nondefOff = TT_NEXT_ULONG( p );
3091 tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
3094 if ( nondefOff != 0 &&
3095 tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3103 FT_CALLBACK_DEF( FT_UInt32* )
3104 tt_cmap14_variants( TT_CMap cmap,
3107 TT_CMap14 cmap14 = (TT_CMap14)cmap;
3108 FT_UInt32 count = cmap14->num_selectors;
3109 FT_Byte* p = cmap->data + 10;
3114 if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
3117 result = cmap14->results;
3118 for ( i = 0; i < count; ++i )
3120 result[i] = (FT_UInt32)TT_NEXT_UINT24( p );
3129 FT_CALLBACK_DEF( FT_UInt32 * )
3130 tt_cmap14_char_variants( TT_CMap cmap,
3132 FT_UInt32 charCode )
3134 TT_CMap14 cmap14 = (TT_CMap14) cmap;
3135 FT_UInt32 count = cmap14->num_selectors;
3136 FT_Byte* p = cmap->data + 10;
3140 if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
3143 for ( q = cmap14->results; count > 0; --count )
3145 FT_UInt32 varSel = TT_NEXT_UINT24( p );
3146 FT_ULong defOff = TT_NEXT_ULONG( p );
3147 FT_ULong nondefOff = TT_NEXT_ULONG( p );
3150 if ( ( defOff != 0 &&
3151 tt_cmap14_char_map_def_binary( cmap->data + defOff,
3154 tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3163 return cmap14->results;
3168 tt_cmap14_def_char_count( FT_Byte *p )
3170 FT_UInt32 numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
3174 p += 3; /* point to the first `cnt' field */
3175 for ( ; numRanges > 0; numRanges-- )
3186 tt_cmap14_get_def_chars( TT_CMap cmap,
3190 TT_CMap14 cmap14 = (TT_CMap14) cmap;
3191 FT_UInt32 numRanges;
3196 cnt = tt_cmap14_def_char_count( p );
3197 numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
3199 if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) )
3202 for ( q = cmap14->results; numRanges > 0; --numRanges )
3204 FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p );
3207 cnt = FT_NEXT_BYTE( p ) + 1;
3214 } while ( --cnt != 0 );
3218 return cmap14->results;
3223 tt_cmap14_get_nondef_chars( TT_CMap cmap,
3227 TT_CMap14 cmap14 = (TT_CMap14) cmap;
3228 FT_UInt32 numMappings;
3233 numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
3235 if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) )
3238 ret = cmap14->results;
3239 for ( i = 0; i < numMappings; ++i )
3241 ret[i] = (FT_UInt32)TT_NEXT_UINT24( p );
3250 FT_CALLBACK_DEF( FT_UInt32 * )
3251 tt_cmap14_variant_chars( TT_CMap cmap,
3253 FT_UInt32 variantSelector )
3255 FT_Byte *p = tt_cmap14_find_variant( cmap->data + 6,
3265 defOff = TT_NEXT_ULONG( p );
3266 nondefOff = TT_NEXT_ULONG( p );
3268 if ( defOff == 0 && nondefOff == 0 )
3272 return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
3274 else if ( nondefOff == 0 )
3275 return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
3279 /* Both a default and a non-default glyph set? That's probably not */
3280 /* good font design, but the spec allows for it... */
3281 TT_CMap14 cmap14 = (TT_CMap14) cmap;
3282 FT_UInt32 numRanges;
3283 FT_UInt32 numMappings;
3293 p = cmap->data + nondefOff;
3294 dp = cmap->data + defOff;
3296 numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
3297 dcnt = tt_cmap14_def_char_count( dp );
3298 numRanges = (FT_UInt32)TT_NEXT_ULONG( dp );
3300 if ( numMappings == 0 )
3301 return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
3304 return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
3307 if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) )
3310 ret = cmap14->results;
3311 duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3312 dcnt = FT_NEXT_BYTE( dp );
3314 nuni = (FT_UInt32)TT_NEXT_UINT24( p );
3321 if ( nuni > duni + dcnt )
3323 for ( k = 0; k <= dcnt; ++k )
3324 ret[i++] = duni + k;
3328 if ( di > numRanges )
3331 duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3332 dcnt = FT_NEXT_BYTE( dp );
3338 /* If it is within the default range then ignore it -- */
3339 /* that should not have happened */
3341 if ( ni > numMappings )
3344 nuni = (FT_UInt32)TT_NEXT_UINT24( p );
3349 if ( ni <= numMappings )
3351 /* If we get here then we have run out of all default ranges. */
3352 /* We have read one non-default mapping which we haven't stored */
3353 /* and there may be others that need to be read. */
3355 while ( ni < numMappings )
3357 ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p );
3362 else if ( di <= numRanges )
3364 /* If we get here then we have run out of all non-default */
3365 /* mappings. We have read one default range which we haven't */
3366 /* stored and there may be others that need to be read. */
3367 for ( k = 0; k <= dcnt; ++k )
3368 ret[i++] = duni + k;
3370 while ( di < numRanges )
3372 duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3373 dcnt = FT_NEXT_BYTE( dp );
3375 for ( k = 0; k <= dcnt; ++k )
3376 ret[i++] = duni + k;
3389 tt_cmap14_class_rec,
3390 sizeof ( TT_CMap14Rec ),
3392 (FT_CMap_InitFunc) tt_cmap14_init,
3393 (FT_CMap_DoneFunc) tt_cmap14_done,
3394 (FT_CMap_CharIndexFunc)tt_cmap14_char_index,
3395 (FT_CMap_CharNextFunc) tt_cmap14_char_next,
3397 /* Format 14 extension functions */
3398 (FT_CMap_CharVarIndexFunc) tt_cmap14_char_var_index,
3399 (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
3400 (FT_CMap_VariantListFunc) tt_cmap14_variants,
3401 (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
3402 (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars,
3405 (TT_CMap_ValidateFunc)tt_cmap14_validate,
3406 (TT_CMap_Info_GetFunc)tt_cmap14_get_info )
3408 #endif /* TT_CONFIG_CMAP_FORMAT_14 */
3411 #ifndef FT_CONFIG_OPTION_PIC
3413 static const TT_CMap_Class tt_cmap_classes[] =
3415 #define TTCMAPCITEM( a ) &a,
3416 #include "ttcmapc.h"
3420 #else /*FT_CONFIG_OPTION_PIC*/
3423 FT_Destroy_Class_tt_cmap_classes( FT_Library library,
3424 TT_CMap_Class* clazz )
3426 FT_Memory memory = library->memory;
3435 FT_Create_Class_tt_cmap_classes( FT_Library library,
3436 TT_CMap_Class** output_class )
3438 TT_CMap_Class* clazz = NULL;
3439 TT_CMap_ClassRec* recs;
3441 FT_Memory memory = library->memory;
3446 #define TTCMAPCITEM( a ) i++;
3447 #include "ttcmapc.h"
3449 /* allocate enough space for both the pointers */
3450 /* plus terminator and the class instances */
3451 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * ( i + 1 ) +
3452 sizeof ( TT_CMap_ClassRec ) * i ) )
3455 /* the location of the class instances follows the array of pointers */
3456 recs = (TT_CMap_ClassRec*)( (char*)clazz +
3457 sizeof ( *clazz ) * ( i + 1 ) );
3461 #define TTCMAPCITEM( a ) \
3462 FT_Init_Class_ ## a( &recs[i] ); \
3463 clazz[i] = &recs[i]; \
3465 #include "ttcmapc.h"
3469 *output_class = clazz;
3473 #endif /*FT_CONFIG_OPTION_PIC*/
3476 /* parse the `cmap' table and build the corresponding TT_CMap objects */
3477 /* in the current face */
3479 FT_LOCAL_DEF( FT_Error )
3480 tt_face_build_cmaps( TT_Face face )
3482 FT_Byte* table = face->cmap_table;
3483 FT_Byte* limit = table + face->cmap_size;
3484 FT_UInt volatile num_cmaps;
3485 FT_Byte* volatile p = table;
3486 FT_Library library = FT_FACE_LIBRARY( face );
3488 FT_UNUSED( library );
3491 if ( !p || p + 4 > limit )
3492 return FT_THROW( Invalid_Table );
3494 /* only recognize format 0 */
3495 if ( TT_NEXT_USHORT( p ) != 0 )
3497 FT_ERROR(( "tt_face_build_cmaps:"
3498 " unsupported `cmap' table format = %d\n",
3499 TT_PEEK_USHORT( p - 2 ) ));
3500 return FT_THROW( Invalid_Table );
3503 num_cmaps = TT_NEXT_USHORT( p );
3505 for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
3507 FT_CharMapRec charmap;
3511 charmap.platform_id = TT_NEXT_USHORT( p );
3512 charmap.encoding_id = TT_NEXT_USHORT( p );
3513 charmap.face = FT_FACE( face );
3514 charmap.encoding = FT_ENCODING_NONE; /* will be filled later */
3515 offset = TT_NEXT_ULONG( p );
3517 if ( offset && offset <= face->cmap_size - 2 )
3519 FT_Byte* volatile cmap = table + offset;
3520 volatile FT_UInt format = TT_PEEK_USHORT( cmap );
3521 const TT_CMap_Class* volatile pclazz = TT_CMAP_CLASSES_GET;
3522 TT_CMap_Class volatile clazz;
3525 for ( ; *pclazz; pclazz++ )
3528 if ( clazz->format == format )
3530 volatile TT_ValidatorRec valid;
3531 volatile FT_Error error = FT_Err_Ok;
3534 ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
3535 FT_VALIDATE_DEFAULT );
3537 valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
3539 if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer) == 0 )
3541 /* validate this cmap sub-table */
3542 error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
3545 if ( valid.validator.error == 0 )
3550 /* It might make sense to store the single variation */
3551 /* selector cmap somewhere special. But it would have to be */
3552 /* in the public FT_FaceRec, and we can't change that. */
3554 if ( !FT_CMap_New( (FT_CMap_Class)clazz,
3555 cmap, &charmap, &ttcmap ) )
3557 /* it is simpler to directly set `flags' than adding */
3558 /* a parameter to FT_CMap_New */
3559 ((TT_CMap)ttcmap)->flags = (FT_Int)error;
3564 FT_TRACE0(( "tt_face_build_cmaps:"
3565 " broken cmap sub-table ignored\n" ));
3571 if ( *pclazz == NULL )
3573 FT_TRACE0(( "tt_face_build_cmaps:"
3574 " unsupported cmap sub-table ignored\n" ));
3583 FT_LOCAL( FT_Error )
3584 tt_get_cmap_info( FT_CharMap charmap,
3585 TT_CMapInfo *cmap_info )
3587 FT_CMap cmap = (FT_CMap)charmap;
3588 TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz;
3591 return clazz->get_cmap_info( charmap, cmap_info );