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