Bug Summary

File:./freetype/ttcmap.c
Warning:line 2306, column 11
Value stored to 'gindex' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple amd64-unknown-openbsd6.8 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name _sfnt.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mthread-model posix -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/local/lib/clang/10.0.1 -I /usr/X11R6/include -I /usr/local/include -fdebug-compilation-dir /home/ben/Projects/ClassiCube/src -ferror-limit 19 -fmessage-length 0 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -fobjc-runtime=gnustep -fdiagnostics-show-option -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/ClassiCube/src/scan/2020-12-10-180422-33404-1 -x c _sfnt.c
1/***************************************************************************/
2/* */
3/* ttcmap.c */
4/* */
5/* TrueType character mapping table (cmap) support (body). */
6/* */
7/* Copyright 2002-2018 by */
8/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
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. */
15/* */
16/***************************************************************************/
17
18
19#include "ft2build.h"
20#include FT_INTERNAL_DEBUG_H"ftdebug.h"
21
22#include "sferrors.h" /* must come before FT_INTERNAL_VALIDATE_H */
23
24#include FT_INTERNAL_VALIDATE_H"ftvalid.h"
25#include FT_INTERNAL_STREAM_H"ftstream.h"
26#include FT_SERVICE_POSTSCRIPT_CMAPS_H"svpscmap.h"
27#include "ttload.h"
28#include "ttcmap.h"
29#include "ttpost.h"
30
31
32 /*************************************************************************/
33 /* */
34 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
35 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
36 /* messages during execution. */
37 /* */
38#undef FT_COMPONENTtrace_ttsbit
39#define FT_COMPONENTtrace_ttsbit trace_ttcmap
40
41
42#define TT_PEEK_SHORTFT_PEEK_SHORT FT_PEEK_SHORT
43#define TT_PEEK_USHORTFT_PEEK_USHORT FT_PEEK_USHORT
44#define TT_PEEK_UINT24FT_PEEK_UOFF3 FT_PEEK_UOFF3
45#define TT_PEEK_LONGFT_PEEK_LONG FT_PEEK_LONG
46#define TT_PEEK_ULONGFT_PEEK_ULONG FT_PEEK_ULONG
47
48#define TT_NEXT_SHORTFT_NEXT_SHORT FT_NEXT_SHORT
49#define TT_NEXT_USHORTFT_NEXT_USHORT FT_NEXT_USHORT
50#define TT_NEXT_UINT24FT_NEXT_UOFF3 FT_NEXT_UOFF3
51#define TT_NEXT_LONGFT_NEXT_LONG FT_NEXT_LONG
52#define TT_NEXT_ULONGFT_NEXT_ULONG FT_NEXT_ULONG
53
54
55 /* Too large glyph index return values are caught in `FT_Get_Char_Index' */
56 /* and `FT_Get_Next_Char' (the latter calls the internal `next' function */
57 /* again in this case). To mark character code return values as invalid */
58 /* it is sufficient to set the corresponding glyph index return value to */
59 /* zero. */
60
61
62 FT_CALLBACK_DEF( FT_Error )static FT_Error
63 tt_cmap_init( TT_CMap cmap,
64 FT_Byte* table )
65 {
66 cmap->data = table;
67 return FT_Err_Ok;
68 }
69
70
71 /*************************************************************************/
72 /*************************************************************************/
73 /***** *****/
74 /***** FORMAT 0 *****/
75 /***** *****/
76 /*************************************************************************/
77 /*************************************************************************/
78
79 /*************************************************************************/
80 /* */
81 /* TABLE OVERVIEW */
82 /* -------------- */
83 /* */
84 /* NAME OFFSET TYPE DESCRIPTION */
85 /* */
86 /* format 0 USHORT must be 0 */
87 /* length 2 USHORT table length in bytes */
88 /* language 4 USHORT Mac language code */
89 /* glyph_ids 6 BYTE[256] array of glyph indices */
90 /* 262 */
91 /* */
92
93#ifdef TT_CONFIG_CMAP_FORMAT_0
94
95 FT_CALLBACK_DEF( FT_Error )static FT_Error
96 tt_cmap0_validate( FT_Byte* table,
97 FT_Validator valid )
98 {
99 FT_Byte* p;
100 FT_UInt length;
101
102
103 if ( table + 2 + 2 > valid->limit )
104 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
105
106 p = table + 2; /* skip format */
107 length = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
108
109 if ( table + length > valid->limit || length < 262 )
110 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
111
112 /* check glyph indices whenever necessary */
113 if ( valid->level >= FT_VALIDATE_TIGHT )
114 {
115 FT_UInt n, idx;
116
117
118 p = table + 6;
119 for ( n = 0; n < 256; n++ )
120 {
121 idx = *p++;
122 if ( idx >= TT_VALID_GLYPH_COUNT( valid )( (TT_Validator)( valid ) )->num_glyphs )
123 FT_INVALID_GLYPH_IDft_validator_error( valid, SFNT_Err_Invalid_Glyph_Index );
124 }
125 }
126
127 return FT_Err_Ok;
128 }
129
130
131 FT_CALLBACK_DEF( FT_UInt )static FT_UInt
132 tt_cmap0_char_index( TT_CMap cmap,
133 FT_UInt32 char_code )
134 {
135 FT_Byte* table = cmap->data;
136
137
138 return char_code < 256 ? table[6 + char_code] : 0;
139 }
140
141
142 FT_CALLBACK_DEF( FT_UInt32 )static FT_UInt32
143 tt_cmap0_char_next( TT_CMap cmap,
144 FT_UInt32 *pchar_code )
145 {
146 FT_Byte* table = cmap->data;
147 FT_UInt32 charcode = *pchar_code;
148 FT_UInt32 result = 0;
149 FT_UInt gindex = 0;
150
151
152 table += 6; /* go to glyph IDs */
153 while ( ++charcode < 256 )
154 {
155 gindex = table[charcode];
156 if ( gindex != 0 )
157 {
158 result = charcode;
159 break;
160 }
161 }
162
163 *pchar_code = result;
164 return gindex;
165 }
166
167
168 FT_CALLBACK_DEF( FT_Error )static FT_Error
169 tt_cmap0_get_info( TT_CMap cmap,
170 TT_CMapInfo *cmap_info )
171 {
172 cmap_info->format = 0;
173 return FT_Err_Ok;
174 }
175
176
177 FT_DEFINE_TT_CMAP(const TT_CMap_ClassRec tt_cmap0_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap0_char_index, (FT_CMap_CharNextFunc
) tt_cmap0_char_next }, 0, (TT_CMap_ValidateFunc)tt_cmap0_validate
, (TT_CMap_Info_GetFunc)tt_cmap0_get_info };
178 tt_cmap0_class_rec,const TT_CMap_ClassRec tt_cmap0_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap0_char_index, (FT_CMap_CharNextFunc
) tt_cmap0_char_next }, 0, (TT_CMap_ValidateFunc)tt_cmap0_validate
, (TT_CMap_Info_GetFunc)tt_cmap0_get_info };
179
180 sizeof ( TT_CMapRec ),const TT_CMap_ClassRec tt_cmap0_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap0_char_index, (FT_CMap_CharNextFunc
) tt_cmap0_char_next }, 0, (TT_CMap_ValidateFunc)tt_cmap0_validate
, (TT_CMap_Info_GetFunc)tt_cmap0_get_info };
181
182 (FT_CMap_InitFunc) tt_cmap_init, /* init */const TT_CMap_ClassRec tt_cmap0_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap0_char_index, (FT_CMap_CharNextFunc
) tt_cmap0_char_next }, 0, (TT_CMap_ValidateFunc)tt_cmap0_validate
, (TT_CMap_Info_GetFunc)tt_cmap0_get_info };
183 (FT_CMap_DoneFunc) NULL, /* done */const TT_CMap_ClassRec tt_cmap0_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap0_char_index, (FT_CMap_CharNextFunc
) tt_cmap0_char_next }, 0, (TT_CMap_ValidateFunc)tt_cmap0_validate
, (TT_CMap_Info_GetFunc)tt_cmap0_get_info };
184 (FT_CMap_CharIndexFunc)tt_cmap0_char_index, /* char_index */const TT_CMap_ClassRec tt_cmap0_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap0_char_index, (FT_CMap_CharNextFunc
) tt_cmap0_char_next }, 0, (TT_CMap_ValidateFunc)tt_cmap0_validate
, (TT_CMap_Info_GetFunc)tt_cmap0_get_info };
185 (FT_CMap_CharNextFunc) tt_cmap0_char_next, /* char_next */const TT_CMap_ClassRec tt_cmap0_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap0_char_index, (FT_CMap_CharNextFunc
) tt_cmap0_char_next }, 0, (TT_CMap_ValidateFunc)tt_cmap0_validate
, (TT_CMap_Info_GetFunc)tt_cmap0_get_info };
186
187 0,const TT_CMap_ClassRec tt_cmap0_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap0_char_index, (FT_CMap_CharNextFunc
) tt_cmap0_char_next }, 0, (TT_CMap_ValidateFunc)tt_cmap0_validate
, (TT_CMap_Info_GetFunc)tt_cmap0_get_info };
188 (TT_CMap_ValidateFunc)tt_cmap0_validate, /* validate */const TT_CMap_ClassRec tt_cmap0_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap0_char_index, (FT_CMap_CharNextFunc
) tt_cmap0_char_next }, 0, (TT_CMap_ValidateFunc)tt_cmap0_validate
, (TT_CMap_Info_GetFunc)tt_cmap0_get_info };
189 (TT_CMap_Info_GetFunc)tt_cmap0_get_info /* get_cmap_info */const TT_CMap_ClassRec tt_cmap0_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap0_char_index, (FT_CMap_CharNextFunc
) tt_cmap0_char_next }, 0, (TT_CMap_ValidateFunc)tt_cmap0_validate
, (TT_CMap_Info_GetFunc)tt_cmap0_get_info };
190 )const TT_CMap_ClassRec tt_cmap0_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap0_char_index, (FT_CMap_CharNextFunc
) tt_cmap0_char_next }, 0, (TT_CMap_ValidateFunc)tt_cmap0_validate
, (TT_CMap_Info_GetFunc)tt_cmap0_get_info };
191
192#endif /* TT_CONFIG_CMAP_FORMAT_0 */
193
194
195 /*************************************************************************/
196 /*************************************************************************/
197 /***** *****/
198 /***** FORMAT 2 *****/
199 /***** *****/
200 /***** This is used for certain CJK encodings that encode text in a *****/
201 /***** mixed 8/16 bits encoding along the following lines. *****/
202 /***** *****/
203 /***** * Certain byte values correspond to an 8-bit character code *****/
204 /***** (typically in the range 0..127 for ASCII compatibility). *****/
205 /***** *****/
206 /***** * Certain byte values signal the first byte of a 2-byte *****/
207 /***** character code (but these values are also valid as the *****/
208 /***** second byte of a 2-byte character). *****/
209 /***** *****/
210 /***** The following charmap lookup and iteration functions all *****/
211 /***** assume that the value `charcode' fulfills the following. *****/
212 /***** *****/
213 /***** - For one-byte characters, `charcode' is simply the *****/
214 /***** character code. *****/
215 /***** *****/
216 /***** - For two-byte characters, `charcode' is the 2-byte *****/
217 /***** character code in big endian format. More precisely: *****/
218 /***** *****/
219 /***** (charcode >> 8) is the first byte value *****/
220 /***** (charcode & 0xFF) is the second byte value *****/
221 /***** *****/
222 /***** Note that not all values of `charcode' are valid according *****/
223 /***** to these rules, and the function moderately checks the *****/
224 /***** arguments. *****/
225 /***** *****/
226 /*************************************************************************/
227 /*************************************************************************/
228
229 /*************************************************************************/
230 /* */
231 /* TABLE OVERVIEW */
232 /* -------------- */
233 /* */
234 /* NAME OFFSET TYPE DESCRIPTION */
235 /* */
236 /* format 0 USHORT must be 2 */
237 /* length 2 USHORT table length in bytes */
238 /* language 4 USHORT Mac language code */
239 /* keys 6 USHORT[256] sub-header keys */
240 /* subs 518 SUBHEAD[NSUBS] sub-headers array */
241 /* glyph_ids 518+NSUB*8 USHORT[] glyph ID array */
242 /* */
243 /* The `keys' table is used to map charcode high bytes to sub-headers. */
244 /* The value of `NSUBS' is the number of sub-headers defined in the */
245 /* table and is computed by finding the maximum of the `keys' table. */
246 /* */
247 /* Note that for any `n', `keys[n]' is a byte offset within the `subs' */
248 /* table, i.e., it is the corresponding sub-header index multiplied */
249 /* by 8. */
250 /* */
251 /* Each sub-header has the following format. */
252 /* */
253 /* NAME OFFSET TYPE DESCRIPTION */
254 /* */
255 /* first 0 USHORT first valid low-byte */
256 /* count 2 USHORT number of valid low-bytes */
257 /* delta 4 SHORT see below */
258 /* offset 6 USHORT see below */
259 /* */
260 /* A sub-header defines, for each high byte, the range of valid */
261 /* low bytes within the charmap. Note that the range defined by `first' */
262 /* and `count' must be completely included in the interval [0..255] */
263 /* according to the specification. */
264 /* */
265 /* If a character code is contained within a given sub-header, then */
266 /* mapping it to a glyph index is done as follows. */
267 /* */
268 /* * The value of `offset' is read. This is a _byte_ distance from the */
269 /* location of the `offset' field itself into a slice of the */
270 /* `glyph_ids' table. Let's call it `slice' (it is a USHORT[], too). */
271 /* */
272 /* * The value `slice[char.lo - first]' is read. If it is 0, there is */
273 /* no glyph for the charcode. Otherwise, the value of `delta' is */
274 /* added to it (modulo 65536) to form a new glyph index. */
275 /* */
276 /* It is up to the validation routine to check that all offsets fall */
277 /* within the glyph IDs table (and not within the `subs' table itself or */
278 /* outside of the CMap). */
279 /* */
280
281#ifdef TT_CONFIG_CMAP_FORMAT_2
282
283 FT_CALLBACK_DEF( FT_Error )static FT_Error
284 tt_cmap2_validate( FT_Byte* table,
285 FT_Validator valid )
286 {
287 FT_Byte* p;
288 FT_UInt length;
289
290 FT_UInt n, max_subs;
291 FT_Byte* keys; /* keys table */
292 FT_Byte* subs; /* sub-headers */
293 FT_Byte* glyph_ids; /* glyph ID array */
294
295
296 if ( table + 2 + 2 > valid->limit )
297 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
298
299 p = table + 2; /* skip format */
300 length = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
301
302 if ( table + length > valid->limit || length < 6 + 512 )
303 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
304
305 keys = table + 6;
306
307 /* parse keys to compute sub-headers count */
308 p = keys;
309 max_subs = 0;
310 for ( n = 0; n < 256; n++ )
311 {
312 FT_UInt idx = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
313
314
315 /* value must be multiple of 8 */
316 if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
317 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
318
319 idx >>= 3;
320
321 if ( idx > max_subs )
322 max_subs = idx;
323 }
324
325 FT_ASSERT( p == table + 518 )do { } while ( 0 );
326
327 subs = p;
328 glyph_ids = subs + ( max_subs + 1 ) * 8;
329 if ( glyph_ids > valid->limit )
330 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
331
332 /* parse sub-headers */
333 for ( n = 0; n <= max_subs; n++ )
334 {
335 FT_UInt first_code, code_count, offset;
336 FT_Int delta;
337
338
339 first_code = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
340 code_count = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
341 delta = TT_NEXT_SHORT( p )( (short)( p += 2, ( (FT_Int16)(( ( (FT_UInt16)(( ((const FT_Byte
*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16)(( ((const
FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
342 offset = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
343
344 /* many Dynalab fonts have empty sub-headers */
345 if ( code_count == 0 )
346 continue;
347
348 /* check range within 0..255 */
349 if ( valid->level >= FT_VALIDATE_PARANOID )
350 {
351 if ( first_code >= 256 || code_count > 256 - first_code )
352 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
353 }
354
355 /* check offset */
356 if ( offset != 0 )
357 {
358 FT_Byte* ids;
359
360
361 ids = p - 2 + offset;
362 if ( ids < glyph_ids || ids + code_count * 2 > table + length )
363 FT_INVALID_OFFSETft_validator_error( valid, SFNT_Err_Invalid_Offset );
364
365 /* check glyph IDs */
366 if ( valid->level >= FT_VALIDATE_TIGHT )
367 {
368 FT_Byte* limit = p + code_count * 2;
369 FT_UInt idx;
370
371
372 for ( ; p < limit; )
373 {
374 idx = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
375 if ( idx != 0 )
376 {
377 idx = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
378 if ( idx >= TT_VALID_GLYPH_COUNT( valid )( (TT_Validator)( valid ) )->num_glyphs )
379 FT_INVALID_GLYPH_IDft_validator_error( valid, SFNT_Err_Invalid_Glyph_Index );
380 }
381 }
382 }
383 }
384 }
385
386 return FT_Err_Ok;
387 }
388
389
390 /* return sub header corresponding to a given character code */
391 /* NULL on invalid charcode */
392 static FT_Byte*
393 tt_cmap2_get_subheader( FT_Byte* table,
394 FT_UInt32 char_code )
395 {
396 FT_Byte* result = NULL((void*)0);
397
398
399 if ( char_code < 0x10000UL )
400 {
401 FT_UInt char_lo = (FT_UInt)( char_code & 0xFF );
402 FT_UInt char_hi = (FT_UInt)( char_code >> 8 );
403 FT_Byte* p = table + 6; /* keys table */
404 FT_Byte* subs = table + 518; /* subheaders table */
405 FT_Byte* sub;
406
407
408 if ( char_hi == 0 )
409 {
410 /* an 8-bit character code -- we use subHeader 0 in this case */
411 /* to test whether the character code is in the charmap */
412 /* */
413 sub = subs; /* jump to first sub-header */
414
415 /* check that the sub-header for this byte is 0, which */
416 /* indicates that it is really a valid one-byte value; */
417 /* otherwise, return 0 */
418 /* */
419 p += char_lo * 2;
420 if ( TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
!= 0 )
421 goto Exit;
422 }
423 else
424 {
425 /* a 16-bit character code */
426
427 /* jump to key entry */
428 p += char_hi * 2;
429 /* jump to sub-header */
430 sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 )( (( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)]
)) ) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p)
)[(1)] )) ) << (0) )) )) & ~( __typeof__ ( ( (FT_UInt16
)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] )) ) << (
8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(1)] )) ) <<
(0) )) ) ) )( (8) - 1 ) )
);
431
432 /* check that the high byte isn't a valid one-byte value */
433 if ( sub == subs )
434 goto Exit;
435 }
436
437 result = sub;
438 }
439
440 Exit:
441 return result;
442 }
443
444
445 FT_CALLBACK_DEF( FT_UInt )static FT_UInt
446 tt_cmap2_char_index( TT_CMap cmap,
447 FT_UInt32 char_code )
448 {
449 FT_Byte* table = cmap->data;
450 FT_UInt result = 0;
451 FT_Byte* subheader;
452
453
454 subheader = tt_cmap2_get_subheader( table, char_code );
455 if ( subheader )
456 {
457 FT_Byte* p = subheader;
458 FT_UInt idx = (FT_UInt)(char_code & 0xFF);
459 FT_UInt start, count;
460 FT_Int delta;
461 FT_UInt offset;
462
463
464 start = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
465 count = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
466 delta = TT_NEXT_SHORT ( p )( (short)( p += 2, ( (FT_Int16)(( ( (FT_UInt16)(( ((const FT_Byte
*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16)(( ((const
FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
467 offset = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
468
469 idx -= start;
470 if ( idx < count && offset != 0 )
471 {
472 p += offset + 2 * idx;
473 idx = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
474
475 if ( idx != 0 )
476 result = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
477 }
478 }
479
480 return result;
481 }
482
483
484 FT_CALLBACK_DEF( FT_UInt32 )static FT_UInt32
485 tt_cmap2_char_next( TT_CMap cmap,
486 FT_UInt32 *pcharcode )
487 {
488 FT_Byte* table = cmap->data;
489 FT_UInt gindex = 0;
490 FT_UInt32 result = 0;
491 FT_UInt32 charcode = *pcharcode + 1;
492 FT_Byte* subheader;
493
494
495 while ( charcode < 0x10000UL )
496 {
497 subheader = tt_cmap2_get_subheader( table, charcode );
498 if ( subheader )
499 {
500 FT_Byte* p = subheader;
501 FT_UInt start = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
502 FT_UInt count = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
503 FT_Int delta = TT_NEXT_SHORT ( p )( (short)( p += 2, ( (FT_Int16)(( ( (FT_UInt16)(( ((const FT_Byte
*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16)(( ((const
FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
504 FT_UInt offset = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
505 FT_UInt char_lo = (FT_UInt)( charcode & 0xFF );
506 FT_UInt pos, idx;
507
508
509 if ( char_lo >= start + count && charcode <= 0xFF )
510 {
511 /* this happens only for a malformed cmap */
512 charcode = 0x100;
513 continue;
514 }
515
516 if ( offset == 0 )
517 {
518 if ( charcode == 0x100 )
519 goto Exit; /* this happens only for a malformed cmap */
520 goto Next_SubHeader;
521 }
522
523 if ( char_lo < start )
524 {
525 char_lo = start;
526 pos = 0;
527 }
528 else
529 pos = (FT_UInt)( char_lo - start );
530
531 p += offset + pos * 2;
532 charcode = FT_PAD_FLOOR( charcode, 256 )( (charcode) & ~( __typeof__ ( charcode ) )( (256) - 1 ) ) + char_lo;
533
534 for ( ; pos < count; pos++, charcode++ )
535 {
536 idx = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
537
538 if ( idx != 0 )
539 {
540 gindex = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
541 if ( gindex != 0 )
542 {
543 result = charcode;
544 goto Exit;
545 }
546 }
547 }
548
549 /* if unsuccessful, avoid `charcode' leaving */
550 /* the current 256-character block */
551 if ( count )
552 charcode--;
553 }
554
555 /* If `charcode' is <= 0xFF, retry with `charcode + 1'. */
556 /* Otherwise jump to the next 256-character block and retry. */
557 Next_SubHeader:
558 if ( charcode <= 0xFF )
559 charcode++;
560 else
561 charcode = FT_PAD_FLOOR( charcode, 0x100 )( (charcode) & ~( __typeof__ ( charcode ) )( (0x100) - 1 )
)
+ 0x100;
562 }
563
564 Exit:
565 *pcharcode = result;
566
567 return gindex;
568 }
569
570
571 FT_CALLBACK_DEF( FT_Error )static FT_Error
572 tt_cmap2_get_info( TT_CMap cmap,
573 TT_CMapInfo *cmap_info )
574 {
575 cmap_info->format = 2;
576 return FT_Err_Ok;
577 }
578
579
580 FT_DEFINE_TT_CMAP(const TT_CMap_ClassRec tt_cmap2_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap2_char_index, (FT_CMap_CharNextFunc
) tt_cmap2_char_next }, 2, (TT_CMap_ValidateFunc)tt_cmap2_validate
, (TT_CMap_Info_GetFunc)tt_cmap2_get_info };
581 tt_cmap2_class_rec,const TT_CMap_ClassRec tt_cmap2_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap2_char_index, (FT_CMap_CharNextFunc
) tt_cmap2_char_next }, 2, (TT_CMap_ValidateFunc)tt_cmap2_validate
, (TT_CMap_Info_GetFunc)tt_cmap2_get_info };
582
583 sizeof ( TT_CMapRec ),const TT_CMap_ClassRec tt_cmap2_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap2_char_index, (FT_CMap_CharNextFunc
) tt_cmap2_char_next }, 2, (TT_CMap_ValidateFunc)tt_cmap2_validate
, (TT_CMap_Info_GetFunc)tt_cmap2_get_info };
584
585 (FT_CMap_InitFunc) tt_cmap_init, /* init */const TT_CMap_ClassRec tt_cmap2_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap2_char_index, (FT_CMap_CharNextFunc
) tt_cmap2_char_next }, 2, (TT_CMap_ValidateFunc)tt_cmap2_validate
, (TT_CMap_Info_GetFunc)tt_cmap2_get_info };
586 (FT_CMap_DoneFunc) NULL, /* done */const TT_CMap_ClassRec tt_cmap2_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap2_char_index, (FT_CMap_CharNextFunc
) tt_cmap2_char_next }, 2, (TT_CMap_ValidateFunc)tt_cmap2_validate
, (TT_CMap_Info_GetFunc)tt_cmap2_get_info };
587 (FT_CMap_CharIndexFunc)tt_cmap2_char_index, /* char_index */const TT_CMap_ClassRec tt_cmap2_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap2_char_index, (FT_CMap_CharNextFunc
) tt_cmap2_char_next }, 2, (TT_CMap_ValidateFunc)tt_cmap2_validate
, (TT_CMap_Info_GetFunc)tt_cmap2_get_info };
588 (FT_CMap_CharNextFunc) tt_cmap2_char_next, /* char_next */const TT_CMap_ClassRec tt_cmap2_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap2_char_index, (FT_CMap_CharNextFunc
) tt_cmap2_char_next }, 2, (TT_CMap_ValidateFunc)tt_cmap2_validate
, (TT_CMap_Info_GetFunc)tt_cmap2_get_info };
589
590 2,const TT_CMap_ClassRec tt_cmap2_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap2_char_index, (FT_CMap_CharNextFunc
) tt_cmap2_char_next }, 2, (TT_CMap_ValidateFunc)tt_cmap2_validate
, (TT_CMap_Info_GetFunc)tt_cmap2_get_info };
591 (TT_CMap_ValidateFunc)tt_cmap2_validate, /* validate */const TT_CMap_ClassRec tt_cmap2_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap2_char_index, (FT_CMap_CharNextFunc
) tt_cmap2_char_next }, 2, (TT_CMap_ValidateFunc)tt_cmap2_validate
, (TT_CMap_Info_GetFunc)tt_cmap2_get_info };
592 (TT_CMap_Info_GetFunc)tt_cmap2_get_info /* get_cmap_info */const TT_CMap_ClassRec tt_cmap2_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap2_char_index, (FT_CMap_CharNextFunc
) tt_cmap2_char_next }, 2, (TT_CMap_ValidateFunc)tt_cmap2_validate
, (TT_CMap_Info_GetFunc)tt_cmap2_get_info };
593 )const TT_CMap_ClassRec tt_cmap2_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap2_char_index, (FT_CMap_CharNextFunc
) tt_cmap2_char_next }, 2, (TT_CMap_ValidateFunc)tt_cmap2_validate
, (TT_CMap_Info_GetFunc)tt_cmap2_get_info };
594
595#endif /* TT_CONFIG_CMAP_FORMAT_2 */
596
597
598 /*************************************************************************/
599 /*************************************************************************/
600 /***** *****/
601 /***** FORMAT 4 *****/
602 /***** *****/
603 /*************************************************************************/
604 /*************************************************************************/
605
606 /*************************************************************************/
607 /* */
608 /* TABLE OVERVIEW */
609 /* -------------- */
610 /* */
611 /* NAME OFFSET TYPE DESCRIPTION */
612 /* */
613 /* format 0 USHORT must be 4 */
614 /* length 2 USHORT table length */
615 /* in bytes */
616 /* language 4 USHORT Mac language code */
617 /* */
618 /* segCountX2 6 USHORT 2*NUM_SEGS */
619 /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */
620 /* entrySelector 10 USHORT LOG_SEGS */
621 /* rangeShift 12 USHORT segCountX2 - */
622 /* searchRange */
623 /* */
624 /* endCount 14 USHORT[NUM_SEGS] end charcode for */
625 /* each segment; last */
626 /* is 0xFFFF */
627 /* */
628 /* pad 14+NUM_SEGS*2 USHORT padding */
629 /* */
630 /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */
631 /* each segment */
632 /* */
633 /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */
634 /* segment */
635 /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */
636 /* each segment; can be */
637 /* zero */
638 /* */
639 /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph ID */
640 /* ranges */
641 /* */
642 /* Character codes are modelled by a series of ordered (increasing) */
643 /* intervals called segments. Each segment has start and end codes, */
644 /* provided by the `startCount' and `endCount' arrays. Segments must */
645 /* not overlap, and the last segment should always contain the value */
646 /* 0xFFFF for `endCount'. */
647 /* */
648 /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
649 /* ignored (they are traces of over-engineering in the TrueType */
650 /* specification). */
651 /* */
652 /* Each segment also has a signed `delta', as well as an optional offset */
653 /* within the `glyphIds' table. */
654 /* */
655 /* If a segment's idOffset is 0, the glyph index corresponding to any */
656 /* charcode within the segment is obtained by adding the value of */
657 /* `idDelta' directly to the charcode, modulo 65536. */
658 /* */
659 /* Otherwise, a glyph index is taken from the glyph IDs sub-array for */
660 /* the segment, and the value of `idDelta' is added to it. */
661 /* */
662 /* */
663 /* Finally, note that a lot of fonts contain an invalid last segment, */
664 /* where `start' and `end' are correctly set to 0xFFFF but both `delta' */
665 /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with */
666 /* OpenOffice.org). We need special code to deal with them correctly. */
667 /* */
668
669#ifdef TT_CONFIG_CMAP_FORMAT_4
670
671 typedef struct TT_CMap4Rec_
672 {
673 TT_CMapRec cmap;
674 FT_UInt32 cur_charcode; /* current charcode */
675 FT_UInt cur_gindex; /* current glyph index */
676
677 FT_UInt num_ranges;
678 FT_UInt cur_range;
679 FT_UInt cur_start;
680 FT_UInt cur_end;
681 FT_Int cur_delta;
682 FT_Byte* cur_values;
683
684 } TT_CMap4Rec, *TT_CMap4;
685
686
687 FT_CALLBACK_DEF( FT_Error )static FT_Error
688 tt_cmap4_init( TT_CMap4 cmap,
689 FT_Byte* table )
690 {
691 FT_Byte* p;
692
693
694 cmap->cmap.data = table;
695
696 p = table + 6;
697 cmap->num_ranges = FT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
>> 1;
698 cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
699 cmap->cur_gindex = 0;
700
701 return FT_Err_Ok;
702 }
703
704
705 static FT_Int
706 tt_cmap4_set_range( TT_CMap4 cmap,
707 FT_UInt range_index )
708 {
709 FT_Byte* table = cmap->cmap.data;
710 FT_Byte* p;
711 FT_UInt num_ranges = cmap->num_ranges;
712
713
714 while ( range_index < num_ranges )
715 {
716 FT_UInt offset;
717
718
719 p = table + 14 + range_index * 2;
720 cmap->cur_end = FT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
721
722 p += 2 + num_ranges * 2;
723 cmap->cur_start = FT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
724
725 p += num_ranges * 2;
726 cmap->cur_delta = FT_PEEK_SHORT( p )( (FT_Int16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] )) )
<< (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(1)
] )) ) << (0) )) )
;
727
728 p += num_ranges * 2;
729 offset = FT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
730
731 /* some fonts have an incorrect last segment; */
732 /* we have to catch it */
733 if ( range_index >= num_ranges - 1 &&
734 cmap->cur_start == 0xFFFFU &&
735 cmap->cur_end == 0xFFFFU )
736 {
737 TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face;
738 FT_Byte* limit = face->cmap_table + face->cmap_size;
739
740
741 if ( offset && p + offset + 2 > limit )
742 {
743 cmap->cur_delta = 1;
744 offset = 0;
745 }
746 }
747
748 if ( offset != 0xFFFFU )
749 {
750 cmap->cur_values = offset ? p + offset : NULL((void*)0);
751 cmap->cur_range = range_index;
752 return 0;
753 }
754
755 /* we skip empty segments */
756 range_index++;
757 }
758
759 return -1;
760 }
761
762
763 /* search the index of the charcode next to cmap->cur_charcode; */
764 /* caller should call tt_cmap4_set_range with proper range */
765 /* before calling this function */
766 /* */
767 static void
768 tt_cmap4_next( TT_CMap4 cmap )
769 {
770 TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face;
771 FT_Byte* limit = face->cmap_table + face->cmap_size;
772
773 FT_UInt charcode;
774
775
776 if ( cmap->cur_charcode >= 0xFFFFUL )
777 goto Fail;
778
779 charcode = (FT_UInt)cmap->cur_charcode + 1;
780
781 if ( charcode < cmap->cur_start )
782 charcode = cmap->cur_start;
783
784 for (;;)
785 {
786 FT_Byte* values = cmap->cur_values;
787 FT_UInt end = cmap->cur_end;
788 FT_Int delta = cmap->cur_delta;
789
790
791 if ( charcode <= end )
792 {
793 if ( values )
794 {
795 FT_Byte* p = values + 2 * ( charcode - cmap->cur_start );
796
797
798 /* if p > limit, the whole segment is invalid */
799 if ( p > limit )
800 goto Next_Segment;
801
802 do
803 {
804 FT_UInt gindex = FT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
805
806
807 if ( gindex )
808 {
809 gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
810 if ( gindex )
811 {
812 cmap->cur_charcode = charcode;
813 cmap->cur_gindex = gindex;
814 return;
815 }
816 }
817 } while ( ++charcode <= end );
818 }
819 else
820 {
821 do
822 {
823 FT_UInt gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
824
825
826 if ( gindex >= (FT_UInt)face->root.num_glyphs )
827 {
828 /* we have an invalid glyph index; if there is an overflow, */
829 /* we can adjust `charcode', otherwise the whole segment is */
830 /* invalid */
831 gindex = 0;
832
833 if ( (FT_Int)charcode + delta < 0 &&
834 (FT_Int)end + delta >= 0 )
835 charcode = (FT_UInt)( -delta );
836
837 else if ( (FT_Int)charcode + delta < 0x10000L &&
838 (FT_Int)end + delta >= 0x10000L )
839 charcode = (FT_UInt)( 0x10000L - delta );
840
841 else
842 goto Next_Segment;
843 }
844
845 if ( gindex )
846 {
847 cmap->cur_charcode = charcode;
848 cmap->cur_gindex = gindex;
849 return;
850 }
851 } while ( ++charcode <= end );
852 }
853 }
854
855 Next_Segment:
856 /* we need to find another range */
857 if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )
858 break;
859
860 if ( charcode < cmap->cur_start )
861 charcode = cmap->cur_start;
862 }
863
864 Fail:
865 cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
866 cmap->cur_gindex = 0;
867 }
868
869
870 FT_CALLBACK_DEF( FT_Error )static FT_Error
871 tt_cmap4_validate( FT_Byte* table,
872 FT_Validator valid )
873 {
874 FT_Byte* p;
875 FT_UInt length;
876
877 FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids;
878 FT_UInt num_segs;
879 FT_Error error = FT_Err_Ok;
880
881
882 if ( table + 2 + 2 > valid->limit )
883 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
884
885 p = table + 2; /* skip format */
886 length = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
887
888 /* in certain fonts, the `length' field is invalid and goes */
889 /* out of bound. We try to correct this here... */
890 if ( table + length > valid->limit )
891 {
892 if ( valid->level >= FT_VALIDATE_TIGHT )
893 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
894
895 length = (FT_UInt)( valid->limit - table );
896 }
897
898 if ( length < 16 )
899 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
900
901 p = table + 6;
902 num_segs = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
; /* read segCountX2 */
903
904 if ( valid->level >= FT_VALIDATE_PARANOID )
905 {
906 /* check that we have an even value here */
907 if ( num_segs & 1 )
908 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
909 }
910
911 num_segs /= 2;
912
913 if ( length < 16 + num_segs * 2 * 4 )
914 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
915
916 /* check the search parameters - even though we never use them */
917 /* */
918 if ( valid->level >= FT_VALIDATE_PARANOID )
919 {
920 /* check the values of `searchRange', `entrySelector', `rangeShift' */
921 FT_UInt search_range = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
922 FT_UInt entry_selector = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
923 FT_UInt range_shift = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
924
925
926 if ( ( search_range | range_shift ) & 1 ) /* must be even values */
927 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
928
929 search_range /= 2;
930 range_shift /= 2;
931
932 /* `search range' is the greatest power of 2 that is <= num_segs */
933
934 if ( search_range > num_segs ||
935 search_range * 2 < num_segs ||
936 search_range + range_shift != num_segs ||
937 search_range != ( 1U << entry_selector ) )
938 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
939 }
940
941 ends = table + 14;
942 starts = table + 16 + num_segs * 2;
943 deltas = starts + num_segs * 2;
944 offsets = deltas + num_segs * 2;
945 glyph_ids = offsets + num_segs * 2;
946
947 /* check last segment; its end count value must be 0xFFFF */
948 if ( valid->level >= FT_VALIDATE_PARANOID )
949 {
950 p = ends + ( num_segs - 1 ) * 2;
951 if ( TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
!= 0xFFFFU )
952 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
953 }
954
955 {
956 FT_UInt start, end, offset, n;
957 FT_UInt last_start = 0, last_end = 0;
958 FT_Int delta;
959 FT_Byte* p_start = starts;
960 FT_Byte* p_end = ends;
961 FT_Byte* p_delta = deltas;
962 FT_Byte* p_offset = offsets;
963
964
965 for ( n = 0; n < num_segs; n++ )
966 {
967 p = p_offset;
968 start = TT_NEXT_USHORT( p_start )( (unsigned short)( p_start += 2, ( (FT_UInt16)(( ( (FT_UInt16
)(( ((const FT_Byte*)(p_start - 2))[(0)] )) ) << (8) ) |
( ( (FT_UInt16)(( ((const FT_Byte*)(p_start - 2))[(1)] )) ) <<
(0) )) ) ) )
;
969 end = TT_NEXT_USHORT( p_end )( (unsigned short)( p_end += 2, ( (FT_UInt16)(( ( (FT_UInt16)
(( ((const FT_Byte*)(p_end - 2))[(0)] )) ) << (8) ) | (
( (FT_UInt16)(( ((const FT_Byte*)(p_end - 2))[(1)] )) ) <<
(0) )) ) ) )
;
970 delta = TT_NEXT_SHORT( p_delta )( (short)( p_delta += 2, ( (FT_Int16)(( ( (FT_UInt16)(( ((const
FT_Byte*)(p_delta - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p_delta - 2))[(1)] )) ) << (0) ))
) ) )
;
971 offset = TT_NEXT_USHORT( p_offset )( (unsigned short)( p_offset += 2, ( (FT_UInt16)(( ( (FT_UInt16
)(( ((const FT_Byte*)(p_offset - 2))[(0)] )) ) << (8) )
| ( ( (FT_UInt16)(( ((const FT_Byte*)(p_offset - 2))[(1)] ))
) << (0) )) ) ) )
;
972
973 if ( start > end )
974 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
975
976 /* this test should be performed at default validation level; */
977 /* unfortunately, some popular Asian fonts have overlapping */
978 /* ranges in their charmaps */
979 /* */
980 if ( start <= last_end && n > 0 )
981 {
982 if ( valid->level >= FT_VALIDATE_TIGHT )
983 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
984 else
985 {
986 /* allow overlapping segments, provided their start points */
987 /* and end points, respectively, are in ascending order */
988 /* */
989 if ( last_start > start || last_end > end )
990 error |= TT_CMAP_FLAG_UNSORTED1;
991 else
992 error |= TT_CMAP_FLAG_OVERLAPPING2;
993 }
994 }
995
996 if ( offset && offset != 0xFFFFU )
997 {
998 p += offset; /* start of glyph ID array */
999
1000 /* check that we point within the glyph IDs table only */
1001 if ( valid->level >= FT_VALIDATE_TIGHT )
1002 {
1003 if ( p < glyph_ids ||
1004 p + ( end - start + 1 ) * 2 > table + length )
1005 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
1006 }
1007 /* Some fonts handle the last segment incorrectly. In */
1008 /* theory, 0xFFFF might point to an ordinary glyph -- */
1009 /* a cmap 4 is versatile and could be used for any */
1010 /* encoding, not only Unicode. However, reality shows */
1011 /* that far too many fonts are sloppy and incorrectly */
1012 /* set all fields but `start' and `end' for the last */
1013 /* segment if it contains only a single character. */
1014 /* */
1015 /* We thus omit the test here, delaying it to the */
1016 /* routines that actually access the cmap. */
1017 else if ( n != num_segs - 1 ||
1018 !( start == 0xFFFFU && end == 0xFFFFU ) )
1019 {
1020 if ( p < glyph_ids ||
1021 p + ( end - start + 1 ) * 2 > valid->limit )
1022 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
1023 }
1024
1025 /* check glyph indices within the segment range */
1026 if ( valid->level >= FT_VALIDATE_TIGHT )
1027 {
1028 FT_UInt i, idx;
1029
1030
1031 for ( i = start; i < end; i++ )
1032 {
1033 idx = FT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
1034 if ( idx != 0 )
1035 {
1036 idx = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
1037
1038 if ( idx >= TT_VALID_GLYPH_COUNT( valid )( (TT_Validator)( valid ) )->num_glyphs )
1039 FT_INVALID_GLYPH_IDft_validator_error( valid, SFNT_Err_Invalid_Glyph_Index );
1040 }
1041 }
1042 }
1043 }
1044 else if ( offset == 0xFFFFU )
1045 {
1046 /* some fonts (erroneously?) use a range offset of 0xFFFF */
1047 /* to mean missing glyph in cmap table */
1048 /* */
1049 if ( valid->level >= FT_VALIDATE_PARANOID ||
1050 n != num_segs - 1 ||
1051 !( start == 0xFFFFU && end == 0xFFFFU ) )
1052 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
1053 }
1054
1055 last_start = start;
1056 last_end = end;
1057 }
1058 }
1059
1060 return error;
1061 }
1062
1063
1064 static FT_UInt
1065 tt_cmap4_char_map_linear( TT_CMap cmap,
1066 FT_UInt32* pcharcode,
1067 FT_Bool next )
1068 {
1069 TT_Face face = (TT_Face)cmap->cmap.charmap.face;
1070 FT_Byte* limit = face->cmap_table + face->cmap_size;
1071
1072
1073 FT_UInt num_segs2, start, end, offset;
1074 FT_Int delta;
1075 FT_UInt i, num_segs;
1076 FT_UInt32 charcode = *pcharcode;
1077 FT_UInt gindex = 0;
1078 FT_Byte* p;
1079 FT_Byte* q;
1080
1081
1082 p = cmap->data + 6;
1083 num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 )( (( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)]
)) ) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p)
)[(1)] )) ) << (0) )) )) & ~( __typeof__ ( ( (FT_UInt16
)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] )) ) << (
8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(1)] )) ) <<
(0) )) ) ) )( (2) - 1 ) )
;
1084
1085 num_segs = num_segs2 >> 1;
1086
1087 if ( !num_segs )
1088 return 0;
1089
1090 if ( next )
1091 charcode++;
1092
1093 if ( charcode > 0xFFFFU )
1094 return 0;
1095
1096 /* linear search */
1097 p = cmap->data + 14; /* ends table */
1098 q = cmap->data + 16 + num_segs2; /* starts table */
1099
1100 for ( i = 0; i < num_segs; i++ )
1101 {
1102 end = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
1103 start = TT_NEXT_USHORT( q )( (unsigned short)( q += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(q - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(q - 2))[(1)] )) ) << (0) )) ) ) )
;
1104
1105 if ( charcode < start )
1106 {
1107 if ( next )
1108 charcode = start;
1109 else
1110 break;
1111 }
1112
1113 Again:
1114 if ( charcode <= end )
1115 {
1116 FT_Byte* r;
1117
1118
1119 r = q - 2 + num_segs2;
1120 delta = TT_PEEK_SHORT( r )( (FT_Int16)(( ( (FT_UInt16)(( ((const FT_Byte*)(r))[(0)] )) )
<< (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(r))[(1)
] )) ) << (0) )) )
;
1121 r += num_segs2;
1122 offset = TT_PEEK_USHORT( r )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(r))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(r))[(
1)] )) ) << (0) )) )
;
1123
1124 /* some fonts have an incorrect last segment; */
1125 /* we have to catch it */
1126 if ( i >= num_segs - 1 &&
1127 start == 0xFFFFU && end == 0xFFFFU )
1128 {
1129 if ( offset && r + offset + 2 > limit )
1130 {
1131 delta = 1;
1132 offset = 0;
1133 }
1134 }
1135
1136 if ( offset == 0xFFFFU )
1137 continue;
1138
1139 if ( offset )
1140 {
1141 r += offset + ( charcode - start ) * 2;
1142
1143 /* if r > limit, the whole segment is invalid */
1144 if ( next && r > limit )
1145 continue;
1146
1147 gindex = TT_PEEK_USHORT( r )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(r))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(r))[(
1)] )) ) << (0) )) )
;
1148 if ( gindex )
1149 {
1150 gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
1151 if ( gindex >= (FT_UInt)face->root.num_glyphs )
1152 gindex = 0;
1153 }
1154 }
1155 else
1156 {
1157 gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
1158
1159 if ( next && gindex >= (FT_UInt)face->root.num_glyphs )
1160 {
1161 /* we have an invalid glyph index; if there is an overflow, */
1162 /* we can adjust `charcode', otherwise the whole segment is */
1163 /* invalid */
1164 gindex = 0;
1165
1166 if ( (FT_Int)charcode + delta < 0 &&
1167 (FT_Int)end + delta >= 0 )
1168 charcode = (FT_UInt)( -delta );
1169
1170 else if ( (FT_Int)charcode + delta < 0x10000L &&
1171 (FT_Int)end + delta >= 0x10000L )
1172 charcode = (FT_UInt)( 0x10000L - delta );
1173
1174 else
1175 continue;
1176 }
1177 }
1178
1179 if ( next && !gindex )
1180 {
1181 if ( charcode >= 0xFFFFU )
1182 break;
1183
1184 charcode++;
1185 goto Again;
1186 }
1187
1188 break;
1189 }
1190 }
1191
1192 if ( next )
1193 *pcharcode = charcode;
1194
1195 return gindex;
1196 }
1197
1198
1199 static FT_UInt
1200 tt_cmap4_char_map_binary( TT_CMap cmap,
1201 FT_UInt32* pcharcode,
1202 FT_Bool next )
1203 {
1204 TT_Face face = (TT_Face)cmap->cmap.charmap.face;
1205 FT_Byte* limit = face->cmap_table + face->cmap_size;
1206
1207 FT_UInt num_segs2, start, end, offset;
1208 FT_Int delta;
1209 FT_UInt max, min, mid, num_segs;
1210 FT_UInt charcode = (FT_UInt)*pcharcode;
1211 FT_UInt gindex = 0;
1212 FT_Byte* p;
1213
1214
1215 p = cmap->data + 6;
1216 num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 )( (( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)]
)) ) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p)
)[(1)] )) ) << (0) )) )) & ~( __typeof__ ( ( (FT_UInt16
)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] )) ) << (
8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(1)] )) ) <<
(0) )) ) ) )( (2) - 1 ) )
;
1217
1218 if ( !num_segs2 )
1219 return 0;
1220
1221 num_segs = num_segs2 >> 1;
1222
1223 /* make compiler happy */
1224 mid = num_segs;
1225 end = 0xFFFFU;
1226
1227 if ( next )
1228 charcode++;
1229
1230 min = 0;
1231 max = num_segs;
1232
1233 /* binary search */
1234 while ( min < max )
1235 {
1236 mid = ( min + max ) >> 1;
1237 p = cmap->data + 14 + mid * 2;
1238 end = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1239 p += 2 + num_segs2;
1240 start = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1241
1242 if ( charcode < start )
1243 max = mid;
1244 else if ( charcode > end )
1245 min = mid + 1;
1246 else
1247 {
1248 p += num_segs2;
1249 delta = TT_PEEK_SHORT( p )( (FT_Int16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] )) )
<< (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(1)
] )) ) << (0) )) )
;
1250 p += num_segs2;
1251 offset = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1252
1253 /* some fonts have an incorrect last segment; */
1254 /* we have to catch it */
1255 if ( mid >= num_segs - 1 &&
1256 start == 0xFFFFU && end == 0xFFFFU )
1257 {
1258 if ( offset && p + offset + 2 > limit )
1259 {
1260 delta = 1;
1261 offset = 0;
1262 }
1263 }
1264
1265 /* search the first segment containing `charcode' */
1266 if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING2 )
1267 {
1268 FT_UInt i;
1269
1270
1271 /* call the current segment `max' */
1272 max = mid;
1273
1274 if ( offset == 0xFFFFU )
1275 mid = max + 1;
1276
1277 /* search in segments before the current segment */
1278 for ( i = max; i > 0; i-- )
1279 {
1280 FT_UInt prev_end;
1281 FT_Byte* old_p;
1282
1283
1284 old_p = p;
1285 p = cmap->data + 14 + ( i - 1 ) * 2;
1286 prev_end = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1287
1288 if ( charcode > prev_end )
1289 {
1290 p = old_p;
1291 break;
1292 }
1293
1294 end = prev_end;
1295 p += 2 + num_segs2;
1296 start = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1297 p += num_segs2;
1298 delta = TT_PEEK_SHORT( p )( (FT_Int16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] )) )
<< (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(1)
] )) ) << (0) )) )
;
1299 p += num_segs2;
1300 offset = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1301
1302 if ( offset != 0xFFFFU )
1303 mid = i - 1;
1304 }
1305
1306 /* no luck */
1307 if ( mid == max + 1 )
1308 {
1309 if ( i != max )
1310 {
1311 p = cmap->data + 14 + max * 2;
1312 end = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1313 p += 2 + num_segs2;
1314 start = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1315 p += num_segs2;
1316 delta = TT_PEEK_SHORT( p )( (FT_Int16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] )) )
<< (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(1)
] )) ) << (0) )) )
;
1317 p += num_segs2;
1318 offset = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1319 }
1320
1321 mid = max;
1322
1323 /* search in segments after the current segment */
1324 for ( i = max + 1; i < num_segs; i++ )
1325 {
1326 FT_UInt next_end, next_start;
1327
1328
1329 p = cmap->data + 14 + i * 2;
1330 next_end = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1331 p += 2 + num_segs2;
1332 next_start = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1333
1334 if ( charcode < next_start )
1335 break;
1336
1337 end = next_end;
1338 start = next_start;
1339 p += num_segs2;
1340 delta = TT_PEEK_SHORT( p )( (FT_Int16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] )) )
<< (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(1)
] )) ) << (0) )) )
;
1341 p += num_segs2;
1342 offset = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1343
1344 if ( offset != 0xFFFFU )
1345 mid = i;
1346 }
1347 i--;
1348
1349 /* still no luck */
1350 if ( mid == max )
1351 {
1352 mid = i;
1353
1354 break;
1355 }
1356 }
1357
1358 /* end, start, delta, and offset are for the i'th segment */
1359 if ( mid != i )
1360 {
1361 p = cmap->data + 14 + mid * 2;
1362 end = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1363 p += 2 + num_segs2;
1364 start = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1365 p += num_segs2;
1366 delta = TT_PEEK_SHORT( p )( (FT_Int16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] )) )
<< (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(1)
] )) ) << (0) )) )
;
1367 p += num_segs2;
1368 offset = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1369 }
1370 }
1371 else
1372 {
1373 if ( offset == 0xFFFFU )
1374 break;
1375 }
1376
1377 if ( offset )
1378 {
1379 p += offset + ( charcode - start ) * 2;
1380
1381 /* if p > limit, the whole segment is invalid */
1382 if ( next && p > limit )
1383 break;
1384
1385 gindex = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1386 if ( gindex )
1387 {
1388 gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
1389 if ( gindex >= (FT_UInt)face->root.num_glyphs )
1390 gindex = 0;
1391 }
1392 }
1393 else
1394 {
1395 gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
1396
1397 if ( next && gindex >= (FT_UInt)face->root.num_glyphs )
1398 {
1399 /* we have an invalid glyph index; if there is an overflow, */
1400 /* we can adjust `charcode', otherwise the whole segment is */
1401 /* invalid */
1402 gindex = 0;
1403
1404 if ( (FT_Int)charcode + delta < 0 &&
1405 (FT_Int)end + delta >= 0 )
1406 charcode = (FT_UInt)( -delta );
1407
1408 else if ( (FT_Int)charcode + delta < 0x10000L &&
1409 (FT_Int)end + delta >= 0x10000L )
1410 charcode = (FT_UInt)( 0x10000L - delta );
1411 }
1412 }
1413
1414 break;
1415 }
1416 }
1417
1418 if ( next )
1419 {
1420 TT_CMap4 cmap4 = (TT_CMap4)cmap;
1421
1422
1423 /* if `charcode' is not in any segment, then `mid' is */
1424 /* the segment nearest to `charcode' */
1425
1426 if ( charcode > end )
1427 {
1428 mid++;
1429 if ( mid == num_segs )
1430 return 0;
1431 }
1432
1433 if ( tt_cmap4_set_range( cmap4, mid ) )
1434 {
1435 if ( gindex )
1436 *pcharcode = charcode;
1437 }
1438 else
1439 {
1440 cmap4->cur_charcode = charcode;
1441
1442 if ( gindex )
1443 cmap4->cur_gindex = gindex;
1444 else
1445 {
1446 cmap4->cur_charcode = charcode;
1447 tt_cmap4_next( cmap4 );
1448 gindex = cmap4->cur_gindex;
1449 }
1450
1451 if ( gindex )
1452 *pcharcode = cmap4->cur_charcode;
1453 }
1454 }
1455
1456 return gindex;
1457 }
1458
1459
1460 FT_CALLBACK_DEF( FT_UInt )static FT_UInt
1461 tt_cmap4_char_index( TT_CMap cmap,
1462 FT_UInt32 char_code )
1463 {
1464 if ( char_code >= 0x10000UL )
1465 return 0;
1466
1467 if ( cmap->flags & TT_CMAP_FLAG_UNSORTED1 )
1468 return tt_cmap4_char_map_linear( cmap, &char_code, 0 );
1469 else
1470 return tt_cmap4_char_map_binary( cmap, &char_code, 0 );
1471 }
1472
1473
1474 FT_CALLBACK_DEF( FT_UInt32 )static FT_UInt32
1475 tt_cmap4_char_next( TT_CMap cmap,
1476 FT_UInt32 *pchar_code )
1477 {
1478 FT_UInt gindex;
1479
1480
1481 if ( *pchar_code >= 0xFFFFU )
1482 return 0;
1483
1484 if ( cmap->flags & TT_CMAP_FLAG_UNSORTED1 )
1485 gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 );
1486 else
1487 {
1488 TT_CMap4 cmap4 = (TT_CMap4)cmap;
1489
1490
1491 /* no need to search */
1492 if ( *pchar_code == cmap4->cur_charcode )
1493 {
1494 tt_cmap4_next( cmap4 );
1495 gindex = cmap4->cur_gindex;
1496 if ( gindex )
1497 *pchar_code = cmap4->cur_charcode;
1498 }
1499 else
1500 gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 );
1501 }
1502
1503 return gindex;
1504 }
1505
1506
1507 FT_CALLBACK_DEF( FT_Error )static FT_Error
1508 tt_cmap4_get_info( TT_CMap cmap,
1509 TT_CMapInfo *cmap_info )
1510 {
1511 cmap_info->format = 4;
1512 return FT_Err_Ok;
1513 }
1514
1515
1516 FT_DEFINE_TT_CMAP(const TT_CMap_ClassRec tt_cmap4_class_rec = { { sizeof ( TT_CMap4Rec
), (FT_CMap_InitFunc) tt_cmap4_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap4_char_index, (FT_CMap_CharNextFunc
) tt_cmap4_char_next }, 4, (TT_CMap_ValidateFunc)tt_cmap4_validate
, (TT_CMap_Info_GetFunc)tt_cmap4_get_info };
1517 tt_cmap4_class_rec,const TT_CMap_ClassRec tt_cmap4_class_rec = { { sizeof ( TT_CMap4Rec
), (FT_CMap_InitFunc) tt_cmap4_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap4_char_index, (FT_CMap_CharNextFunc
) tt_cmap4_char_next }, 4, (TT_CMap_ValidateFunc)tt_cmap4_validate
, (TT_CMap_Info_GetFunc)tt_cmap4_get_info };
1518
1519 sizeof ( TT_CMap4Rec ),const TT_CMap_ClassRec tt_cmap4_class_rec = { { sizeof ( TT_CMap4Rec
), (FT_CMap_InitFunc) tt_cmap4_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap4_char_index, (FT_CMap_CharNextFunc
) tt_cmap4_char_next }, 4, (TT_CMap_ValidateFunc)tt_cmap4_validate
, (TT_CMap_Info_GetFunc)tt_cmap4_get_info };
1520
1521 (FT_CMap_InitFunc) tt_cmap4_init, /* init */const TT_CMap_ClassRec tt_cmap4_class_rec = { { sizeof ( TT_CMap4Rec
), (FT_CMap_InitFunc) tt_cmap4_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap4_char_index, (FT_CMap_CharNextFunc
) tt_cmap4_char_next }, 4, (TT_CMap_ValidateFunc)tt_cmap4_validate
, (TT_CMap_Info_GetFunc)tt_cmap4_get_info };
1522 (FT_CMap_DoneFunc) NULL, /* done */const TT_CMap_ClassRec tt_cmap4_class_rec = { { sizeof ( TT_CMap4Rec
), (FT_CMap_InitFunc) tt_cmap4_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap4_char_index, (FT_CMap_CharNextFunc
) tt_cmap4_char_next }, 4, (TT_CMap_ValidateFunc)tt_cmap4_validate
, (TT_CMap_Info_GetFunc)tt_cmap4_get_info };
1523 (FT_CMap_CharIndexFunc)tt_cmap4_char_index, /* char_index */const TT_CMap_ClassRec tt_cmap4_class_rec = { { sizeof ( TT_CMap4Rec
), (FT_CMap_InitFunc) tt_cmap4_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap4_char_index, (FT_CMap_CharNextFunc
) tt_cmap4_char_next }, 4, (TT_CMap_ValidateFunc)tt_cmap4_validate
, (TT_CMap_Info_GetFunc)tt_cmap4_get_info };
1524 (FT_CMap_CharNextFunc) tt_cmap4_char_next, /* char_next */const TT_CMap_ClassRec tt_cmap4_class_rec = { { sizeof ( TT_CMap4Rec
), (FT_CMap_InitFunc) tt_cmap4_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap4_char_index, (FT_CMap_CharNextFunc
) tt_cmap4_char_next }, 4, (TT_CMap_ValidateFunc)tt_cmap4_validate
, (TT_CMap_Info_GetFunc)tt_cmap4_get_info };
1525
1526 4,const TT_CMap_ClassRec tt_cmap4_class_rec = { { sizeof ( TT_CMap4Rec
), (FT_CMap_InitFunc) tt_cmap4_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap4_char_index, (FT_CMap_CharNextFunc
) tt_cmap4_char_next }, 4, (TT_CMap_ValidateFunc)tt_cmap4_validate
, (TT_CMap_Info_GetFunc)tt_cmap4_get_info };
1527 (TT_CMap_ValidateFunc)tt_cmap4_validate, /* validate */const TT_CMap_ClassRec tt_cmap4_class_rec = { { sizeof ( TT_CMap4Rec
), (FT_CMap_InitFunc) tt_cmap4_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap4_char_index, (FT_CMap_CharNextFunc
) tt_cmap4_char_next }, 4, (TT_CMap_ValidateFunc)tt_cmap4_validate
, (TT_CMap_Info_GetFunc)tt_cmap4_get_info };
1528 (TT_CMap_Info_GetFunc)tt_cmap4_get_info /* get_cmap_info */const TT_CMap_ClassRec tt_cmap4_class_rec = { { sizeof ( TT_CMap4Rec
), (FT_CMap_InitFunc) tt_cmap4_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap4_char_index, (FT_CMap_CharNextFunc
) tt_cmap4_char_next }, 4, (TT_CMap_ValidateFunc)tt_cmap4_validate
, (TT_CMap_Info_GetFunc)tt_cmap4_get_info };
1529 )const TT_CMap_ClassRec tt_cmap4_class_rec = { { sizeof ( TT_CMap4Rec
), (FT_CMap_InitFunc) tt_cmap4_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap4_char_index, (FT_CMap_CharNextFunc
) tt_cmap4_char_next }, 4, (TT_CMap_ValidateFunc)tt_cmap4_validate
, (TT_CMap_Info_GetFunc)tt_cmap4_get_info };
1530
1531#endif /* TT_CONFIG_CMAP_FORMAT_4 */
1532
1533
1534 /*************************************************************************/
1535 /*************************************************************************/
1536 /***** *****/
1537 /***** FORMAT 6 *****/
1538 /***** *****/
1539 /*************************************************************************/
1540 /*************************************************************************/
1541
1542 /*************************************************************************/
1543 /* */
1544 /* TABLE OVERVIEW */
1545 /* -------------- */
1546 /* */
1547 /* NAME OFFSET TYPE DESCRIPTION */
1548 /* */
1549 /* format 0 USHORT must be 6 */
1550 /* length 2 USHORT table length in bytes */
1551 /* language 4 USHORT Mac language code */
1552 /* */
1553 /* first 6 USHORT first segment code */
1554 /* count 8 USHORT segment size in chars */
1555 /* glyphIds 10 USHORT[count] glyph IDs */
1556 /* */
1557 /* A very simplified segment mapping. */
1558 /* */
1559
1560#ifdef TT_CONFIG_CMAP_FORMAT_6
1561
1562 FT_CALLBACK_DEF( FT_Error )static FT_Error
1563 tt_cmap6_validate( FT_Byte* table,
1564 FT_Validator valid )
1565 {
1566 FT_Byte* p;
1567 FT_UInt length, count;
1568
1569
1570 if ( table + 10 > valid->limit )
1571 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
1572
1573 p = table + 2;
1574 length = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
1575
1576 p = table + 8; /* skip language and start index */
1577 count = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
1578
1579 if ( table + length > valid->limit || length < 10 + count * 2 )
1580 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
1581
1582 /* check glyph indices */
1583 if ( valid->level >= FT_VALIDATE_TIGHT )
1584 {
1585 FT_UInt gindex;
1586
1587
1588 for ( ; count > 0; count-- )
1589 {
1590 gindex = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
1591 if ( gindex >= TT_VALID_GLYPH_COUNT( valid )( (TT_Validator)( valid ) )->num_glyphs )
1592 FT_INVALID_GLYPH_IDft_validator_error( valid, SFNT_Err_Invalid_Glyph_Index );
1593 }
1594 }
1595
1596 return FT_Err_Ok;
1597 }
1598
1599
1600 FT_CALLBACK_DEF( FT_UInt )static FT_UInt
1601 tt_cmap6_char_index( TT_CMap cmap,
1602 FT_UInt32 char_code )
1603 {
1604 FT_Byte* table = cmap->data;
1605 FT_UInt result = 0;
1606 FT_Byte* p = table + 6;
1607 FT_UInt start = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
1608 FT_UInt count = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
1609 FT_UInt idx = (FT_UInt)( char_code - start );
1610
1611
1612 if ( idx < count )
1613 {
1614 p += 2 * idx;
1615 result = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
1616 }
1617
1618 return result;
1619 }
1620
1621
1622 FT_CALLBACK_DEF( FT_UInt32 )static FT_UInt32
1623 tt_cmap6_char_next( TT_CMap cmap,
1624 FT_UInt32 *pchar_code )
1625 {
1626 FT_Byte* table = cmap->data;
1627 FT_UInt32 result = 0;
1628 FT_UInt32 char_code = *pchar_code + 1;
1629 FT_UInt gindex = 0;
1630
1631 FT_Byte* p = table + 6;
1632 FT_UInt start = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
1633 FT_UInt count = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
1634 FT_UInt idx;
1635
1636
1637 if ( char_code >= 0x10000UL )
1638 return 0;
1639
1640 if ( char_code < start )
1641 char_code = start;
1642
1643 idx = (FT_UInt)( char_code - start );
1644 p += 2 * idx;
1645
1646 for ( ; idx < count; idx++ )
1647 {
1648 gindex = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
1649 if ( gindex != 0 )
1650 {
1651 result = char_code;
1652 break;
1653 }
1654
1655 if ( char_code >= 0xFFFFU )
1656 return 0;
1657
1658 char_code++;
1659 }
1660
1661 *pchar_code = result;
1662 return gindex;
1663 }
1664
1665
1666 FT_CALLBACK_DEF( FT_Error )static FT_Error
1667 tt_cmap6_get_info( TT_CMap cmap,
1668 TT_CMapInfo *cmap_info )
1669 {
1670 cmap_info->format = 6;
1671 return FT_Err_Ok;
1672 }
1673
1674
1675 FT_DEFINE_TT_CMAP(const TT_CMap_ClassRec tt_cmap6_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap6_char_index, (FT_CMap_CharNextFunc
) tt_cmap6_char_next }, 6, (TT_CMap_ValidateFunc)tt_cmap6_validate
, (TT_CMap_Info_GetFunc)tt_cmap6_get_info };
1676 tt_cmap6_class_rec,const TT_CMap_ClassRec tt_cmap6_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap6_char_index, (FT_CMap_CharNextFunc
) tt_cmap6_char_next }, 6, (TT_CMap_ValidateFunc)tt_cmap6_validate
, (TT_CMap_Info_GetFunc)tt_cmap6_get_info };
1677
1678 sizeof ( TT_CMapRec ),const TT_CMap_ClassRec tt_cmap6_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap6_char_index, (FT_CMap_CharNextFunc
) tt_cmap6_char_next }, 6, (TT_CMap_ValidateFunc)tt_cmap6_validate
, (TT_CMap_Info_GetFunc)tt_cmap6_get_info };
1679
1680 (FT_CMap_InitFunc) tt_cmap_init, /* init */const TT_CMap_ClassRec tt_cmap6_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap6_char_index, (FT_CMap_CharNextFunc
) tt_cmap6_char_next }, 6, (TT_CMap_ValidateFunc)tt_cmap6_validate
, (TT_CMap_Info_GetFunc)tt_cmap6_get_info };
1681 (FT_CMap_DoneFunc) NULL, /* done */const TT_CMap_ClassRec tt_cmap6_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap6_char_index, (FT_CMap_CharNextFunc
) tt_cmap6_char_next }, 6, (TT_CMap_ValidateFunc)tt_cmap6_validate
, (TT_CMap_Info_GetFunc)tt_cmap6_get_info };
1682 (FT_CMap_CharIndexFunc)tt_cmap6_char_index, /* char_index */const TT_CMap_ClassRec tt_cmap6_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap6_char_index, (FT_CMap_CharNextFunc
) tt_cmap6_char_next }, 6, (TT_CMap_ValidateFunc)tt_cmap6_validate
, (TT_CMap_Info_GetFunc)tt_cmap6_get_info };
1683 (FT_CMap_CharNextFunc) tt_cmap6_char_next, /* char_next */const TT_CMap_ClassRec tt_cmap6_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap6_char_index, (FT_CMap_CharNextFunc
) tt_cmap6_char_next }, 6, (TT_CMap_ValidateFunc)tt_cmap6_validate
, (TT_CMap_Info_GetFunc)tt_cmap6_get_info };
1684
1685 6,const TT_CMap_ClassRec tt_cmap6_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap6_char_index, (FT_CMap_CharNextFunc
) tt_cmap6_char_next }, 6, (TT_CMap_ValidateFunc)tt_cmap6_validate
, (TT_CMap_Info_GetFunc)tt_cmap6_get_info };
1686 (TT_CMap_ValidateFunc)tt_cmap6_validate, /* validate */const TT_CMap_ClassRec tt_cmap6_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap6_char_index, (FT_CMap_CharNextFunc
) tt_cmap6_char_next }, 6, (TT_CMap_ValidateFunc)tt_cmap6_validate
, (TT_CMap_Info_GetFunc)tt_cmap6_get_info };
1687 (TT_CMap_Info_GetFunc)tt_cmap6_get_info /* get_cmap_info */const TT_CMap_ClassRec tt_cmap6_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap6_char_index, (FT_CMap_CharNextFunc
) tt_cmap6_char_next }, 6, (TT_CMap_ValidateFunc)tt_cmap6_validate
, (TT_CMap_Info_GetFunc)tt_cmap6_get_info };
1688 )const TT_CMap_ClassRec tt_cmap6_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap6_char_index, (FT_CMap_CharNextFunc
) tt_cmap6_char_next }, 6, (TT_CMap_ValidateFunc)tt_cmap6_validate
, (TT_CMap_Info_GetFunc)tt_cmap6_get_info };
1689
1690#endif /* TT_CONFIG_CMAP_FORMAT_6 */
1691
1692
1693 /*************************************************************************/
1694 /*************************************************************************/
1695 /***** *****/
1696 /***** FORMAT 8 *****/
1697 /***** *****/
1698 /***** It is hard to completely understand what the OpenType spec *****/
1699 /***** says about this format, but here is my conclusion. *****/
1700 /***** *****/
1701 /***** The purpose of this format is to easily map UTF-16 text to *****/
1702 /***** glyph indices. Basically, the `char_code' must be in one of *****/
1703 /***** the following formats. *****/
1704 /***** *****/
1705 /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/
1706 /***** Area (i.e. U+D800-U+DFFF). *****/
1707 /***** *****/
1708 /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/
1709 /***** `char_code = (char_hi << 16) | char_lo', then both *****/
1710 /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/
1711 /***** Area. *****/
1712 /***** *****/
1713 /***** The `is32' table embedded in the charmap indicates whether a *****/
1714 /***** given 16-bit value is in the surrogates area or not. *****/
1715 /***** *****/
1716 /***** So, for any given `char_code', we can assert the following. *****/
1717 /***** *****/
1718 /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/
1719 /***** *****/
1720 /***** If `char_hi != 0' then we must have both *****/
1721 /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/
1722 /***** *****/
1723 /*************************************************************************/
1724 /*************************************************************************/
1725
1726 /*************************************************************************/
1727 /* */
1728 /* TABLE OVERVIEW */
1729 /* -------------- */
1730 /* */
1731 /* NAME OFFSET TYPE DESCRIPTION */
1732 /* */
1733 /* format 0 USHORT must be 8 */
1734 /* reserved 2 USHORT reserved */
1735 /* length 4 ULONG length in bytes */
1736 /* language 8 ULONG Mac language code */
1737 /* is32 12 BYTE[8192] 32-bitness bitmap */
1738 /* count 8204 ULONG number of groups */
1739 /* */
1740 /* This header is followed by `count' groups of the following format: */
1741 /* */
1742 /* start 0 ULONG first charcode */
1743 /* end 4 ULONG last charcode */
1744 /* startId 8 ULONG start glyph ID for the group */
1745 /* */
1746
1747#ifdef TT_CONFIG_CMAP_FORMAT_8
1748
1749 FT_CALLBACK_DEF( FT_Error )static FT_Error
1750 tt_cmap8_validate( FT_Byte* table,
1751 FT_Validator valid )
1752 {
1753 FT_Byte* p = table + 4;
1754 FT_Byte* is32;
1755 FT_UInt32 length;
1756 FT_UInt32 num_groups;
1757
1758
1759 if ( table + 16 + 8192 > valid->limit )
1760 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
1761
1762 length = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
1763 if ( length > (FT_UInt32)( valid->limit - table ) || length < 8192 + 16 )
1764 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
1765
1766 is32 = table + 12;
1767 p = is32 + 8192; /* skip `is32' array */
1768 num_groups = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
1769
1770 /* p + num_groups * 12 > valid->limit ? */
1771 if ( num_groups > (FT_UInt32)( valid->limit - p ) / 12 )
1772 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
1773
1774 /* check groups, they must be in increasing order */
1775 {
1776 FT_UInt32 n, start, end, start_id, count, last = 0;
1777
1778
1779 for ( n = 0; n < num_groups; n++ )
1780 {
1781 FT_UInt hi, lo;
1782
1783
1784 start = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
1785 end = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
1786 start_id = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
1787
1788 if ( start > end )
1789 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
1790
1791 if ( n > 0 && start <= last )
1792 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
1793
1794 if ( valid->level >= FT_VALIDATE_TIGHT )
1795 {
1796 FT_UInt32 d = end - start;
1797
1798
1799 /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
1800 if ( d > TT_VALID_GLYPH_COUNT( valid )( (TT_Validator)( valid ) )->num_glyphs ||
1801 start_id >= TT_VALID_GLYPH_COUNT( valid )( (TT_Validator)( valid ) )->num_glyphs - d )
1802 FT_INVALID_GLYPH_IDft_validator_error( valid, SFNT_Err_Invalid_Glyph_Index );
1803
1804 count = (FT_UInt32)( end - start + 1 );
1805
1806 if ( start & ~0xFFFFU )
1807 {
1808 /* start_hi != 0; check that is32[i] is 1 for each i in */
1809 /* the `hi' and `lo' of the range [start..end] */
1810 for ( ; count > 0; count--, start++ )
1811 {
1812 hi = (FT_UInt)( start >> 16 );
1813 lo = (FT_UInt)( start & 0xFFFFU );
1814
1815 if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
1816 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
1817
1818 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
1819 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
1820 }
1821 }
1822 else
1823 {
1824 /* start_hi == 0; check that is32[i] is 0 for each i in */
1825 /* the range [start..end] */
1826
1827 /* end_hi cannot be != 0! */
1828 if ( end & ~0xFFFFU )
1829 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
1830
1831 for ( ; count > 0; count--, start++ )
1832 {
1833 lo = (FT_UInt)( start & 0xFFFFU );
1834
1835 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
1836 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
1837 }
1838 }
1839 }
1840
1841 last = end;
1842 }
1843 }
1844
1845 return FT_Err_Ok;
1846 }
1847
1848
1849 FT_CALLBACK_DEF( FT_UInt )static FT_UInt
1850 tt_cmap8_char_index( TT_CMap cmap,
1851 FT_UInt32 char_code )
1852 {
1853 FT_Byte* table = cmap->data;
1854 FT_UInt result = 0;
1855 FT_Byte* p = table + 8204;
1856 FT_UInt32 num_groups = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
1857 FT_UInt32 start, end, start_id;
1858
1859
1860 for ( ; num_groups > 0; num_groups-- )
1861 {
1862 start = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
1863 end = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
1864 start_id = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
1865
1866 if ( char_code < start )
1867 break;
1868
1869 if ( char_code <= end )
1870 {
1871 if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
1872 return 0;
1873
1874 result = (FT_UInt)( start_id + ( char_code - start ) );
1875 break;
1876 }
1877 }
1878 return result;
1879 }
1880
1881
1882 FT_CALLBACK_DEF( FT_UInt32 )static FT_UInt32
1883 tt_cmap8_char_next( TT_CMap cmap,
1884 FT_UInt32 *pchar_code )
1885 {
1886 FT_Face face = cmap->cmap.charmap.face;
1887 FT_UInt32 result = 0;
1888 FT_UInt32 char_code;
1889 FT_UInt gindex = 0;
1890 FT_Byte* table = cmap->data;
1891 FT_Byte* p = table + 8204;
1892 FT_UInt32 num_groups = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
1893 FT_UInt32 start, end, start_id;
1894
1895
1896 if ( *pchar_code >= 0xFFFFFFFFUL )
1897 return 0;
1898
1899 char_code = *pchar_code + 1;
1900
1901 p = table + 8208;
1902
1903 for ( ; num_groups > 0; num_groups-- )
1904 {
1905 start = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
1906 end = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
1907 start_id = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
1908
1909 if ( char_code < start )
1910 char_code = start;
1911
1912 Again:
1913 if ( char_code <= end )
1914 {
1915 /* ignore invalid group */
1916 if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
1917 continue;
1918
1919 gindex = (FT_UInt)( start_id + ( char_code - start ) );
1920
1921 /* does first element of group point to `.notdef' glyph? */
1922 if ( gindex == 0 )
1923 {
1924 if ( char_code >= 0xFFFFFFFFUL )
1925 break;
1926
1927 char_code++;
1928 goto Again;
1929 }
1930
1931 /* if `gindex' is invalid, the remaining values */
1932 /* in this group are invalid, too */
1933 if ( gindex >= (FT_UInt)face->num_glyphs )
1934 {
1935 gindex = 0;
1936 continue;
1937 }
1938
1939 result = char_code;
1940 break;
1941 }
1942 }
1943
1944 *pchar_code = result;
1945 return gindex;
1946 }
1947
1948
1949 FT_CALLBACK_DEF( FT_Error )static FT_Error
1950 tt_cmap8_get_info( TT_CMap cmap,
1951 TT_CMapInfo *cmap_info )
1952 {
1953 cmap_info->format = 8;
1954 return FT_Err_Ok;
1955 }
1956
1957
1958 FT_DEFINE_TT_CMAP(const TT_CMap_ClassRec tt_cmap8_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap8_char_index, (FT_CMap_CharNextFunc
) tt_cmap8_char_next }, 8, (TT_CMap_ValidateFunc)tt_cmap8_validate
, (TT_CMap_Info_GetFunc)tt_cmap8_get_info };
1959 tt_cmap8_class_rec,const TT_CMap_ClassRec tt_cmap8_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap8_char_index, (FT_CMap_CharNextFunc
) tt_cmap8_char_next }, 8, (TT_CMap_ValidateFunc)tt_cmap8_validate
, (TT_CMap_Info_GetFunc)tt_cmap8_get_info };
1960
1961 sizeof ( TT_CMapRec ),const TT_CMap_ClassRec tt_cmap8_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap8_char_index, (FT_CMap_CharNextFunc
) tt_cmap8_char_next }, 8, (TT_CMap_ValidateFunc)tt_cmap8_validate
, (TT_CMap_Info_GetFunc)tt_cmap8_get_info };
1962
1963 (FT_CMap_InitFunc) tt_cmap_init, /* init */const TT_CMap_ClassRec tt_cmap8_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap8_char_index, (FT_CMap_CharNextFunc
) tt_cmap8_char_next }, 8, (TT_CMap_ValidateFunc)tt_cmap8_validate
, (TT_CMap_Info_GetFunc)tt_cmap8_get_info };
1964 (FT_CMap_DoneFunc) NULL, /* done */const TT_CMap_ClassRec tt_cmap8_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap8_char_index, (FT_CMap_CharNextFunc
) tt_cmap8_char_next }, 8, (TT_CMap_ValidateFunc)tt_cmap8_validate
, (TT_CMap_Info_GetFunc)tt_cmap8_get_info };
1965 (FT_CMap_CharIndexFunc)tt_cmap8_char_index, /* char_index */const TT_CMap_ClassRec tt_cmap8_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap8_char_index, (FT_CMap_CharNextFunc
) tt_cmap8_char_next }, 8, (TT_CMap_ValidateFunc)tt_cmap8_validate
, (TT_CMap_Info_GetFunc)tt_cmap8_get_info };
1966 (FT_CMap_CharNextFunc) tt_cmap8_char_next, /* char_next */const TT_CMap_ClassRec tt_cmap8_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap8_char_index, (FT_CMap_CharNextFunc
) tt_cmap8_char_next }, 8, (TT_CMap_ValidateFunc)tt_cmap8_validate
, (TT_CMap_Info_GetFunc)tt_cmap8_get_info };
1967
1968 8,const TT_CMap_ClassRec tt_cmap8_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap8_char_index, (FT_CMap_CharNextFunc
) tt_cmap8_char_next }, 8, (TT_CMap_ValidateFunc)tt_cmap8_validate
, (TT_CMap_Info_GetFunc)tt_cmap8_get_info };
1969 (TT_CMap_ValidateFunc)tt_cmap8_validate, /* validate */const TT_CMap_ClassRec tt_cmap8_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap8_char_index, (FT_CMap_CharNextFunc
) tt_cmap8_char_next }, 8, (TT_CMap_ValidateFunc)tt_cmap8_validate
, (TT_CMap_Info_GetFunc)tt_cmap8_get_info };
1970 (TT_CMap_Info_GetFunc)tt_cmap8_get_info /* get_cmap_info */const TT_CMap_ClassRec tt_cmap8_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap8_char_index, (FT_CMap_CharNextFunc
) tt_cmap8_char_next }, 8, (TT_CMap_ValidateFunc)tt_cmap8_validate
, (TT_CMap_Info_GetFunc)tt_cmap8_get_info };
1971 )const TT_CMap_ClassRec tt_cmap8_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap8_char_index, (FT_CMap_CharNextFunc
) tt_cmap8_char_next }, 8, (TT_CMap_ValidateFunc)tt_cmap8_validate
, (TT_CMap_Info_GetFunc)tt_cmap8_get_info };
1972
1973#endif /* TT_CONFIG_CMAP_FORMAT_8 */
1974
1975
1976 /*************************************************************************/
1977 /*************************************************************************/
1978 /***** *****/
1979 /***** FORMAT 10 *****/
1980 /***** *****/
1981 /*************************************************************************/
1982 /*************************************************************************/
1983
1984 /*************************************************************************/
1985 /* */
1986 /* TABLE OVERVIEW */
1987 /* -------------- */
1988 /* */
1989 /* NAME OFFSET TYPE DESCRIPTION */
1990 /* */
1991 /* format 0 USHORT must be 10 */
1992 /* reserved 2 USHORT reserved */
1993 /* length 4 ULONG length in bytes */
1994 /* language 8 ULONG Mac language code */
1995 /* */
1996 /* start 12 ULONG first char in range */
1997 /* count 16 ULONG number of chars in range */
1998 /* glyphIds 20 USHORT[count] glyph indices covered */
1999 /* */
2000
2001#ifdef TT_CONFIG_CMAP_FORMAT_10
2002
2003 FT_CALLBACK_DEF( FT_Error )static FT_Error
2004 tt_cmap10_validate( FT_Byte* table,
2005 FT_Validator valid )
2006 {
2007 FT_Byte* p = table + 4;
2008 FT_ULong length, count;
2009
2010
2011 if ( table + 20 > valid->limit )
2012 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
2013
2014 length = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2015 p = table + 16;
2016 count = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2017
2018 if ( length > (FT_ULong)( valid->limit - table ) ||
2019 /* length < 20 + count * 2 ? */
2020 length < 20 ||
2021 ( length - 20 ) / 2 < count )
2022 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
2023
2024 /* check glyph indices */
2025 if ( valid->level >= FT_VALIDATE_TIGHT )
2026 {
2027 FT_UInt gindex;
2028
2029
2030 for ( ; count > 0; count-- )
2031 {
2032 gindex = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
2033 if ( gindex >= TT_VALID_GLYPH_COUNT( valid )( (TT_Validator)( valid ) )->num_glyphs )
2034 FT_INVALID_GLYPH_IDft_validator_error( valid, SFNT_Err_Invalid_Glyph_Index );
2035 }
2036 }
2037
2038 return FT_Err_Ok;
2039 }
2040
2041
2042 FT_CALLBACK_DEF( FT_UInt )static FT_UInt
2043 tt_cmap10_char_index( TT_CMap cmap,
2044 FT_UInt32 char_code )
2045 {
2046 FT_Byte* table = cmap->data;
2047 FT_UInt result = 0;
2048 FT_Byte* p = table + 12;
2049 FT_UInt32 start = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2050 FT_UInt32 count = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2051 FT_UInt32 idx;
2052
2053
2054 if ( char_code < start )
2055 return 0;
2056
2057 idx = char_code - start;
2058
2059 if ( idx < count )
2060 {
2061 p += 2 * idx;
2062 result = TT_PEEK_USHORT( p )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(0)] ))
) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(p))[(
1)] )) ) << (0) )) )
;
2063 }
2064
2065 return result;
2066 }
2067
2068
2069 FT_CALLBACK_DEF( FT_UInt32 )static FT_UInt32
2070 tt_cmap10_char_next( TT_CMap cmap,
2071 FT_UInt32 *pchar_code )
2072 {
2073 FT_Byte* table = cmap->data;
2074 FT_UInt32 char_code;
2075 FT_UInt gindex = 0;
2076 FT_Byte* p = table + 12;
2077 FT_UInt32 start = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2078 FT_UInt32 count = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2079 FT_UInt32 idx;
2080
2081
2082 if ( *pchar_code >= 0xFFFFFFFFUL )
2083 return 0;
2084
2085 char_code = *pchar_code + 1;
2086
2087 if ( char_code < start )
2088 char_code = start;
2089
2090 idx = char_code - start;
2091 p += 2 * idx;
2092
2093 for ( ; idx < count; idx++ )
2094 {
2095 gindex = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
2096 if ( gindex != 0 )
2097 break;
2098
2099 if ( char_code >= 0xFFFFFFFFUL )
2100 return 0;
2101
2102 char_code++;
2103 }
2104
2105 *pchar_code = char_code;
2106 return gindex;
2107 }
2108
2109
2110 FT_CALLBACK_DEF( FT_Error )static FT_Error
2111 tt_cmap10_get_info( TT_CMap cmap,
2112 TT_CMapInfo *cmap_info )
2113 {
2114 cmap_info->format = 10;
2115 return FT_Err_Ok;
2116 }
2117
2118
2119 FT_DEFINE_TT_CMAP(const TT_CMap_ClassRec tt_cmap10_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap10_char_index, (FT_CMap_CharNextFunc
) tt_cmap10_char_next }, 10, (TT_CMap_ValidateFunc)tt_cmap10_validate
, (TT_CMap_Info_GetFunc)tt_cmap10_get_info };
2120 tt_cmap10_class_rec,const TT_CMap_ClassRec tt_cmap10_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap10_char_index, (FT_CMap_CharNextFunc
) tt_cmap10_char_next }, 10, (TT_CMap_ValidateFunc)tt_cmap10_validate
, (TT_CMap_Info_GetFunc)tt_cmap10_get_info };
2121
2122 sizeof ( TT_CMapRec ),const TT_CMap_ClassRec tt_cmap10_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap10_char_index, (FT_CMap_CharNextFunc
) tt_cmap10_char_next }, 10, (TT_CMap_ValidateFunc)tt_cmap10_validate
, (TT_CMap_Info_GetFunc)tt_cmap10_get_info };
2123
2124 (FT_CMap_InitFunc) tt_cmap_init, /* init */const TT_CMap_ClassRec tt_cmap10_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap10_char_index, (FT_CMap_CharNextFunc
) tt_cmap10_char_next }, 10, (TT_CMap_ValidateFunc)tt_cmap10_validate
, (TT_CMap_Info_GetFunc)tt_cmap10_get_info };
2125 (FT_CMap_DoneFunc) NULL, /* done */const TT_CMap_ClassRec tt_cmap10_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap10_char_index, (FT_CMap_CharNextFunc
) tt_cmap10_char_next }, 10, (TT_CMap_ValidateFunc)tt_cmap10_validate
, (TT_CMap_Info_GetFunc)tt_cmap10_get_info };
2126 (FT_CMap_CharIndexFunc)tt_cmap10_char_index, /* char_index */const TT_CMap_ClassRec tt_cmap10_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap10_char_index, (FT_CMap_CharNextFunc
) tt_cmap10_char_next }, 10, (TT_CMap_ValidateFunc)tt_cmap10_validate
, (TT_CMap_Info_GetFunc)tt_cmap10_get_info };
2127 (FT_CMap_CharNextFunc) tt_cmap10_char_next, /* char_next */const TT_CMap_ClassRec tt_cmap10_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap10_char_index, (FT_CMap_CharNextFunc
) tt_cmap10_char_next }, 10, (TT_CMap_ValidateFunc)tt_cmap10_validate
, (TT_CMap_Info_GetFunc)tt_cmap10_get_info };
2128
2129 10,const TT_CMap_ClassRec tt_cmap10_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap10_char_index, (FT_CMap_CharNextFunc
) tt_cmap10_char_next }, 10, (TT_CMap_ValidateFunc)tt_cmap10_validate
, (TT_CMap_Info_GetFunc)tt_cmap10_get_info };
2130 (TT_CMap_ValidateFunc)tt_cmap10_validate, /* validate */const TT_CMap_ClassRec tt_cmap10_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap10_char_index, (FT_CMap_CharNextFunc
) tt_cmap10_char_next }, 10, (TT_CMap_ValidateFunc)tt_cmap10_validate
, (TT_CMap_Info_GetFunc)tt_cmap10_get_info };
2131 (TT_CMap_Info_GetFunc)tt_cmap10_get_info /* get_cmap_info */const TT_CMap_ClassRec tt_cmap10_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap10_char_index, (FT_CMap_CharNextFunc
) tt_cmap10_char_next }, 10, (TT_CMap_ValidateFunc)tt_cmap10_validate
, (TT_CMap_Info_GetFunc)tt_cmap10_get_info };
2132 )const TT_CMap_ClassRec tt_cmap10_class_rec = { { sizeof ( TT_CMapRec
), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap10_char_index, (FT_CMap_CharNextFunc
) tt_cmap10_char_next }, 10, (TT_CMap_ValidateFunc)tt_cmap10_validate
, (TT_CMap_Info_GetFunc)tt_cmap10_get_info };
2133
2134#endif /* TT_CONFIG_CMAP_FORMAT_10 */
2135
2136
2137 /*************************************************************************/
2138 /*************************************************************************/
2139 /***** *****/
2140 /***** FORMAT 12 *****/
2141 /***** *****/
2142 /*************************************************************************/
2143 /*************************************************************************/
2144
2145 /*************************************************************************/
2146 /* */
2147 /* TABLE OVERVIEW */
2148 /* -------------- */
2149 /* */
2150 /* NAME OFFSET TYPE DESCRIPTION */
2151 /* */
2152 /* format 0 USHORT must be 12 */
2153 /* reserved 2 USHORT reserved */
2154 /* length 4 ULONG length in bytes */
2155 /* language 8 ULONG Mac language code */
2156 /* count 12 ULONG number of groups */
2157 /* 16 */
2158 /* */
2159 /* This header is followed by `count' groups of the following format: */
2160 /* */
2161 /* start 0 ULONG first charcode */
2162 /* end 4 ULONG last charcode */
2163 /* startId 8 ULONG start glyph ID for the group */
2164 /* */
2165
2166#ifdef TT_CONFIG_CMAP_FORMAT_12
2167
2168 typedef struct TT_CMap12Rec_
2169 {
2170 TT_CMapRec cmap;
2171 FT_Bool valid;
2172 FT_ULong cur_charcode;
2173 FT_UInt cur_gindex;
2174 FT_ULong cur_group;
2175 FT_ULong num_groups;
2176
2177 } TT_CMap12Rec, *TT_CMap12;
2178
2179
2180 FT_CALLBACK_DEF( FT_Error )static FT_Error
2181 tt_cmap12_init( TT_CMap12 cmap,
2182 FT_Byte* table )
2183 {
2184 cmap->cmap.data = table;
2185
2186 table += 12;
2187 cmap->num_groups = FT_PEEK_ULONG( table )( (FT_UInt32)(( ( (FT_UInt32)(( ((const FT_Byte*)(table))[(0)
] )) ) << (24) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(
table))[(1)] )) ) << (16) ) | ( ( (FT_UInt32)(( ((const
FT_Byte*)(table))[(2)] )) ) << (8) ) | ( ( (FT_UInt32)
(( ((const FT_Byte*)(table))[(3)] )) ) << (0) )) )
;
2188
2189 cmap->valid = 0;
2190
2191 return FT_Err_Ok;
2192 }
2193
2194
2195 FT_CALLBACK_DEF( FT_Error )static FT_Error
2196 tt_cmap12_validate( FT_Byte* table,
2197 FT_Validator valid )
2198 {
2199 FT_Byte* p;
2200 FT_ULong length;
2201 FT_ULong num_groups;
2202
2203
2204 if ( table + 16 > valid->limit )
2205 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
2206
2207 p = table + 4;
2208 length = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2209
2210 p = table + 12;
2211 num_groups = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2212
2213 if ( length > (FT_ULong)( valid->limit - table ) ||
2214 /* length < 16 + 12 * num_groups ? */
2215 length < 16 ||
2216 ( length - 16 ) / 12 < num_groups )
2217 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
2218
2219 /* check groups, they must be in increasing order */
2220 {
2221 FT_ULong n, start, end, start_id, last = 0;
2222
2223
2224 for ( n = 0; n < num_groups; n++ )
2225 {
2226 start = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2227 end = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2228 start_id = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2229
2230 if ( start > end )
2231 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
2232
2233 if ( n > 0 && start <= last )
2234 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
2235
2236 if ( valid->level >= FT_VALIDATE_TIGHT )
2237 {
2238 FT_UInt32 d = end - start;
2239
2240
2241 /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
2242 if ( d > TT_VALID_GLYPH_COUNT( valid )( (TT_Validator)( valid ) )->num_glyphs ||
2243 start_id >= TT_VALID_GLYPH_COUNT( valid )( (TT_Validator)( valid ) )->num_glyphs - d )
2244 FT_INVALID_GLYPH_IDft_validator_error( valid, SFNT_Err_Invalid_Glyph_Index );
2245 }
2246
2247 last = end;
2248 }
2249 }
2250
2251 return FT_Err_Ok;
2252 }
2253
2254
2255 /* search the index of the charcode next to cmap->cur_charcode */
2256 /* cmap->cur_group should be set up properly by caller */
2257 /* */
2258 static void
2259 tt_cmap12_next( TT_CMap12 cmap )
2260 {
2261 FT_Face face = cmap->cmap.cmap.charmap.face;
2262 FT_Byte* p;
2263 FT_ULong start, end, start_id, char_code;
2264 FT_ULong n;
2265 FT_UInt gindex;
2266
2267
2268 if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
2269 goto Fail;
2270
2271 char_code = cmap->cur_charcode + 1;
2272
2273 for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
2274 {
2275 p = cmap->cmap.data + 16 + 12 * n;
2276 start = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2277 end = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2278 start_id = TT_PEEK_ULONG( p )( (FT_UInt32)(( ( (FT_UInt32)(( ((const FT_Byte*)(p))[(0)] ))
) << (24) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p))[
(1)] )) ) << (16) ) | ( ( (FT_UInt32)(( ((const FT_Byte
*)(p))[(2)] )) ) << (8) ) | ( ( (FT_UInt32)(( ((const FT_Byte
*)(p))[(3)] )) ) << (0) )) )
;
2279
2280 if ( char_code < start )
2281 char_code = start;
2282
2283 Again:
2284 if ( char_code <= end )
2285 {
2286 /* ignore invalid group */
2287 if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
2288 continue;
2289
2290 gindex = (FT_UInt)( start_id + ( char_code - start ) );
2291
2292 /* does first element of group point to `.notdef' glyph? */
2293 if ( gindex == 0 )
2294 {
2295 if ( char_code >= 0xFFFFFFFFUL )
2296 goto Fail;
2297
2298 char_code++;
2299 goto Again;
2300 }
2301
2302 /* if `gindex' is invalid, the remaining values */
2303 /* in this group are invalid, too */
2304 if ( gindex >= (FT_UInt)face->num_glyphs )
2305 {
2306 gindex = 0;
Value stored to 'gindex' is never read
2307 continue;
2308 }
2309
2310 cmap->cur_charcode = char_code;
2311 cmap->cur_gindex = gindex;
2312 cmap->cur_group = n;
2313
2314 return;
2315 }
2316 }
2317
2318 Fail:
2319 cmap->valid = 0;
2320 }
2321
2322
2323 static FT_UInt
2324 tt_cmap12_char_map_binary( TT_CMap cmap,
2325 FT_UInt32* pchar_code,
2326 FT_Bool next )
2327 {
2328 FT_UInt gindex = 0;
2329 FT_Byte* p = cmap->data + 12;
2330 FT_UInt32 num_groups = TT_PEEK_ULONG( p )( (FT_UInt32)(( ( (FT_UInt32)(( ((const FT_Byte*)(p))[(0)] ))
) << (24) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p))[
(1)] )) ) << (16) ) | ( ( (FT_UInt32)(( ((const FT_Byte
*)(p))[(2)] )) ) << (8) ) | ( ( (FT_UInt32)(( ((const FT_Byte
*)(p))[(3)] )) ) << (0) )) )
;
2331 FT_UInt32 char_code = *pchar_code;
2332 FT_UInt32 start, end, start_id;
2333 FT_UInt32 max, min, mid;
2334
2335
2336 if ( !num_groups )
2337 return 0;
2338
2339 /* make compiler happy */
2340 mid = num_groups;
2341 end = 0xFFFFFFFFUL;
2342
2343 if ( next )
2344 {
2345 if ( char_code >= 0xFFFFFFFFUL )
2346 return 0;
2347
2348 char_code++;
2349 }
2350
2351 min = 0;
2352 max = num_groups;
2353
2354 /* binary search */
2355 while ( min < max )
2356 {
2357 mid = ( min + max ) >> 1;
2358 p = cmap->data + 16 + 12 * mid;
2359
2360 start = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2361 end = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2362
2363 if ( char_code < start )
2364 max = mid;
2365 else if ( char_code > end )
2366 min = mid + 1;
2367 else
2368 {
2369 start_id = TT_PEEK_ULONG( p )( (FT_UInt32)(( ( (FT_UInt32)(( ((const FT_Byte*)(p))[(0)] ))
) << (24) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p))[
(1)] )) ) << (16) ) | ( ( (FT_UInt32)(( ((const FT_Byte
*)(p))[(2)] )) ) << (8) ) | ( ( (FT_UInt32)(( ((const FT_Byte
*)(p))[(3)] )) ) << (0) )) )
;
2370
2371 /* reject invalid glyph index */
2372 if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
2373 gindex = 0;
2374 else
2375 gindex = (FT_UInt)( start_id + ( char_code - start ) );
2376 break;
2377 }
2378 }
2379
2380 if ( next )
2381 {
2382 FT_Face face = cmap->cmap.charmap.face;
2383 TT_CMap12 cmap12 = (TT_CMap12)cmap;
2384
2385
2386 /* if `char_code' is not in any group, then `mid' is */
2387 /* the group nearest to `char_code' */
2388
2389 if ( char_code > end )
2390 {
2391 mid++;
2392 if ( mid == num_groups )
2393 return 0;
2394 }
2395
2396 cmap12->valid = 1;
2397 cmap12->cur_charcode = char_code;
2398 cmap12->cur_group = mid;
2399
2400 if ( gindex >= (FT_UInt)face->num_glyphs )
2401 gindex = 0;
2402
2403 if ( !gindex )
2404 {
2405 tt_cmap12_next( cmap12 );
2406
2407 if ( cmap12->valid )
2408 gindex = cmap12->cur_gindex;
2409 }
2410 else
2411 cmap12->cur_gindex = gindex;
2412
2413 *pchar_code = cmap12->cur_charcode;
2414 }
2415
2416 return gindex;
2417 }
2418
2419
2420 FT_CALLBACK_DEF( FT_UInt )static FT_UInt
2421 tt_cmap12_char_index( TT_CMap cmap,
2422 FT_UInt32 char_code )
2423 {
2424 return tt_cmap12_char_map_binary( cmap, &char_code, 0 );
2425 }
2426
2427
2428 FT_CALLBACK_DEF( FT_UInt32 )static FT_UInt32
2429 tt_cmap12_char_next( TT_CMap cmap,
2430 FT_UInt32 *pchar_code )
2431 {
2432 TT_CMap12 cmap12 = (TT_CMap12)cmap;
2433 FT_UInt gindex;
2434
2435
2436 /* no need to search */
2437 if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
2438 {
2439 tt_cmap12_next( cmap12 );
2440 if ( cmap12->valid )
2441 {
2442 gindex = cmap12->cur_gindex;
2443 *pchar_code = (FT_UInt32)cmap12->cur_charcode;
2444 }
2445 else
2446 gindex = 0;
2447 }
2448 else
2449 gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
2450
2451 return gindex;
2452 }
2453
2454
2455 FT_CALLBACK_DEF( FT_Error )static FT_Error
2456 tt_cmap12_get_info( TT_CMap cmap,
2457 TT_CMapInfo *cmap_info )
2458 {
2459 cmap_info->format = 12;
2460 return FT_Err_Ok;
2461 }
2462
2463
2464 FT_DEFINE_TT_CMAP(const TT_CMap_ClassRec tt_cmap12_class_rec = { { sizeof ( TT_CMap12Rec
), (FT_CMap_InitFunc) tt_cmap12_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap12_char_index, (FT_CMap_CharNextFunc
) tt_cmap12_char_next }, 12, (TT_CMap_ValidateFunc)tt_cmap12_validate
, (TT_CMap_Info_GetFunc)tt_cmap12_get_info };
2465 tt_cmap12_class_rec,const TT_CMap_ClassRec tt_cmap12_class_rec = { { sizeof ( TT_CMap12Rec
), (FT_CMap_InitFunc) tt_cmap12_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap12_char_index, (FT_CMap_CharNextFunc
) tt_cmap12_char_next }, 12, (TT_CMap_ValidateFunc)tt_cmap12_validate
, (TT_CMap_Info_GetFunc)tt_cmap12_get_info };
2466
2467 sizeof ( TT_CMap12Rec ),const TT_CMap_ClassRec tt_cmap12_class_rec = { { sizeof ( TT_CMap12Rec
), (FT_CMap_InitFunc) tt_cmap12_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap12_char_index, (FT_CMap_CharNextFunc
) tt_cmap12_char_next }, 12, (TT_CMap_ValidateFunc)tt_cmap12_validate
, (TT_CMap_Info_GetFunc)tt_cmap12_get_info };
2468
2469 (FT_CMap_InitFunc) tt_cmap12_init, /* init */const TT_CMap_ClassRec tt_cmap12_class_rec = { { sizeof ( TT_CMap12Rec
), (FT_CMap_InitFunc) tt_cmap12_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap12_char_index, (FT_CMap_CharNextFunc
) tt_cmap12_char_next }, 12, (TT_CMap_ValidateFunc)tt_cmap12_validate
, (TT_CMap_Info_GetFunc)tt_cmap12_get_info };
2470 (FT_CMap_DoneFunc) NULL, /* done */const TT_CMap_ClassRec tt_cmap12_class_rec = { { sizeof ( TT_CMap12Rec
), (FT_CMap_InitFunc) tt_cmap12_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap12_char_index, (FT_CMap_CharNextFunc
) tt_cmap12_char_next }, 12, (TT_CMap_ValidateFunc)tt_cmap12_validate
, (TT_CMap_Info_GetFunc)tt_cmap12_get_info };
2471 (FT_CMap_CharIndexFunc)tt_cmap12_char_index, /* char_index */const TT_CMap_ClassRec tt_cmap12_class_rec = { { sizeof ( TT_CMap12Rec
), (FT_CMap_InitFunc) tt_cmap12_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap12_char_index, (FT_CMap_CharNextFunc
) tt_cmap12_char_next }, 12, (TT_CMap_ValidateFunc)tt_cmap12_validate
, (TT_CMap_Info_GetFunc)tt_cmap12_get_info };
2472 (FT_CMap_CharNextFunc) tt_cmap12_char_next, /* char_next */const TT_CMap_ClassRec tt_cmap12_class_rec = { { sizeof ( TT_CMap12Rec
), (FT_CMap_InitFunc) tt_cmap12_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap12_char_index, (FT_CMap_CharNextFunc
) tt_cmap12_char_next }, 12, (TT_CMap_ValidateFunc)tt_cmap12_validate
, (TT_CMap_Info_GetFunc)tt_cmap12_get_info };
2473
2474 12,const TT_CMap_ClassRec tt_cmap12_class_rec = { { sizeof ( TT_CMap12Rec
), (FT_CMap_InitFunc) tt_cmap12_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap12_char_index, (FT_CMap_CharNextFunc
) tt_cmap12_char_next }, 12, (TT_CMap_ValidateFunc)tt_cmap12_validate
, (TT_CMap_Info_GetFunc)tt_cmap12_get_info };
2475 (TT_CMap_ValidateFunc)tt_cmap12_validate, /* validate */const TT_CMap_ClassRec tt_cmap12_class_rec = { { sizeof ( TT_CMap12Rec
), (FT_CMap_InitFunc) tt_cmap12_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap12_char_index, (FT_CMap_CharNextFunc
) tt_cmap12_char_next }, 12, (TT_CMap_ValidateFunc)tt_cmap12_validate
, (TT_CMap_Info_GetFunc)tt_cmap12_get_info };
2476 (TT_CMap_Info_GetFunc)tt_cmap12_get_info /* get_cmap_info */const TT_CMap_ClassRec tt_cmap12_class_rec = { { sizeof ( TT_CMap12Rec
), (FT_CMap_InitFunc) tt_cmap12_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap12_char_index, (FT_CMap_CharNextFunc
) tt_cmap12_char_next }, 12, (TT_CMap_ValidateFunc)tt_cmap12_validate
, (TT_CMap_Info_GetFunc)tt_cmap12_get_info };
2477 )const TT_CMap_ClassRec tt_cmap12_class_rec = { { sizeof ( TT_CMap12Rec
), (FT_CMap_InitFunc) tt_cmap12_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap12_char_index, (FT_CMap_CharNextFunc
) tt_cmap12_char_next }, 12, (TT_CMap_ValidateFunc)tt_cmap12_validate
, (TT_CMap_Info_GetFunc)tt_cmap12_get_info };
2478
2479#endif /* TT_CONFIG_CMAP_FORMAT_12 */
2480
2481
2482 /*************************************************************************/
2483 /*************************************************************************/
2484 /***** *****/
2485 /***** FORMAT 13 *****/
2486 /***** *****/
2487 /*************************************************************************/
2488 /*************************************************************************/
2489
2490 /*************************************************************************/
2491 /* */
2492 /* TABLE OVERVIEW */
2493 /* -------------- */
2494 /* */
2495 /* NAME OFFSET TYPE DESCRIPTION */
2496 /* */
2497 /* format 0 USHORT must be 13 */
2498 /* reserved 2 USHORT reserved */
2499 /* length 4 ULONG length in bytes */
2500 /* language 8 ULONG Mac language code */
2501 /* count 12 ULONG number of groups */
2502 /* 16 */
2503 /* */
2504 /* This header is followed by `count' groups of the following format: */
2505 /* */
2506 /* start 0 ULONG first charcode */
2507 /* end 4 ULONG last charcode */
2508 /* glyphId 8 ULONG glyph ID for the whole group */
2509 /* */
2510
2511#ifdef TT_CONFIG_CMAP_FORMAT_13
2512
2513 typedef struct TT_CMap13Rec_
2514 {
2515 TT_CMapRec cmap;
2516 FT_Bool valid;
2517 FT_ULong cur_charcode;
2518 FT_UInt cur_gindex;
2519 FT_ULong cur_group;
2520 FT_ULong num_groups;
2521
2522 } TT_CMap13Rec, *TT_CMap13;
2523
2524
2525 FT_CALLBACK_DEF( FT_Error )static FT_Error
2526 tt_cmap13_init( TT_CMap13 cmap,
2527 FT_Byte* table )
2528 {
2529 cmap->cmap.data = table;
2530
2531 table += 12;
2532 cmap->num_groups = FT_PEEK_ULONG( table )( (FT_UInt32)(( ( (FT_UInt32)(( ((const FT_Byte*)(table))[(0)
] )) ) << (24) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(
table))[(1)] )) ) << (16) ) | ( ( (FT_UInt32)(( ((const
FT_Byte*)(table))[(2)] )) ) << (8) ) | ( ( (FT_UInt32)
(( ((const FT_Byte*)(table))[(3)] )) ) << (0) )) )
;
2533
2534 cmap->valid = 0;
2535
2536 return FT_Err_Ok;
2537 }
2538
2539
2540 FT_CALLBACK_DEF( FT_Error )static FT_Error
2541 tt_cmap13_validate( FT_Byte* table,
2542 FT_Validator valid )
2543 {
2544 FT_Byte* p;
2545 FT_ULong length;
2546 FT_ULong num_groups;
2547
2548
2549 if ( table + 16 > valid->limit )
2550 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
2551
2552 p = table + 4;
2553 length = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2554
2555 p = table + 12;
2556 num_groups = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2557
2558 if ( length > (FT_ULong)( valid->limit - table ) ||
2559 /* length < 16 + 12 * num_groups ? */
2560 length < 16 ||
2561 ( length - 16 ) / 12 < num_groups )
2562 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
2563
2564 /* check groups, they must be in increasing order */
2565 {
2566 FT_ULong n, start, end, glyph_id, last = 0;
2567
2568
2569 for ( n = 0; n < num_groups; n++ )
2570 {
2571 start = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2572 end = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2573 glyph_id = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2574
2575 if ( start > end )
2576 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
2577
2578 if ( n > 0 && start <= last )
2579 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
2580
2581 if ( valid->level >= FT_VALIDATE_TIGHT )
2582 {
2583 if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid )( (TT_Validator)( valid ) )->num_glyphs )
2584 FT_INVALID_GLYPH_IDft_validator_error( valid, SFNT_Err_Invalid_Glyph_Index );
2585 }
2586
2587 last = end;
2588 }
2589 }
2590
2591 return FT_Err_Ok;
2592 }
2593
2594
2595 /* search the index of the charcode next to cmap->cur_charcode */
2596 /* cmap->cur_group should be set up properly by caller */
2597 /* */
2598 static void
2599 tt_cmap13_next( TT_CMap13 cmap )
2600 {
2601 FT_Face face = cmap->cmap.cmap.charmap.face;
2602 FT_Byte* p;
2603 FT_ULong start, end, glyph_id, char_code;
2604 FT_ULong n;
2605 FT_UInt gindex;
2606
2607
2608 if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
2609 goto Fail;
2610
2611 char_code = cmap->cur_charcode + 1;
2612
2613 for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
2614 {
2615 p = cmap->cmap.data + 16 + 12 * n;
2616 start = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2617 end = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2618 glyph_id = TT_PEEK_ULONG( p )( (FT_UInt32)(( ( (FT_UInt32)(( ((const FT_Byte*)(p))[(0)] ))
) << (24) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p))[
(1)] )) ) << (16) ) | ( ( (FT_UInt32)(( ((const FT_Byte
*)(p))[(2)] )) ) << (8) ) | ( ( (FT_UInt32)(( ((const FT_Byte
*)(p))[(3)] )) ) << (0) )) )
;
2619
2620 if ( char_code < start )
2621 char_code = start;
2622
2623 if ( char_code <= end )
2624 {
2625 gindex = (FT_UInt)glyph_id;
2626
2627 if ( gindex && gindex < (FT_UInt)face->num_glyphs )
2628 {
2629 cmap->cur_charcode = char_code;
2630 cmap->cur_gindex = gindex;
2631 cmap->cur_group = n;
2632
2633 return;
2634 }
2635 }
2636 }
2637
2638 Fail:
2639 cmap->valid = 0;
2640 }
2641
2642
2643 static FT_UInt
2644 tt_cmap13_char_map_binary( TT_CMap cmap,
2645 FT_UInt32* pchar_code,
2646 FT_Bool next )
2647 {
2648 FT_UInt gindex = 0;
2649 FT_Byte* p = cmap->data + 12;
2650 FT_UInt32 num_groups = TT_PEEK_ULONG( p )( (FT_UInt32)(( ( (FT_UInt32)(( ((const FT_Byte*)(p))[(0)] ))
) << (24) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p))[
(1)] )) ) << (16) ) | ( ( (FT_UInt32)(( ((const FT_Byte
*)(p))[(2)] )) ) << (8) ) | ( ( (FT_UInt32)(( ((const FT_Byte
*)(p))[(3)] )) ) << (0) )) )
;
2651 FT_UInt32 char_code = *pchar_code;
2652 FT_UInt32 start, end;
2653 FT_UInt32 max, min, mid;
2654
2655
2656 if ( !num_groups )
2657 return 0;
2658
2659 /* make compiler happy */
2660 mid = num_groups;
2661 end = 0xFFFFFFFFUL;
2662
2663 if ( next )
2664 {
2665 if ( char_code >= 0xFFFFFFFFUL )
2666 return 0;
2667
2668 char_code++;
2669 }
2670
2671 min = 0;
2672 max = num_groups;
2673
2674 /* binary search */
2675 while ( min < max )
2676 {
2677 mid = ( min + max ) >> 1;
2678 p = cmap->data + 16 + 12 * mid;
2679
2680 start = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2681 end = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2682
2683 if ( char_code < start )
2684 max = mid;
2685 else if ( char_code > end )
2686 min = mid + 1;
2687 else
2688 {
2689 gindex = (FT_UInt)TT_PEEK_ULONG( p )( (FT_UInt32)(( ( (FT_UInt32)(( ((const FT_Byte*)(p))[(0)] ))
) << (24) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p))[
(1)] )) ) << (16) ) | ( ( (FT_UInt32)(( ((const FT_Byte
*)(p))[(2)] )) ) << (8) ) | ( ( (FT_UInt32)(( ((const FT_Byte
*)(p))[(3)] )) ) << (0) )) )
;
2690
2691 break;
2692 }
2693 }
2694
2695 if ( next )
2696 {
2697 FT_Face face = cmap->cmap.charmap.face;
2698 TT_CMap13 cmap13 = (TT_CMap13)cmap;
2699
2700
2701 /* if `char_code' is not in any group, then `mid' is */
2702 /* the group nearest to `char_code' */
2703
2704 if ( char_code > end )
2705 {
2706 mid++;
2707 if ( mid == num_groups )
2708 return 0;
2709 }
2710
2711 cmap13->valid = 1;
2712 cmap13->cur_charcode = char_code;
2713 cmap13->cur_group = mid;
2714
2715 if ( gindex >= (FT_UInt)face->num_glyphs )
2716 gindex = 0;
2717
2718 if ( !gindex )
2719 {
2720 tt_cmap13_next( cmap13 );
2721
2722 if ( cmap13->valid )
2723 gindex = cmap13->cur_gindex;
2724 }
2725 else
2726 cmap13->cur_gindex = gindex;
2727
2728 *pchar_code = cmap13->cur_charcode;
2729 }
2730
2731 return gindex;
2732 }
2733
2734
2735 FT_CALLBACK_DEF( FT_UInt )static FT_UInt
2736 tt_cmap13_char_index( TT_CMap cmap,
2737 FT_UInt32 char_code )
2738 {
2739 return tt_cmap13_char_map_binary( cmap, &char_code, 0 );
2740 }
2741
2742
2743 FT_CALLBACK_DEF( FT_UInt32 )static FT_UInt32
2744 tt_cmap13_char_next( TT_CMap cmap,
2745 FT_UInt32 *pchar_code )
2746 {
2747 TT_CMap13 cmap13 = (TT_CMap13)cmap;
2748 FT_UInt gindex;
2749
2750
2751 /* no need to search */
2752 if ( cmap13->valid && cmap13->cur_charcode == *pchar_code )
2753 {
2754 tt_cmap13_next( cmap13 );
2755 if ( cmap13->valid )
2756 {
2757 gindex = cmap13->cur_gindex;
2758 *pchar_code = cmap13->cur_charcode;
2759 }
2760 else
2761 gindex = 0;
2762 }
2763 else
2764 gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 );
2765
2766 return gindex;
2767 }
2768
2769
2770 FT_CALLBACK_DEF( FT_Error )static FT_Error
2771 tt_cmap13_get_info( TT_CMap cmap,
2772 TT_CMapInfo *cmap_info )
2773 {
2774 cmap_info->format = 13;
2775 return FT_Err_Ok;
2776 }
2777
2778
2779 FT_DEFINE_TT_CMAP(const TT_CMap_ClassRec tt_cmap13_class_rec = { { sizeof ( TT_CMap13Rec
), (FT_CMap_InitFunc) tt_cmap13_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap13_char_index, (FT_CMap_CharNextFunc
) tt_cmap13_char_next }, 13, (TT_CMap_ValidateFunc)tt_cmap13_validate
, (TT_CMap_Info_GetFunc)tt_cmap13_get_info };
2780 tt_cmap13_class_rec,const TT_CMap_ClassRec tt_cmap13_class_rec = { { sizeof ( TT_CMap13Rec
), (FT_CMap_InitFunc) tt_cmap13_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap13_char_index, (FT_CMap_CharNextFunc
) tt_cmap13_char_next }, 13, (TT_CMap_ValidateFunc)tt_cmap13_validate
, (TT_CMap_Info_GetFunc)tt_cmap13_get_info };
2781
2782 sizeof ( TT_CMap13Rec ),const TT_CMap_ClassRec tt_cmap13_class_rec = { { sizeof ( TT_CMap13Rec
), (FT_CMap_InitFunc) tt_cmap13_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap13_char_index, (FT_CMap_CharNextFunc
) tt_cmap13_char_next }, 13, (TT_CMap_ValidateFunc)tt_cmap13_validate
, (TT_CMap_Info_GetFunc)tt_cmap13_get_info };
2783
2784 (FT_CMap_InitFunc) tt_cmap13_init, /* init */const TT_CMap_ClassRec tt_cmap13_class_rec = { { sizeof ( TT_CMap13Rec
), (FT_CMap_InitFunc) tt_cmap13_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap13_char_index, (FT_CMap_CharNextFunc
) tt_cmap13_char_next }, 13, (TT_CMap_ValidateFunc)tt_cmap13_validate
, (TT_CMap_Info_GetFunc)tt_cmap13_get_info };
2785 (FT_CMap_DoneFunc) NULL, /* done */const TT_CMap_ClassRec tt_cmap13_class_rec = { { sizeof ( TT_CMap13Rec
), (FT_CMap_InitFunc) tt_cmap13_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap13_char_index, (FT_CMap_CharNextFunc
) tt_cmap13_char_next }, 13, (TT_CMap_ValidateFunc)tt_cmap13_validate
, (TT_CMap_Info_GetFunc)tt_cmap13_get_info };
2786 (FT_CMap_CharIndexFunc)tt_cmap13_char_index, /* char_index */const TT_CMap_ClassRec tt_cmap13_class_rec = { { sizeof ( TT_CMap13Rec
), (FT_CMap_InitFunc) tt_cmap13_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap13_char_index, (FT_CMap_CharNextFunc
) tt_cmap13_char_next }, 13, (TT_CMap_ValidateFunc)tt_cmap13_validate
, (TT_CMap_Info_GetFunc)tt_cmap13_get_info };
2787 (FT_CMap_CharNextFunc) tt_cmap13_char_next, /* char_next */const TT_CMap_ClassRec tt_cmap13_class_rec = { { sizeof ( TT_CMap13Rec
), (FT_CMap_InitFunc) tt_cmap13_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap13_char_index, (FT_CMap_CharNextFunc
) tt_cmap13_char_next }, 13, (TT_CMap_ValidateFunc)tt_cmap13_validate
, (TT_CMap_Info_GetFunc)tt_cmap13_get_info };
2788
2789 13,const TT_CMap_ClassRec tt_cmap13_class_rec = { { sizeof ( TT_CMap13Rec
), (FT_CMap_InitFunc) tt_cmap13_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap13_char_index, (FT_CMap_CharNextFunc
) tt_cmap13_char_next }, 13, (TT_CMap_ValidateFunc)tt_cmap13_validate
, (TT_CMap_Info_GetFunc)tt_cmap13_get_info };
2790 (TT_CMap_ValidateFunc)tt_cmap13_validate, /* validate */const TT_CMap_ClassRec tt_cmap13_class_rec = { { sizeof ( TT_CMap13Rec
), (FT_CMap_InitFunc) tt_cmap13_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap13_char_index, (FT_CMap_CharNextFunc
) tt_cmap13_char_next }, 13, (TT_CMap_ValidateFunc)tt_cmap13_validate
, (TT_CMap_Info_GetFunc)tt_cmap13_get_info };
2791 (TT_CMap_Info_GetFunc)tt_cmap13_get_info /* get_cmap_info */const TT_CMap_ClassRec tt_cmap13_class_rec = { { sizeof ( TT_CMap13Rec
), (FT_CMap_InitFunc) tt_cmap13_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap13_char_index, (FT_CMap_CharNextFunc
) tt_cmap13_char_next }, 13, (TT_CMap_ValidateFunc)tt_cmap13_validate
, (TT_CMap_Info_GetFunc)tt_cmap13_get_info };
2792 )const TT_CMap_ClassRec tt_cmap13_class_rec = { { sizeof ( TT_CMap13Rec
), (FT_CMap_InitFunc) tt_cmap13_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap13_char_index, (FT_CMap_CharNextFunc
) tt_cmap13_char_next }, 13, (TT_CMap_ValidateFunc)tt_cmap13_validate
, (TT_CMap_Info_GetFunc)tt_cmap13_get_info };
2793
2794#endif /* TT_CONFIG_CMAP_FORMAT_13 */
2795
2796
2797 /*************************************************************************/
2798 /*************************************************************************/
2799 /***** *****/
2800 /***** FORMAT 14 *****/
2801 /***** *****/
2802 /*************************************************************************/
2803 /*************************************************************************/
2804
2805 /*************************************************************************/
2806 /* */
2807 /* TABLE OVERVIEW */
2808 /* -------------- */
2809 /* */
2810 /* NAME OFFSET TYPE DESCRIPTION */
2811 /* */
2812 /* format 0 USHORT must be 14 */
2813 /* length 2 ULONG table length in bytes */
2814 /* numSelector 6 ULONG number of variation sel. records */
2815 /* */
2816 /* Followed by numSelector records, each of which looks like */
2817 /* */
2818 /* varSelector 0 UINT24 Unicode codepoint of sel. */
2819 /* defaultOff 3 ULONG offset to a default UVS table */
2820 /* describing any variants to be found in */
2821 /* the normal Unicode subtable. */
2822 /* nonDefOff 7 ULONG offset to a non-default UVS table */
2823 /* describing any variants not in the */
2824 /* standard cmap, with GIDs here */
2825 /* (either offset may be 0 NULL) */
2826 /* */
2827 /* Selectors are sorted by code point. */
2828 /* */
2829 /* A default Unicode Variation Selector (UVS) subtable is just a list of */
2830 /* ranges of code points which are to be found in the standard cmap. No */
2831 /* glyph IDs (GIDs) here. */
2832 /* */
2833 /* numRanges 0 ULONG number of ranges following */
2834 /* */
2835 /* A range looks like */
2836 /* */
2837 /* uniStart 0 UINT24 code point of the first character in */
2838 /* this range */
2839 /* additionalCnt 3 UBYTE count of additional characters in this */
2840 /* range (zero means a range of a single */
2841 /* character) */
2842 /* */
2843 /* Ranges are sorted by `uniStart'. */
2844 /* */
2845 /* A non-default Unicode Variation Selector (UVS) subtable is a list of */
2846 /* mappings from codepoint to GID. */
2847 /* */
2848 /* numMappings 0 ULONG number of mappings */
2849 /* */
2850 /* A range looks like */
2851 /* */
2852 /* uniStart 0 UINT24 code point of the first character in */
2853 /* this range */
2854 /* GID 3 USHORT and its GID */
2855 /* */
2856 /* Ranges are sorted by `uniStart'. */
2857
2858#ifdef TT_CONFIG_CMAP_FORMAT_14
2859
2860 typedef struct TT_CMap14Rec_
2861 {
2862 TT_CMapRec cmap;
2863 FT_ULong num_selectors;
2864
2865 } TT_CMap14Rec, *TT_CMap14;
2866
2867
2868 FT_CALLBACK_DEF( FT_Error )static FT_Error
2869 tt_cmap14_init( TT_CMap14 cmap,
2870 FT_Byte* table )
2871 {
2872 cmap->cmap.data = table;
2873
2874 table += 6;
2875 cmap->num_selectors = FT_PEEK_ULONG( table )( (FT_UInt32)(( ( (FT_UInt32)(( ((const FT_Byte*)(table))[(0)
] )) ) << (24) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(
table))[(1)] )) ) << (16) ) | ( ( (FT_UInt32)(( ((const
FT_Byte*)(table))[(2)] )) ) << (8) ) | ( ( (FT_UInt32)
(( ((const FT_Byte*)(table))[(3)] )) ) << (0) )) )
;
2876 return FT_Err_Ok;
2877 }
2878
2879
2880 FT_CALLBACK_DEF( FT_Error )static FT_Error
2881 tt_cmap14_validate( FT_Byte* table,
2882 FT_Validator valid )
2883 {
2884 FT_Byte* p;
2885 FT_ULong length;
2886 FT_ULong num_selectors;
2887
2888
2889 if ( table + 2 + 4 + 4 > valid->limit )
2890 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
2891
2892 p = table + 2;
2893 length = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2894 num_selectors = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2895
2896 if ( length > (FT_ULong)( valid->limit - table ) ||
2897 /* length < 10 + 11 * num_selectors ? */
2898 length < 10 ||
2899 ( length - 10 ) / 11 < num_selectors )
2900 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
2901
2902 /* check selectors, they must be in increasing order */
2903 {
2904 /* we start lastVarSel at 1 because a variant selector value of 0
2905 * isn't valid.
2906 */
2907 FT_ULong n, lastVarSel = 1;
2908
2909
2910 for ( n = 0; n < num_selectors; n++ )
2911 {
2912 FT_ULong varSel = TT_NEXT_UINT24( p )( (unsigned long)( p += 3, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 3))[(0)] )) ) << (16) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 3))[(1)] )) ) << (8) ) | ( ( (
FT_UInt32)(( ((const FT_Byte*)(p - 3))[(2)] )) ) << (0)
)) ) ) )
;
2913 FT_ULong defOff = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2914 FT_ULong nondefOff = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
2915
2916
2917 if ( defOff >= length || nondefOff >= length )
2918 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
2919
2920 if ( varSel < lastVarSel )
2921 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
2922
2923 lastVarSel = varSel + 1;
2924
2925 /* check the default table (these glyphs should be reached */
2926 /* through the normal Unicode cmap, no GIDs, just check order) */
2927 if ( defOff != 0 )
2928 {
2929 FT_Byte* defp = table + defOff;
2930 FT_ULong numRanges;
2931 FT_ULong i;
2932 FT_ULong lastBase = 0;
2933
2934
2935 if ( defp + 4 > valid->limit )
2936 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
2937
2938 numRanges = TT_NEXT_ULONG( defp )( (unsigned long)( defp += 4, ( (FT_UInt32)(( ( (FT_UInt32)((
((const FT_Byte*)(defp - 4))[(0)] )) ) << (24) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(defp - 4))[(1)] )) ) <<
(16) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(defp - 4))[(2)]
)) ) << (8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(defp
- 4))[(3)] )) ) << (0) )) ) ) )
;
2939
2940 /* defp + numRanges * 4 > valid->limit ? */
2941 if ( numRanges > (FT_ULong)( valid->limit - defp ) / 4 )
2942 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
2943
2944 for ( i = 0; i < numRanges; i++ )
2945 {
2946 FT_ULong base = TT_NEXT_UINT24( defp )( (unsigned long)( defp += 3, ( (FT_UInt32)(( ( (FT_UInt32)((
((const FT_Byte*)(defp - 3))[(0)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(defp - 3))[(1)] )) ) <<
(8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(defp - 3))[(2)] )
) ) << (0) )) ) ) )
;
2947 FT_ULong cnt = FT_NEXT_BYTE( defp )( (unsigned char)*defp++ );
2948
2949
2950 if ( base + cnt >= 0x110000UL ) /* end of Unicode */
2951 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
2952
2953 if ( base < lastBase )
2954 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
2955
2956 lastBase = base + cnt + 1U;
2957 }
2958 }
2959
2960 /* and the non-default table (these glyphs are specified here) */
2961 if ( nondefOff != 0 )
2962 {
2963 FT_Byte* ndp = table + nondefOff;
2964 FT_ULong numMappings;
2965 FT_ULong i, lastUni = 0;
2966
2967
2968 if ( ndp + 4 > valid->limit )
2969 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
2970
2971 numMappings = TT_NEXT_ULONG( ndp )( (unsigned long)( ndp += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( (
(const FT_Byte*)(ndp - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(ndp - 4))[(1)] )) ) << (16) ) | (
( (FT_UInt32)(( ((const FT_Byte*)(ndp - 4))[(2)] )) ) <<
(8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(ndp - 4))[(3)] )
) ) << (0) )) ) ) )
;
2972
2973 /* numMappings * 5 > (FT_ULong)( valid->limit - ndp ) ? */
2974 if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 5 )
2975 FT_INVALID_TOO_SHORTft_validator_error( valid, SFNT_Err_Invalid_Table );
2976
2977 for ( i = 0; i < numMappings; i++ )
2978 {
2979 FT_ULong uni = TT_NEXT_UINT24( ndp )( (unsigned long)( ndp += 3, ( (FT_UInt32)(( ( (FT_UInt32)(( (
(const FT_Byte*)(ndp - 3))[(0)] )) ) << (16) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(ndp - 3))[(1)] )) ) << (8) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(ndp - 3))[(2)] )) ) <<
(0) )) ) ) )
;
2980 FT_ULong gid = TT_NEXT_USHORT( ndp )( (unsigned short)( ndp += 2, ( (FT_UInt16)(( ( (FT_UInt16)((
((const FT_Byte*)(ndp - 2))[(0)] )) ) << (8) ) | ( ( (
FT_UInt16)(( ((const FT_Byte*)(ndp - 2))[(1)] )) ) << (
0) )) ) ) )
;
2981
2982
2983 if ( uni >= 0x110000UL ) /* end of Unicode */
2984 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
2985
2986 if ( uni < lastUni )
2987 FT_INVALID_DATAft_validator_error( valid, SFNT_Err_Invalid_Table );
2988
2989 lastUni = uni + 1U;
2990
2991 if ( valid->level >= FT_VALIDATE_TIGHT &&
2992 gid >= TT_VALID_GLYPH_COUNT( valid )( (TT_Validator)( valid ) )->num_glyphs )
2993 FT_INVALID_GLYPH_IDft_validator_error( valid, SFNT_Err_Invalid_Glyph_Index );
2994 }
2995 }
2996 }
2997 }
2998
2999 return FT_Err_Ok;
3000 }
3001
3002
3003 FT_CALLBACK_DEF( FT_UInt )static FT_UInt
3004 tt_cmap14_char_index( TT_CMap cmap,
3005 FT_UInt32 char_code )
3006 {
3007 FT_UNUSED( cmap )( (cmap) = (cmap) );
3008 FT_UNUSED( char_code )( (char_code) = (char_code) );
3009
3010 /* This can't happen */
3011 return 0;
3012 }
3013
3014
3015 FT_CALLBACK_DEF( FT_UInt32 )static FT_UInt32
3016 tt_cmap14_char_next( TT_CMap cmap,
3017 FT_UInt32 *pchar_code )
3018 {
3019 FT_UNUSED( cmap )( (cmap) = (cmap) );
3020
3021 /* This can't happen */
3022 *pchar_code = 0;
3023 return 0;
3024 }
3025
3026
3027 FT_CALLBACK_DEF( FT_Error )static FT_Error
3028 tt_cmap14_get_info( TT_CMap cmap,
3029 TT_CMapInfo *cmap_info )
3030 {
3031 cmap_info->format = 14;
3032 return FT_Err_Ok;
3033 }
3034
3035
3036 FT_DEFINE_TT_CMAP(const TT_CMap_ClassRec tt_cmap14_class_rec = { { sizeof ( TT_CMap14Rec
), (FT_CMap_InitFunc) tt_cmap14_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap14_char_index, (FT_CMap_CharNextFunc
) tt_cmap14_char_next }, 14, (TT_CMap_ValidateFunc)tt_cmap14_validate
, (TT_CMap_Info_GetFunc)tt_cmap14_get_info };
3037 tt_cmap14_class_rec,const TT_CMap_ClassRec tt_cmap14_class_rec = { { sizeof ( TT_CMap14Rec
), (FT_CMap_InitFunc) tt_cmap14_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap14_char_index, (FT_CMap_CharNextFunc
) tt_cmap14_char_next }, 14, (TT_CMap_ValidateFunc)tt_cmap14_validate
, (TT_CMap_Info_GetFunc)tt_cmap14_get_info };
3038
3039 sizeof ( TT_CMap14Rec ),const TT_CMap_ClassRec tt_cmap14_class_rec = { { sizeof ( TT_CMap14Rec
), (FT_CMap_InitFunc) tt_cmap14_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap14_char_index, (FT_CMap_CharNextFunc
) tt_cmap14_char_next }, 14, (TT_CMap_ValidateFunc)tt_cmap14_validate
, (TT_CMap_Info_GetFunc)tt_cmap14_get_info };
3040
3041 (FT_CMap_InitFunc) tt_cmap14_init, /* init */const TT_CMap_ClassRec tt_cmap14_class_rec = { { sizeof ( TT_CMap14Rec
), (FT_CMap_InitFunc) tt_cmap14_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap14_char_index, (FT_CMap_CharNextFunc
) tt_cmap14_char_next }, 14, (TT_CMap_ValidateFunc)tt_cmap14_validate
, (TT_CMap_Info_GetFunc)tt_cmap14_get_info };
3042 (FT_CMap_DoneFunc) NULL, /* done */const TT_CMap_ClassRec tt_cmap14_class_rec = { { sizeof ( TT_CMap14Rec
), (FT_CMap_InitFunc) tt_cmap14_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap14_char_index, (FT_CMap_CharNextFunc
) tt_cmap14_char_next }, 14, (TT_CMap_ValidateFunc)tt_cmap14_validate
, (TT_CMap_Info_GetFunc)tt_cmap14_get_info };
3043 (FT_CMap_CharIndexFunc)tt_cmap14_char_index, /* char_index */const TT_CMap_ClassRec tt_cmap14_class_rec = { { sizeof ( TT_CMap14Rec
), (FT_CMap_InitFunc) tt_cmap14_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap14_char_index, (FT_CMap_CharNextFunc
) tt_cmap14_char_next }, 14, (TT_CMap_ValidateFunc)tt_cmap14_validate
, (TT_CMap_Info_GetFunc)tt_cmap14_get_info };
3044 (FT_CMap_CharNextFunc) tt_cmap14_char_next, /* char_next */const TT_CMap_ClassRec tt_cmap14_class_rec = { { sizeof ( TT_CMap14Rec
), (FT_CMap_InitFunc) tt_cmap14_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap14_char_index, (FT_CMap_CharNextFunc
) tt_cmap14_char_next }, 14, (TT_CMap_ValidateFunc)tt_cmap14_validate
, (TT_CMap_Info_GetFunc)tt_cmap14_get_info };
3045
3046 14,const TT_CMap_ClassRec tt_cmap14_class_rec = { { sizeof ( TT_CMap14Rec
), (FT_CMap_InitFunc) tt_cmap14_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap14_char_index, (FT_CMap_CharNextFunc
) tt_cmap14_char_next }, 14, (TT_CMap_ValidateFunc)tt_cmap14_validate
, (TT_CMap_Info_GetFunc)tt_cmap14_get_info };
3047 (TT_CMap_ValidateFunc)tt_cmap14_validate, /* validate */const TT_CMap_ClassRec tt_cmap14_class_rec = { { sizeof ( TT_CMap14Rec
), (FT_CMap_InitFunc) tt_cmap14_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap14_char_index, (FT_CMap_CharNextFunc
) tt_cmap14_char_next }, 14, (TT_CMap_ValidateFunc)tt_cmap14_validate
, (TT_CMap_Info_GetFunc)tt_cmap14_get_info };
3048 (TT_CMap_Info_GetFunc)tt_cmap14_get_info /* get_cmap_info */const TT_CMap_ClassRec tt_cmap14_class_rec = { { sizeof ( TT_CMap14Rec
), (FT_CMap_InitFunc) tt_cmap14_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap14_char_index, (FT_CMap_CharNextFunc
) tt_cmap14_char_next }, 14, (TT_CMap_ValidateFunc)tt_cmap14_validate
, (TT_CMap_Info_GetFunc)tt_cmap14_get_info };
3049 )const TT_CMap_ClassRec tt_cmap14_class_rec = { { sizeof ( TT_CMap14Rec
), (FT_CMap_InitFunc) tt_cmap14_init, (FT_CMap_DoneFunc) ((void
*)0), (FT_CMap_CharIndexFunc)tt_cmap14_char_index, (FT_CMap_CharNextFunc
) tt_cmap14_char_next }, 14, (TT_CMap_ValidateFunc)tt_cmap14_validate
, (TT_CMap_Info_GetFunc)tt_cmap14_get_info };
3050
3051#endif /* TT_CONFIG_CMAP_FORMAT_14 */
3052
3053
3054 /*************************************************************************/
3055 /*************************************************************************/
3056 /***** *****/
3057 /***** SYNTHETIC UNICODE *****/
3058 /***** *****/
3059 /*************************************************************************/
3060 /*************************************************************************/
3061
3062 /* This charmap is generated using postscript glyph names. */
3063
3064#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
3065
3066 FT_CALLBACK_DEF( const char * )static const char *
3067 tt_get_glyph_name( TT_Face face,
3068 FT_UInt idx )
3069 {
3070 FT_String* PSname;
3071
3072
3073 tt_face_get_ps_name( face, idx, &PSname );
3074
3075 return PSname;
3076 }
3077
3078
3079 FT_CALLBACK_DEF( FT_Error )static FT_Error
3080 tt_cmap_unicode_init( PS_Unicodes unicodes,
3081 FT_Pointer pointer )
3082 {
3083 TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes )( (FT_CMap)( unicodes ) )->charmap.face;
3084 FT_Memory memory = FT_FACE_MEMORY( face )( (FT_Face)(face) )->memory;
3085 FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;
3086
3087 FT_UNUSED( pointer )( (pointer) = (pointer) );
3088
3089
3090 return psnames->unicodes_init( memory,
3091 unicodes,
3092 face->root.num_glyphs,
3093 (PS_GetGlyphNameFunc)&tt_get_glyph_name,
3094 (PS_FreeGlyphNameFunc)NULL((void*)0),
3095 (FT_Pointer)face );
3096 }
3097
3098
3099 FT_CALLBACK_DEF( void )static void
3100 tt_cmap_unicode_done( PS_Unicodes unicodes )
3101 {
3102 FT_Face face = FT_CMAP_FACE( unicodes )( (FT_CMap)( unicodes ) )->charmap.face;
3103 FT_Memory memory = FT_FACE_MEMORY( face )( (FT_Face)(face) )->memory;
3104
3105
3106 FT_FREE( unicodes->maps )do { ft_mem_free( memory, (unicodes->maps) ); (unicodes->
maps) = ((void*)0); } while ( 0 )
;
3107 unicodes->num_maps = 0;
3108 }
3109
3110
3111 FT_CALLBACK_DEF( FT_UInt )static FT_UInt
3112 tt_cmap_unicode_char_index( PS_Unicodes unicodes,
3113 FT_UInt32 char_code )
3114 {
3115 TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes )( (FT_CMap)( unicodes ) )->charmap.face;
3116 FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;
3117
3118
3119 return psnames->unicodes_char_index( unicodes, char_code );
3120 }
3121
3122
3123 FT_CALLBACK_DEF( FT_UInt32 )static FT_UInt32
3124 tt_cmap_unicode_char_next( PS_Unicodes unicodes,
3125 FT_UInt32 *pchar_code )
3126 {
3127 TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes )( (FT_CMap)( unicodes ) )->charmap.face;
3128 FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;
3129
3130
3131 return psnames->unicodes_char_next( unicodes, pchar_code );
3132 }
3133
3134
3135 FT_DEFINE_TT_CMAP(const TT_CMap_ClassRec tt_cmap_unicode_class_rec = { { sizeof
( PS_UnicodesRec ), (FT_CMap_InitFunc) tt_cmap_unicode_init,
(FT_CMap_DoneFunc) tt_cmap_unicode_done, (FT_CMap_CharIndexFunc
)tt_cmap_unicode_char_index, (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next
}, ~0U, (TT_CMap_ValidateFunc)((void*)0), (TT_CMap_Info_GetFunc
)((void*)0) };
3136 tt_cmap_unicode_class_rec,const TT_CMap_ClassRec tt_cmap_unicode_class_rec = { { sizeof
( PS_UnicodesRec ), (FT_CMap_InitFunc) tt_cmap_unicode_init,
(FT_CMap_DoneFunc) tt_cmap_unicode_done, (FT_CMap_CharIndexFunc
)tt_cmap_unicode_char_index, (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next
}, ~0U, (TT_CMap_ValidateFunc)((void*)0), (TT_CMap_Info_GetFunc
)((void*)0) };
3137
3138 sizeof ( PS_UnicodesRec ),const TT_CMap_ClassRec tt_cmap_unicode_class_rec = { { sizeof
( PS_UnicodesRec ), (FT_CMap_InitFunc) tt_cmap_unicode_init,
(FT_CMap_DoneFunc) tt_cmap_unicode_done, (FT_CMap_CharIndexFunc
)tt_cmap_unicode_char_index, (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next
}, ~0U, (TT_CMap_ValidateFunc)((void*)0), (TT_CMap_Info_GetFunc
)((void*)0) };
3139
3140 (FT_CMap_InitFunc) tt_cmap_unicode_init, /* init */const TT_CMap_ClassRec tt_cmap_unicode_class_rec = { { sizeof
( PS_UnicodesRec ), (FT_CMap_InitFunc) tt_cmap_unicode_init,
(FT_CMap_DoneFunc) tt_cmap_unicode_done, (FT_CMap_CharIndexFunc
)tt_cmap_unicode_char_index, (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next
}, ~0U, (TT_CMap_ValidateFunc)((void*)0), (TT_CMap_Info_GetFunc
)((void*)0) };
3141 (FT_CMap_DoneFunc) tt_cmap_unicode_done, /* done */const TT_CMap_ClassRec tt_cmap_unicode_class_rec = { { sizeof
( PS_UnicodesRec ), (FT_CMap_InitFunc) tt_cmap_unicode_init,
(FT_CMap_DoneFunc) tt_cmap_unicode_done, (FT_CMap_CharIndexFunc
)tt_cmap_unicode_char_index, (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next
}, ~0U, (TT_CMap_ValidateFunc)((void*)0), (TT_CMap_Info_GetFunc
)((void*)0) };
3142 (FT_CMap_CharIndexFunc)tt_cmap_unicode_char_index, /* char_index */const TT_CMap_ClassRec tt_cmap_unicode_class_rec = { { sizeof
( PS_UnicodesRec ), (FT_CMap_InitFunc) tt_cmap_unicode_init,
(FT_CMap_DoneFunc) tt_cmap_unicode_done, (FT_CMap_CharIndexFunc
)tt_cmap_unicode_char_index, (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next
}, ~0U, (TT_CMap_ValidateFunc)((void*)0), (TT_CMap_Info_GetFunc
)((void*)0) };
3143 (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next, /* char_next */const TT_CMap_ClassRec tt_cmap_unicode_class_rec = { { sizeof
( PS_UnicodesRec ), (FT_CMap_InitFunc) tt_cmap_unicode_init,
(FT_CMap_DoneFunc) tt_cmap_unicode_done, (FT_CMap_CharIndexFunc
)tt_cmap_unicode_char_index, (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next
}, ~0U, (TT_CMap_ValidateFunc)((void*)0), (TT_CMap_Info_GetFunc
)((void*)0) };
3144
3145 ~0U,const TT_CMap_ClassRec tt_cmap_unicode_class_rec = { { sizeof
( PS_UnicodesRec ), (FT_CMap_InitFunc) tt_cmap_unicode_init,
(FT_CMap_DoneFunc) tt_cmap_unicode_done, (FT_CMap_CharIndexFunc
)tt_cmap_unicode_char_index, (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next
}, ~0U, (TT_CMap_ValidateFunc)((void*)0), (TT_CMap_Info_GetFunc
)((void*)0) };
3146 (TT_CMap_ValidateFunc)NULL, /* validate */const TT_CMap_ClassRec tt_cmap_unicode_class_rec = { { sizeof
( PS_UnicodesRec ), (FT_CMap_InitFunc) tt_cmap_unicode_init,
(FT_CMap_DoneFunc) tt_cmap_unicode_done, (FT_CMap_CharIndexFunc
)tt_cmap_unicode_char_index, (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next
}, ~0U, (TT_CMap_ValidateFunc)((void*)0), (TT_CMap_Info_GetFunc
)((void*)0) };
3147 (TT_CMap_Info_GetFunc)NULL /* get_cmap_info */const TT_CMap_ClassRec tt_cmap_unicode_class_rec = { { sizeof
( PS_UnicodesRec ), (FT_CMap_InitFunc) tt_cmap_unicode_init,
(FT_CMap_DoneFunc) tt_cmap_unicode_done, (FT_CMap_CharIndexFunc
)tt_cmap_unicode_char_index, (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next
}, ~0U, (TT_CMap_ValidateFunc)((void*)0), (TT_CMap_Info_GetFunc
)((void*)0) };
3148 )const TT_CMap_ClassRec tt_cmap_unicode_class_rec = { { sizeof
( PS_UnicodesRec ), (FT_CMap_InitFunc) tt_cmap_unicode_init,
(FT_CMap_DoneFunc) tt_cmap_unicode_done, (FT_CMap_CharIndexFunc
)tt_cmap_unicode_char_index, (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next
}, ~0U, (TT_CMap_ValidateFunc)((void*)0), (TT_CMap_Info_GetFunc
)((void*)0) };
3149
3150#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
3151
3152
3153 static const TT_CMap_Class tt_cmap_classes[] =
3154 {
3155#define TTCMAPCITEM( a )&a, &a,
3156#include "ttcmapc.h"
3157 NULL((void*)0),
3158 };
3159
3160
3161 /* parse the `cmap' table and build the corresponding TT_CMap objects */
3162 /* in the current face */
3163 /* */
3164 FT_LOCAL_DEF( FT_Error )static FT_Error
3165 tt_face_build_cmaps( TT_Face face )
3166 {
3167 FT_Byte* table = face->cmap_table;
3168 FT_Byte* limit = table + face->cmap_size;
3169 FT_UInt volatile num_cmaps;
3170 FT_Byte* volatile p = table;
3171 FT_Library library = FT_FACE_LIBRARY( face )( (FT_Face)(face) )->driver->root.library;
3172
3173 FT_UNUSED( library )( (library) = (library) );
3174
3175
3176 if ( !p || p + 4 > limit )
3177 return FT_THROW( Invalid_Table )SFNT_Err_Invalid_Table;
3178
3179 /* only recognize format 0 */
3180 if ( TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
!= 0 )
3181 {
3182 FT_ERROR(( "tt_face_build_cmaps:"do { } while ( 0 )
3183 " unsupported `cmap' table format = %d\n",do { } while ( 0 )
3184 TT_PEEK_USHORT( p - 2 ) ))do { } while ( 0 );
3185 return FT_THROW( Invalid_Table )SFNT_Err_Invalid_Table;
3186 }
3187
3188 num_cmaps = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
3189
3190 for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
3191 {
3192 FT_CharMapRec charmap;
3193 FT_UInt32 offset;
3194
3195
3196 charmap.platform_id = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
3197 charmap.encoding_id = TT_NEXT_USHORT( p )( (unsigned short)( p += 2, ( (FT_UInt16)(( ( (FT_UInt16)(( (
(const FT_Byte*)(p - 2))[(0)] )) ) << (8) ) | ( ( (FT_UInt16
)(( ((const FT_Byte*)(p - 2))[(1)] )) ) << (0) )) ) ) )
;
3198 charmap.face = FT_FACE( face )( (FT_Face)(face) );
3199 charmap.encoding = FT_ENCODING_NONE; /* will be filled later */
3200 offset = TT_NEXT_ULONG( p )( (unsigned long)( p += 4, ( (FT_UInt32)(( ( (FT_UInt32)(( ((
const FT_Byte*)(p - 4))[(0)] )) ) << (24) ) | ( ( (FT_UInt32
)(( ((const FT_Byte*)(p - 4))[(1)] )) ) << (16) ) | ( (
(FT_UInt32)(( ((const FT_Byte*)(p - 4))[(2)] )) ) << (
8) ) | ( ( (FT_UInt32)(( ((const FT_Byte*)(p - 4))[(3)] )) ) <<
(0) )) ) ) )
;
3201
3202 if ( offset && offset <= face->cmap_size - 2 )
3203 {
3204 FT_Byte* volatile cmap = table + offset;
3205 volatile FT_UInt format = TT_PEEK_USHORT( cmap )( (FT_UInt16)(( ( (FT_UInt16)(( ((const FT_Byte*)(cmap))[(0)]
)) ) << (8) ) | ( ( (FT_UInt16)(( ((const FT_Byte*)(cmap
))[(1)] )) ) << (0) )) )
;
3206 const TT_CMap_Class* volatile pclazz = tt_cmap_classes;
3207 TT_CMap_Class volatile clazz;
3208
3209
3210 for ( ; *pclazz; pclazz++ )
3211 {
3212 clazz = *pclazz;
3213 if ( clazz->format == format )
3214 {
3215 volatile TT_ValidatorRec valid;
3216 volatile FT_Error error = FT_Err_Ok;
3217
3218
3219 ft_validator_init( FT_VALIDATOR( &valid )( (FT_Validator)( &valid ) ), cmap, limit,
3220 FT_VALIDATE_DEFAULT );
3221
3222 valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
3223
3224 if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer)setjmp( *(jmp_buf*) &(( (FT_Validator)( &valid ) )->
jump_buffer) )
== 0 )
3225 {
3226 /* validate this cmap sub-table */
3227 error = clazz->validate( cmap, FT_VALIDATOR( &valid )( (FT_Validator)( &valid ) ) );
3228 }
3229
3230 if ( !valid.validator.error )
3231 {
3232 FT_CMap ttcmap;
3233
3234
3235 /* It might make sense to store the single variation */
3236 /* selector cmap somewhere special. But it would have to be */
3237 /* in the public FT_FaceRec, and we can't change that. */
3238
3239 if ( !FT_CMap_New( (FT_CMap_Class)clazz,
3240 cmap, &charmap, &ttcmap ) )
3241 {
3242 /* it is simpler to directly set `flags' than adding */
3243 /* a parameter to FT_CMap_New */
3244 ((TT_CMap)ttcmap)->flags = (FT_Int)error;
3245 }
3246 }
3247 else
3248 {
3249 FT_TRACE0(( "tt_face_build_cmaps:"do { } while ( 0 )
3250 " broken cmap sub-table ignored\n" ))do { } while ( 0 );
3251 }
3252 break;
3253 }
3254 }
3255
3256 if ( !*pclazz )
3257 {
3258 FT_TRACE0(( "tt_face_build_cmaps:"do { } while ( 0 )
3259 " unsupported cmap sub-table ignored\n" ))do { } while ( 0 );
3260 }
3261 }
3262 }
3263
3264 return FT_Err_Ok;
3265 }
3266
3267
3268 FT_LOCAL( FT_Error )static FT_Error
3269 tt_get_cmap_info( FT_CharMap charmap,
3270 TT_CMapInfo *cmap_info )
3271 {
3272 FT_CMap cmap = (FT_CMap)charmap;
3273 TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz;
3274
3275 if ( clazz->get_cmap_info )
3276 return clazz->get_cmap_info( charmap, cmap_info );
3277 else
3278 return FT_THROW( Invalid_CharMap_Format )SFNT_Err_Invalid_CharMap_Format;
3279 }
3280
3281
3282/* END */