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 by */ |
---|
8 | /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
---|
9 | /* */ |
---|
10 | /* This file is part of the FreeType project, and may only be used, */ |
---|
11 | /* modified, and distributed under the terms of the FreeType project */ |
---|
12 | /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
---|
13 | /* this file you indicate that you have read the license and */ |
---|
14 | /* understand and accept it fully. */ |
---|
15 | /* */ |
---|
16 | /***************************************************************************/ |
---|
17 | |
---|
18 | |
---|
19 | #include <ft2build.h> |
---|
20 | #include FT_INTERNAL_DEBUG_H |
---|
21 | #include FT_INTERNAL_OBJECTS_H |
---|
22 | #include FT_INTERNAL_STREAM_H |
---|
23 | #include FT_SERVICE_POSTSCRIPT_CMAPS_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 = FT_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 = 0; |
---|
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 | static FT_Error |
---|
382 | cff_index_get_pointers( CFF_Index idx, |
---|
383 | FT_Byte*** table ) |
---|
384 | { |
---|
385 | FT_Error error = CFF_Err_Ok; |
---|
386 | FT_Memory memory = idx->stream->memory; |
---|
387 | FT_ULong n, offset, old_offset; |
---|
388 | FT_Byte** t; |
---|
389 | |
---|
390 | |
---|
391 | *table = 0; |
---|
392 | |
---|
393 | if ( idx->offsets == NULL ) |
---|
394 | { |
---|
395 | error = cff_index_load_offsets( idx ); |
---|
396 | if ( error ) |
---|
397 | goto Exit; |
---|
398 | } |
---|
399 | |
---|
400 | if ( idx->count > 0 && !FT_NEW_ARRAY( t, idx->count + 1 ) ) |
---|
401 | { |
---|
402 | old_offset = 1; |
---|
403 | for ( n = 0; n <= idx->count; n++ ) |
---|
404 | { |
---|
405 | offset = idx->offsets[n]; |
---|
406 | if ( !offset ) |
---|
407 | offset = old_offset; |
---|
408 | |
---|
409 | /* two sanity checks for invalid offset tables */ |
---|
410 | else if ( offset < old_offset ) |
---|
411 | offset = old_offset; |
---|
412 | |
---|
413 | else if ( offset - 1 >= idx->data_size && n < idx->count ) |
---|
414 | offset = old_offset; |
---|
415 | |
---|
416 | t[n] = idx->bytes + offset - 1; |
---|
417 | |
---|
418 | old_offset = offset; |
---|
419 | } |
---|
420 | *table = t; |
---|
421 | } |
---|
422 | |
---|
423 | Exit: |
---|
424 | return error; |
---|
425 | } |
---|
426 | |
---|
427 | |
---|
428 | FT_LOCAL_DEF( FT_Error ) |
---|
429 | cff_index_access_element( CFF_Index idx, |
---|
430 | FT_UInt element, |
---|
431 | FT_Byte** pbytes, |
---|
432 | FT_ULong* pbyte_len ) |
---|
433 | { |
---|
434 | FT_Error error = CFF_Err_Ok; |
---|
435 | |
---|
436 | |
---|
437 | if ( idx && idx->count > element ) |
---|
438 | { |
---|
439 | /* compute start and end offsets */ |
---|
440 | FT_Stream stream = idx->stream; |
---|
441 | FT_ULong off1, off2 = 0; |
---|
442 | |
---|
443 | |
---|
444 | /* load offsets from file or the offset table */ |
---|
445 | if ( !idx->offsets ) |
---|
446 | { |
---|
447 | FT_ULong pos = element * idx->off_size; |
---|
448 | |
---|
449 | |
---|
450 | if ( FT_STREAM_SEEK( idx->start + 3 + pos ) ) |
---|
451 | goto Exit; |
---|
452 | |
---|
453 | off1 = cff_index_read_offset( idx, &error ); |
---|
454 | if ( error ) |
---|
455 | goto Exit; |
---|
456 | |
---|
457 | if ( off1 != 0 ) |
---|
458 | { |
---|
459 | do |
---|
460 | { |
---|
461 | element++; |
---|
462 | off2 = cff_index_read_offset( idx, &error ); |
---|
463 | } |
---|
464 | while ( off2 == 0 && element < idx->count ); |
---|
465 | } |
---|
466 | } |
---|
467 | else /* use offsets table */ |
---|
468 | { |
---|
469 | off1 = idx->offsets[element]; |
---|
470 | if ( off1 ) |
---|
471 | { |
---|
472 | do |
---|
473 | { |
---|
474 | element++; |
---|
475 | off2 = idx->offsets[element]; |
---|
476 | |
---|
477 | } while ( off2 == 0 && element < idx->count ); |
---|
478 | } |
---|
479 | } |
---|
480 | |
---|
481 | /* access element */ |
---|
482 | if ( off1 && off2 > off1 ) |
---|
483 | { |
---|
484 | *pbyte_len = off2 - off1; |
---|
485 | |
---|
486 | if ( idx->bytes ) |
---|
487 | { |
---|
488 | /* this index was completely loaded in memory, that's easy */ |
---|
489 | *pbytes = idx->bytes + off1 - 1; |
---|
490 | } |
---|
491 | else |
---|
492 | { |
---|
493 | /* this index is still on disk/file, access it through a frame */ |
---|
494 | if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) || |
---|
495 | FT_FRAME_EXTRACT( off2 - off1, *pbytes ) ) |
---|
496 | goto Exit; |
---|
497 | } |
---|
498 | } |
---|
499 | else |
---|
500 | { |
---|
501 | /* empty index element */ |
---|
502 | *pbytes = 0; |
---|
503 | *pbyte_len = 0; |
---|
504 | } |
---|
505 | } |
---|
506 | else |
---|
507 | error = CFF_Err_Invalid_Argument; |
---|
508 | |
---|
509 | Exit: |
---|
510 | return error; |
---|
511 | } |
---|
512 | |
---|
513 | |
---|
514 | FT_LOCAL_DEF( void ) |
---|
515 | cff_index_forget_element( CFF_Index idx, |
---|
516 | FT_Byte** pbytes ) |
---|
517 | { |
---|
518 | if ( idx->bytes == 0 ) |
---|
519 | { |
---|
520 | FT_Stream stream = idx->stream; |
---|
521 | |
---|
522 | |
---|
523 | FT_FRAME_RELEASE( *pbytes ); |
---|
524 | } |
---|
525 | } |
---|
526 | |
---|
527 | |
---|
528 | FT_LOCAL_DEF( FT_String* ) |
---|
529 | cff_index_get_name( CFF_Index idx, |
---|
530 | FT_UInt element ) |
---|
531 | { |
---|
532 | FT_Memory memory = idx->stream->memory; |
---|
533 | FT_Byte* bytes; |
---|
534 | FT_ULong byte_len; |
---|
535 | FT_Error error; |
---|
536 | FT_String* name = 0; |
---|
537 | |
---|
538 | |
---|
539 | error = cff_index_access_element( idx, element, &bytes, &byte_len ); |
---|
540 | if ( error ) |
---|
541 | goto Exit; |
---|
542 | |
---|
543 | if ( !FT_ALLOC( name, byte_len + 1 ) ) |
---|
544 | { |
---|
545 | FT_MEM_COPY( name, bytes, byte_len ); |
---|
546 | name[byte_len] = 0; |
---|
547 | } |
---|
548 | cff_index_forget_element( idx, &bytes ); |
---|
549 | |
---|
550 | Exit: |
---|
551 | return name; |
---|
552 | } |
---|
553 | |
---|
554 | |
---|
555 | FT_LOCAL_DEF( FT_String* ) |
---|
556 | cff_index_get_sid_string( CFF_Index idx, |
---|
557 | FT_UInt sid, |
---|
558 | FT_Service_PsCMaps psnames ) |
---|
559 | { |
---|
560 | /* value 0xFFFFU indicates a missing dictionary entry */ |
---|
561 | if ( sid == 0xFFFFU ) |
---|
562 | return 0; |
---|
563 | |
---|
564 | /* if it is not a standard string, return it */ |
---|
565 | if ( sid > 390 ) |
---|
566 | return cff_index_get_name( idx, sid - 391 ); |
---|
567 | |
---|
568 | /* CID-keyed CFF fonts don't have glyph names */ |
---|
569 | if ( !psnames ) |
---|
570 | return 0; |
---|
571 | |
---|
572 | /* that's a standard string, fetch a copy from the PSName module */ |
---|
573 | { |
---|
574 | FT_String* name = 0; |
---|
575 | const char* adobe_name = psnames->adobe_std_strings( sid ); |
---|
576 | |
---|
577 | |
---|
578 | if ( adobe_name ) |
---|
579 | { |
---|
580 | FT_Memory memory = idx->stream->memory; |
---|
581 | FT_Error error; |
---|
582 | |
---|
583 | |
---|
584 | (void)FT_STRDUP( name, adobe_name ); |
---|
585 | |
---|
586 | FT_UNUSED( error ); |
---|
587 | } |
---|
588 | |
---|
589 | return name; |
---|
590 | } |
---|
591 | } |
---|
592 | |
---|
593 | |
---|
594 | /*************************************************************************/ |
---|
595 | /*************************************************************************/ |
---|
596 | /*** ***/ |
---|
597 | /*** FD Select table support ***/ |
---|
598 | /*** ***/ |
---|
599 | /*************************************************************************/ |
---|
600 | /*************************************************************************/ |
---|
601 | |
---|
602 | |
---|
603 | static void |
---|
604 | CFF_Done_FD_Select( CFF_FDSelect fdselect, |
---|
605 | FT_Stream stream ) |
---|
606 | { |
---|
607 | if ( fdselect->data ) |
---|
608 | FT_FRAME_RELEASE( fdselect->data ); |
---|
609 | |
---|
610 | fdselect->data_size = 0; |
---|
611 | fdselect->format = 0; |
---|
612 | fdselect->range_count = 0; |
---|
613 | } |
---|
614 | |
---|
615 | |
---|
616 | static FT_Error |
---|
617 | CFF_Load_FD_Select( CFF_FDSelect fdselect, |
---|
618 | FT_UInt num_glyphs, |
---|
619 | FT_Stream stream, |
---|
620 | FT_ULong offset ) |
---|
621 | { |
---|
622 | FT_Error error; |
---|
623 | FT_Byte format; |
---|
624 | FT_UInt num_ranges; |
---|
625 | |
---|
626 | |
---|
627 | /* read format */ |
---|
628 | if ( FT_STREAM_SEEK( offset ) || FT_READ_BYTE( format ) ) |
---|
629 | goto Exit; |
---|
630 | |
---|
631 | fdselect->format = format; |
---|
632 | fdselect->cache_count = 0; /* clear cache */ |
---|
633 | |
---|
634 | switch ( format ) |
---|
635 | { |
---|
636 | case 0: /* format 0, that's simple */ |
---|
637 | fdselect->data_size = num_glyphs; |
---|
638 | goto Load_Data; |
---|
639 | |
---|
640 | case 3: /* format 3, a tad more complex */ |
---|
641 | if ( FT_READ_USHORT( num_ranges ) ) |
---|
642 | goto Exit; |
---|
643 | |
---|
644 | fdselect->data_size = num_ranges * 3 + 2; |
---|
645 | |
---|
646 | Load_Data: |
---|
647 | if ( FT_FRAME_EXTRACT( fdselect->data_size, fdselect->data ) ) |
---|
648 | goto Exit; |
---|
649 | break; |
---|
650 | |
---|
651 | default: /* hmm... that's wrong */ |
---|
652 | error = CFF_Err_Invalid_File_Format; |
---|
653 | } |
---|
654 | |
---|
655 | Exit: |
---|
656 | return error; |
---|
657 | } |
---|
658 | |
---|
659 | |
---|
660 | FT_LOCAL_DEF( FT_Byte ) |
---|
661 | cff_fd_select_get( CFF_FDSelect fdselect, |
---|
662 | FT_UInt glyph_index ) |
---|
663 | { |
---|
664 | FT_Byte fd = 0; |
---|
665 | |
---|
666 | |
---|
667 | switch ( fdselect->format ) |
---|
668 | { |
---|
669 | case 0: |
---|
670 | fd = fdselect->data[glyph_index]; |
---|
671 | break; |
---|
672 | |
---|
673 | case 3: |
---|
674 | /* first, compare to cache */ |
---|
675 | if ( (FT_UInt)( glyph_index - fdselect->cache_first ) < |
---|
676 | fdselect->cache_count ) |
---|
677 | { |
---|
678 | fd = fdselect->cache_fd; |
---|
679 | break; |
---|
680 | } |
---|
681 | |
---|
682 | /* then, lookup the ranges array */ |
---|
683 | { |
---|
684 | FT_Byte* p = fdselect->data; |
---|
685 | FT_Byte* p_limit = p + fdselect->data_size; |
---|
686 | FT_Byte fd2; |
---|
687 | FT_UInt first, limit; |
---|
688 | |
---|
689 | |
---|
690 | first = FT_NEXT_USHORT( p ); |
---|
691 | do |
---|
692 | { |
---|
693 | if ( glyph_index < first ) |
---|
694 | break; |
---|
695 | |
---|
696 | fd2 = *p++; |
---|
697 | limit = FT_NEXT_USHORT( p ); |
---|
698 | |
---|
699 | if ( glyph_index < limit ) |
---|
700 | { |
---|
701 | fd = fd2; |
---|
702 | |
---|
703 | /* update cache */ |
---|
704 | fdselect->cache_first = first; |
---|
705 | fdselect->cache_count = limit-first; |
---|
706 | fdselect->cache_fd = fd2; |
---|
707 | break; |
---|
708 | } |
---|
709 | first = limit; |
---|
710 | |
---|
711 | } while ( p < p_limit ); |
---|
712 | } |
---|
713 | break; |
---|
714 | |
---|
715 | default: |
---|
716 | ; |
---|
717 | } |
---|
718 | |
---|
719 | return fd; |
---|
720 | } |
---|
721 | |
---|
722 | |
---|
723 | /*************************************************************************/ |
---|
724 | /*************************************************************************/ |
---|
725 | /*** ***/ |
---|
726 | /*** CFF font support ***/ |
---|
727 | /*** ***/ |
---|
728 | /*************************************************************************/ |
---|
729 | /*************************************************************************/ |
---|
730 | |
---|
731 | static FT_Error |
---|
732 | cff_charset_compute_cids( CFF_Charset charset, |
---|
733 | FT_UInt num_glyphs, |
---|
734 | FT_Memory memory ) |
---|
735 | { |
---|
736 | FT_Error error = FT_Err_Ok; |
---|
737 | FT_UInt i; |
---|
738 | FT_UShort max_cid = 0; |
---|
739 | |
---|
740 | |
---|
741 | if ( charset->max_cid > 0 ) |
---|
742 | goto Exit; |
---|
743 | |
---|
744 | for ( i = 0; i < num_glyphs; i++ ) |
---|
745 | if ( charset->sids[i] > max_cid ) |
---|
746 | max_cid = charset->sids[i]; |
---|
747 | max_cid++; |
---|
748 | |
---|
749 | if ( FT_NEW_ARRAY( charset->cids, max_cid ) ) |
---|
750 | goto Exit; |
---|
751 | |
---|
752 | for ( i = 0; i < num_glyphs; i++ ) |
---|
753 | charset->cids[charset->sids[i]] = (FT_UShort)i; |
---|
754 | |
---|
755 | charset->max_cid = max_cid; |
---|
756 | charset->num_glyphs = num_glyphs; |
---|
757 | |
---|
758 | Exit: |
---|
759 | return error; |
---|
760 | } |
---|
761 | |
---|
762 | |
---|
763 | FT_LOCAL_DEF( FT_UInt ) |
---|
764 | cff_charset_cid_to_gindex( CFF_Charset charset, |
---|
765 | FT_UInt cid ) |
---|
766 | { |
---|
767 | FT_UInt result = 0; |
---|
768 | |
---|
769 | |
---|
770 | if ( cid < charset->max_cid ) |
---|
771 | result = charset->cids[cid]; |
---|
772 | |
---|
773 | return result; |
---|
774 | } |
---|
775 | |
---|
776 | |
---|
777 | static void |
---|
778 | cff_charset_free_cids( CFF_Charset charset, |
---|
779 | FT_Memory memory ) |
---|
780 | { |
---|
781 | FT_FREE( charset->cids ); |
---|
782 | charset->max_cid = 0; |
---|
783 | } |
---|
784 | |
---|
785 | |
---|
786 | static void |
---|
787 | cff_charset_done( CFF_Charset charset, |
---|
788 | FT_Stream stream ) |
---|
789 | { |
---|
790 | FT_Memory memory = stream->memory; |
---|
791 | |
---|
792 | |
---|
793 | cff_charset_free_cids( charset, memory ); |
---|
794 | |
---|
795 | FT_FREE( charset->sids ); |
---|
796 | charset->format = 0; |
---|
797 | charset->offset = 0; |
---|
798 | } |
---|
799 | |
---|
800 | |
---|
801 | static FT_Error |
---|
802 | cff_charset_load( CFF_Charset charset, |
---|
803 | FT_UInt num_glyphs, |
---|
804 | FT_Stream stream, |
---|
805 | FT_ULong base_offset, |
---|
806 | FT_ULong offset, |
---|
807 | FT_Bool invert ) |
---|
808 | { |
---|
809 | FT_Memory memory = stream->memory; |
---|
810 | FT_Error error = CFF_Err_Ok; |
---|
811 | FT_UShort glyph_sid; |
---|
812 | |
---|
813 | |
---|
814 | /* If the the offset is greater than 2, we have to parse the */ |
---|
815 | /* charset table. */ |
---|
816 | if ( offset > 2 ) |
---|
817 | { |
---|
818 | FT_UInt j; |
---|
819 | |
---|
820 | |
---|
821 | charset->offset = base_offset + offset; |
---|
822 | |
---|
823 | /* Get the format of the table. */ |
---|
824 | if ( FT_STREAM_SEEK( charset->offset ) || |
---|
825 | FT_READ_BYTE( charset->format ) ) |
---|
826 | goto Exit; |
---|
827 | |
---|
828 | /* Allocate memory for sids. */ |
---|
829 | if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) |
---|
830 | goto Exit; |
---|
831 | |
---|
832 | /* assign the .notdef glyph */ |
---|
833 | charset->sids[0] = 0; |
---|
834 | |
---|
835 | switch ( charset->format ) |
---|
836 | { |
---|
837 | case 0: |
---|
838 | if ( num_glyphs > 0 ) |
---|
839 | { |
---|
840 | if ( FT_FRAME_ENTER( ( num_glyphs - 1 ) * 2 ) ) |
---|
841 | goto Exit; |
---|
842 | |
---|
843 | for ( j = 1; j < num_glyphs; j++ ) |
---|
844 | charset->sids[j] = FT_GET_USHORT(); |
---|
845 | |
---|
846 | FT_FRAME_EXIT(); |
---|
847 | } |
---|
848 | break; |
---|
849 | |
---|
850 | case 1: |
---|
851 | case 2: |
---|
852 | { |
---|
853 | FT_UInt nleft; |
---|
854 | FT_UInt i; |
---|
855 | |
---|
856 | |
---|
857 | j = 1; |
---|
858 | |
---|
859 | while ( j < num_glyphs ) |
---|
860 | { |
---|
861 | /* Read the first glyph sid of the range. */ |
---|
862 | if ( FT_READ_USHORT( glyph_sid ) ) |
---|
863 | goto Exit; |
---|
864 | |
---|
865 | /* Read the number of glyphs in the range. */ |
---|
866 | if ( charset->format == 2 ) |
---|
867 | { |
---|
868 | if ( FT_READ_USHORT( nleft ) ) |
---|
869 | goto Exit; |
---|
870 | } |
---|
871 | else |
---|
872 | { |
---|
873 | if ( FT_READ_BYTE( nleft ) ) |
---|
874 | goto Exit; |
---|
875 | } |
---|
876 | |
---|
877 | /* Fill in the range of sids -- `nleft + 1' glyphs. */ |
---|
878 | for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ ) |
---|
879 | charset->sids[j] = glyph_sid; |
---|
880 | } |
---|
881 | } |
---|
882 | break; |
---|
883 | |
---|
884 | default: |
---|
885 | FT_ERROR(( "cff_charset_load: invalid table format!\n" )); |
---|
886 | error = CFF_Err_Invalid_File_Format; |
---|
887 | goto Exit; |
---|
888 | } |
---|
889 | } |
---|
890 | else |
---|
891 | { |
---|
892 | /* Parse default tables corresponding to offset == 0, 1, or 2. */ |
---|
893 | /* CFF specification intimates the following: */ |
---|
894 | /* */ |
---|
895 | /* In order to use a predefined charset, the following must be */ |
---|
896 | /* true: The charset constructed for the glyphs in the font's */ |
---|
897 | /* charstrings dictionary must match the predefined charset in */ |
---|
898 | /* the first num_glyphs. */ |
---|
899 | |
---|
900 | charset->offset = offset; /* record charset type */ |
---|
901 | |
---|
902 | switch ( (FT_UInt)offset ) |
---|
903 | { |
---|
904 | case 0: |
---|
905 | if ( num_glyphs > 229 ) |
---|
906 | { |
---|
907 | FT_ERROR(( "cff_charset_load: implicit charset larger than\n" |
---|
908 | "predefined charset (Adobe ISO-Latin)!\n" )); |
---|
909 | error = CFF_Err_Invalid_File_Format; |
---|
910 | goto Exit; |
---|
911 | } |
---|
912 | |
---|
913 | /* Allocate memory for sids. */ |
---|
914 | if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) |
---|
915 | goto Exit; |
---|
916 | |
---|
917 | /* Copy the predefined charset into the allocated memory. */ |
---|
918 | FT_ARRAY_COPY( charset->sids, cff_isoadobe_charset, num_glyphs ); |
---|
919 | |
---|
920 | break; |
---|
921 | |
---|
922 | case 1: |
---|
923 | if ( num_glyphs > 166 ) |
---|
924 | { |
---|
925 | FT_ERROR(( "cff_charset_load: implicit charset larger than\n" |
---|
926 | "predefined charset (Adobe Expert)!\n" )); |
---|
927 | error = CFF_Err_Invalid_File_Format; |
---|
928 | goto Exit; |
---|
929 | } |
---|
930 | |
---|
931 | /* Allocate memory for sids. */ |
---|
932 | if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) |
---|
933 | goto Exit; |
---|
934 | |
---|
935 | /* Copy the predefined charset into the allocated memory. */ |
---|
936 | FT_ARRAY_COPY( charset->sids, cff_expert_charset, num_glyphs ); |
---|
937 | |
---|
938 | break; |
---|
939 | |
---|
940 | case 2: |
---|
941 | if ( num_glyphs > 87 ) |
---|
942 | { |
---|
943 | FT_ERROR(( "cff_charset_load: implicit charset larger than\n" |
---|
944 | "predefined charset (Adobe Expert Subset)!\n" )); |
---|
945 | error = CFF_Err_Invalid_File_Format; |
---|
946 | goto Exit; |
---|
947 | } |
---|
948 | |
---|
949 | /* Allocate memory for sids. */ |
---|
950 | if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) |
---|
951 | goto Exit; |
---|
952 | |
---|
953 | /* Copy the predefined charset into the allocated memory. */ |
---|
954 | FT_ARRAY_COPY( charset->sids, cff_expertsubset_charset, num_glyphs ); |
---|
955 | |
---|
956 | break; |
---|
957 | |
---|
958 | default: |
---|
959 | error = CFF_Err_Invalid_File_Format; |
---|
960 | goto Exit; |
---|
961 | } |
---|
962 | } |
---|
963 | |
---|
964 | /* we have to invert the `sids' array for subsetted CID-keyed fonts */ |
---|
965 | if ( invert ) |
---|
966 | error = cff_charset_compute_cids( charset, num_glyphs, memory ); |
---|
967 | |
---|
968 | Exit: |
---|
969 | /* Clean up if there was an error. */ |
---|
970 | if ( error ) |
---|
971 | { |
---|
972 | FT_FREE( charset->sids ); |
---|
973 | FT_FREE( charset->cids ); |
---|
974 | charset->format = 0; |
---|
975 | charset->offset = 0; |
---|
976 | charset->sids = 0; |
---|
977 | } |
---|
978 | |
---|
979 | return error; |
---|
980 | } |
---|
981 | |
---|
982 | |
---|
983 | static void |
---|
984 | cff_encoding_done( CFF_Encoding encoding ) |
---|
985 | { |
---|
986 | encoding->format = 0; |
---|
987 | encoding->offset = 0; |
---|
988 | encoding->count = 0; |
---|
989 | } |
---|
990 | |
---|
991 | |
---|
992 | static FT_Error |
---|
993 | cff_encoding_load( CFF_Encoding encoding, |
---|
994 | CFF_Charset charset, |
---|
995 | FT_UInt num_glyphs, |
---|
996 | FT_Stream stream, |
---|
997 | FT_ULong base_offset, |
---|
998 | FT_ULong offset ) |
---|
999 | { |
---|
1000 | FT_Error error = CFF_Err_Ok; |
---|
1001 | FT_UInt count; |
---|
1002 | FT_UInt j; |
---|
1003 | FT_UShort glyph_sid; |
---|
1004 | FT_UInt glyph_code; |
---|
1005 | |
---|
1006 | |
---|
1007 | /* Check for charset->sids. If we do not have this, we fail. */ |
---|
1008 | if ( !charset->sids ) |
---|
1009 | { |
---|
1010 | error = CFF_Err_Invalid_File_Format; |
---|
1011 | goto Exit; |
---|
1012 | } |
---|
1013 | |
---|
1014 | /* Zero out the code to gid/sid mappings. */ |
---|
1015 | for ( j = 0; j < 256; j++ ) |
---|
1016 | { |
---|
1017 | encoding->sids [j] = 0; |
---|
1018 | encoding->codes[j] = 0; |
---|
1019 | } |
---|
1020 | |
---|
1021 | /* Note: The encoding table in a CFF font is indexed by glyph index; */ |
---|
1022 | /* the first encoded glyph index is 1. Hence, we read the character */ |
---|
1023 | /* code (`glyph_code') at index j and make the assignment: */ |
---|
1024 | /* */ |
---|
1025 | /* encoding->codes[glyph_code] = j + 1 */ |
---|
1026 | /* */ |
---|
1027 | /* We also make the assignment: */ |
---|
1028 | /* */ |
---|
1029 | /* encoding->sids[glyph_code] = charset->sids[j + 1] */ |
---|
1030 | /* */ |
---|
1031 | /* This gives us both a code to GID and a code to SID mapping. */ |
---|
1032 | |
---|
1033 | if ( offset > 1 ) |
---|
1034 | { |
---|
1035 | encoding->offset = base_offset + offset; |
---|
1036 | |
---|
1037 | /* we need to parse the table to determine its size */ |
---|
1038 | if ( FT_STREAM_SEEK( encoding->offset ) || |
---|
1039 | FT_READ_BYTE( encoding->format ) || |
---|
1040 | FT_READ_BYTE( count ) ) |
---|
1041 | goto Exit; |
---|
1042 | |
---|
1043 | switch ( encoding->format & 0x7F ) |
---|
1044 | { |
---|
1045 | case 0: |
---|
1046 | { |
---|
1047 | FT_Byte* p; |
---|
1048 | |
---|
1049 | |
---|
1050 | /* By convention, GID 0 is always ".notdef" and is never */ |
---|
1051 | /* coded in the font. Hence, the number of codes found */ |
---|
1052 | /* in the table is `count+1'. */ |
---|
1053 | /* */ |
---|
1054 | encoding->count = count + 1; |
---|
1055 | |
---|
1056 | if ( FT_FRAME_ENTER( count ) ) |
---|
1057 | goto Exit; |
---|
1058 | |
---|
1059 | p = (FT_Byte*)stream->cursor; |
---|
1060 | |
---|
1061 | for ( j = 1; j <= count; j++ ) |
---|
1062 | { |
---|
1063 | glyph_code = *p++; |
---|
1064 | |
---|
1065 | /* Make sure j is not too big. */ |
---|
1066 | if ( j < num_glyphs ) |
---|
1067 | { |
---|
1068 | /* Assign code to GID mapping. */ |
---|
1069 | encoding->codes[glyph_code] = (FT_UShort)j; |
---|
1070 | |
---|
1071 | /* Assign code to SID mapping. */ |
---|
1072 | encoding->sids[glyph_code] = charset->sids[j]; |
---|
1073 | } |
---|
1074 | } |
---|
1075 | |
---|
1076 | FT_FRAME_EXIT(); |
---|
1077 | } |
---|
1078 | break; |
---|
1079 | |
---|
1080 | case 1: |
---|
1081 | { |
---|
1082 | FT_UInt nleft; |
---|
1083 | FT_UInt i = 1; |
---|
1084 | FT_UInt k; |
---|
1085 | |
---|
1086 | |
---|
1087 | encoding->count = 0; |
---|
1088 | |
---|
1089 | /* Parse the Format1 ranges. */ |
---|
1090 | for ( j = 0; j < count; j++, i += nleft ) |
---|
1091 | { |
---|
1092 | /* Read the first glyph code of the range. */ |
---|
1093 | if ( FT_READ_BYTE( glyph_code ) ) |
---|
1094 | goto Exit; |
---|
1095 | |
---|
1096 | /* Read the number of codes in the range. */ |
---|
1097 | if ( FT_READ_BYTE( nleft ) ) |
---|
1098 | goto Exit; |
---|
1099 | |
---|
1100 | /* Increment nleft, so we read `nleft + 1' codes/sids. */ |
---|
1101 | nleft++; |
---|
1102 | |
---|
1103 | /* compute max number of character codes */ |
---|
1104 | if ( (FT_UInt)nleft > encoding->count ) |
---|
1105 | encoding->count = nleft; |
---|
1106 | |
---|
1107 | /* Fill in the range of codes/sids. */ |
---|
1108 | for ( k = i; k < nleft + i; k++, glyph_code++ ) |
---|
1109 | { |
---|
1110 | /* Make sure k is not too big. */ |
---|
1111 | if ( k < num_glyphs && glyph_code < 256 ) |
---|
1112 | { |
---|
1113 | /* Assign code to GID mapping. */ |
---|
1114 | encoding->codes[glyph_code] = (FT_UShort)k; |
---|
1115 | |
---|
1116 | /* Assign code to SID mapping. */ |
---|
1117 | encoding->sids[glyph_code] = charset->sids[k]; |
---|
1118 | } |
---|
1119 | } |
---|
1120 | } |
---|
1121 | |
---|
1122 | /* simple check; one never knows what can be found in a font */ |
---|
1123 | if ( encoding->count > 256 ) |
---|
1124 | encoding->count = 256; |
---|
1125 | } |
---|
1126 | break; |
---|
1127 | |
---|
1128 | default: |
---|
1129 | FT_ERROR(( "cff_encoding_load: invalid table format!\n" )); |
---|
1130 | error = CFF_Err_Invalid_File_Format; |
---|
1131 | goto Exit; |
---|
1132 | } |
---|
1133 | |
---|
1134 | /* Parse supplemental encodings, if any. */ |
---|
1135 | if ( encoding->format & 0x80 ) |
---|
1136 | { |
---|
1137 | FT_UInt gindex; |
---|
1138 | |
---|
1139 | |
---|
1140 | /* count supplements */ |
---|
1141 | if ( FT_READ_BYTE( count ) ) |
---|
1142 | goto Exit; |
---|
1143 | |
---|
1144 | for ( j = 0; j < count; j++ ) |
---|
1145 | { |
---|
1146 | /* Read supplemental glyph code. */ |
---|
1147 | if ( FT_READ_BYTE( glyph_code ) ) |
---|
1148 | goto Exit; |
---|
1149 | |
---|
1150 | /* Read the SID associated with this glyph code. */ |
---|
1151 | if ( FT_READ_USHORT( glyph_sid ) ) |
---|
1152 | goto Exit; |
---|
1153 | |
---|
1154 | /* Assign code to SID mapping. */ |
---|
1155 | encoding->sids[glyph_code] = glyph_sid; |
---|
1156 | |
---|
1157 | /* First, look up GID which has been assigned to */ |
---|
1158 | /* SID glyph_sid. */ |
---|
1159 | for ( gindex = 0; gindex < num_glyphs; gindex++ ) |
---|
1160 | { |
---|
1161 | if ( charset->sids[gindex] == glyph_sid ) |
---|
1162 | { |
---|
1163 | encoding->codes[glyph_code] = (FT_UShort)gindex; |
---|
1164 | break; |
---|
1165 | } |
---|
1166 | } |
---|
1167 | } |
---|
1168 | } |
---|
1169 | } |
---|
1170 | else |
---|
1171 | { |
---|
1172 | /* We take into account the fact a CFF font can use a predefined */ |
---|
1173 | /* encoding without containing all of the glyphs encoded by this */ |
---|
1174 | /* encoding (see the note at the end of section 12 in the CFF */ |
---|
1175 | /* specification). */ |
---|
1176 | |
---|
1177 | switch ( (FT_UInt)offset ) |
---|
1178 | { |
---|
1179 | case 0: |
---|
1180 | /* First, copy the code to SID mapping. */ |
---|
1181 | FT_ARRAY_COPY( encoding->sids, cff_standard_encoding, 256 ); |
---|
1182 | goto Populate; |
---|
1183 | |
---|
1184 | case 1: |
---|
1185 | /* First, copy the code to SID mapping. */ |
---|
1186 | FT_ARRAY_COPY( encoding->sids, cff_expert_encoding, 256 ); |
---|
1187 | |
---|
1188 | Populate: |
---|
1189 | /* Construct code to GID mapping from code to SID mapping */ |
---|
1190 | /* and charset. */ |
---|
1191 | |
---|
1192 | encoding->count = 0; |
---|
1193 | |
---|
1194 | error = cff_charset_compute_cids( charset, num_glyphs, |
---|
1195 | stream->memory ); |
---|
1196 | if ( error ) |
---|
1197 | goto Exit; |
---|
1198 | |
---|
1199 | for ( j = 0; j < 256; j++ ) |
---|
1200 | { |
---|
1201 | FT_UInt sid = encoding->sids[j]; |
---|
1202 | FT_UInt gid = 0; |
---|
1203 | |
---|
1204 | |
---|
1205 | if ( sid ) |
---|
1206 | gid = cff_charset_cid_to_gindex( charset, sid ); |
---|
1207 | |
---|
1208 | if ( gid != 0 ) |
---|
1209 | { |
---|
1210 | encoding->codes[j] = (FT_UShort)gid; |
---|
1211 | |
---|
1212 | if ( encoding->count < j + 1 ) |
---|
1213 | encoding->count = j + 1; |
---|
1214 | } |
---|
1215 | else |
---|
1216 | { |
---|
1217 | encoding->codes[j] = 0; |
---|
1218 | encoding->sids [j] = 0; |
---|
1219 | } |
---|
1220 | } |
---|
1221 | break; |
---|
1222 | |
---|
1223 | default: |
---|
1224 | FT_ERROR(( "cff_encoding_load: invalid table format!\n" )); |
---|
1225 | error = CFF_Err_Invalid_File_Format; |
---|
1226 | goto Exit; |
---|
1227 | } |
---|
1228 | } |
---|
1229 | |
---|
1230 | Exit: |
---|
1231 | |
---|
1232 | /* Clean up if there was an error. */ |
---|
1233 | return error; |
---|
1234 | } |
---|
1235 | |
---|
1236 | |
---|
1237 | static FT_Error |
---|
1238 | cff_subfont_load( CFF_SubFont font, |
---|
1239 | CFF_Index idx, |
---|
1240 | FT_UInt font_index, |
---|
1241 | FT_Stream stream, |
---|
1242 | FT_ULong base_offset ) |
---|
1243 | { |
---|
1244 | FT_Error error; |
---|
1245 | CFF_ParserRec parser; |
---|
1246 | FT_Byte* dict = NULL; |
---|
1247 | FT_ULong dict_len; |
---|
1248 | CFF_FontRecDict top = &font->font_dict; |
---|
1249 | CFF_Private priv = &font->private_dict; |
---|
1250 | |
---|
1251 | |
---|
1252 | cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict ); |
---|
1253 | |
---|
1254 | /* set defaults */ |
---|
1255 | FT_MEM_ZERO( top, sizeof ( *top ) ); |
---|
1256 | |
---|
1257 | top->underline_position = -100L << 16; |
---|
1258 | top->underline_thickness = 50L << 16; |
---|
1259 | top->charstring_type = 2; |
---|
1260 | top->font_matrix.xx = 0x10000L; |
---|
1261 | top->font_matrix.yy = 0x10000L; |
---|
1262 | top->cid_count = 8720; |
---|
1263 | |
---|
1264 | /* we use the implementation specific SID value 0xFFFF to indicate */ |
---|
1265 | /* missing entries */ |
---|
1266 | top->version = 0xFFFFU; |
---|
1267 | top->notice = 0xFFFFU; |
---|
1268 | top->copyright = 0xFFFFU; |
---|
1269 | top->full_name = 0xFFFFU; |
---|
1270 | top->family_name = 0xFFFFU; |
---|
1271 | top->weight = 0xFFFFU; |
---|
1272 | top->embedded_postscript = 0xFFFFU; |
---|
1273 | |
---|
1274 | top->cid_registry = 0xFFFFU; |
---|
1275 | top->cid_ordering = 0xFFFFU; |
---|
1276 | top->cid_font_name = 0xFFFFU; |
---|
1277 | |
---|
1278 | error = cff_index_access_element( idx, font_index, &dict, &dict_len ); |
---|
1279 | if ( !error ) |
---|
1280 | error = cff_parser_run( &parser, dict, dict + dict_len ); |
---|
1281 | |
---|
1282 | cff_index_forget_element( idx, &dict ); |
---|
1283 | |
---|
1284 | if ( error ) |
---|
1285 | goto Exit; |
---|
1286 | |
---|
1287 | /* if it is a CID font, we stop there */ |
---|
1288 | if ( top->cid_registry != 0xFFFFU ) |
---|
1289 | goto Exit; |
---|
1290 | |
---|
1291 | /* parse the private dictionary, if any */ |
---|
1292 | if ( top->private_offset && top->private_size ) |
---|
1293 | { |
---|
1294 | /* set defaults */ |
---|
1295 | FT_MEM_ZERO( priv, sizeof ( *priv ) ); |
---|
1296 | |
---|
1297 | priv->blue_shift = 7; |
---|
1298 | priv->blue_fuzz = 1; |
---|
1299 | priv->lenIV = -1; |
---|
1300 | priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L ); |
---|
1301 | priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 ); |
---|
1302 | |
---|
1303 | cff_parser_init( &parser, CFF_CODE_PRIVATE, priv ); |
---|
1304 | |
---|
1305 | if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) || |
---|
1306 | FT_FRAME_ENTER( font->font_dict.private_size ) ) |
---|
1307 | goto Exit; |
---|
1308 | |
---|
1309 | error = cff_parser_run( &parser, |
---|
1310 | (FT_Byte*)stream->cursor, |
---|
1311 | (FT_Byte*)stream->limit ); |
---|
1312 | FT_FRAME_EXIT(); |
---|
1313 | if ( error ) |
---|
1314 | goto Exit; |
---|
1315 | |
---|
1316 | /* ensure that `num_blue_values' is even */ |
---|
1317 | priv->num_blue_values &= ~1; |
---|
1318 | } |
---|
1319 | |
---|
1320 | /* read the local subrs, if any */ |
---|
1321 | if ( priv->local_subrs_offset ) |
---|
1322 | { |
---|
1323 | if ( FT_STREAM_SEEK( base_offset + top->private_offset + |
---|
1324 | priv->local_subrs_offset ) ) |
---|
1325 | goto Exit; |
---|
1326 | |
---|
1327 | error = cff_index_init( &font->local_subrs_index, stream, 1 ); |
---|
1328 | if ( error ) |
---|
1329 | goto Exit; |
---|
1330 | |
---|
1331 | font->num_local_subrs = font->local_subrs_index.count; |
---|
1332 | error = cff_index_get_pointers( &font->local_subrs_index, |
---|
1333 | &font->local_subrs ); |
---|
1334 | if ( error ) |
---|
1335 | goto Exit; |
---|
1336 | } |
---|
1337 | |
---|
1338 | Exit: |
---|
1339 | return error; |
---|
1340 | } |
---|
1341 | |
---|
1342 | |
---|
1343 | static void |
---|
1344 | cff_subfont_done( FT_Memory memory, |
---|
1345 | CFF_SubFont subfont ) |
---|
1346 | { |
---|
1347 | if ( subfont ) |
---|
1348 | { |
---|
1349 | cff_index_done( &subfont->local_subrs_index ); |
---|
1350 | FT_FREE( subfont->local_subrs ); |
---|
1351 | } |
---|
1352 | } |
---|
1353 | |
---|
1354 | |
---|
1355 | FT_LOCAL_DEF( FT_Error ) |
---|
1356 | cff_font_load( FT_Stream stream, |
---|
1357 | FT_Int face_index, |
---|
1358 | CFF_Font font, |
---|
1359 | FT_Bool pure_cff ) |
---|
1360 | { |
---|
1361 | static const FT_Frame_Field cff_header_fields[] = |
---|
1362 | { |
---|
1363 | #undef FT_STRUCTURE |
---|
1364 | #define FT_STRUCTURE CFF_FontRec |
---|
1365 | |
---|
1366 | FT_FRAME_START( 4 ), |
---|
1367 | FT_FRAME_BYTE( version_major ), |
---|
1368 | FT_FRAME_BYTE( version_minor ), |
---|
1369 | FT_FRAME_BYTE( header_size ), |
---|
1370 | FT_FRAME_BYTE( absolute_offsize ), |
---|
1371 | FT_FRAME_END |
---|
1372 | }; |
---|
1373 | |
---|
1374 | FT_Error error; |
---|
1375 | FT_Memory memory = stream->memory; |
---|
1376 | FT_ULong base_offset; |
---|
1377 | CFF_FontRecDict dict; |
---|
1378 | |
---|
1379 | |
---|
1380 | FT_ZERO( font ); |
---|
1381 | |
---|
1382 | font->stream = stream; |
---|
1383 | font->memory = memory; |
---|
1384 | dict = &font->top_font.font_dict; |
---|
1385 | base_offset = FT_STREAM_POS(); |
---|
1386 | |
---|
1387 | /* read CFF font header */ |
---|
1388 | if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) ) |
---|
1389 | goto Exit; |
---|
1390 | |
---|
1391 | /* check format */ |
---|
1392 | if ( font->version_major != 1 || |
---|
1393 | font->header_size < 4 || |
---|
1394 | font->absolute_offsize > 4 ) |
---|
1395 | { |
---|
1396 | FT_TRACE2(( "[not a CFF font header!]\n" )); |
---|
1397 | error = CFF_Err_Unknown_File_Format; |
---|
1398 | goto Exit; |
---|
1399 | } |
---|
1400 | |
---|
1401 | /* skip the rest of the header */ |
---|
1402 | if ( FT_STREAM_SKIP( font->header_size - 4 ) ) |
---|
1403 | goto Exit; |
---|
1404 | |
---|
1405 | /* read the name, top dict, string and global subrs index */ |
---|
1406 | if ( FT_SET_ERROR( cff_index_init( &font->name_index, |
---|
1407 | stream, 0 ) ) || |
---|
1408 | FT_SET_ERROR( cff_index_init( &font->font_dict_index, |
---|
1409 | stream, 0 ) ) || |
---|
1410 | FT_SET_ERROR( cff_index_init( &font->string_index, |
---|
1411 | stream, 0 ) ) || |
---|
1412 | FT_SET_ERROR( cff_index_init( &font->global_subrs_index, |
---|
1413 | stream, 1 ) ) ) |
---|
1414 | goto Exit; |
---|
1415 | |
---|
1416 | /* well, we don't really forget the `disabled' fonts... */ |
---|
1417 | font->num_faces = font->name_index.count; |
---|
1418 | if ( face_index >= (FT_Int)font->num_faces ) |
---|
1419 | { |
---|
1420 | FT_ERROR(( "cff_font_load: incorrect face index = %d\n", |
---|
1421 | face_index )); |
---|
1422 | error = CFF_Err_Invalid_Argument; |
---|
1423 | } |
---|
1424 | |
---|
1425 | /* in case of a font format check, simply exit now */ |
---|
1426 | if ( face_index < 0 ) |
---|
1427 | goto Exit; |
---|
1428 | |
---|
1429 | /* now, parse the top-level font dictionary */ |
---|
1430 | error = cff_subfont_load( &font->top_font, |
---|
1431 | &font->font_dict_index, |
---|
1432 | face_index, |
---|
1433 | stream, |
---|
1434 | base_offset ); |
---|
1435 | if ( error ) |
---|
1436 | goto Exit; |
---|
1437 | |
---|
1438 | if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) ) |
---|
1439 | goto Exit; |
---|
1440 | |
---|
1441 | error = cff_index_init( &font->charstrings_index, stream, 0 ); |
---|
1442 | if ( error ) |
---|
1443 | goto Exit; |
---|
1444 | |
---|
1445 | /* now, check for a CID font */ |
---|
1446 | if ( dict->cid_registry != 0xFFFFU ) |
---|
1447 | { |
---|
1448 | CFF_IndexRec fd_index; |
---|
1449 | CFF_SubFont sub; |
---|
1450 | FT_UInt idx; |
---|
1451 | |
---|
1452 | |
---|
1453 | /* this is a CID-keyed font, we must now allocate a table of */ |
---|
1454 | /* sub-fonts, then load each of them separately */ |
---|
1455 | if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) ) |
---|
1456 | goto Exit; |
---|
1457 | |
---|
1458 | error = cff_index_init( &fd_index, stream, 0 ); |
---|
1459 | if ( error ) |
---|
1460 | goto Exit; |
---|
1461 | |
---|
1462 | if ( fd_index.count > CFF_MAX_CID_FONTS ) |
---|
1463 | { |
---|
1464 | FT_ERROR(( "cff_font_load: FD array too large in CID font\n" )); |
---|
1465 | goto Fail_CID; |
---|
1466 | } |
---|
1467 | |
---|
1468 | /* allocate & read each font dict independently */ |
---|
1469 | font->num_subfonts = fd_index.count; |
---|
1470 | if ( FT_NEW_ARRAY( sub, fd_index.count ) ) |
---|
1471 | goto Fail_CID; |
---|
1472 | |
---|
1473 | /* set up pointer table */ |
---|
1474 | for ( idx = 0; idx < fd_index.count; idx++ ) |
---|
1475 | font->subfonts[idx] = sub + idx; |
---|
1476 | |
---|
1477 | /* now load each subfont independently */ |
---|
1478 | for ( idx = 0; idx < fd_index.count; idx++ ) |
---|
1479 | { |
---|
1480 | sub = font->subfonts[idx]; |
---|
1481 | error = cff_subfont_load( sub, &fd_index, idx, |
---|
1482 | stream, base_offset ); |
---|
1483 | if ( error ) |
---|
1484 | goto Fail_CID; |
---|
1485 | } |
---|
1486 | |
---|
1487 | /* now load the FD Select array */ |
---|
1488 | error = CFF_Load_FD_Select( &font->fd_select, |
---|
1489 | font->charstrings_index.count, |
---|
1490 | stream, |
---|
1491 | base_offset + dict->cid_fd_select_offset ); |
---|
1492 | |
---|
1493 | Fail_CID: |
---|
1494 | cff_index_done( &fd_index ); |
---|
1495 | |
---|
1496 | if ( error ) |
---|
1497 | goto Exit; |
---|
1498 | } |
---|
1499 | else |
---|
1500 | font->num_subfonts = 0; |
---|
1501 | |
---|
1502 | /* read the charstrings index now */ |
---|
1503 | if ( dict->charstrings_offset == 0 ) |
---|
1504 | { |
---|
1505 | FT_ERROR(( "cff_font_load: no charstrings offset!\n" )); |
---|
1506 | error = CFF_Err_Unknown_File_Format; |
---|
1507 | goto Exit; |
---|
1508 | } |
---|
1509 | |
---|
1510 | /* explicit the global subrs */ |
---|
1511 | font->num_global_subrs = font->global_subrs_index.count; |
---|
1512 | font->num_glyphs = font->charstrings_index.count; |
---|
1513 | |
---|
1514 | error = cff_index_get_pointers( &font->global_subrs_index, |
---|
1515 | &font->global_subrs ) ; |
---|
1516 | |
---|
1517 | if ( error ) |
---|
1518 | goto Exit; |
---|
1519 | |
---|
1520 | /* read the Charset and Encoding tables if available */ |
---|
1521 | if ( font->num_glyphs > 0 ) |
---|
1522 | { |
---|
1523 | FT_Bool invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff ); |
---|
1524 | |
---|
1525 | |
---|
1526 | error = cff_charset_load( &font->charset, font->num_glyphs, stream, |
---|
1527 | base_offset, dict->charset_offset, invert ); |
---|
1528 | if ( error ) |
---|
1529 | goto Exit; |
---|
1530 | |
---|
1531 | /* CID-keyed CFFs don't have an encoding */ |
---|
1532 | if ( dict->cid_registry == 0xFFFFU ) |
---|
1533 | { |
---|
1534 | error = cff_encoding_load( &font->encoding, |
---|
1535 | &font->charset, |
---|
1536 | font->num_glyphs, |
---|
1537 | stream, |
---|
1538 | base_offset, |
---|
1539 | dict->encoding_offset ); |
---|
1540 | if ( error ) |
---|
1541 | goto Exit; |
---|
1542 | } |
---|
1543 | else |
---|
1544 | /* CID-keyed fonts only need CIDs */ |
---|
1545 | FT_FREE( font->charset.sids ); |
---|
1546 | } |
---|
1547 | |
---|
1548 | /* get the font name (/CIDFontName for CID-keyed fonts, */ |
---|
1549 | /* /FontName otherwise) */ |
---|
1550 | font->font_name = cff_index_get_name( &font->name_index, face_index ); |
---|
1551 | |
---|
1552 | Exit: |
---|
1553 | return error; |
---|
1554 | } |
---|
1555 | |
---|
1556 | |
---|
1557 | FT_LOCAL_DEF( void ) |
---|
1558 | cff_font_done( CFF_Font font ) |
---|
1559 | { |
---|
1560 | FT_Memory memory = font->memory; |
---|
1561 | FT_UInt idx; |
---|
1562 | |
---|
1563 | |
---|
1564 | cff_index_done( &font->global_subrs_index ); |
---|
1565 | cff_index_done( &font->string_index ); |
---|
1566 | cff_index_done( &font->font_dict_index ); |
---|
1567 | cff_index_done( &font->name_index ); |
---|
1568 | cff_index_done( &font->charstrings_index ); |
---|
1569 | |
---|
1570 | /* release font dictionaries, but only if working with */ |
---|
1571 | /* a CID keyed CFF font */ |
---|
1572 | if ( font->num_subfonts > 0 ) |
---|
1573 | { |
---|
1574 | for ( idx = 0; idx < font->num_subfonts; idx++ ) |
---|
1575 | cff_subfont_done( memory, font->subfonts[idx] ); |
---|
1576 | |
---|
1577 | /* the subfonts array has been allocated as a single block */ |
---|
1578 | FT_FREE( font->subfonts[0] ); |
---|
1579 | } |
---|
1580 | |
---|
1581 | cff_encoding_done( &font->encoding ); |
---|
1582 | cff_charset_done( &font->charset, font->stream ); |
---|
1583 | |
---|
1584 | cff_subfont_done( memory, &font->top_font ); |
---|
1585 | |
---|
1586 | CFF_Done_FD_Select( &font->fd_select, font->stream ); |
---|
1587 | |
---|
1588 | if (font->font_info != NULL) |
---|
1589 | { |
---|
1590 | FT_FREE( font->font_info->version ); |
---|
1591 | FT_FREE( font->font_info->notice ); |
---|
1592 | FT_FREE( font->font_info->full_name ); |
---|
1593 | FT_FREE( font->font_info->family_name ); |
---|
1594 | FT_FREE( font->font_info->weight ); |
---|
1595 | FT_FREE( font->font_info ); |
---|
1596 | } |
---|
1597 | |
---|
1598 | FT_FREE( font->registry ); |
---|
1599 | FT_FREE( font->ordering ); |
---|
1600 | |
---|
1601 | FT_FREE( font->global_subrs ); |
---|
1602 | FT_FREE( font->font_name ); |
---|
1603 | } |
---|
1604 | |
---|
1605 | |
---|
1606 | /* END */ |
---|