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