1
/***************************************************************************/
5
/* TrueType new character mapping table (cmap) support (body). */
7
/* Copyright 2002 by */
8
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
10
/* This file is part of the FreeType project, and may only be used, */
11
/* modified, and distributed under the terms of the FreeType project */
12
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13
/* this file you indicate that you have read the license and */
14
/* understand and accept it fully. */
16
/***************************************************************************/
20
#include FT_INTERNAL_DEBUG_H
21
#include FT_INTERNAL_OBJECTS_H
22
#include FT_INTERNAL_STREAM_H
28
/*************************************************************************/
30
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
31
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
32
/* messages during execution. */
35
#define FT_COMPONENT trace_ttcmap
38
#define TT_PEEK_SHORT FT_PEEK_SHORT
39
#define TT_PEEK_USHORT FT_PEEK_USHORT
40
#define TT_PEEK_LONG FT_PEEK_LONG
41
#define TT_PEEK_ULONG FT_PEEK_ULONG
43
#define TT_NEXT_SHORT FT_NEXT_SHORT
44
#define TT_NEXT_USHORT FT_NEXT_USHORT
45
#define TT_NEXT_LONG FT_NEXT_LONG
46
#define TT_NEXT_ULONG FT_NEXT_ULONG
49
FT_CALLBACK_DEF( FT_Error )
50
tt_cmap_init( TT_CMap cmap,
58
/*************************************************************************/
59
/*************************************************************************/
61
/***** FORMAT 0 *****/
63
/*************************************************************************/
64
/*************************************************************************/
66
/*************************************************************************/
71
/* NAME OFFSET TYPE DESCRIPTION */
73
/* format 0 USHORT must be 0 */
74
/* length 2 USHORT table length in bytes */
75
/* language 4 USHORT Mac language code */
76
/* glyph_ids 6 BYTE[256] array of glyph indices */
80
#ifdef TT_CONFIG_CMAP_FORMAT_0
82
FT_CALLBACK_DEF( void )
83
tt_cmap0_validate( FT_Byte* table,
86
FT_Byte* p = table + 2;
87
FT_UInt length = TT_NEXT_USHORT( p );
90
if ( table + length > valid->limit || length < 262 )
93
/* check glyph indices whenever necessary */
94
if ( valid->level >= FT_VALIDATE_TIGHT )
100
for ( n = 0; n < 256; n++ )
103
if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
110
FT_CALLBACK_DEF( FT_UInt )
111
tt_cmap0_char_index( TT_CMap cmap,
112
FT_UInt32 char_code )
114
FT_Byte* table = cmap->data;
117
return char_code < 256 ? table[6 + char_code] : 0;
121
FT_CALLBACK_DEF( FT_UInt )
122
tt_cmap0_char_next( TT_CMap cmap,
123
FT_UInt32 *pchar_code )
125
FT_Byte* table = cmap->data;
126
FT_UInt32 charcode = *pchar_code;
127
FT_UInt32 result = 0;
131
table += 6; /* go to glyph ids */
132
while ( ++charcode < 256 )
134
gindex = table[charcode];
142
*pchar_code = result;
147
FT_CALLBACK_TABLE_DEF
148
const TT_CMap_ClassRec tt_cmap0_class_rec =
151
sizeof( TT_CMapRec ),
153
(FT_CMap_InitFunc) tt_cmap_init,
154
(FT_CMap_DoneFunc) NULL,
155
(FT_CMap_CharIndexFunc)tt_cmap0_char_index,
156
(FT_CMap_CharNextFunc) tt_cmap0_char_next
159
(TT_CMap_ValidateFunc) tt_cmap0_validate
162
#endif /* TT_CONFIG_CMAP_FORMAT_0 */
165
/*************************************************************************/
166
/*************************************************************************/
168
/***** FORMAT 2 *****/
170
/***** This is used for certain CJK encodings that encode text in a *****/
171
/***** mixed 8/16 bits encoding along the following lines: *****/
173
/***** * Certain byte values correspond to an 8-bit character code *****/
174
/***** (typically in the range 0..127 for ASCII compatibility). *****/
176
/***** * Certain byte values signal the first byte of a 2-byte *****/
177
/***** character code (but these values are also valid as the *****/
178
/***** second byte of a 2-byte character). *****/
180
/***** The following charmap lookup and iteration functions all *****/
181
/***** assume that the value "charcode" correspond to following: *****/
183
/***** - For one byte characters, "charcode" is simply the *****/
184
/***** character code. *****/
186
/***** - For two byte characters, "charcode" is the 2-byte *****/
187
/***** character code in big endian format. More exactly: *****/
189
/***** (charcode >> 8) is the first byte value *****/
190
/***** (charcode & 0xFF) is the second byte value *****/
192
/***** Note that not all values of "charcode" are valid according *****/
193
/***** to these rules, and the function moderately check the *****/
194
/***** arguments. *****/
196
/*************************************************************************/
197
/*************************************************************************/
199
/*************************************************************************/
204
/* NAME OFFSET TYPE DESCRIPTION */
206
/* format 0 USHORT must be 2 */
207
/* length 2 USHORT table length in bytes */
208
/* language 4 USHORT Mac language code */
209
/* keys 6 USHORT[256] sub-header keys */
210
/* subs 518 SUBHEAD[NSUBS] sub-headers array */
211
/* glyph_ids 518+NSUB*8 USHORT[] glyph id array */
213
/* The `keys' table is used to map charcode high-bytes to sub-headers. */
214
/* The value of `NSUBS' is the number of sub-headers defined in the */
215
/* table and is computed by finding the maximum of the `keys' table. */
217
/* Note that for any n, `keys[n]' is a byte offset within the `subs' */
218
/* table, i.e., it is the corresponding sub-header index multiplied */
221
/* Each sub-header has the following format: */
223
/* NAME OFFSET TYPE DESCRIPTION */
225
/* first 0 USHORT first valid low-byte */
226
/* count 2 USHORT number of valid low-bytes */
227
/* delta 4 SHORT see below */
228
/* offset 6 USHORT see below */
230
/* A sub-header defines, for each high-byte, the range of valid */
231
/* low-bytes within the charmap. Note that the range defined by `first' */
232
/* and `count' must be completely included in the interval [0..255] */
233
/* according to the specification. */
235
/* If a character code is contained within a given sub-header, then */
236
/* mapping it to a glyph index is done as follows: */
238
/* * The value of `offset' is read. This is a _byte_ distance from the */
239
/* location of the `offset' field itself into a slice of the */
240
/* `glyph_ids' table. Let's call it `slice' (it's a USHORT[] too). */
242
/* * The value `slice[char.lo - first]' is read. If it is 0, there is */
243
/* no glyph for the charcode. Otherwise, the value of `delta' is */
244
/* added to it (modulo 65536) to form a new glyph index. */
246
/* It is up to the validation routine to check that all offsets fall */
247
/* within the glyph ids table (and not within the `subs' table itself or */
248
/* outside of the CMap). */
251
#ifdef TT_CONFIG_CMAP_FORMAT_2
253
FT_CALLBACK_DEF( void )
254
tt_cmap2_validate( FT_Byte* table,
257
FT_Byte* p = table + 2; /* skip format */
258
FT_UInt length = TT_PEEK_USHORT( p );
260
FT_Byte* keys; /* keys table */
261
FT_Byte* subs; /* sub-headers */
262
FT_Byte* glyph_ids; /* glyph id array */
265
if ( table + length > valid->limit || length < 6 + 512 )
266
FT_INVALID_TOO_SHORT;
270
/* parse keys to compute sub-headers count */
273
for ( n = 0; n < 256; n++ )
275
FT_UInt idx = TT_NEXT_USHORT( p );
278
/* value must be multiple of 8 */
279
if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
284
if ( idx > max_subs )
288
FT_ASSERT( p == table + 518 );
291
glyph_ids = subs + (max_subs + 1) * 8;
292
if ( glyph_ids > valid->limit )
293
FT_INVALID_TOO_SHORT;
295
/* parse sub-headers */
296
for ( n = 0; n <= max_subs; n++ )
298
FT_UInt first_code, code_count, offset;
303
first_code = TT_NEXT_USHORT( p );
304
code_count = TT_NEXT_USHORT( p );
305
delta = TT_NEXT_SHORT( p );
306
offset = TT_NEXT_USHORT( p );
308
/* check range within 0..255 */
309
if ( valid->level >= FT_VALIDATE_PARANOID )
311
if ( first_code >= 256 || first_code + code_count > 256 )
318
ids = p - 2 + offset;
319
if ( ids < glyph_ids || ids + code_count*2 > table + length )
322
/* check glyph ids */
323
if ( valid->level >= FT_VALIDATE_TIGHT )
325
FT_Byte* limit = p + code_count * 2;
331
idx = TT_NEXT_USHORT( p );
334
idx = ( idx + delta ) & 0xFFFFU;
335
if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
345
/* return sub header corresponding to a given character code */
346
/* NULL on invalid charcode */
348
tt_cmap2_get_subheader( FT_Byte* table,
349
FT_UInt32 char_code )
351
FT_Byte* result = NULL;
354
if ( char_code < 0x10000UL )
356
FT_UInt char_lo = (FT_UInt)( char_code & 0xFF );
357
FT_UInt char_hi = (FT_UInt)( char_code >> 8 );
358
FT_Byte* p = table + 6; /* keys table */
359
FT_Byte* subs = table + 518; /* subheaders table */
365
/* an 8-bit character code -- we use subHeader 0 in this case */
366
/* to test whether the character code is in the charmap */
368
sub = subs; /* jump to first sub-header */
370
/* check that the sub-header for this byte is 0, which */
371
/* indicates that it's really a valid one-byte value */
372
/* Otherwise, return 0 */
375
if ( TT_PEEK_USHORT( p ) != 0 )
380
/* a 16-bit character code */
381
p += char_hi * 2; /* jump to key entry */
382
sub = subs + ( TT_PEEK_USHORT( p ) & -8 ); /* jump to sub-header */
384
/* check that the hi byte isn't a valid one-byte value */
395
FT_CALLBACK_DEF( FT_UInt )
396
tt_cmap2_char_index( TT_CMap cmap,
397
FT_UInt32 char_code )
399
FT_Byte* table = cmap->data;
404
subheader = tt_cmap2_get_subheader( table, char_code );
407
FT_Byte* p = subheader;
408
FT_UInt idx = (FT_UInt)(char_code & 0xFF);
409
FT_UInt start, count;
414
start = TT_NEXT_USHORT( p );
415
count = TT_NEXT_USHORT( p );
416
delta = TT_NEXT_SHORT ( p );
417
offset = TT_PEEK_USHORT( p );
420
if ( idx < count && offset != 0 )
422
p += offset + 2 * idx;
423
idx = TT_PEEK_USHORT( p );
426
result = (FT_UInt)( idx + delta ) & 0xFFFFU;
433
FT_CALLBACK_DEF( FT_UInt )
434
tt_cmap2_char_next( TT_CMap cmap,
435
FT_UInt32 *pcharcode )
437
FT_Byte* table = cmap->data;
439
FT_UInt32 result = 0;
440
FT_UInt32 charcode = *pcharcode + 1;
444
while ( charcode < 0x10000UL )
446
subheader = tt_cmap2_get_subheader( table, charcode );
449
FT_Byte* p = subheader;
450
FT_UInt start = TT_NEXT_USHORT( p );
451
FT_UInt count = TT_NEXT_USHORT( p );
452
FT_Int delta = TT_NEXT_SHORT ( p );
453
FT_UInt offset = TT_PEEK_USHORT( p );
454
FT_UInt char_lo = (FT_UInt)( charcode & 0xFF );
461
if ( char_lo < start )
467
pos = (FT_UInt)( char_lo - start );
469
p += offset + pos * 2;
470
charcode = ( charcode & -256 ) + char_lo;
472
for ( ; pos < count; pos++, charcode++ )
474
idx = TT_NEXT_USHORT( p );
478
gindex = ( idx + delta ) & 0xFFFFU;
488
/* jump to next sub-header, i.e. higher byte value */
490
charcode = ( charcode & -256 ) + 256;
500
FT_CALLBACK_TABLE_DEF
501
const TT_CMap_ClassRec tt_cmap2_class_rec =
504
sizeof( TT_CMapRec ),
506
(FT_CMap_InitFunc) tt_cmap_init,
507
(FT_CMap_DoneFunc) NULL,
508
(FT_CMap_CharIndexFunc)tt_cmap2_char_index,
509
(FT_CMap_CharNextFunc) tt_cmap2_char_next
512
(TT_CMap_ValidateFunc) tt_cmap2_validate
515
#endif /* TT_CONFIG_CMAP_FORMAT_2 */
518
/*************************************************************************/
519
/*************************************************************************/
521
/***** FORMAT 4 *****/
523
/*************************************************************************/
524
/*************************************************************************/
526
/*************************************************************************/
531
/* NAME OFFSET TYPE DESCRIPTION */
533
/* format 0 USHORT must be 4 */
534
/* length 2 USHORT table length */
536
/* language 4 USHORT Mac language code */
538
/* segCountX2 6 USHORT 2*NUM_SEGS */
539
/* searchRange 8 USHORT 2*(1 << LOG_SEGS) */
540
/* entrySelector 10 USHORT LOG_SEGS */
541
/* rangeShift 12 USHORT segCountX2 - */
544
/* endCount 14 USHORT[NUM_SEGS] end charcode for */
545
/* each segment; last */
548
/* pad 14+NUM_SEGS*2 USHORT padding */
550
/* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */
553
/* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */
555
/* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */
556
/* each segment; can be */
559
/* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph id */
562
/* Character codes are modelled by a series of ordered (increasing) */
563
/* intervals called segments. Each segment has start and end codes, */
564
/* provided by the `startCount' and `endCount' arrays. Segments must */
565
/* not be overlapping and the last segment should always contain the */
566
/* `0xFFFF' endCount. */
568
/* The fields `searchRange', `entrySelector' and `rangeShift' are better */
569
/* ignored (they are traces of over-engineering in the TrueType */
570
/* specification). */
572
/* Each segment also has a signed `delta', as well as an optional offset */
573
/* within the `glyphIds' table. */
575
/* If a segment's idOffset is 0, the glyph index corresponding to any */
576
/* charcode within the segment is obtained by adding the value of */
577
/* `idDelta' directly to the charcode, modulo 65536. */
579
/* Otherwise, a glyph index is taken from the glyph ids sub-array for */
580
/* the segment, and the value of `idDelta' is added to it. */
583
#ifdef TT_CONFIG_CMAP_FORMAT_4
585
FT_CALLBACK_DEF( void )
586
tt_cmap4_validate( FT_Byte* table,
589
FT_Byte* p = table + 2; /* skip format */
590
FT_UInt length = TT_NEXT_USHORT( p );
591
FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids;
595
if ( table + length > valid->limit || length < 16 )
596
FT_INVALID_TOO_SHORT;
599
num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */
601
if ( valid->level >= FT_VALIDATE_PARANOID )
603
/* check that we have an even value here */
610
/* check the search parameters - even though we never use them */
612
if ( valid->level >= FT_VALIDATE_PARANOID )
614
/* check the values of 'searchRange', 'entrySelector', 'rangeShift' */
615
FT_UInt search_range = TT_NEXT_USHORT( p );
616
FT_UInt entry_selector = TT_NEXT_USHORT( p );
617
FT_UInt range_shift = TT_NEXT_USHORT( p );
620
if ( ( search_range | range_shift ) & 1 ) /* must be even values */
626
/* `search range' is the greatest power of 2 that is <= num_segs */
628
if ( search_range > num_segs ||
629
search_range * 2 < num_segs ||
630
search_range + range_shift != num_segs ||
631
search_range != ( 1U << entry_selector ) )
636
starts = table + 16 + num_segs * 2;
637
deltas = starts + num_segs * 2;
638
offsets = deltas + num_segs * 2;
639
glyph_ids = offsets + num_segs * 2;
641
if ( glyph_ids > table + length )
642
FT_INVALID_TOO_SHORT;
644
/* check last segment, its end count must be FFFF */
645
if ( valid->level >= FT_VALIDATE_PARANOID )
647
p = ends + ( num_segs - 1 ) * 2;
648
if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
652
/* check that segments are sorted in increasing order and do not */
653
/* overlap; check also the offsets */
655
FT_UInt start, end, last = 0, offset, n;
659
for ( n = 0; n < num_segs; n++ )
662
start = TT_PEEK_USHORT( p );
664
end = TT_PEEK_USHORT( p );
666
delta = TT_PEEK_SHORT( p );
668
offset = TT_PEEK_USHORT( p );
673
/* this test should be performed at default validation level; */
674
/* unfortunately, some popular Asian fonts present overlapping */
675
/* ranges in their charmaps */
677
if ( valid->level >= FT_VALIDATE_TIGHT )
679
if ( n > 0 && start <= last )
685
p += offset; /* start of glyph id array */
687
/* check that we point within the glyph ids table only */
688
if ( p < glyph_ids ||
689
p + ( end - start + 1 ) * 2 > table + length )
692
/* check glyph indices within the segment range */
693
if ( valid->level >= FT_VALIDATE_TIGHT )
698
for ( ; start < end; )
700
idx = FT_NEXT_USHORT( p );
703
idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
705
if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
718
FT_CALLBACK_DEF( FT_UInt )
719
tt_cmap4_char_index( TT_CMap cmap,
720
FT_UInt32 char_code )
722
FT_Byte* table = cmap->data;
726
if ( char_code < 0x10000UL )
728
FT_UInt idx, num_segs2;
730
FT_UInt code = (FT_UInt)char_code;
735
num_segs2 = TT_PEEK_USHORT( p ) & -2; /* be paranoid! */
738
/* Some fonts have more than 170 segments in their charmaps! */
739
/* We changed this function to use a more efficient binary */
740
/* search for improving performance */
743
FT_UInt max = num_segs2 >> 1;
744
FT_UInt mid, start, end, offset;
749
mid = ( min + max ) >> 1;
750
p = table + 14 + mid * 2;
751
end = TT_NEXT_USHORT( p );
753
start = TT_PEEK_USHORT( p);
758
else if ( code > end )
763
/* we found the segment */
767
delta = TT_PEEK_SHORT( p );
770
offset = TT_PEEK_USHORT( p );
774
p += offset + 2 * ( idx - start );
775
idx = TT_PEEK_USHORT( p );
779
result = (FT_UInt)( idx + delta ) & 0xFFFFU;
786
#else /* 0 - old code */
793
p = table + 14; /* ends table */
794
q = table + 16 + num_segs2; /* starts table */
797
for ( n = 0; n < num_segs2; n += 2 )
799
FT_UInt end = TT_NEXT_USHORT( p );
800
FT_UInt start = TT_NEXT_USHORT( q );
811
p = q + num_segs2 - 2;
812
delta = TT_PEEK_SHORT( p );
814
offset = TT_PEEK_USHORT( p );
818
p += offset + 2 * ( idx - start );
819
idx = TT_PEEK_USHORT( p );
823
result = (FT_UInt)( idx + delta ) & 0xFFFFU;
837
FT_CALLBACK_DEF( FT_UInt )
838
tt_cmap4_char_next( TT_CMap cmap,
839
FT_UInt32 *pchar_code )
841
FT_Byte* table = cmap->data;
842
FT_UInt32 result = 0;
843
FT_UInt32 char_code = *pchar_code + 1;
847
FT_UInt code, num_segs2;
850
if ( char_code >= 0x10000UL )
853
code = (FT_UInt)char_code;
855
num_segs2 = TT_PEEK_USHORT(p) & -2; /* ensure even-ness */
863
p = table + 14; /* ends table */
864
q = table + 16 + num_segs2; /* starts table */
866
for ( n = 0; n < num_segs2; n += 2 )
868
FT_UInt end = TT_NEXT_USHORT( p );
869
FT_UInt start = TT_NEXT_USHORT( q );
877
p = q + num_segs2 - 2;
878
delta = TT_PEEK_SHORT( p );
880
offset = TT_PEEK_USHORT( p );
884
/* parse the glyph ids array for non-0 index */
885
p += offset + ( code - start ) * 2;
886
while ( code <= end )
888
gindex = TT_NEXT_USHORT( p );
891
gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
899
gindex = (FT_UInt)( code + delta ) & 0xFFFFU;
909
/* loop to next trial charcode */
910
if ( code >= 0xFFFFU )
918
*pchar_code = result;
923
FT_CALLBACK_TABLE_DEF
924
const TT_CMap_ClassRec tt_cmap4_class_rec =
927
sizeof ( TT_CMapRec ),
929
(FT_CMap_InitFunc) tt_cmap_init,
930
(FT_CMap_DoneFunc) NULL,
931
(FT_CMap_CharIndexFunc)tt_cmap4_char_index,
932
(FT_CMap_CharNextFunc) tt_cmap4_char_next
935
(TT_CMap_ValidateFunc) tt_cmap4_validate
938
#endif /* TT_CONFIG_CMAP_FORMAT_4 */
941
/*************************************************************************/
942
/*************************************************************************/
944
/***** FORMAT 6 *****/
946
/*************************************************************************/
947
/*************************************************************************/
949
/*************************************************************************/
954
/* NAME OFFSET TYPE DESCRIPTION */
956
/* format 0 USHORT must be 4 */
957
/* length 2 USHORT table length in bytes */
958
/* language 4 USHORT Mac language code */
960
/* first 6 USHORT first segment code */
961
/* count 8 USHORT segment size in chars */
962
/* glyphIds 10 USHORT[count] glyph ids */
964
/* A very simplified segment mapping. */
967
#ifdef TT_CONFIG_CMAP_FORMAT_6
969
FT_CALLBACK_DEF( void )
970
tt_cmap6_validate( FT_Byte* table,
974
FT_UInt length, start, count;
977
if ( table + 10 > valid->limit )
978
FT_INVALID_TOO_SHORT;
981
length = TT_NEXT_USHORT( p );
983
p = table + 6; /* skip language */
984
start = TT_NEXT_USHORT( p );
985
count = TT_NEXT_USHORT( p );
987
if ( table + length > valid->limit || length < 10 + count * 2 )
988
FT_INVALID_TOO_SHORT;
990
/* check glyph indices */
991
if ( valid->level >= FT_VALIDATE_TIGHT )
996
for ( ; count > 0; count-- )
998
gindex = TT_NEXT_USHORT( p );
999
if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1000
FT_INVALID_GLYPH_ID;
1006
FT_CALLBACK_DEF( FT_UInt )
1007
tt_cmap6_char_index( TT_CMap cmap,
1008
FT_UInt32 char_code )
1010
FT_Byte* table = cmap->data;
1012
FT_Byte* p = table + 6;
1013
FT_UInt start = TT_NEXT_USHORT( p );
1014
FT_UInt count = TT_NEXT_USHORT( p );
1015
FT_UInt idx = (FT_UInt)( char_code - start );
1021
result = TT_PEEK_USHORT( p );
1027
FT_CALLBACK_DEF( FT_UInt )
1028
tt_cmap6_char_next( TT_CMap cmap,
1029
FT_UInt32 *pchar_code )
1031
FT_Byte* table = cmap->data;
1032
FT_UInt32 result = 0;
1033
FT_UInt32 char_code = *pchar_code + 1;
1036
FT_Byte* p = table + 6;
1037
FT_UInt start = TT_NEXT_USHORT( p );
1038
FT_UInt count = TT_NEXT_USHORT( p );
1042
if ( char_code >= 0x10000UL )
1045
if ( char_code < start )
1048
idx = (FT_UInt)( char_code - start );
1051
for ( ; idx < count; idx++ )
1053
gindex = TT_NEXT_USHORT( p );
1063
*pchar_code = result;
1068
FT_CALLBACK_TABLE_DEF
1069
const TT_CMap_ClassRec tt_cmap6_class_rec =
1072
sizeof ( TT_CMapRec ),
1074
(FT_CMap_InitFunc) tt_cmap_init,
1075
(FT_CMap_DoneFunc) NULL,
1076
(FT_CMap_CharIndexFunc)tt_cmap6_char_index,
1077
(FT_CMap_CharNextFunc) tt_cmap6_char_next
1080
(TT_CMap_ValidateFunc) tt_cmap6_validate
1083
#endif /* TT_CONFIG_CMAP_FORMAT_6 */
1086
/*************************************************************************/
1087
/*************************************************************************/
1089
/***** FORMAT 8 *****/
1091
/***** It's hard to completely understand what the OpenType spec *****/
1092
/***** says about this format, but here is my conclusion. *****/
1094
/***** The purpose of this format is to easily map UTF-16 text to *****/
1095
/***** glyph indices. Basically, the `char_code' must be in one of *****/
1096
/***** the following formats: *****/
1098
/***** - A 16-bit value that isn't part of the Unicode Surrogates *****/
1099
/***** Area (i.e. U+D800-U+DFFF). *****/
1101
/***** - A 32-bit value, made of two surrogate values, i.e.. if *****/
1102
/***** `char_code = (char_hi << 16) | char_lo', then both *****/
1103
/***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/
1106
/***** The 'is32' table embedded in the charmap indicates whether a *****/
1107
/***** given 16-bit value is in the surrogates area or not. *****/
1109
/***** So, for any given `char_code', we can assert the following: *****/
1111
/***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/
1113
/***** If `char_hi != 0' then we must have both *****/
1114
/***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/
1116
/*************************************************************************/
1117
/*************************************************************************/
1119
/*************************************************************************/
1121
/* TABLE OVERVIEW */
1122
/* -------------- */
1124
/* NAME OFFSET TYPE DESCRIPTION */
1126
/* format 0 USHORT must be 8 */
1127
/* reseved 2 USHORT reserved */
1128
/* length 4 ULONG length in bytes */
1129
/* language 8 ULONG Mac language code */
1130
/* is32 12 BYTE[8192] 32-bitness bitmap */
1131
/* count 8204 ULONG number of groups */
1133
/* This header is followed by 'count' groups of the following format: */
1135
/* start 0 ULONG first charcode */
1136
/* end 4 ULONG last charcode */
1137
/* startId 8 ULONG start glyph id for the group */
1140
#ifdef TT_CONFIG_CMAP_FORMAT_8
1142
FT_CALLBACK_DEF( void )
1143
tt_cmap8_validate( FT_Byte* table,
1144
FT_Validator valid )
1146
FT_Byte* p = table + 4;
1149
FT_UInt32 num_groups;
1152
if ( table + 16 + 8192 > valid->limit )
1153
FT_INVALID_TOO_SHORT;
1155
length = TT_NEXT_ULONG( p );
1156
if ( table + length > valid->limit || length < 8208 )
1157
FT_INVALID_TOO_SHORT;
1160
p = is32 + 8192; /* skip `is32' array */
1161
num_groups = TT_NEXT_ULONG( p );
1163
if ( p + num_groups * 12 > valid->limit )
1164
FT_INVALID_TOO_SHORT;
1166
/* check groups, they must be in increasing order */
1168
FT_UInt32 n, start, end, start_id, count, last = 0;
1171
for ( n = 0; n < num_groups; n++ )
1176
start = TT_NEXT_ULONG( p );
1177
end = TT_NEXT_ULONG( p );
1178
start_id = TT_NEXT_ULONG( p );
1183
if ( n > 0 && start <= last )
1186
if ( valid->level >= FT_VALIDATE_TIGHT )
1188
if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
1189
FT_INVALID_GLYPH_ID;
1191
count = (FT_UInt32)( end - start + 1 );
1193
if ( start & ~0xFFFFU )
1195
/* start_hi != 0; check that is32[i] is 1 for each i in */
1196
/* the `hi' and `lo' of the range [start..end] */
1197
for ( ; count > 0; count--, start++ )
1199
hi = (FT_UInt)( start >> 16 );
1200
lo = (FT_UInt)( start & 0xFFFFU );
1202
if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
1205
if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
1211
/* start_hi == 0; check that is32[i] is 0 for each i in */
1212
/* the range [start..end] */
1214
/* end_hi cannot be != 0! */
1215
if ( end & ~0xFFFFU )
1218
for ( ; count > 0; count--, start++ )
1220
lo = (FT_UInt)( start & 0xFFFFU );
1222
if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
1234
FT_CALLBACK_DEF( FT_UInt )
1235
tt_cmap8_char_index( TT_CMap cmap,
1236
FT_UInt32 char_code )
1238
FT_Byte* table = cmap->data;
1240
FT_Byte* p = table + 8204;
1241
FT_UInt32 num_groups = TT_NEXT_ULONG( p );
1242
FT_UInt32 start, end, start_id;
1245
for ( ; num_groups > 0; num_groups-- )
1247
start = TT_NEXT_ULONG( p );
1248
end = TT_NEXT_ULONG( p );
1249
start_id = TT_NEXT_ULONG( p );
1251
if ( char_code < start )
1254
if ( char_code <= end )
1256
result = start_id + char_code - start;
1264
FT_CALLBACK_DEF( FT_UInt )
1265
tt_cmap8_char_next( TT_CMap cmap,
1266
FT_UInt32 *pchar_code )
1268
FT_UInt32 result = 0;
1269
FT_UInt32 char_code = *pchar_code + 1;
1271
FT_Byte* table = cmap->data;
1272
FT_Byte* p = table + 8204;
1273
FT_UInt32 num_groups = TT_NEXT_ULONG( p );
1274
FT_UInt32 start, end, start_id;
1279
for ( ; num_groups > 0; num_groups-- )
1281
start = TT_NEXT_ULONG( p );
1282
end = TT_NEXT_ULONG( p );
1283
start_id = TT_NEXT_ULONG( p );
1285
if ( char_code < start )
1288
if ( char_code <= end )
1290
gindex = (FT_UInt)( char_code - start + start_id );
1300
*pchar_code = result;
1305
FT_CALLBACK_TABLE_DEF
1306
const TT_CMap_ClassRec tt_cmap8_class_rec =
1309
sizeof ( TT_CMapRec ),
1311
(FT_CMap_InitFunc) tt_cmap_init,
1312
(FT_CMap_DoneFunc) NULL,
1313
(FT_CMap_CharIndexFunc)tt_cmap8_char_index,
1314
(FT_CMap_CharNextFunc) tt_cmap8_char_next
1317
(TT_CMap_ValidateFunc) tt_cmap8_validate
1320
#endif /* TT_CONFIG_CMAP_FORMAT_8 */
1323
/*************************************************************************/
1324
/*************************************************************************/
1326
/***** FORMAT 10 *****/
1328
/*************************************************************************/
1329
/*************************************************************************/
1331
/*************************************************************************/
1333
/* TABLE OVERVIEW */
1334
/* -------------- */
1336
/* NAME OFFSET TYPE DESCRIPTION */
1338
/* format 0 USHORT must be 10 */
1339
/* reserved 2 USHORT reserved */
1340
/* length 4 ULONG length in bytes */
1341
/* language 8 ULONG Mac language code */
1343
/* start 12 ULONG first char in range */
1344
/* count 16 ULONG number of chars in range */
1345
/* glyphIds 20 USHORT[count] glyph indices covered */
1348
#ifdef TT_CONFIG_CMAP_FORMAT_10
1350
FT_CALLBACK_DEF( void )
1351
tt_cmap10_validate( FT_Byte* table,
1352
FT_Validator valid )
1354
FT_Byte* p = table + 4;
1355
FT_ULong length, start, count;
1358
if ( table + 20 > valid->limit )
1359
FT_INVALID_TOO_SHORT;
1361
length = TT_NEXT_ULONG( p );
1363
start = TT_NEXT_ULONG( p );
1364
count = TT_NEXT_ULONG( p );
1366
if ( table + length > valid->limit || length < 20 + count * 2 )
1367
FT_INVALID_TOO_SHORT;
1369
/* check glyph indices */
1370
if ( valid->level >= FT_VALIDATE_TIGHT )
1375
for ( ; count > 0; count-- )
1377
gindex = TT_NEXT_USHORT( p );
1378
if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1379
FT_INVALID_GLYPH_ID;
1385
FT_CALLBACK_DEF( FT_UInt )
1386
tt_cmap10_char_index( TT_CMap cmap,
1387
FT_UInt32 char_code )
1389
FT_Byte* table = cmap->data;
1391
FT_Byte* p = table + 12;
1392
FT_UInt32 start = TT_NEXT_ULONG( p );
1393
FT_UInt32 count = TT_NEXT_ULONG( p );
1394
FT_UInt32 idx = (FT_ULong)( char_code - start );
1400
result = TT_PEEK_USHORT( p );
1406
FT_CALLBACK_DEF( FT_UInt )
1407
tt_cmap10_char_next( TT_CMap cmap,
1408
FT_UInt32 *pchar_code )
1410
FT_Byte* table = cmap->data;
1411
FT_UInt32 result = 0;
1412
FT_UInt32 char_code = *pchar_code + 1;
1414
FT_Byte* p = table + 12;
1415
FT_UInt32 start = TT_NEXT_ULONG( p );
1416
FT_UInt32 count = TT_NEXT_ULONG( p );
1420
if ( char_code < start )
1423
idx = (FT_UInt32)( char_code - start );
1426
for ( ; idx < count; idx++ )
1428
gindex = TT_NEXT_USHORT( p );
1437
*pchar_code = char_code;
1442
FT_CALLBACK_TABLE_DEF
1443
const TT_CMap_ClassRec tt_cmap10_class_rec =
1446
sizeof ( TT_CMapRec ),
1448
(FT_CMap_InitFunc) tt_cmap_init,
1449
(FT_CMap_DoneFunc) NULL,
1450
(FT_CMap_CharIndexFunc)tt_cmap10_char_index,
1451
(FT_CMap_CharNextFunc) tt_cmap10_char_next
1454
(TT_CMap_ValidateFunc) tt_cmap10_validate
1457
#endif /* TT_CONFIG_CMAP_FORMAT_10 */
1460
/*************************************************************************/
1461
/*************************************************************************/
1463
/***** FORMAT 12 *****/
1465
/*************************************************************************/
1466
/*************************************************************************/
1468
/*************************************************************************/
1470
/* TABLE OVERVIEW */
1471
/* -------------- */
1473
/* NAME OFFSET TYPE DESCRIPTION */
1475
/* format 0 USHORT must be 12 */
1476
/* reserved 2 USHORT reserved */
1477
/* length 4 ULONG length in bytes */
1478
/* language 8 ULONG Mac language code */
1479
/* count 12 ULONG number of groups */
1482
/* This header is followed by `count' groups of the following format: */
1484
/* start 0 ULONG first charcode */
1485
/* end 4 ULONG last charcode */
1486
/* startId 8 ULONG start glyph id for the group */
1489
#ifdef TT_CONFIG_CMAP_FORMAT_12
1491
FT_CALLBACK_DEF( void )
1492
tt_cmap12_validate( FT_Byte* table,
1493
FT_Validator valid )
1497
FT_ULong num_groups;
1500
if ( table + 16 > valid->limit )
1501
FT_INVALID_TOO_SHORT;
1504
length = TT_NEXT_ULONG( p );
1507
num_groups = TT_NEXT_ULONG( p );
1509
if ( table + length > valid->limit || length < 16 + 12 * num_groups )
1510
FT_INVALID_TOO_SHORT;
1512
/* check groups, they must be in increasing order */
1514
FT_ULong n, start, end, start_id, last = 0;
1517
for ( n = 0; n < num_groups; n++ )
1519
start = TT_NEXT_ULONG( p );
1520
end = TT_NEXT_ULONG( p );
1521
start_id = TT_NEXT_ULONG( p );
1526
if ( n > 0 && start <= last )
1529
if ( valid->level >= FT_VALIDATE_TIGHT )
1531
if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
1532
FT_INVALID_GLYPH_ID;
1541
FT_CALLBACK_DEF( FT_UInt )
1542
tt_cmap12_char_index( TT_CMap cmap,
1543
FT_UInt32 char_code )
1546
FT_Byte* table = cmap->data;
1547
FT_Byte* p = table + 12;
1548
FT_UInt32 num_groups = TT_NEXT_ULONG( p );
1549
FT_UInt32 start, end, start_id;
1552
for ( ; num_groups > 0; num_groups-- )
1554
start = TT_NEXT_ULONG( p );
1555
end = TT_NEXT_ULONG( p );
1556
start_id = TT_NEXT_ULONG( p );
1558
if ( char_code < start )
1561
if ( char_code <= end )
1563
result = start_id + char_code - start;
1571
FT_CALLBACK_DEF( FT_UInt )
1572
tt_cmap12_char_next( TT_CMap cmap,
1573
FT_UInt32 *pchar_code )
1575
FT_Byte* table = cmap->data;
1576
FT_UInt32 result = 0;
1577
FT_UInt32 char_code = *pchar_code + 1;
1579
FT_Byte* p = table + 12;
1580
FT_UInt32 num_groups = TT_NEXT_ULONG( p );
1581
FT_UInt32 start, end, start_id;
1586
for ( ; num_groups > 0; num_groups-- )
1588
start = TT_NEXT_ULONG( p );
1589
end = TT_NEXT_ULONG( p );
1590
start_id = TT_NEXT_ULONG( p );
1592
if ( char_code < start )
1595
if ( char_code <= end )
1597
gindex = (FT_UInt)(char_code - start + start_id);
1607
*pchar_code = result;
1612
FT_CALLBACK_TABLE_DEF
1613
const TT_CMap_ClassRec tt_cmap12_class_rec =
1616
sizeof ( TT_CMapRec ),
1618
(FT_CMap_InitFunc) tt_cmap_init,
1619
(FT_CMap_DoneFunc) NULL,
1620
(FT_CMap_CharIndexFunc)tt_cmap12_char_index,
1621
(FT_CMap_CharNextFunc) tt_cmap12_char_next
1624
(TT_CMap_ValidateFunc) tt_cmap12_validate
1628
#endif /* TT_CONFIG_CMAP_FORMAT_12 */
1631
#ifdef FT_CONFIG_OPTION_USE_CMAPS
1633
static const TT_CMap_Class tt_cmap_classes[] =
1635
#ifdef TT_CONFIG_CMAP_FORMAT_0
1636
&tt_cmap0_class_rec,
1639
#ifdef TT_CONFIG_CMAP_FORMAT_2
1640
&tt_cmap2_class_rec,
1643
#ifdef TT_CONFIG_CMAP_FORMAT_4
1644
&tt_cmap4_class_rec,
1647
#ifdef TT_CONFIG_CMAP_FORMAT_6
1648
&tt_cmap6_class_rec,
1651
#ifdef TT_CONFIG_CMAP_FORMAT_8
1652
&tt_cmap8_class_rec,
1655
#ifdef TT_CONFIG_CMAP_FORMAT_10
1656
&tt_cmap10_class_rec,
1659
#ifdef TT_CONFIG_CMAP_FORMAT_12
1660
&tt_cmap12_class_rec,
1667
/* parse the `cmap' table and build the corresponding TT_CMap objects */
1668
/* in the current face */
1670
FT_LOCAL_DEF( FT_Error )
1671
TT_Build_CMaps( TT_Face face )
1673
FT_Byte* table = face->cmap_table;
1674
FT_Byte* limit = table + face->cmap_size;
1675
volatile FT_UInt num_cmaps;
1676
volatile FT_Byte* p = table;
1679
if ( p + 4 > limit )
1680
return FT_Err_Invalid_Table;
1682
/* only recognize format 0 */
1683
if ( TT_NEXT_USHORT( p ) != 0 )
1686
FT_ERROR(( "TT_Build_CMaps: unsupported `cmap' table format = %d\n",
1687
TT_PEEK_USHORT( p ) ));
1688
return FT_Err_Invalid_Table;
1691
num_cmaps = TT_NEXT_USHORT( p );
1693
for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
1695
FT_CharMapRec charmap;
1699
charmap.platform_id = TT_NEXT_USHORT( p );
1700
charmap.encoding_id = TT_NEXT_USHORT( p );
1701
charmap.face = FT_FACE( face );
1702
charmap.encoding = ft_encoding_none; /* will be filled later */
1703
offset = TT_NEXT_ULONG( p );
1705
if ( offset && table + offset + 2 < limit )
1707
FT_Byte* cmap = table + offset;
1708
FT_UInt format = TT_PEEK_USHORT( cmap );
1709
volatile const TT_CMap_Class* pclazz = tt_cmap_classes;
1710
TT_CMap_Class clazz;
1713
for ( ; *pclazz; pclazz++ )
1716
if ( clazz->format == format )
1718
volatile TT_ValidatorRec valid;
1721
ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
1722
FT_VALIDATE_DEFAULT );
1724
valid.num_glyphs = face->root.num_glyphs;
1726
if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer ) == 0 )
1728
/* validate this cmap sub-table */
1729
clazz->validate( cmap, FT_VALIDATOR( &valid ) );
1732
if ( valid.validator.error == 0 )
1733
(void)FT_CMap_New( (FT_CMap_Class)clazz, cmap, &charmap, NULL );
1736
FT_ERROR(( "TT_Build_CMaps:" ));
1737
FT_ERROR(( " broken cmap sub-table ignored!\n" ));
1747
#endif /* FT_CONFIG_OPTION_USE_CMAPS */