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