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