OLD | NEW |
| (Empty) |
1 /***************************************************************************/ | |
2 /* */ | |
3 /* cffload.c */ | |
4 /* */ | |
5 /* OpenType and CFF data/program tables loader (body). */ | |
6 /* */ | |
7 /* Copyright 1996-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 #include "../../include/freetype/internal/ftobjs.h" | |
22 #include "../../include/freetype/internal/ftstream.h" | |
23 #include "../../include/freetype/tttags.h" | |
24 #include "../../include/freetype/t1tables.h" | |
25 | |
26 #include "cffload.h" | |
27 #include "cffparse.h" | |
28 | |
29 #include "cfferrs.h" | |
30 | |
31 | |
32 #if 1 | |
33 | |
34 static const FT_UShort cff_isoadobe_charset[229] = | |
35 { | |
36 0, 1, 2, 3, 4, 5, 6, 7, | |
37 8, 9, 10, 11, 12, 13, 14, 15, | |
38 16, 17, 18, 19, 20, 21, 22, 23, | |
39 24, 25, 26, 27, 28, 29, 30, 31, | |
40 32, 33, 34, 35, 36, 37, 38, 39, | |
41 40, 41, 42, 43, 44, 45, 46, 47, | |
42 48, 49, 50, 51, 52, 53, 54, 55, | |
43 56, 57, 58, 59, 60, 61, 62, 63, | |
44 64, 65, 66, 67, 68, 69, 70, 71, | |
45 72, 73, 74, 75, 76, 77, 78, 79, | |
46 80, 81, 82, 83, 84, 85, 86, 87, | |
47 88, 89, 90, 91, 92, 93, 94, 95, | |
48 96, 97, 98, 99, 100, 101, 102, 103, | |
49 104, 105, 106, 107, 108, 109, 110, 111, | |
50 112, 113, 114, 115, 116, 117, 118, 119, | |
51 120, 121, 122, 123, 124, 125, 126, 127, | |
52 128, 129, 130, 131, 132, 133, 134, 135, | |
53 136, 137, 138, 139, 140, 141, 142, 143, | |
54 144, 145, 146, 147, 148, 149, 150, 151, | |
55 152, 153, 154, 155, 156, 157, 158, 159, | |
56 160, 161, 162, 163, 164, 165, 166, 167, | |
57 168, 169, 170, 171, 172, 173, 174, 175, | |
58 176, 177, 178, 179, 180, 181, 182, 183, | |
59 184, 185, 186, 187, 188, 189, 190, 191, | |
60 192, 193, 194, 195, 196, 197, 198, 199, | |
61 200, 201, 202, 203, 204, 205, 206, 207, | |
62 208, 209, 210, 211, 212, 213, 214, 215, | |
63 216, 217, 218, 219, 220, 221, 222, 223, | |
64 224, 225, 226, 227, 228 | |
65 }; | |
66 | |
67 static const FT_UShort cff_expert_charset[166] = | |
68 { | |
69 0, 1, 229, 230, 231, 232, 233, 234, | |
70 235, 236, 237, 238, 13, 14, 15, 99, | |
71 239, 240, 241, 242, 243, 244, 245, 246, | |
72 247, 248, 27, 28, 249, 250, 251, 252, | |
73 253, 254, 255, 256, 257, 258, 259, 260, | |
74 261, 262, 263, 264, 265, 266, 109, 110, | |
75 267, 268, 269, 270, 271, 272, 273, 274, | |
76 275, 276, 277, 278, 279, 280, 281, 282, | |
77 283, 284, 285, 286, 287, 288, 289, 290, | |
78 291, 292, 293, 294, 295, 296, 297, 298, | |
79 299, 300, 301, 302, 303, 304, 305, 306, | |
80 307, 308, 309, 310, 311, 312, 313, 314, | |
81 315, 316, 317, 318, 158, 155, 163, 319, | |
82 320, 321, 322, 323, 324, 325, 326, 150, | |
83 164, 169, 327, 328, 329, 330, 331, 332, | |
84 333, 334, 335, 336, 337, 338, 339, 340, | |
85 341, 342, 343, 344, 345, 346, 347, 348, | |
86 349, 350, 351, 352, 353, 354, 355, 356, | |
87 357, 358, 359, 360, 361, 362, 363, 364, | |
88 365, 366, 367, 368, 369, 370, 371, 372, | |
89 373, 374, 375, 376, 377, 378 | |
90 }; | |
91 | |
92 static const FT_UShort cff_expertsubset_charset[87] = | |
93 { | |
94 0, 1, 231, 232, 235, 236, 237, 238, | |
95 13, 14, 15, 99, 239, 240, 241, 242, | |
96 243, 244, 245, 246, 247, 248, 27, 28, | |
97 249, 250, 251, 253, 254, 255, 256, 257, | |
98 258, 259, 260, 261, 262, 263, 264, 265, | |
99 266, 109, 110, 267, 268, 269, 270, 272, | |
100 300, 301, 302, 305, 314, 315, 158, 155, | |
101 163, 320, 321, 322, 323, 324, 325, 326, | |
102 150, 164, 169, 327, 328, 329, 330, 331, | |
103 332, 333, 334, 335, 336, 337, 338, 339, | |
104 340, 341, 342, 343, 344, 345, 346 | |
105 }; | |
106 | |
107 static const FT_UShort cff_standard_encoding[256] = | |
108 { | |
109 0, 0, 0, 0, 0, 0, 0, 0, | |
110 0, 0, 0, 0, 0, 0, 0, 0, | |
111 0, 0, 0, 0, 0, 0, 0, 0, | |
112 0, 0, 0, 0, 0, 0, 0, 0, | |
113 1, 2, 3, 4, 5, 6, 7, 8, | |
114 9, 10, 11, 12, 13, 14, 15, 16, | |
115 17, 18, 19, 20, 21, 22, 23, 24, | |
116 25, 26, 27, 28, 29, 30, 31, 32, | |
117 33, 34, 35, 36, 37, 38, 39, 40, | |
118 41, 42, 43, 44, 45, 46, 47, 48, | |
119 49, 50, 51, 52, 53, 54, 55, 56, | |
120 57, 58, 59, 60, 61, 62, 63, 64, | |
121 65, 66, 67, 68, 69, 70, 71, 72, | |
122 73, 74, 75, 76, 77, 78, 79, 80, | |
123 81, 82, 83, 84, 85, 86, 87, 88, | |
124 89, 90, 91, 92, 93, 94, 95, 0, | |
125 0, 0, 0, 0, 0, 0, 0, 0, | |
126 0, 0, 0, 0, 0, 0, 0, 0, | |
127 0, 0, 0, 0, 0, 0, 0, 0, | |
128 0, 0, 0, 0, 0, 0, 0, 0, | |
129 0, 96, 97, 98, 99, 100, 101, 102, | |
130 103, 104, 105, 106, 107, 108, 109, 110, | |
131 0, 111, 112, 113, 114, 0, 115, 116, | |
132 117, 118, 119, 120, 121, 122, 0, 123, | |
133 0, 124, 125, 126, 127, 128, 129, 130, | |
134 131, 0, 132, 133, 0, 134, 135, 136, | |
135 137, 0, 0, 0, 0, 0, 0, 0, | |
136 0, 0, 0, 0, 0, 0, 0, 0, | |
137 0, 138, 0, 139, 0, 0, 0, 0, | |
138 140, 141, 142, 143, 0, 0, 0, 0, | |
139 0, 144, 0, 0, 0, 145, 0, 0, | |
140 146, 147, 148, 149, 0, 0, 0, 0 | |
141 }; | |
142 | |
143 static const FT_UShort cff_expert_encoding[256] = | |
144 { | |
145 0, 0, 0, 0, 0, 0, 0, 0, | |
146 0, 0, 0, 0, 0, 0, 0, 0, | |
147 0, 0, 0, 0, 0, 0, 0, 0, | |
148 0, 0, 0, 0, 0, 0, 0, 0, | |
149 1, 229, 230, 0, 231, 232, 233, 234, | |
150 235, 236, 237, 238, 13, 14, 15, 99, | |
151 239, 240, 241, 242, 243, 244, 245, 246, | |
152 247, 248, 27, 28, 249, 250, 251, 252, | |
153 0, 253, 254, 255, 256, 257, 0, 0, | |
154 0, 258, 0, 0, 259, 260, 261, 262, | |
155 0, 0, 263, 264, 265, 0, 266, 109, | |
156 110, 267, 268, 269, 0, 270, 271, 272, | |
157 273, 274, 275, 276, 277, 278, 279, 280, | |
158 281, 282, 283, 284, 285, 286, 287, 288, | |
159 289, 290, 291, 292, 293, 294, 295, 296, | |
160 297, 298, 299, 300, 301, 302, 303, 0, | |
161 0, 0, 0, 0, 0, 0, 0, 0, | |
162 0, 0, 0, 0, 0, 0, 0, 0, | |
163 0, 0, 0, 0, 0, 0, 0, 0, | |
164 0, 0, 0, 0, 0, 0, 0, 0, | |
165 0, 304, 305, 306, 0, 0, 307, 308, | |
166 309, 310, 311, 0, 312, 0, 0, 312, | |
167 0, 0, 314, 315, 0, 0, 316, 317, | |
168 318, 0, 0, 0, 158, 155, 163, 319, | |
169 320, 321, 322, 323, 324, 325, 0, 0, | |
170 326, 150, 164, 169, 327, 328, 329, 330, | |
171 331, 332, 333, 334, 335, 336, 337, 338, | |
172 339, 340, 341, 342, 343, 344, 345, 346, | |
173 347, 348, 349, 350, 351, 352, 353, 354, | |
174 355, 356, 357, 358, 359, 360, 361, 362, | |
175 363, 364, 365, 366, 367, 368, 369, 370, | |
176 371, 372, 373, 374, 375, 376, 377, 378 | |
177 }; | |
178 | |
179 #endif /* 1 */ | |
180 | |
181 | |
182 FT_LOCAL_DEF( FT_UShort ) | |
183 cff_get_standard_encoding( FT_UInt charcode ) | |
184 { | |
185 return (FT_UShort)( charcode < 256 ? cff_standard_encoding[charcode] | |
186 : 0 ); | |
187 } | |
188 | |
189 | |
190 /*************************************************************************/ | |
191 /* */ | |
192 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ | |
193 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ | |
194 /* messages during execution. */ | |
195 /* */ | |
196 #undef FT_COMPONENT | |
197 #define FT_COMPONENT trace_cffload | |
198 | |
199 | |
200 /* read an offset from the index's stream current position */ | |
201 static FT_ULong | |
202 cff_index_read_offset( CFF_Index idx, | |
203 FT_Error *errorp ) | |
204 { | |
205 FT_Error error; | |
206 FT_Stream stream = idx->stream; | |
207 FT_Byte tmp[4]; | |
208 FT_ULong result = 0; | |
209 | |
210 | |
211 if ( !FT_STREAM_READ( tmp, idx->off_size ) ) | |
212 { | |
213 FT_Int nn; | |
214 | |
215 | |
216 for ( nn = 0; nn < idx->off_size; nn++ ) | |
217 result = ( result << 8 ) | tmp[nn]; | |
218 } | |
219 | |
220 *errorp = error; | |
221 return result; | |
222 } | |
223 | |
224 | |
225 static FT_Error | |
226 cff_index_init( CFF_Index idx, | |
227 FT_Stream stream, | |
228 FT_Bool load ) | |
229 { | |
230 FT_Error error; | |
231 FT_Memory memory = stream->memory; | |
232 FT_UShort count; | |
233 | |
234 | |
235 FT_MEM_ZERO( idx, sizeof ( *idx ) ); | |
236 | |
237 idx->stream = stream; | |
238 idx->start = FT_STREAM_POS(); | |
239 if ( !FT_READ_USHORT( count ) && | |
240 count > 0 ) | |
241 { | |
242 FT_Byte offsize; | |
243 FT_ULong size; | |
244 | |
245 | |
246 /* there is at least one element; read the offset size, */ | |
247 /* then access the offset table to compute the index's total size */ | |
248 if ( FT_READ_BYTE( offsize ) ) | |
249 goto Exit; | |
250 | |
251 if ( offsize < 1 || offsize > 4 ) | |
252 { | |
253 error = FT_THROW( Invalid_Table ); | |
254 goto Exit; | |
255 } | |
256 | |
257 idx->count = count; | |
258 idx->off_size = offsize; | |
259 size = (FT_ULong)( count + 1 ) * offsize; | |
260 | |
261 idx->data_offset = idx->start + 3 + size; | |
262 | |
263 if ( FT_STREAM_SKIP( size - offsize ) ) | |
264 goto Exit; | |
265 | |
266 size = cff_index_read_offset( idx, &error ); | |
267 if ( error ) | |
268 goto Exit; | |
269 | |
270 if ( size == 0 ) | |
271 { | |
272 error = FT_THROW( Invalid_Table ); | |
273 goto Exit; | |
274 } | |
275 | |
276 idx->data_size = --size; | |
277 | |
278 if ( load ) | |
279 { | |
280 /* load the data */ | |
281 if ( FT_FRAME_EXTRACT( size, idx->bytes ) ) | |
282 goto Exit; | |
283 } | |
284 else | |
285 { | |
286 /* skip the data */ | |
287 if ( FT_STREAM_SKIP( size ) ) | |
288 goto Exit; | |
289 } | |
290 } | |
291 | |
292 Exit: | |
293 if ( error ) | |
294 FT_FREE( idx->offsets ); | |
295 | |
296 return error; | |
297 } | |
298 | |
299 | |
300 static void | |
301 cff_index_done( CFF_Index idx ) | |
302 { | |
303 if ( idx->stream ) | |
304 { | |
305 FT_Stream stream = idx->stream; | |
306 FT_Memory memory = stream->memory; | |
307 | |
308 | |
309 if ( idx->bytes ) | |
310 FT_FRAME_RELEASE( idx->bytes ); | |
311 | |
312 FT_FREE( idx->offsets ); | |
313 FT_MEM_ZERO( idx, sizeof ( *idx ) ); | |
314 } | |
315 } | |
316 | |
317 | |
318 static FT_Error | |
319 cff_index_load_offsets( CFF_Index idx ) | |
320 { | |
321 FT_Error error = FT_Err_Ok; | |
322 FT_Stream stream = idx->stream; | |
323 FT_Memory memory = stream->memory; | |
324 | |
325 | |
326 if ( idx->count > 0 && idx->offsets == NULL ) | |
327 { | |
328 FT_Byte offsize = idx->off_size; | |
329 FT_ULong data_size; | |
330 FT_Byte* p; | |
331 FT_Byte* p_end; | |
332 FT_ULong* poff; | |
333 | |
334 | |
335 data_size = (FT_ULong)( idx->count + 1 ) * offsize; | |
336 | |
337 if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) || | |
338 FT_STREAM_SEEK( idx->start + 3 ) || | |
339 FT_FRAME_ENTER( data_size ) ) | |
340 goto Exit; | |
341 | |
342 poff = idx->offsets; | |
343 p = (FT_Byte*)stream->cursor; | |
344 p_end = p + data_size; | |
345 | |
346 switch ( offsize ) | |
347 { | |
348 case 1: | |
349 for ( ; p < p_end; p++, poff++ ) | |
350 poff[0] = p[0]; | |
351 break; | |
352 | |
353 case 2: | |
354 for ( ; p < p_end; p += 2, poff++ ) | |
355 poff[0] = FT_PEEK_USHORT( p ); | |
356 break; | |
357 | |
358 case 3: | |
359 for ( ; p < p_end; p += 3, poff++ ) | |
360 poff[0] = FT_PEEK_OFF3( p ); | |
361 break; | |
362 | |
363 default: | |
364 for ( ; p < p_end; p += 4, poff++ ) | |
365 poff[0] = FT_PEEK_ULONG( p ); | |
366 } | |
367 | |
368 FT_FRAME_EXIT(); | |
369 } | |
370 | |
371 Exit: | |
372 if ( error ) | |
373 FT_FREE( idx->offsets ); | |
374 | |
375 return error; | |
376 } | |
377 | |
378 | |
379 /* Allocate a table containing pointers to an index's elements. */ | |
380 /* The `pool' argument makes this function convert the index */ | |
381 /* entries to C-style strings (this is, NULL-terminated). */ | |
382 static FT_Error | |
383 cff_index_get_pointers( CFF_Index idx, | |
384 FT_Byte*** table, | |
385 FT_Byte** pool ) | |
386 { | |
387 FT_Error error = FT_Err_Ok; | |
388 FT_Memory memory = idx->stream->memory; | |
389 | |
390 FT_Byte** t = NULL; | |
391 FT_Byte* new_bytes = NULL; | |
392 | |
393 | |
394 *table = NULL; | |
395 | |
396 if ( idx->offsets == NULL ) | |
397 { | |
398 error = cff_index_load_offsets( idx ); | |
399 if ( error ) | |
400 goto Exit; | |
401 } | |
402 | |
403 if ( idx->count > 0 && | |
404 !FT_NEW_ARRAY( t, idx->count + 1 ) && | |
405 ( !pool || !FT_ALLOC( new_bytes, | |
406 idx->data_size + idx->count ) ) ) | |
407 { | |
408 FT_ULong n, cur_offset; | |
409 FT_ULong extra = 0; | |
410 FT_Byte* org_bytes = idx->bytes; | |
411 | |
412 | |
413 /* at this point, `idx->offsets' can't be NULL */ | |
414 cur_offset = idx->offsets[0] - 1; | |
415 | |
416 /* sanity check */ | |
417 if ( cur_offset >= idx->data_size ) | |
418 { | |
419 FT_TRACE0(( "cff_index_get_pointers:" | |
420 " invalid first offset value %d set to zero\n", | |
421 cur_offset )); | |
422 cur_offset = 0; | |
423 } | |
424 | |
425 if ( !pool ) | |
426 t[0] = org_bytes + cur_offset; | |
427 else | |
428 t[0] = new_bytes + cur_offset; | |
429 | |
430 for ( n = 1; n <= idx->count; n++ ) | |
431 { | |
432 FT_ULong next_offset = idx->offsets[n] - 1; | |
433 | |
434 | |
435 /* empty slot + two sanity checks for invalid offset tables */ | |
436 if ( next_offset == 0 || | |
437 next_offset < cur_offset || | |
438 ( next_offset >= idx->data_size && n < idx->count ) ) | |
439 next_offset = cur_offset; | |
440 | |
441 if ( !pool ) | |
442 t[n] = org_bytes + next_offset; | |
443 else | |
444 { | |
445 t[n] = new_bytes + next_offset + extra; | |
446 | |
447 if ( next_offset != cur_offset ) | |
448 { | |
449 FT_MEM_COPY( t[n - 1], org_bytes + cur_offset, t[n] - t[n - 1] ); | |
450 t[n][0] = '\0'; | |
451 t[n] += 1; | |
452 extra++; | |
453 } | |
454 } | |
455 | |
456 cur_offset = next_offset; | |
457 } | |
458 *table = t; | |
459 | |
460 if ( pool ) | |
461 *pool = new_bytes; | |
462 } | |
463 | |
464 Exit: | |
465 return error; | |
466 } | |
467 | |
468 | |
469 FT_LOCAL_DEF( FT_Error ) | |
470 cff_index_access_element( CFF_Index idx, | |
471 FT_UInt element, | |
472 FT_Byte** pbytes, | |
473 FT_ULong* pbyte_len ) | |
474 { | |
475 FT_Error error = FT_Err_Ok; | |
476 | |
477 | |
478 if ( idx && idx->count > element ) | |
479 { | |
480 /* compute start and end offsets */ | |
481 FT_Stream stream = idx->stream; | |
482 FT_ULong off1, off2 = 0; | |
483 | |
484 | |
485 /* load offsets from file or the offset table */ | |
486 if ( !idx->offsets ) | |
487 { | |
488 FT_ULong pos = element * idx->off_size; | |
489 | |
490 | |
491 if ( FT_STREAM_SEEK( idx->start + 3 + pos ) ) | |
492 goto Exit; | |
493 | |
494 off1 = cff_index_read_offset( idx, &error ); | |
495 if ( error ) | |
496 goto Exit; | |
497 | |
498 if ( off1 != 0 ) | |
499 { | |
500 do | |
501 { | |
502 element++; | |
503 off2 = cff_index_read_offset( idx, &error ); | |
504 } | |
505 while ( off2 == 0 && element < idx->count ); | |
506 } | |
507 } | |
508 else /* use offsets table */ | |
509 { | |
510 off1 = idx->offsets[element]; | |
511 if ( off1 ) | |
512 { | |
513 do | |
514 { | |
515 element++; | |
516 off2 = idx->offsets[element]; | |
517 | |
518 } while ( off2 == 0 && element < idx->count ); | |
519 } | |
520 } | |
521 | |
522 /* XXX: should check off2 does not exceed the end of this entry; */ | |
523 /* at present, only truncate off2 at the end of this stream */ | |
524 if ( off2 > stream->size + 1 || | |
525 idx->data_offset > stream->size - off2 + 1 ) | |
526 { | |
527 FT_ERROR(( "cff_index_access_element:" | |
528 " offset to next entry (%d)" | |
529 " exceeds the end of stream (%d)\n", | |
530 off2, stream->size - idx->data_offset + 1 )); | |
531 off2 = stream->size - idx->data_offset + 1; | |
532 } | |
533 | |
534 /* access element */ | |
535 if ( off1 && off2 > off1 ) | |
536 { | |
537 *pbyte_len = off2 - off1; | |
538 | |
539 if ( idx->bytes ) | |
540 { | |
541 /* this index was completely loaded in memory, that's easy */ | |
542 *pbytes = idx->bytes + off1 - 1; | |
543 } | |
544 else | |
545 { | |
546 /* this index is still on disk/file, access it through a frame */ | |
547 if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) || | |
548 FT_FRAME_EXTRACT( off2 - off1, *pbytes ) ) | |
549 goto Exit; | |
550 } | |
551 } | |
552 else | |
553 { | |
554 /* empty index element */ | |
555 *pbytes = 0; | |
556 *pbyte_len = 0; | |
557 } | |
558 } | |
559 else | |
560 error = FT_THROW( Invalid_Argument ); | |
561 | |
562 Exit: | |
563 return error; | |
564 } | |
565 | |
566 | |
567 FT_LOCAL_DEF( void ) | |
568 cff_index_forget_element( CFF_Index idx, | |
569 FT_Byte** pbytes ) | |
570 { | |
571 if ( idx->bytes == 0 ) | |
572 { | |
573 FT_Stream stream = idx->stream; | |
574 | |
575 | |
576 FT_FRAME_RELEASE( *pbytes ); | |
577 } | |
578 } | |
579 | |
580 | |
581 /* get an entry from Name INDEX */ | |
582 FT_LOCAL_DEF( FT_String* ) | |
583 cff_index_get_name( CFF_Font font, | |
584 FT_UInt element ) | |
585 { | |
586 CFF_Index idx = &font->name_index; | |
587 FT_Memory memory = idx->stream->memory; | |
588 FT_Byte* bytes; | |
589 FT_ULong byte_len; | |
590 FT_Error error; | |
591 FT_String* name = 0; | |
592 | |
593 | |
594 error = cff_index_access_element( idx, element, &bytes, &byte_len ); | |
595 if ( error ) | |
596 goto Exit; | |
597 | |
598 if ( !FT_ALLOC( name, byte_len + 1 ) ) | |
599 { | |
600 FT_MEM_COPY( name, bytes, byte_len ); | |
601 name[byte_len] = 0; | |
602 } | |
603 cff_index_forget_element( idx, &bytes ); | |
604 | |
605 Exit: | |
606 return name; | |
607 } | |
608 | |
609 | |
610 /* get an entry from String INDEX */ | |
611 FT_LOCAL_DEF( FT_String* ) | |
612 cff_index_get_string( CFF_Font font, | |
613 FT_UInt element ) | |
614 { | |
615 return ( element < font->num_strings ) | |
616 ? (FT_String*)font->strings[element] | |
617 : NULL; | |
618 } | |
619 | |
620 | |
621 FT_LOCAL_DEF( FT_String* ) | |
622 cff_index_get_sid_string( CFF_Font font, | |
623 FT_UInt sid ) | |
624 { | |
625 /* value 0xFFFFU indicates a missing dictionary entry */ | |
626 if ( sid == 0xFFFFU ) | |
627 return NULL; | |
628 | |
629 /* if it is not a standard string, return it */ | |
630 if ( sid > 390 ) | |
631 return cff_index_get_string( font, sid - 391 ); | |
632 | |
633 /* CID-keyed CFF fonts don't have glyph names */ | |
634 if ( !font->psnames ) | |
635 return NULL; | |
636 | |
637 /* this is a standard string */ | |
638 return (FT_String *)font->psnames->adobe_std_strings( sid ); | |
639 } | |
640 | |
641 | |
642 /*************************************************************************/ | |
643 /*************************************************************************/ | |
644 /*** ***/ | |
645 /*** FD Select table support ***/ | |
646 /*** ***/ | |
647 /*************************************************************************/ | |
648 /*************************************************************************/ | |
649 | |
650 | |
651 static void | |
652 CFF_Done_FD_Select( CFF_FDSelect fdselect, | |
653 FT_Stream stream ) | |
654 { | |
655 if ( fdselect->data ) | |
656 FT_FRAME_RELEASE( fdselect->data ); | |
657 | |
658 fdselect->data_size = 0; | |
659 fdselect->format = 0; | |
660 fdselect->range_count = 0; | |
661 } | |
662 | |
663 | |
664 static FT_Error | |
665 CFF_Load_FD_Select( CFF_FDSelect fdselect, | |
666 FT_UInt num_glyphs, | |
667 FT_Stream stream, | |
668 FT_ULong offset ) | |
669 { | |
670 FT_Error error; | |
671 FT_Byte format; | |
672 FT_UInt num_ranges; | |
673 | |
674 | |
675 /* read format */ | |
676 if ( FT_STREAM_SEEK( offset ) || FT_READ_BYTE( format ) ) | |
677 goto Exit; | |
678 | |
679 fdselect->format = format; | |
680 fdselect->cache_count = 0; /* clear cache */ | |
681 | |
682 switch ( format ) | |
683 { | |
684 case 0: /* format 0, that's simple */ | |
685 fdselect->data_size = num_glyphs; | |
686 goto Load_Data; | |
687 | |
688 case 3: /* format 3, a tad more complex */ | |
689 if ( FT_READ_USHORT( num_ranges ) ) | |
690 goto Exit; | |
691 | |
692 fdselect->data_size = num_ranges * 3 + 2; | |
693 | |
694 Load_Data: | |
695 if ( FT_FRAME_EXTRACT( fdselect->data_size, fdselect->data ) ) | |
696 goto Exit; | |
697 break; | |
698 | |
699 default: /* hmm... that's wrong */ | |
700 error = FT_THROW( Invalid_File_Format ); | |
701 } | |
702 | |
703 Exit: | |
704 return error; | |
705 } | |
706 | |
707 | |
708 FT_LOCAL_DEF( FT_Byte ) | |
709 cff_fd_select_get( CFF_FDSelect fdselect, | |
710 FT_UInt glyph_index ) | |
711 { | |
712 FT_Byte fd = 0; | |
713 | |
714 | |
715 switch ( fdselect->format ) | |
716 { | |
717 case 0: | |
718 fd = fdselect->data[glyph_index]; | |
719 break; | |
720 | |
721 case 3: | |
722 /* first, compare to cache */ | |
723 if ( (FT_UInt)( glyph_index - fdselect->cache_first ) < | |
724 fdselect->cache_count ) | |
725 { | |
726 fd = fdselect->cache_fd; | |
727 break; | |
728 } | |
729 | |
730 /* then, lookup the ranges array */ | |
731 { | |
732 FT_Byte* p = fdselect->data; | |
733 FT_Byte* p_limit = p + fdselect->data_size; | |
734 FT_Byte fd2; | |
735 FT_UInt first, limit; | |
736 | |
737 | |
738 first = FT_NEXT_USHORT( p ); | |
739 do | |
740 { | |
741 if ( glyph_index < first ) | |
742 break; | |
743 | |
744 fd2 = *p++; | |
745 limit = FT_NEXT_USHORT( p ); | |
746 | |
747 if ( glyph_index < limit ) | |
748 { | |
749 fd = fd2; | |
750 | |
751 /* update cache */ | |
752 fdselect->cache_first = first; | |
753 fdselect->cache_count = limit-first; | |
754 fdselect->cache_fd = fd2; | |
755 break; | |
756 } | |
757 first = limit; | |
758 | |
759 } while ( p < p_limit ); | |
760 } | |
761 break; | |
762 | |
763 default: | |
764 ; | |
765 } | |
766 | |
767 return fd; | |
768 } | |
769 | |
770 | |
771 /*************************************************************************/ | |
772 /*************************************************************************/ | |
773 /*** ***/ | |
774 /*** CFF font support ***/ | |
775 /*** ***/ | |
776 /*************************************************************************/ | |
777 /*************************************************************************/ | |
778 | |
779 static FT_Error | |
780 cff_charset_compute_cids( CFF_Charset charset, | |
781 FT_UInt num_glyphs, | |
782 FT_Memory memory ) | |
783 { | |
784 FT_Error error = FT_Err_Ok; | |
785 FT_UInt i; | |
786 FT_Long j; | |
787 FT_UShort max_cid = 0; | |
788 | |
789 | |
790 if ( charset->max_cid > 0 ) | |
791 goto Exit; | |
792 | |
793 for ( i = 0; i < num_glyphs; i++ ) | |
794 { | |
795 if ( charset->sids[i] > max_cid ) | |
796 max_cid = charset->sids[i]; | |
797 } | |
798 | |
799 if ( FT_NEW_ARRAY( charset->cids, (FT_ULong)max_cid + 1 ) ) | |
800 goto Exit; | |
801 | |
802 /* When multiple GIDs map to the same CID, we choose the lowest */ | |
803 /* GID. This is not described in any spec, but it matches the */ | |
804 /* behaviour of recent Acroread versions. */ | |
805 for ( j = num_glyphs - 1; j >= 0 ; j-- ) | |
806 charset->cids[charset->sids[j]] = (FT_UShort)j; | |
807 | |
808 charset->max_cid = max_cid; | |
809 charset->num_glyphs = num_glyphs; | |
810 | |
811 Exit: | |
812 return error; | |
813 } | |
814 | |
815 | |
816 FT_LOCAL_DEF( FT_UInt ) | |
817 cff_charset_cid_to_gindex( CFF_Charset charset, | |
818 FT_UInt cid ) | |
819 { | |
820 FT_UInt result = 0; | |
821 | |
822 | |
823 if ( cid <= charset->max_cid ) | |
824 result = charset->cids[cid]; | |
825 | |
826 return result; | |
827 } | |
828 | |
829 | |
830 static void | |
831 cff_charset_free_cids( CFF_Charset charset, | |
832 FT_Memory memory ) | |
833 { | |
834 FT_FREE( charset->cids ); | |
835 charset->max_cid = 0; | |
836 } | |
837 | |
838 | |
839 static void | |
840 cff_charset_done( CFF_Charset charset, | |
841 FT_Stream stream ) | |
842 { | |
843 FT_Memory memory = stream->memory; | |
844 | |
845 | |
846 cff_charset_free_cids( charset, memory ); | |
847 | |
848 FT_FREE( charset->sids ); | |
849 charset->format = 0; | |
850 charset->offset = 0; | |
851 } | |
852 | |
853 | |
854 static FT_Error | |
855 cff_charset_load( CFF_Charset charset, | |
856 FT_UInt num_glyphs, | |
857 FT_Stream stream, | |
858 FT_ULong base_offset, | |
859 FT_ULong offset, | |
860 FT_Bool invert ) | |
861 { | |
862 FT_Memory memory = stream->memory; | |
863 FT_Error error = FT_Err_Ok; | |
864 FT_UShort glyph_sid; | |
865 | |
866 | |
867 /* If the the offset is greater than 2, we have to parse the */ | |
868 /* charset table. */ | |
869 if ( offset > 2 ) | |
870 { | |
871 FT_UInt j; | |
872 | |
873 | |
874 charset->offset = base_offset + offset; | |
875 | |
876 /* Get the format of the table. */ | |
877 if ( FT_STREAM_SEEK( charset->offset ) || | |
878 FT_READ_BYTE( charset->format ) ) | |
879 goto Exit; | |
880 | |
881 /* Allocate memory for sids. */ | |
882 if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) | |
883 goto Exit; | |
884 | |
885 /* assign the .notdef glyph */ | |
886 charset->sids[0] = 0; | |
887 | |
888 switch ( charset->format ) | |
889 { | |
890 case 0: | |
891 if ( num_glyphs > 0 ) | |
892 { | |
893 if ( FT_FRAME_ENTER( ( num_glyphs - 1 ) * 2 ) ) | |
894 goto Exit; | |
895 | |
896 for ( j = 1; j < num_glyphs; j++ ) | |
897 charset->sids[j] = FT_GET_USHORT(); | |
898 | |
899 FT_FRAME_EXIT(); | |
900 } | |
901 break; | |
902 | |
903 case 1: | |
904 case 2: | |
905 { | |
906 FT_UInt nleft; | |
907 FT_UInt i; | |
908 | |
909 | |
910 j = 1; | |
911 | |
912 while ( j < num_glyphs ) | |
913 { | |
914 /* Read the first glyph sid of the range. */ | |
915 if ( FT_READ_USHORT( glyph_sid ) ) | |
916 goto Exit; | |
917 | |
918 /* Read the number of glyphs in the range. */ | |
919 if ( charset->format == 2 ) | |
920 { | |
921 if ( FT_READ_USHORT( nleft ) ) | |
922 goto Exit; | |
923 } | |
924 else | |
925 { | |
926 if ( FT_READ_BYTE( nleft ) ) | |
927 goto Exit; | |
928 } | |
929 | |
930 /* try to rescue some of the SIDs if `nleft' is too large */ | |
931 if ( glyph_sid > 0xFFFFL - nleft ) | |
932 { | |
933 FT_ERROR(( "cff_charset_load: invalid SID range trimmed" | |
934 " nleft=%d -> %d\n", nleft, 0xFFFFL - glyph_sid )); | |
935 nleft = ( FT_UInt )( 0xFFFFL - glyph_sid ); | |
936 } | |
937 | |
938 /* Fill in the range of sids -- `nleft + 1' glyphs. */ | |
939 for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ ) | |
940 charset->sids[j] = glyph_sid; | |
941 } | |
942 } | |
943 break; | |
944 | |
945 default: | |
946 FT_ERROR(( "cff_charset_load: invalid table format\n" )); | |
947 error = FT_THROW( Invalid_File_Format ); | |
948 goto Exit; | |
949 } | |
950 } | |
951 else | |
952 { | |
953 /* Parse default tables corresponding to offset == 0, 1, or 2. */ | |
954 /* CFF specification intimates the following: */ | |
955 /* */ | |
956 /* In order to use a predefined charset, the following must be */ | |
957 /* true: The charset constructed for the glyphs in the font's */ | |
958 /* charstrings dictionary must match the predefined charset in */ | |
959 /* the first num_glyphs. */ | |
960 | |
961 charset->offset = offset; /* record charset type */ | |
962 | |
963 switch ( (FT_UInt)offset ) | |
964 { | |
965 case 0: | |
966 if ( num_glyphs > 229 ) | |
967 { | |
968 FT_ERROR(( "cff_charset_load: implicit charset larger than\n" | |
969 "predefined charset (Adobe ISO-Latin)\n" )); | |
970 error = FT_THROW( Invalid_File_Format ); | |
971 goto Exit; | |
972 } | |
973 | |
974 /* Allocate memory for sids. */ | |
975 if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) | |
976 goto Exit; | |
977 | |
978 /* Copy the predefined charset into the allocated memory. */ | |
979 FT_ARRAY_COPY( charset->sids, cff_isoadobe_charset, num_glyphs ); | |
980 | |
981 break; | |
982 | |
983 case 1: | |
984 if ( num_glyphs > 166 ) | |
985 { | |
986 FT_ERROR(( "cff_charset_load: implicit charset larger than\n" | |
987 "predefined charset (Adobe Expert)\n" )); | |
988 error = FT_THROW( Invalid_File_Format ); | |
989 goto Exit; | |
990 } | |
991 | |
992 /* Allocate memory for sids. */ | |
993 if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) | |
994 goto Exit; | |
995 | |
996 /* Copy the predefined charset into the allocated memory. */ | |
997 FT_ARRAY_COPY( charset->sids, cff_expert_charset, num_glyphs ); | |
998 | |
999 break; | |
1000 | |
1001 case 2: | |
1002 if ( num_glyphs > 87 ) | |
1003 { | |
1004 FT_ERROR(( "cff_charset_load: implicit charset larger than\n" | |
1005 "predefined charset (Adobe Expert Subset)\n" )); | |
1006 error = FT_THROW( Invalid_File_Format ); | |
1007 goto Exit; | |
1008 } | |
1009 | |
1010 /* Allocate memory for sids. */ | |
1011 if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) | |
1012 goto Exit; | |
1013 | |
1014 /* Copy the predefined charset into the allocated memory. */ | |
1015 FT_ARRAY_COPY( charset->sids, cff_expertsubset_charset, num_glyphs ); | |
1016 | |
1017 break; | |
1018 | |
1019 default: | |
1020 error = FT_THROW( Invalid_File_Format ); | |
1021 goto Exit; | |
1022 } | |
1023 } | |
1024 | |
1025 /* we have to invert the `sids' array for subsetted CID-keyed fonts */ | |
1026 if ( invert ) | |
1027 error = cff_charset_compute_cids( charset, num_glyphs, memory ); | |
1028 | |
1029 Exit: | |
1030 /* Clean up if there was an error. */ | |
1031 if ( error ) | |
1032 { | |
1033 FT_FREE( charset->sids ); | |
1034 FT_FREE( charset->cids ); | |
1035 charset->format = 0; | |
1036 charset->offset = 0; | |
1037 charset->sids = 0; | |
1038 } | |
1039 | |
1040 return error; | |
1041 } | |
1042 | |
1043 | |
1044 static void | |
1045 cff_encoding_done( CFF_Encoding encoding ) | |
1046 { | |
1047 encoding->format = 0; | |
1048 encoding->offset = 0; | |
1049 encoding->count = 0; | |
1050 } | |
1051 | |
1052 | |
1053 static FT_Error | |
1054 cff_encoding_load( CFF_Encoding encoding, | |
1055 CFF_Charset charset, | |
1056 FT_UInt num_glyphs, | |
1057 FT_Stream stream, | |
1058 FT_ULong base_offset, | |
1059 FT_ULong offset ) | |
1060 { | |
1061 FT_Error error = FT_Err_Ok; | |
1062 FT_UInt count; | |
1063 FT_UInt j; | |
1064 FT_UShort glyph_sid; | |
1065 FT_UInt glyph_code; | |
1066 | |
1067 | |
1068 /* Check for charset->sids. If we do not have this, we fail. */ | |
1069 if ( !charset->sids ) | |
1070 { | |
1071 error = FT_THROW( Invalid_File_Format ); | |
1072 goto Exit; | |
1073 } | |
1074 | |
1075 /* Zero out the code to gid/sid mappings. */ | |
1076 for ( j = 0; j < 256; j++ ) | |
1077 { | |
1078 encoding->sids [j] = 0; | |
1079 encoding->codes[j] = 0; | |
1080 } | |
1081 | |
1082 /* Note: The encoding table in a CFF font is indexed by glyph index; */ | |
1083 /* the first encoded glyph index is 1. Hence, we read the character */ | |
1084 /* code (`glyph_code') at index j and make the assignment: */ | |
1085 /* */ | |
1086 /* encoding->codes[glyph_code] = j + 1 */ | |
1087 /* */ | |
1088 /* We also make the assignment: */ | |
1089 /* */ | |
1090 /* encoding->sids[glyph_code] = charset->sids[j + 1] */ | |
1091 /* */ | |
1092 /* This gives us both a code to GID and a code to SID mapping. */ | |
1093 | |
1094 if ( offset > 1 ) | |
1095 { | |
1096 encoding->offset = base_offset + offset; | |
1097 | |
1098 /* we need to parse the table to determine its size */ | |
1099 if ( FT_STREAM_SEEK( encoding->offset ) || | |
1100 FT_READ_BYTE( encoding->format ) || | |
1101 FT_READ_BYTE( count ) ) | |
1102 goto Exit; | |
1103 | |
1104 switch ( encoding->format & 0x7F ) | |
1105 { | |
1106 case 0: | |
1107 { | |
1108 FT_Byte* p; | |
1109 | |
1110 | |
1111 /* By convention, GID 0 is always ".notdef" and is never */ | |
1112 /* coded in the font. Hence, the number of codes found */ | |
1113 /* in the table is `count+1'. */ | |
1114 /* */ | |
1115 encoding->count = count + 1; | |
1116 | |
1117 if ( FT_FRAME_ENTER( count ) ) | |
1118 goto Exit; | |
1119 | |
1120 p = (FT_Byte*)stream->cursor; | |
1121 | |
1122 for ( j = 1; j <= count; j++ ) | |
1123 { | |
1124 glyph_code = *p++; | |
1125 | |
1126 /* Make sure j is not too big. */ | |
1127 if ( j < num_glyphs ) | |
1128 { | |
1129 /* Assign code to GID mapping. */ | |
1130 encoding->codes[glyph_code] = (FT_UShort)j; | |
1131 | |
1132 /* Assign code to SID mapping. */ | |
1133 encoding->sids[glyph_code] = charset->sids[j]; | |
1134 } | |
1135 } | |
1136 | |
1137 FT_FRAME_EXIT(); | |
1138 } | |
1139 break; | |
1140 | |
1141 case 1: | |
1142 { | |
1143 FT_UInt nleft; | |
1144 FT_UInt i = 1; | |
1145 FT_UInt k; | |
1146 | |
1147 | |
1148 encoding->count = 0; | |
1149 | |
1150 /* Parse the Format1 ranges. */ | |
1151 for ( j = 0; j < count; j++, i += nleft ) | |
1152 { | |
1153 /* Read the first glyph code of the range. */ | |
1154 if ( FT_READ_BYTE( glyph_code ) ) | |
1155 goto Exit; | |
1156 | |
1157 /* Read the number of codes in the range. */ | |
1158 if ( FT_READ_BYTE( nleft ) ) | |
1159 goto Exit; | |
1160 | |
1161 /* Increment nleft, so we read `nleft + 1' codes/sids. */ | |
1162 nleft++; | |
1163 | |
1164 /* compute max number of character codes */ | |
1165 if ( (FT_UInt)nleft > encoding->count ) | |
1166 encoding->count = nleft; | |
1167 | |
1168 /* Fill in the range of codes/sids. */ | |
1169 for ( k = i; k < nleft + i; k++, glyph_code++ ) | |
1170 { | |
1171 /* Make sure k is not too big. */ | |
1172 if ( k < num_glyphs && glyph_code < 256 ) | |
1173 { | |
1174 /* Assign code to GID mapping. */ | |
1175 encoding->codes[glyph_code] = (FT_UShort)k; | |
1176 | |
1177 /* Assign code to SID mapping. */ | |
1178 encoding->sids[glyph_code] = charset->sids[k]; | |
1179 } | |
1180 } | |
1181 } | |
1182 | |
1183 /* simple check; one never knows what can be found in a font */ | |
1184 if ( encoding->count > 256 ) | |
1185 encoding->count = 256; | |
1186 } | |
1187 break; | |
1188 | |
1189 default: | |
1190 FT_ERROR(( "cff_encoding_load: invalid table format\n" )); | |
1191 error = FT_THROW( Invalid_File_Format ); | |
1192 goto Exit; | |
1193 } | |
1194 | |
1195 /* Parse supplemental encodings, if any. */ | |
1196 if ( encoding->format & 0x80 ) | |
1197 { | |
1198 FT_UInt gindex; | |
1199 | |
1200 | |
1201 /* count supplements */ | |
1202 if ( FT_READ_BYTE( count ) ) | |
1203 goto Exit; | |
1204 | |
1205 for ( j = 0; j < count; j++ ) | |
1206 { | |
1207 /* Read supplemental glyph code. */ | |
1208 if ( FT_READ_BYTE( glyph_code ) ) | |
1209 goto Exit; | |
1210 | |
1211 /* Read the SID associated with this glyph code. */ | |
1212 if ( FT_READ_USHORT( glyph_sid ) ) | |
1213 goto Exit; | |
1214 | |
1215 /* Assign code to SID mapping. */ | |
1216 encoding->sids[glyph_code] = glyph_sid; | |
1217 | |
1218 /* First, look up GID which has been assigned to */ | |
1219 /* SID glyph_sid. */ | |
1220 for ( gindex = 0; gindex < num_glyphs; gindex++ ) | |
1221 { | |
1222 if ( charset->sids[gindex] == glyph_sid ) | |
1223 { | |
1224 encoding->codes[glyph_code] = (FT_UShort)gindex; | |
1225 break; | |
1226 } | |
1227 } | |
1228 } | |
1229 } | |
1230 } | |
1231 else | |
1232 { | |
1233 /* We take into account the fact a CFF font can use a predefined */ | |
1234 /* encoding without containing all of the glyphs encoded by this */ | |
1235 /* encoding (see the note at the end of section 12 in the CFF */ | |
1236 /* specification). */ | |
1237 | |
1238 switch ( (FT_UInt)offset ) | |
1239 { | |
1240 case 0: | |
1241 /* First, copy the code to SID mapping. */ | |
1242 FT_ARRAY_COPY( encoding->sids, cff_standard_encoding, 256 ); | |
1243 goto Populate; | |
1244 | |
1245 case 1: | |
1246 /* First, copy the code to SID mapping. */ | |
1247 FT_ARRAY_COPY( encoding->sids, cff_expert_encoding, 256 ); | |
1248 | |
1249 Populate: | |
1250 /* Construct code to GID mapping from code to SID mapping */ | |
1251 /* and charset. */ | |
1252 | |
1253 encoding->count = 0; | |
1254 | |
1255 error = cff_charset_compute_cids( charset, num_glyphs, | |
1256 stream->memory ); | |
1257 if ( error ) | |
1258 goto Exit; | |
1259 | |
1260 for ( j = 0; j < 256; j++ ) | |
1261 { | |
1262 FT_UInt sid = encoding->sids[j]; | |
1263 FT_UInt gid = 0; | |
1264 | |
1265 | |
1266 if ( sid ) | |
1267 gid = cff_charset_cid_to_gindex( charset, sid ); | |
1268 | |
1269 if ( gid != 0 ) | |
1270 { | |
1271 encoding->codes[j] = (FT_UShort)gid; | |
1272 encoding->count = j + 1; | |
1273 } | |
1274 else | |
1275 { | |
1276 encoding->codes[j] = 0; | |
1277 encoding->sids [j] = 0; | |
1278 } | |
1279 } | |
1280 break; | |
1281 | |
1282 default: | |
1283 FT_ERROR(( "cff_encoding_load: invalid table format\n" )); | |
1284 error = FT_THROW( Invalid_File_Format ); | |
1285 goto Exit; | |
1286 } | |
1287 } | |
1288 | |
1289 Exit: | |
1290 | |
1291 /* Clean up if there was an error. */ | |
1292 return error; | |
1293 } | |
1294 | |
1295 | |
1296 static FT_Error | |
1297 cff_subfont_load( CFF_SubFont font, | |
1298 CFF_Index idx, | |
1299 FT_UInt font_index, | |
1300 FT_Stream stream, | |
1301 FT_ULong base_offset, | |
1302 FT_Library library ) | |
1303 { | |
1304 FT_Error error; | |
1305 CFF_ParserRec parser; | |
1306 FT_Byte* dict = NULL; | |
1307 FT_ULong dict_len; | |
1308 CFF_FontRecDict top = &font->font_dict; | |
1309 CFF_Private priv = &font->private_dict; | |
1310 | |
1311 | |
1312 cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict, library ); | |
1313 | |
1314 /* set defaults */ | |
1315 FT_MEM_ZERO( top, sizeof ( *top ) ); | |
1316 | |
1317 top->underline_position = -( 100L << 16 ); | |
1318 top->underline_thickness = 50L << 16; | |
1319 top->charstring_type = 2; | |
1320 top->font_matrix.xx = 0x10000L; | |
1321 top->font_matrix.yy = 0x10000L; | |
1322 top->cid_count = 8720; | |
1323 | |
1324 /* we use the implementation specific SID value 0xFFFF to indicate */ | |
1325 /* missing entries */ | |
1326 top->version = 0xFFFFU; | |
1327 top->notice = 0xFFFFU; | |
1328 top->copyright = 0xFFFFU; | |
1329 top->full_name = 0xFFFFU; | |
1330 top->family_name = 0xFFFFU; | |
1331 top->weight = 0xFFFFU; | |
1332 top->embedded_postscript = 0xFFFFU; | |
1333 | |
1334 top->cid_registry = 0xFFFFU; | |
1335 top->cid_ordering = 0xFFFFU; | |
1336 top->cid_font_name = 0xFFFFU; | |
1337 | |
1338 error = cff_index_access_element( idx, font_index, &dict, &dict_len ); | |
1339 if ( !error ) | |
1340 { | |
1341 FT_TRACE4(( " top dictionary:\n" )); | |
1342 error = cff_parser_run( &parser, dict, dict + dict_len ); | |
1343 } | |
1344 | |
1345 cff_index_forget_element( idx, &dict ); | |
1346 | |
1347 if ( error ) | |
1348 goto Exit; | |
1349 | |
1350 /* if it is a CID font, we stop there */ | |
1351 if ( top->cid_registry != 0xFFFFU ) | |
1352 goto Exit; | |
1353 | |
1354 /* parse the private dictionary, if any */ | |
1355 if ( top->private_offset && top->private_size ) | |
1356 { | |
1357 /* set defaults */ | |
1358 FT_MEM_ZERO( priv, sizeof ( *priv ) ); | |
1359 | |
1360 priv->blue_shift = 7; | |
1361 priv->blue_fuzz = 1; | |
1362 priv->lenIV = -1; | |
1363 priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L ); | |
1364 priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 ); | |
1365 | |
1366 cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library ); | |
1367 | |
1368 if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) || | |
1369 FT_FRAME_ENTER( font->font_dict.private_size ) ) | |
1370 goto Exit; | |
1371 | |
1372 FT_TRACE4(( " private dictionary:\n" )); | |
1373 error = cff_parser_run( &parser, | |
1374 (FT_Byte*)stream->cursor, | |
1375 (FT_Byte*)stream->limit ); | |
1376 FT_FRAME_EXIT(); | |
1377 if ( error ) | |
1378 goto Exit; | |
1379 | |
1380 /* ensure that `num_blue_values' is even */ | |
1381 priv->num_blue_values &= ~1; | |
1382 } | |
1383 | |
1384 /* read the local subrs, if any */ | |
1385 if ( priv->local_subrs_offset ) | |
1386 { | |
1387 if ( FT_STREAM_SEEK( base_offset + top->private_offset + | |
1388 priv->local_subrs_offset ) ) | |
1389 goto Exit; | |
1390 | |
1391 error = cff_index_init( &font->local_subrs_index, stream, 1 ); | |
1392 if ( error ) | |
1393 goto Exit; | |
1394 | |
1395 error = cff_index_get_pointers( &font->local_subrs_index, | |
1396 &font->local_subrs, NULL ); | |
1397 if ( error ) | |
1398 goto Exit; | |
1399 } | |
1400 | |
1401 Exit: | |
1402 return error; | |
1403 } | |
1404 | |
1405 | |
1406 static void | |
1407 cff_subfont_done( FT_Memory memory, | |
1408 CFF_SubFont subfont ) | |
1409 { | |
1410 if ( subfont ) | |
1411 { | |
1412 cff_index_done( &subfont->local_subrs_index ); | |
1413 FT_FREE( subfont->local_subrs ); | |
1414 } | |
1415 } | |
1416 | |
1417 | |
1418 FT_LOCAL_DEF( FT_Error ) | |
1419 cff_font_load( FT_Library library, | |
1420 FT_Stream stream, | |
1421 FT_Int face_index, | |
1422 CFF_Font font, | |
1423 FT_Bool pure_cff ) | |
1424 { | |
1425 static const FT_Frame_Field cff_header_fields[] = | |
1426 { | |
1427 #undef FT_STRUCTURE | |
1428 #define FT_STRUCTURE CFF_FontRec | |
1429 | |
1430 FT_FRAME_START( 4 ), | |
1431 FT_FRAME_BYTE( version_major ), | |
1432 FT_FRAME_BYTE( version_minor ), | |
1433 FT_FRAME_BYTE( header_size ), | |
1434 FT_FRAME_BYTE( absolute_offsize ), | |
1435 FT_FRAME_END | |
1436 }; | |
1437 | |
1438 FT_Error error; | |
1439 FT_Memory memory = stream->memory; | |
1440 FT_ULong base_offset; | |
1441 CFF_FontRecDict dict; | |
1442 CFF_IndexRec string_index; | |
1443 FT_Int subfont_index; | |
1444 | |
1445 | |
1446 FT_ZERO( font ); | |
1447 FT_ZERO( &string_index ); | |
1448 | |
1449 font->stream = stream; | |
1450 font->memory = memory; | |
1451 dict = &font->top_font.font_dict; | |
1452 base_offset = FT_STREAM_POS(); | |
1453 | |
1454 /* read CFF font header */ | |
1455 if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) ) | |
1456 goto Exit; | |
1457 | |
1458 /* check format */ | |
1459 if ( font->version_major != 1 || | |
1460 font->header_size < 4 || | |
1461 font->absolute_offsize > 4 ) | |
1462 { | |
1463 FT_TRACE2(( " not a CFF font header\n" )); | |
1464 error = FT_THROW( Unknown_File_Format ); | |
1465 goto Exit; | |
1466 } | |
1467 | |
1468 /* skip the rest of the header */ | |
1469 if ( FT_STREAM_SKIP( font->header_size - 4 ) ) | |
1470 goto Exit; | |
1471 | |
1472 /* read the name, top dict, string and global subrs index */ | |
1473 if ( FT_SET_ERROR( cff_index_init( &font->name_index, | |
1474 stream, 0 ) ) || | |
1475 FT_SET_ERROR( cff_index_init( &font->font_dict_index, | |
1476 stream, 0 ) ) || | |
1477 FT_SET_ERROR( cff_index_init( &string_index, | |
1478 stream, 1 ) ) || | |
1479 FT_SET_ERROR( cff_index_init( &font->global_subrs_index, | |
1480 stream, 1 ) ) || | |
1481 FT_SET_ERROR( cff_index_get_pointers( &string_index, | |
1482 &font->strings, | |
1483 &font->string_pool ) ) ) | |
1484 goto Exit; | |
1485 | |
1486 font->num_strings = string_index.count; | |
1487 | |
1488 if ( pure_cff ) | |
1489 { | |
1490 /* well, we don't really forget the `disabled' fonts... */ | |
1491 subfont_index = face_index; | |
1492 | |
1493 if ( subfont_index >= (FT_Int)font->name_index.count ) | |
1494 { | |
1495 FT_ERROR(( "cff_font_load:" | |
1496 " invalid subfont index for pure CFF font (%d)\n", | |
1497 subfont_index )); | |
1498 error = FT_THROW( Invalid_Argument ); | |
1499 goto Exit; | |
1500 } | |
1501 | |
1502 font->num_faces = font->name_index.count; | |
1503 } | |
1504 else | |
1505 { | |
1506 subfont_index = 0; | |
1507 | |
1508 if ( font->name_index.count > 1 ) | |
1509 { | |
1510 FT_ERROR(( "cff_font_load:" | |
1511 " invalid CFF font with multiple subfonts\n" | |
1512 " " | |
1513 " in SFNT wrapper\n" )); | |
1514 error = FT_THROW( Invalid_File_Format ); | |
1515 goto Exit; | |
1516 } | |
1517 } | |
1518 | |
1519 /* in case of a font format check, simply exit now */ | |
1520 if ( face_index < 0 ) | |
1521 goto Exit; | |
1522 | |
1523 /* now, parse the top-level font dictionary */ | |
1524 FT_TRACE4(( "parsing top-level\n" )); | |
1525 error = cff_subfont_load( &font->top_font, | |
1526 &font->font_dict_index, | |
1527 subfont_index, | |
1528 stream, | |
1529 base_offset, | |
1530 library ); | |
1531 if ( error ) | |
1532 goto Exit; | |
1533 | |
1534 if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) ) | |
1535 goto Exit; | |
1536 | |
1537 error = cff_index_init( &font->charstrings_index, stream, 0 ); | |
1538 if ( error ) | |
1539 goto Exit; | |
1540 | |
1541 /* now, check for a CID font */ | |
1542 if ( dict->cid_registry != 0xFFFFU ) | |
1543 { | |
1544 CFF_IndexRec fd_index; | |
1545 CFF_SubFont sub = NULL; | |
1546 FT_UInt idx; | |
1547 | |
1548 | |
1549 /* this is a CID-keyed font, we must now allocate a table of */ | |
1550 /* sub-fonts, then load each of them separately */ | |
1551 if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) ) | |
1552 goto Exit; | |
1553 | |
1554 error = cff_index_init( &fd_index, stream, 0 ); | |
1555 if ( error ) | |
1556 goto Exit; | |
1557 | |
1558 if ( fd_index.count > CFF_MAX_CID_FONTS ) | |
1559 { | |
1560 FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" )); | |
1561 goto Fail_CID; | |
1562 } | |
1563 | |
1564 /* allocate & read each font dict independently */ | |
1565 font->num_subfonts = fd_index.count; | |
1566 if ( FT_NEW_ARRAY( sub, fd_index.count ) ) | |
1567 goto Fail_CID; | |
1568 | |
1569 /* set up pointer table */ | |
1570 for ( idx = 0; idx < fd_index.count; idx++ ) | |
1571 font->subfonts[idx] = sub + idx; | |
1572 | |
1573 /* now load each subfont independently */ | |
1574 for ( idx = 0; idx < fd_index.count; idx++ ) | |
1575 { | |
1576 sub = font->subfonts[idx]; | |
1577 FT_TRACE4(( "parsing subfont %u\n", idx )); | |
1578 error = cff_subfont_load( sub, &fd_index, idx, | |
1579 stream, base_offset, library ); | |
1580 if ( error ) | |
1581 goto Fail_CID; | |
1582 } | |
1583 | |
1584 /* now load the FD Select array */ | |
1585 error = CFF_Load_FD_Select( &font->fd_select, | |
1586 font->charstrings_index.count, | |
1587 stream, | |
1588 base_offset + dict->cid_fd_select_offset ); | |
1589 | |
1590 Fail_CID: | |
1591 cff_index_done( &fd_index ); | |
1592 | |
1593 if ( error ) | |
1594 goto Exit; | |
1595 } | |
1596 else | |
1597 font->num_subfonts = 0; | |
1598 | |
1599 /* read the charstrings index now */ | |
1600 if ( dict->charstrings_offset == 0 ) | |
1601 { | |
1602 FT_ERROR(( "cff_font_load: no charstrings offset\n" )); | |
1603 error = FT_THROW( Invalid_File_Format ); | |
1604 goto Exit; | |
1605 } | |
1606 | |
1607 font->num_glyphs = font->charstrings_index.count; | |
1608 | |
1609 error = cff_index_get_pointers( &font->global_subrs_index, | |
1610 &font->global_subrs, NULL ); | |
1611 | |
1612 if ( error ) | |
1613 goto Exit; | |
1614 | |
1615 /* read the Charset and Encoding tables if available */ | |
1616 if ( font->num_glyphs > 0 ) | |
1617 { | |
1618 FT_Bool invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff ); | |
1619 | |
1620 | |
1621 error = cff_charset_load( &font->charset, font->num_glyphs, stream, | |
1622 base_offset, dict->charset_offset, invert ); | |
1623 if ( error ) | |
1624 goto Exit; | |
1625 | |
1626 /* CID-keyed CFFs don't have an encoding */ | |
1627 if ( dict->cid_registry == 0xFFFFU ) | |
1628 { | |
1629 error = cff_encoding_load( &font->encoding, | |
1630 &font->charset, | |
1631 font->num_glyphs, | |
1632 stream, | |
1633 base_offset, | |
1634 dict->encoding_offset ); | |
1635 if ( error ) | |
1636 goto Exit; | |
1637 } | |
1638 } | |
1639 | |
1640 /* get the font name (/CIDFontName for CID-keyed fonts, */ | |
1641 /* /FontName otherwise) */ | |
1642 font->font_name = cff_index_get_name( font, subfont_index ); | |
1643 | |
1644 Exit: | |
1645 cff_index_done( &string_index ); | |
1646 | |
1647 return error; | |
1648 } | |
1649 | |
1650 | |
1651 FT_LOCAL_DEF( void ) | |
1652 cff_font_done( CFF_Font font ) | |
1653 { | |
1654 FT_Memory memory = font->memory; | |
1655 FT_UInt idx; | |
1656 | |
1657 | |
1658 cff_index_done( &font->global_subrs_index ); | |
1659 cff_index_done( &font->font_dict_index ); | |
1660 cff_index_done( &font->name_index ); | |
1661 cff_index_done( &font->charstrings_index ); | |
1662 | |
1663 /* release font dictionaries, but only if working with */ | |
1664 /* a CID keyed CFF font */ | |
1665 if ( font->num_subfonts > 0 ) | |
1666 { | |
1667 for ( idx = 0; idx < font->num_subfonts; idx++ ) | |
1668 cff_subfont_done( memory, font->subfonts[idx] ); | |
1669 | |
1670 /* the subfonts array has been allocated as a single block */ | |
1671 FT_FREE( font->subfonts[0] ); | |
1672 } | |
1673 | |
1674 cff_encoding_done( &font->encoding ); | |
1675 cff_charset_done( &font->charset, font->stream ); | |
1676 | |
1677 cff_subfont_done( memory, &font->top_font ); | |
1678 | |
1679 CFF_Done_FD_Select( &font->fd_select, font->stream ); | |
1680 | |
1681 FT_FREE( font->font_info ); | |
1682 | |
1683 FT_FREE( font->font_name ); | |
1684 FT_FREE( font->global_subrs ); | |
1685 FT_FREE( font->strings ); | |
1686 FT_FREE( font->string_pool ); | |
1687 | |
1688 if ( font->cf2_instance.finalizer ) | |
1689 { | |
1690 font->cf2_instance.finalizer( font->cf2_instance.data ); | |
1691 FT_FREE( font->cf2_instance.data ); | |
1692 } | |
1693 } | |
1694 | |
1695 | |
1696 /* END */ | |
OLD | NEW |