1 /***************************************************************************/ |
|
2 /* */ |
|
3 /* cffload.c */ |
|
4 /* */ |
|
5 /* OpenType and CFF data/program tables loader (body). */ |
|
6 /* */ |
|
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ |
|
8 /* 2010 by */ |
|
9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
|
10 /* */ |
|
11 /* This file is part of the FreeType project, and may only be used, */ |
|
12 /* modified, and distributed under the terms of the FreeType project */ |
|
13 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
|
14 /* this file you indicate that you have read the license and */ |
|
15 /* understand and accept it fully. */ |
|
16 /* */ |
|
17 /***************************************************************************/ |
|
18 |
|
19 |
|
20 #include <ft2build.h> |
|
21 #include FT_INTERNAL_DEBUG_H |
|
22 #include FT_INTERNAL_OBJECTS_H |
|
23 #include FT_INTERNAL_STREAM_H |
|
24 #include FT_TRUETYPE_TAGS_H |
|
25 #include FT_TYPE1_TABLES_H |
|
26 |
|
27 #include "cffload.h" |
|
28 #include "cffparse.h" |
|
29 |
|
30 #include "cfferrs.h" |
|
31 |
|
32 |
|
33 #if 1 |
|
34 |
|
35 static const FT_UShort cff_isoadobe_charset[229] = |
|
36 { |
|
37 0, 1, 2, 3, 4, 5, 6, 7, |
|
38 8, 9, 10, 11, 12, 13, 14, 15, |
|
39 16, 17, 18, 19, 20, 21, 22, 23, |
|
40 24, 25, 26, 27, 28, 29, 30, 31, |
|
41 32, 33, 34, 35, 36, 37, 38, 39, |
|
42 40, 41, 42, 43, 44, 45, 46, 47, |
|
43 48, 49, 50, 51, 52, 53, 54, 55, |
|
44 56, 57, 58, 59, 60, 61, 62, 63, |
|
45 64, 65, 66, 67, 68, 69, 70, 71, |
|
46 72, 73, 74, 75, 76, 77, 78, 79, |
|
47 80, 81, 82, 83, 84, 85, 86, 87, |
|
48 88, 89, 90, 91, 92, 93, 94, 95, |
|
49 96, 97, 98, 99, 100, 101, 102, 103, |
|
50 104, 105, 106, 107, 108, 109, 110, 111, |
|
51 112, 113, 114, 115, 116, 117, 118, 119, |
|
52 120, 121, 122, 123, 124, 125, 126, 127, |
|
53 128, 129, 130, 131, 132, 133, 134, 135, |
|
54 136, 137, 138, 139, 140, 141, 142, 143, |
|
55 144, 145, 146, 147, 148, 149, 150, 151, |
|
56 152, 153, 154, 155, 156, 157, 158, 159, |
|
57 160, 161, 162, 163, 164, 165, 166, 167, |
|
58 168, 169, 170, 171, 172, 173, 174, 175, |
|
59 176, 177, 178, 179, 180, 181, 182, 183, |
|
60 184, 185, 186, 187, 188, 189, 190, 191, |
|
61 192, 193, 194, 195, 196, 197, 198, 199, |
|
62 200, 201, 202, 203, 204, 205, 206, 207, |
|
63 208, 209, 210, 211, 212, 213, 214, 215, |
|
64 216, 217, 218, 219, 220, 221, 222, 223, |
|
65 224, 225, 226, 227, 228 |
|
66 }; |
|
67 |
|
68 static const FT_UShort cff_expert_charset[166] = |
|
69 { |
|
70 0, 1, 229, 230, 231, 232, 233, 234, |
|
71 235, 236, 237, 238, 13, 14, 15, 99, |
|
72 239, 240, 241, 242, 243, 244, 245, 246, |
|
73 247, 248, 27, 28, 249, 250, 251, 252, |
|
74 253, 254, 255, 256, 257, 258, 259, 260, |
|
75 261, 262, 263, 264, 265, 266, 109, 110, |
|
76 267, 268, 269, 270, 271, 272, 273, 274, |
|
77 275, 276, 277, 278, 279, 280, 281, 282, |
|
78 283, 284, 285, 286, 287, 288, 289, 290, |
|
79 291, 292, 293, 294, 295, 296, 297, 298, |
|
80 299, 300, 301, 302, 303, 304, 305, 306, |
|
81 307, 308, 309, 310, 311, 312, 313, 314, |
|
82 315, 316, 317, 318, 158, 155, 163, 319, |
|
83 320, 321, 322, 323, 324, 325, 326, 150, |
|
84 164, 169, 327, 328, 329, 330, 331, 332, |
|
85 333, 334, 335, 336, 337, 338, 339, 340, |
|
86 341, 342, 343, 344, 345, 346, 347, 348, |
|
87 349, 350, 351, 352, 353, 354, 355, 356, |
|
88 357, 358, 359, 360, 361, 362, 363, 364, |
|
89 365, 366, 367, 368, 369, 370, 371, 372, |
|
90 373, 374, 375, 376, 377, 378 |
|
91 }; |
|
92 |
|
93 static const FT_UShort cff_expertsubset_charset[87] = |
|
94 { |
|
95 0, 1, 231, 232, 235, 236, 237, 238, |
|
96 13, 14, 15, 99, 239, 240, 241, 242, |
|
97 243, 244, 245, 246, 247, 248, 27, 28, |
|
98 249, 250, 251, 253, 254, 255, 256, 257, |
|
99 258, 259, 260, 261, 262, 263, 264, 265, |
|
100 266, 109, 110, 267, 268, 269, 270, 272, |
|
101 300, 301, 302, 305, 314, 315, 158, 155, |
|
102 163, 320, 321, 322, 323, 324, 325, 326, |
|
103 150, 164, 169, 327, 328, 329, 330, 331, |
|
104 332, 333, 334, 335, 336, 337, 338, 339, |
|
105 340, 341, 342, 343, 344, 345, 346 |
|
106 }; |
|
107 |
|
108 static const FT_UShort cff_standard_encoding[256] = |
|
109 { |
|
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 0, 0, 0, 0, 0, 0, 0, 0, |
|
114 1, 2, 3, 4, 5, 6, 7, 8, |
|
115 9, 10, 11, 12, 13, 14, 15, 16, |
|
116 17, 18, 19, 20, 21, 22, 23, 24, |
|
117 25, 26, 27, 28, 29, 30, 31, 32, |
|
118 33, 34, 35, 36, 37, 38, 39, 40, |
|
119 41, 42, 43, 44, 45, 46, 47, 48, |
|
120 49, 50, 51, 52, 53, 54, 55, 56, |
|
121 57, 58, 59, 60, 61, 62, 63, 64, |
|
122 65, 66, 67, 68, 69, 70, 71, 72, |
|
123 73, 74, 75, 76, 77, 78, 79, 80, |
|
124 81, 82, 83, 84, 85, 86, 87, 88, |
|
125 89, 90, 91, 92, 93, 94, 95, 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, 0, 0, 0, 0, 0, 0, 0, |
|
130 0, 96, 97, 98, 99, 100, 101, 102, |
|
131 103, 104, 105, 106, 107, 108, 109, 110, |
|
132 0, 111, 112, 113, 114, 0, 115, 116, |
|
133 117, 118, 119, 120, 121, 122, 0, 123, |
|
134 0, 124, 125, 126, 127, 128, 129, 130, |
|
135 131, 0, 132, 133, 0, 134, 135, 136, |
|
136 137, 0, 0, 0, 0, 0, 0, 0, |
|
137 0, 0, 0, 0, 0, 0, 0, 0, |
|
138 0, 138, 0, 139, 0, 0, 0, 0, |
|
139 140, 141, 142, 143, 0, 0, 0, 0, |
|
140 0, 144, 0, 0, 0, 145, 0, 0, |
|
141 146, 147, 148, 149, 0, 0, 0, 0 |
|
142 }; |
|
143 |
|
144 static const FT_UShort cff_expert_encoding[256] = |
|
145 { |
|
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 0, 0, 0, 0, 0, 0, 0, 0, |
|
150 1, 229, 230, 0, 231, 232, 233, 234, |
|
151 235, 236, 237, 238, 13, 14, 15, 99, |
|
152 239, 240, 241, 242, 243, 244, 245, 246, |
|
153 247, 248, 27, 28, 249, 250, 251, 252, |
|
154 0, 253, 254, 255, 256, 257, 0, 0, |
|
155 0, 258, 0, 0, 259, 260, 261, 262, |
|
156 0, 0, 263, 264, 265, 0, 266, 109, |
|
157 110, 267, 268, 269, 0, 270, 271, 272, |
|
158 273, 274, 275, 276, 277, 278, 279, 280, |
|
159 281, 282, 283, 284, 285, 286, 287, 288, |
|
160 289, 290, 291, 292, 293, 294, 295, 296, |
|
161 297, 298, 299, 300, 301, 302, 303, 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, 0, 0, 0, 0, 0, 0, 0, |
|
166 0, 304, 305, 306, 0, 0, 307, 308, |
|
167 309, 310, 311, 0, 312, 0, 0, 312, |
|
168 0, 0, 314, 315, 0, 0, 316, 317, |
|
169 318, 0, 0, 0, 158, 155, 163, 319, |
|
170 320, 321, 322, 323, 324, 325, 0, 0, |
|
171 326, 150, 164, 169, 327, 328, 329, 330, |
|
172 331, 332, 333, 334, 335, 336, 337, 338, |
|
173 339, 340, 341, 342, 343, 344, 345, 346, |
|
174 347, 348, 349, 350, 351, 352, 353, 354, |
|
175 355, 356, 357, 358, 359, 360, 361, 362, |
|
176 363, 364, 365, 366, 367, 368, 369, 370, |
|
177 371, 372, 373, 374, 375, 376, 377, 378 |
|
178 }; |
|
179 |
|
180 #endif /* 1 */ |
|
181 |
|
182 |
|
183 FT_LOCAL_DEF( FT_UShort ) |
|
184 cff_get_standard_encoding( FT_UInt charcode ) |
|
185 { |
|
186 return (FT_UShort)( charcode < 256 ? cff_standard_encoding[charcode] |
|
187 : 0 ); |
|
188 } |
|
189 |
|
190 |
|
191 /*************************************************************************/ |
|
192 /* */ |
|
193 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
|
194 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
|
195 /* messages during execution. */ |
|
196 /* */ |
|
197 #undef FT_COMPONENT |
|
198 #define FT_COMPONENT trace_cffload |
|
199 |
|
200 |
|
201 /* read an offset from the index's stream current position */ |
|
202 static FT_ULong |
|
203 cff_index_read_offset( CFF_Index idx, |
|
204 FT_Error *errorp ) |
|
205 { |
|
206 FT_Error error; |
|
207 FT_Stream stream = idx->stream; |
|
208 FT_Byte tmp[4]; |
|
209 FT_ULong result = 0; |
|
210 |
|
211 |
|
212 if ( !FT_STREAM_READ( tmp, idx->off_size ) ) |
|
213 { |
|
214 FT_Int nn; |
|
215 |
|
216 |
|
217 for ( nn = 0; nn < idx->off_size; nn++ ) |
|
218 result = ( result << 8 ) | tmp[nn]; |
|
219 } |
|
220 |
|
221 *errorp = error; |
|
222 return result; |
|
223 } |
|
224 |
|
225 |
|
226 static FT_Error |
|
227 cff_index_init( CFF_Index idx, |
|
228 FT_Stream stream, |
|
229 FT_Bool load ) |
|
230 { |
|
231 FT_Error error; |
|
232 FT_Memory memory = stream->memory; |
|
233 FT_UShort count; |
|
234 |
|
235 |
|
236 FT_MEM_ZERO( idx, sizeof ( *idx ) ); |
|
237 |
|
238 idx->stream = stream; |
|
239 idx->start = FT_STREAM_POS(); |
|
240 if ( !FT_READ_USHORT( count ) && |
|
241 count > 0 ) |
|
242 { |
|
243 FT_Byte offsize; |
|
244 FT_ULong size; |
|
245 |
|
246 |
|
247 /* there is at least one element; read the offset size, */ |
|
248 /* then access the offset table to compute the index's total size */ |
|
249 if ( FT_READ_BYTE( offsize ) ) |
|
250 goto Exit; |
|
251 |
|
252 if ( offsize < 1 || offsize > 4 ) |
|
253 { |
|
254 error = CFF_Err_Invalid_Table; |
|
255 goto Exit; |
|
256 } |
|
257 |
|
258 idx->count = count; |
|
259 idx->off_size = offsize; |
|
260 size = (FT_ULong)( count + 1 ) * offsize; |
|
261 |
|
262 idx->data_offset = idx->start + 3 + size; |
|
263 |
|
264 if ( FT_STREAM_SKIP( size - offsize ) ) |
|
265 goto Exit; |
|
266 |
|
267 size = cff_index_read_offset( idx, &error ); |
|
268 if ( error ) |
|
269 goto Exit; |
|
270 |
|
271 if ( size == 0 ) |
|
272 { |
|
273 error = CFF_Err_Invalid_Table; |
|
274 goto Exit; |
|
275 } |
|
276 |
|
277 idx->data_size = --size; |
|
278 |
|
279 if ( load ) |
|
280 { |
|
281 /* load the data */ |
|
282 if ( FT_FRAME_EXTRACT( size, idx->bytes ) ) |
|
283 goto Exit; |
|
284 } |
|
285 else |
|
286 { |
|
287 /* skip the data */ |
|
288 if ( FT_STREAM_SKIP( size ) ) |
|
289 goto Exit; |
|
290 } |
|
291 } |
|
292 |
|
293 Exit: |
|
294 if ( error ) |
|
295 FT_FREE( idx->offsets ); |
|
296 |
|
297 return error; |
|
298 } |
|
299 |
|
300 |
|
301 static void |
|
302 cff_index_done( CFF_Index idx ) |
|
303 { |
|
304 if ( idx->stream ) |
|
305 { |
|
306 FT_Stream stream = idx->stream; |
|
307 FT_Memory memory = stream->memory; |
|
308 |
|
309 |
|
310 if ( idx->bytes ) |
|
311 FT_FRAME_RELEASE( idx->bytes ); |
|
312 |
|
313 FT_FREE( idx->offsets ); |
|
314 FT_MEM_ZERO( idx, sizeof ( *idx ) ); |
|
315 } |
|
316 } |
|
317 |
|
318 |
|
319 static FT_Error |
|
320 cff_index_load_offsets( CFF_Index idx ) |
|
321 { |
|
322 FT_Error error = CFF_Err_Ok; |
|
323 FT_Stream stream = idx->stream; |
|
324 FT_Memory memory = stream->memory; |
|
325 |
|
326 |
|
327 if ( idx->count > 0 && idx->offsets == NULL ) |
|
328 { |
|
329 FT_Byte offsize = idx->off_size; |
|
330 FT_ULong data_size; |
|
331 FT_Byte* p; |
|
332 FT_Byte* p_end; |
|
333 FT_ULong* poff; |
|
334 |
|
335 |
|
336 data_size = (FT_ULong)( idx->count + 1 ) * offsize; |
|
337 |
|
338 if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) || |
|
339 FT_STREAM_SEEK( idx->start + 3 ) || |
|
340 FT_FRAME_ENTER( data_size ) ) |
|
341 goto Exit; |
|
342 |
|
343 poff = idx->offsets; |
|
344 p = (FT_Byte*)stream->cursor; |
|
345 p_end = p + data_size; |
|
346 |
|
347 switch ( offsize ) |
|
348 { |
|
349 case 1: |
|
350 for ( ; p < p_end; p++, poff++ ) |
|
351 poff[0] = p[0]; |
|
352 break; |
|
353 |
|
354 case 2: |
|
355 for ( ; p < p_end; p += 2, poff++ ) |
|
356 poff[0] = FT_PEEK_USHORT( p ); |
|
357 break; |
|
358 |
|
359 case 3: |
|
360 for ( ; p < p_end; p += 3, poff++ ) |
|
361 poff[0] = FT_PEEK_OFF3( p ); |
|
362 break; |
|
363 |
|
364 default: |
|
365 for ( ; p < p_end; p += 4, poff++ ) |
|
366 poff[0] = FT_PEEK_ULONG( p ); |
|
367 } |
|
368 |
|
369 FT_FRAME_EXIT(); |
|
370 } |
|
371 |
|
372 Exit: |
|
373 if ( error ) |
|
374 FT_FREE( idx->offsets ); |
|
375 |
|
376 return error; |
|
377 } |
|
378 |
|
379 |
|
380 /* Allocate a table containing pointers to an index's elements. */ |
|
381 /* The `pool' argument makes this function convert the index */ |
|
382 /* entries to C-style strings (this is, NULL-terminated). */ |
|
383 static FT_Error |
|
384 cff_index_get_pointers( CFF_Index idx, |
|
385 FT_Byte*** table, |
|
386 FT_Byte** pool ) |
|
387 { |
|
388 FT_Error error = CFF_Err_Ok; |
|
389 FT_Memory memory = idx->stream->memory; |
|
390 FT_Byte** t; |
|
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 = CFF_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 = CFF_Err_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 = CFF_Err_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 = CFF_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 = CFF_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 = CFF_Err_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 = CFF_Err_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 = CFF_Err_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 = CFF_Err_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 = CFF_Err_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 = CFF_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 = CFF_Err_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 = CFF_Err_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 = CFF_Err_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 error = cff_parser_run( &parser, dict, dict + dict_len ); |
|
1341 |
|
1342 cff_index_forget_element( idx, &dict ); |
|
1343 |
|
1344 if ( error ) |
|
1345 goto Exit; |
|
1346 |
|
1347 /* if it is a CID font, we stop there */ |
|
1348 if ( top->cid_registry != 0xFFFFU ) |
|
1349 goto Exit; |
|
1350 |
|
1351 /* parse the private dictionary, if any */ |
|
1352 if ( top->private_offset && top->private_size ) |
|
1353 { |
|
1354 /* set defaults */ |
|
1355 FT_MEM_ZERO( priv, sizeof ( *priv ) ); |
|
1356 |
|
1357 priv->blue_shift = 7; |
|
1358 priv->blue_fuzz = 1; |
|
1359 priv->lenIV = -1; |
|
1360 priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L ); |
|
1361 priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 ); |
|
1362 |
|
1363 cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library ); |
|
1364 |
|
1365 if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) || |
|
1366 FT_FRAME_ENTER( font->font_dict.private_size ) ) |
|
1367 goto Exit; |
|
1368 |
|
1369 error = cff_parser_run( &parser, |
|
1370 (FT_Byte*)stream->cursor, |
|
1371 (FT_Byte*)stream->limit ); |
|
1372 FT_FRAME_EXIT(); |
|
1373 if ( error ) |
|
1374 goto Exit; |
|
1375 |
|
1376 /* ensure that `num_blue_values' is even */ |
|
1377 priv->num_blue_values &= ~1; |
|
1378 } |
|
1379 |
|
1380 /* read the local subrs, if any */ |
|
1381 if ( priv->local_subrs_offset ) |
|
1382 { |
|
1383 if ( FT_STREAM_SEEK( base_offset + top->private_offset + |
|
1384 priv->local_subrs_offset ) ) |
|
1385 goto Exit; |
|
1386 |
|
1387 error = cff_index_init( &font->local_subrs_index, stream, 1 ); |
|
1388 if ( error ) |
|
1389 goto Exit; |
|
1390 |
|
1391 error = cff_index_get_pointers( &font->local_subrs_index, |
|
1392 &font->local_subrs, NULL ); |
|
1393 if ( error ) |
|
1394 goto Exit; |
|
1395 } |
|
1396 |
|
1397 Exit: |
|
1398 return error; |
|
1399 } |
|
1400 |
|
1401 |
|
1402 static void |
|
1403 cff_subfont_done( FT_Memory memory, |
|
1404 CFF_SubFont subfont ) |
|
1405 { |
|
1406 if ( subfont ) |
|
1407 { |
|
1408 cff_index_done( &subfont->local_subrs_index ); |
|
1409 FT_FREE( subfont->local_subrs ); |
|
1410 } |
|
1411 } |
|
1412 |
|
1413 |
|
1414 FT_LOCAL_DEF( FT_Error ) |
|
1415 cff_font_load( FT_Library library, |
|
1416 FT_Stream stream, |
|
1417 FT_Int face_index, |
|
1418 CFF_Font font, |
|
1419 FT_Bool pure_cff ) |
|
1420 { |
|
1421 static const FT_Frame_Field cff_header_fields[] = |
|
1422 { |
|
1423 #undef FT_STRUCTURE |
|
1424 #define FT_STRUCTURE CFF_FontRec |
|
1425 |
|
1426 FT_FRAME_START( 4 ), |
|
1427 FT_FRAME_BYTE( version_major ), |
|
1428 FT_FRAME_BYTE( version_minor ), |
|
1429 FT_FRAME_BYTE( header_size ), |
|
1430 FT_FRAME_BYTE( absolute_offsize ), |
|
1431 FT_FRAME_END |
|
1432 }; |
|
1433 |
|
1434 FT_Error error; |
|
1435 FT_Memory memory = stream->memory; |
|
1436 FT_ULong base_offset; |
|
1437 CFF_FontRecDict dict; |
|
1438 CFF_IndexRec string_index; |
|
1439 |
|
1440 |
|
1441 FT_ZERO( font ); |
|
1442 FT_ZERO( &string_index ); |
|
1443 |
|
1444 font->stream = stream; |
|
1445 font->memory = memory; |
|
1446 dict = &font->top_font.font_dict; |
|
1447 base_offset = FT_STREAM_POS(); |
|
1448 |
|
1449 /* read CFF font header */ |
|
1450 if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) ) |
|
1451 goto Exit; |
|
1452 |
|
1453 /* check format */ |
|
1454 if ( font->version_major != 1 || |
|
1455 font->header_size < 4 || |
|
1456 font->absolute_offsize > 4 ) |
|
1457 { |
|
1458 FT_TRACE2(( "[not a CFF font header]\n" )); |
|
1459 error = CFF_Err_Unknown_File_Format; |
|
1460 goto Exit; |
|
1461 } |
|
1462 |
|
1463 /* skip the rest of the header */ |
|
1464 if ( FT_STREAM_SKIP( font->header_size - 4 ) ) |
|
1465 goto Exit; |
|
1466 |
|
1467 /* read the name, top dict, string and global subrs index */ |
|
1468 if ( FT_SET_ERROR( cff_index_init( &font->name_index, |
|
1469 stream, 0 ) ) || |
|
1470 FT_SET_ERROR( cff_index_init( &font->font_dict_index, |
|
1471 stream, 0 ) ) || |
|
1472 FT_SET_ERROR( cff_index_init( &string_index, |
|
1473 stream, 1 ) ) || |
|
1474 FT_SET_ERROR( cff_index_init( &font->global_subrs_index, |
|
1475 stream, 1 ) ) || |
|
1476 FT_SET_ERROR( cff_index_get_pointers( &string_index, |
|
1477 &font->strings, |
|
1478 &font->string_pool ) ) ) |
|
1479 goto Exit; |
|
1480 |
|
1481 font->num_strings = string_index.count; |
|
1482 |
|
1483 /* well, we don't really forget the `disabled' fonts... */ |
|
1484 font->num_faces = font->name_index.count; |
|
1485 if ( face_index >= (FT_Int)font->num_faces ) |
|
1486 { |
|
1487 FT_ERROR(( "cff_font_load: incorrect face index = %d\n", |
|
1488 face_index )); |
|
1489 error = CFF_Err_Invalid_Argument; |
|
1490 } |
|
1491 |
|
1492 /* in case of a font format check, simply exit now */ |
|
1493 if ( face_index < 0 ) |
|
1494 goto Exit; |
|
1495 |
|
1496 /* now, parse the top-level font dictionary */ |
|
1497 error = cff_subfont_load( &font->top_font, |
|
1498 &font->font_dict_index, |
|
1499 face_index, |
|
1500 stream, |
|
1501 base_offset, |
|
1502 library ); |
|
1503 if ( error ) |
|
1504 goto Exit; |
|
1505 |
|
1506 if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) ) |
|
1507 goto Exit; |
|
1508 |
|
1509 error = cff_index_init( &font->charstrings_index, stream, 0 ); |
|
1510 if ( error ) |
|
1511 goto Exit; |
|
1512 |
|
1513 /* now, check for a CID font */ |
|
1514 if ( dict->cid_registry != 0xFFFFU ) |
|
1515 { |
|
1516 CFF_IndexRec fd_index; |
|
1517 CFF_SubFont sub; |
|
1518 FT_UInt idx; |
|
1519 |
|
1520 |
|
1521 /* this is a CID-keyed font, we must now allocate a table of */ |
|
1522 /* sub-fonts, then load each of them separately */ |
|
1523 if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) ) |
|
1524 goto Exit; |
|
1525 |
|
1526 error = cff_index_init( &fd_index, stream, 0 ); |
|
1527 if ( error ) |
|
1528 goto Exit; |
|
1529 |
|
1530 if ( fd_index.count > CFF_MAX_CID_FONTS ) |
|
1531 { |
|
1532 FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" )); |
|
1533 goto Fail_CID; |
|
1534 } |
|
1535 |
|
1536 /* allocate & read each font dict independently */ |
|
1537 font->num_subfonts = fd_index.count; |
|
1538 if ( FT_NEW_ARRAY( sub, fd_index.count ) ) |
|
1539 goto Fail_CID; |
|
1540 |
|
1541 /* set up pointer table */ |
|
1542 for ( idx = 0; idx < fd_index.count; idx++ ) |
|
1543 font->subfonts[idx] = sub + idx; |
|
1544 |
|
1545 /* now load each subfont independently */ |
|
1546 for ( idx = 0; idx < fd_index.count; idx++ ) |
|
1547 { |
|
1548 sub = font->subfonts[idx]; |
|
1549 error = cff_subfont_load( sub, &fd_index, idx, |
|
1550 stream, base_offset, library ); |
|
1551 if ( error ) |
|
1552 goto Fail_CID; |
|
1553 } |
|
1554 |
|
1555 /* now load the FD Select array */ |
|
1556 error = CFF_Load_FD_Select( &font->fd_select, |
|
1557 font->charstrings_index.count, |
|
1558 stream, |
|
1559 base_offset + dict->cid_fd_select_offset ); |
|
1560 |
|
1561 Fail_CID: |
|
1562 cff_index_done( &fd_index ); |
|
1563 |
|
1564 if ( error ) |
|
1565 goto Exit; |
|
1566 } |
|
1567 else |
|
1568 font->num_subfonts = 0; |
|
1569 |
|
1570 /* read the charstrings index now */ |
|
1571 if ( dict->charstrings_offset == 0 ) |
|
1572 { |
|
1573 FT_ERROR(( "cff_font_load: no charstrings offset\n" )); |
|
1574 error = CFF_Err_Unknown_File_Format; |
|
1575 goto Exit; |
|
1576 } |
|
1577 |
|
1578 font->num_glyphs = font->charstrings_index.count; |
|
1579 |
|
1580 error = cff_index_get_pointers( &font->global_subrs_index, |
|
1581 &font->global_subrs, NULL ); |
|
1582 |
|
1583 if ( error ) |
|
1584 goto Exit; |
|
1585 |
|
1586 /* read the Charset and Encoding tables if available */ |
|
1587 if ( font->num_glyphs > 0 ) |
|
1588 { |
|
1589 FT_Bool invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff ); |
|
1590 |
|
1591 |
|
1592 error = cff_charset_load( &font->charset, font->num_glyphs, stream, |
|
1593 base_offset, dict->charset_offset, invert ); |
|
1594 if ( error ) |
|
1595 goto Exit; |
|
1596 |
|
1597 /* CID-keyed CFFs don't have an encoding */ |
|
1598 if ( dict->cid_registry == 0xFFFFU ) |
|
1599 { |
|
1600 error = cff_encoding_load( &font->encoding, |
|
1601 &font->charset, |
|
1602 font->num_glyphs, |
|
1603 stream, |
|
1604 base_offset, |
|
1605 dict->encoding_offset ); |
|
1606 if ( error ) |
|
1607 goto Exit; |
|
1608 } |
|
1609 } |
|
1610 |
|
1611 /* get the font name (/CIDFontName for CID-keyed fonts, */ |
|
1612 /* /FontName otherwise) */ |
|
1613 font->font_name = cff_index_get_name( font, face_index ); |
|
1614 |
|
1615 Exit: |
|
1616 cff_index_done( &string_index ); |
|
1617 |
|
1618 return error; |
|
1619 } |
|
1620 |
|
1621 |
|
1622 FT_LOCAL_DEF( void ) |
|
1623 cff_font_done( CFF_Font font ) |
|
1624 { |
|
1625 FT_Memory memory = font->memory; |
|
1626 FT_UInt idx; |
|
1627 |
|
1628 |
|
1629 cff_index_done( &font->global_subrs_index ); |
|
1630 cff_index_done( &font->font_dict_index ); |
|
1631 cff_index_done( &font->name_index ); |
|
1632 cff_index_done( &font->charstrings_index ); |
|
1633 |
|
1634 /* release font dictionaries, but only if working with */ |
|
1635 /* a CID keyed CFF font */ |
|
1636 if ( font->num_subfonts > 0 ) |
|
1637 { |
|
1638 for ( idx = 0; idx < font->num_subfonts; idx++ ) |
|
1639 cff_subfont_done( memory, font->subfonts[idx] ); |
|
1640 |
|
1641 /* the subfonts array has been allocated as a single block */ |
|
1642 FT_FREE( font->subfonts[0] ); |
|
1643 } |
|
1644 |
|
1645 cff_encoding_done( &font->encoding ); |
|
1646 cff_charset_done( &font->charset, font->stream ); |
|
1647 |
|
1648 cff_subfont_done( memory, &font->top_font ); |
|
1649 |
|
1650 CFF_Done_FD_Select( &font->fd_select, font->stream ); |
|
1651 |
|
1652 FT_FREE( font->font_info ); |
|
1653 |
|
1654 FT_FREE( font->font_name ); |
|
1655 FT_FREE( font->global_subrs ); |
|
1656 FT_FREE( font->strings ); |
|
1657 FT_FREE( font->string_pool ); |
|
1658 } |
|
1659 |
|
1660 |
|
1661 /* END */ |
|