/src/ghostpdl/psi/zfapi.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2025 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Font API client */ |
18 | | |
19 | | #include "stdlib.h" /* abs() */ |
20 | | |
21 | | #include "memory_.h" |
22 | | #include "math_.h" |
23 | | #include "stat_.h" /* include before definition of esp macro, bug 691123 */ |
24 | | #include "string_.h" |
25 | | #include "ghost.h" |
26 | | #include "gp.h" |
27 | | #include "oper.h" |
28 | | #include "gxdevice.h" |
29 | | #include "gxfont.h" |
30 | | #include "gxfont1.h" |
31 | | #include "gxchar.h" |
32 | | #include "gzpath.h" |
33 | | #include "gxpath.h" |
34 | | #include "gxfcache.h" |
35 | | #include "gxchrout.h" |
36 | | #include "gximask.h" |
37 | | #include "gscoord.h" |
38 | | #include "gspaint.h" |
39 | | #include "gsfont.h" |
40 | | #include "gspath.h" |
41 | | #include "bfont.h" |
42 | | #include "dstack.h" |
43 | | #include "estack.h" |
44 | | #include "ichar.h" |
45 | | #include "idict.h" |
46 | | #include "iname.h" |
47 | | #include "ifont.h" |
48 | | #include "icid.h" |
49 | | #include "igstate.h" |
50 | | #include "icharout.h" |
51 | | |
52 | | #include "ifapi.h" |
53 | | #include "iplugin.h" |
54 | | #include "store.h" |
55 | | #include "gzstate.h" |
56 | | /* #include "gdevpsf.h" */ |
57 | | #include "stream.h" /* for files.h */ |
58 | | #include "gscrypt1.h" |
59 | | #include "gxfcid.h" |
60 | | #include "gsstype.h" |
61 | | #include "gxchar.h" /* for st_gs_show_enum */ |
62 | | #include "ipacked.h" /* for packed_next */ |
63 | | #include "iddict.h" |
64 | | #include "ifont42.h" /* for string_array_access_proc */ |
65 | | #include "gdebug.h" |
66 | | #include "gsimage.h" |
67 | | #include "gxcldev.h" |
68 | | #include "gxdevmem.h" |
69 | | |
70 | | #include "gxfapi.h" |
71 | | |
72 | | /* -------------------------------------------------------- */ |
73 | | |
74 | | typedef struct sfnts_reader_s sfnts_reader; |
75 | | struct sfnts_reader_s |
76 | | { |
77 | | ref *sfnts; |
78 | | const gs_memory_t *memory; |
79 | | const byte *p; |
80 | | long index; |
81 | | uint offset; |
82 | | uint length; |
83 | | int error; |
84 | | byte(*rbyte) (sfnts_reader *r); |
85 | | ushort(*rword) (sfnts_reader *r); |
86 | | ulong(*rlong) (sfnts_reader *r); |
87 | | int (*rstring) (sfnts_reader *r, byte *v, int length); |
88 | | void (*seek) (sfnts_reader *r, ulong pos); |
89 | | }; |
90 | | |
91 | | static void |
92 | | sfnts_next_elem(sfnts_reader *r) |
93 | 438 | { |
94 | 438 | ref s; |
95 | 438 | int code; |
96 | | |
97 | 438 | if (r->error < 0) |
98 | 0 | return; |
99 | 438 | do { |
100 | 438 | r->index++; |
101 | 438 | code = array_get(r->memory, r->sfnts, r->index, &s); |
102 | 438 | if (code < 0) { |
103 | 22 | r->error = code; |
104 | 22 | return; |
105 | 22 | } |
106 | 416 | if (!r_has_type(&s, t_string)) { |
107 | 8 | r->error = gs_note_error(gs_error_typecheck); |
108 | 8 | return; |
109 | 8 | } |
110 | 408 | r->p = s.value.const_bytes; |
111 | 408 | r->length = r_size(&s) & ~(uint) 1; /* See Adobe Technical Note # 5012, section 4.2. */ |
112 | 408 | } while (r->length == 0); |
113 | 408 | r->offset = 0; |
114 | 408 | } |
115 | | |
116 | | static inline byte |
117 | | sfnts_reader_rbyte_inline(sfnts_reader *r) |
118 | 6.91k | { |
119 | 6.91k | if (r->offset >= r->length) |
120 | 0 | sfnts_next_elem(r); |
121 | 6.91k | return ((r->error < 0) ? 0 : r->p[r->offset++]); |
122 | 6.91k | } |
123 | | |
124 | | static byte |
125 | | sfnts_reader_rbyte(sfnts_reader *r) |
126 | 0 | { /* old compiler compatibility */ |
127 | 0 | return (sfnts_reader_rbyte_inline(r)); |
128 | 0 | } |
129 | | |
130 | 512 | #define SFNTS_READER_RBYTE_TO_USHORT(r) ((ulong)sfnts_reader_rbyte_inline(r)) |
131 | | |
132 | | static ushort |
133 | | sfnts_reader_rword(sfnts_reader *r) |
134 | 256 | { |
135 | 256 | ushort retval; |
136 | | |
137 | 256 | retval = SFNTS_READER_RBYTE_TO_USHORT(r) << 8; |
138 | 256 | retval += SFNTS_READER_RBYTE_TO_USHORT(r); |
139 | | |
140 | 256 | return retval; |
141 | 256 | } |
142 | | |
143 | | #undef SFNTS_READER_RBYTE_TO_USHORT |
144 | | |
145 | 6.40k | #define SFNTS_READER_RBYTE_TO_ULONG(r) ((ulong)sfnts_reader_rbyte_inline(r)) |
146 | | |
147 | | static ulong |
148 | | sfnts_reader_rlong(sfnts_reader *r) |
149 | 1.60k | { |
150 | 1.60k | ulong retval; |
151 | 1.60k | retval = SFNTS_READER_RBYTE_TO_ULONG(r) << 24; |
152 | 1.60k | retval += SFNTS_READER_RBYTE_TO_ULONG(r) << 16; |
153 | 1.60k | retval += SFNTS_READER_RBYTE_TO_ULONG(r) << 8; |
154 | 1.60k | retval += SFNTS_READER_RBYTE_TO_ULONG(r); |
155 | 1.60k | return retval; |
156 | 1.60k | } |
157 | | |
158 | | #undef SFNTS_READER_RWORD_TO_LONG |
159 | | |
160 | | static int |
161 | | sfnts_reader_rstring(sfnts_reader *r, byte *v, int length) |
162 | 536 | { |
163 | 536 | int rlength = length; |
164 | | |
165 | 536 | if (length <= 0) |
166 | 0 | return (0); |
167 | 560 | while (r->error >= 0) { |
168 | 548 | int l = min(length, r->length - r->offset); |
169 | | |
170 | 548 | memcpy(v, r->p + r->offset, l); |
171 | 548 | length -= l; |
172 | 548 | r->offset += l; |
173 | 548 | if (length <= 0) |
174 | 524 | return (rlength); |
175 | 24 | v += l; |
176 | 24 | sfnts_next_elem(r); |
177 | 24 | } |
178 | 12 | return (rlength - length); |
179 | 536 | } |
180 | | |
181 | | static void |
182 | | sfnts_reader_seek(sfnts_reader *r, ulong pos) |
183 | 42 | { /* fixme : optimize */ |
184 | 42 | ulong skipped = 0; |
185 | | |
186 | 42 | r->index = -1; |
187 | 42 | sfnts_next_elem(r); |
188 | 350 | while (skipped + r->length < pos && r->error >= 0) { |
189 | 308 | skipped += r->length; |
190 | 308 | sfnts_next_elem(r); |
191 | 308 | } |
192 | 42 | r->offset = pos - skipped; |
193 | 42 | } |
194 | | |
195 | | static void |
196 | | sfnts_reader_init(const gs_memory_t *mem, sfnts_reader *r, ref *pdr) |
197 | 64 | { |
198 | 64 | r->memory = mem; |
199 | 64 | r->rbyte = sfnts_reader_rbyte; |
200 | 64 | r->rword = sfnts_reader_rword; |
201 | 64 | r->rlong = sfnts_reader_rlong; |
202 | 64 | r->rstring = sfnts_reader_rstring; |
203 | 64 | r->seek = sfnts_reader_seek; |
204 | 64 | r->index = -1; |
205 | 64 | r->error = 0; |
206 | 64 | if (r_type(pdr) != t_dictionary || |
207 | 64 | dict_find_string(pdr, "sfnts", &r->sfnts) <= 0) |
208 | 0 | r->error = gs_error_undefined; |
209 | 64 | sfnts_next_elem(r); |
210 | 64 | } |
211 | | |
212 | | /* -------------------------------------------------------- */ |
213 | | |
214 | | typedef struct sfnts_writer_s sfnts_writer; |
215 | | struct sfnts_writer_s |
216 | | { |
217 | | byte *buf, *p; |
218 | | int buf_size; |
219 | | void (*wbyte) (sfnts_writer *w, byte v); |
220 | | void (*wword) (sfnts_writer *w, ushort v); |
221 | | void (*wlong) (sfnts_writer *w, ulong v); |
222 | | void (*wstring) (sfnts_writer *w, byte *v, int length); |
223 | | }; |
224 | | |
225 | | static void |
226 | | sfnts_writer_wbyte(sfnts_writer *w, byte v) |
227 | 4 | { |
228 | 4 | if (w->buf + w->buf_size < w->p + 1) |
229 | 0 | return; /* safety */ |
230 | 4 | w->p[0] = v; |
231 | 4 | w->p++; |
232 | 4 | } |
233 | | |
234 | | static void |
235 | | sfnts_writer_wword(sfnts_writer *w, ushort v) |
236 | 128 | { |
237 | 128 | if (w->buf + w->buf_size < w->p + 2) |
238 | 0 | return; /* safety */ |
239 | 128 | w->p[0] = v / 256; |
240 | 128 | w->p[1] = v % 256; |
241 | 128 | w->p += 2; |
242 | 128 | } |
243 | | |
244 | | static void |
245 | | sfnts_writer_wlong(sfnts_writer *w, ulong v) |
246 | 608 | { |
247 | 608 | if (w->buf + w->buf_size < w->p + 4) |
248 | 0 | return; /* safety */ |
249 | 608 | w->p[0] = v >> 24; |
250 | 608 | w->p[1] = (v >> 16) & 0xFF; |
251 | 608 | w->p[2] = (v >> 8) & 0xFF; |
252 | 608 | w->p[3] = v & 0xFF; |
253 | 608 | w->p += 4; |
254 | 608 | } |
255 | | |
256 | | static void |
257 | | sfnts_writer_wstring(sfnts_writer *w, byte *v, int length) |
258 | 216 | { |
259 | 216 | if (w->buf + w->buf_size < w->p + length) |
260 | 0 | return; /* safety */ |
261 | 216 | memcpy(w->p, v, length); |
262 | 216 | w->p += length; |
263 | 216 | } |
264 | | |
265 | | static const sfnts_writer sfnts_writer_stub = { |
266 | | 0, 0, 0, |
267 | | sfnts_writer_wbyte, |
268 | | sfnts_writer_wword, |
269 | | sfnts_writer_wlong, |
270 | | sfnts_writer_wstring |
271 | | }; |
272 | | |
273 | | /* -------------------------------------------------------- */ |
274 | | |
275 | | static inline bool |
276 | | sfnts_need_copy_table(byte *tag) |
277 | 814 | { |
278 | 814 | return (memcmp(tag, "glyf", 4) && memcmp(tag, "glyx", 4) && /* Presents in files created by AdobePS5.dll Version 5.1.2 */ |
279 | 814 | memcmp(tag, "loca", 4) && memcmp(tag, "locx", 4) && /* Presents in files created by AdobePS5.dll Version 5.1.2 */ |
280 | 814 | memcmp(tag, "cmap", 4)); |
281 | 814 | } |
282 | | |
283 | | static void |
284 | | sfnt_copy_table(sfnts_reader *r, sfnts_writer *w, int length) |
285 | 42 | { |
286 | 42 | byte buf[1024]; |
287 | | |
288 | 66 | while (length > 0 && r->error >= 0) { |
289 | 24 | int l = min(length, sizeof(buf)); |
290 | | |
291 | 24 | (void)r->rstring(r, buf, l); |
292 | 24 | w->wstring(w, buf, l); |
293 | 24 | length -= l; |
294 | 24 | } |
295 | 42 | } |
296 | | |
297 | | static int |
298 | | sfnts_copy_except_glyf(sfnts_reader *r, sfnts_writer *w) |
299 | 64 | { /* Note : TTC is not supported and probably is unuseful for Type 42. */ |
300 | | /* This skips glyf, loca and cmap from copying. */ |
301 | 64 | struct |
302 | 64 | { |
303 | 64 | byte tag[4]; |
304 | 64 | ulong checkSum, offset, offset_new, length; |
305 | 64 | } tables[40]; |
306 | 64 | const ushort alignment = 4; /* Not sure, maybe 2 */ |
307 | 64 | ulong version = r->rlong(r); |
308 | 64 | ushort num_tables = r->rword(r); |
309 | 64 | ushort i, num_tables_new = 0; |
310 | 64 | ushort searchRange, entrySelector = 0, rangeShift, v; |
311 | 64 | ulong size_new = 12; |
312 | | |
313 | 64 | if (num_tables > countof(tables)) { |
314 | 0 | r->error = gs_note_error(gs_error_invalidfont); |
315 | 0 | return r->error; |
316 | 0 | } |
317 | | |
318 | 64 | r->rword(r); /* searchRange */ |
319 | 64 | if (r->error < 0) |
320 | 0 | return r->error; |
321 | | |
322 | 64 | r->rword(r); /* entrySelector */ |
323 | 64 | if (r->error < 0) |
324 | 0 | return r->error; |
325 | | |
326 | 64 | r->rword(r); /* rangeShift */ |
327 | 64 | if (r->error < 0) |
328 | 0 | return r->error; |
329 | | |
330 | 576 | for (i = 0; i < num_tables && r->error >= 0; i++) { |
331 | 512 | (void)r->rstring(r, tables[i].tag, 4); |
332 | 512 | if (r->error < 0) |
333 | 0 | continue; |
334 | 512 | tables[i].checkSum = r->rlong(r); |
335 | 512 | tables[i].offset = r->rlong(r); |
336 | 512 | tables[i].length = r->rlong(r); |
337 | 512 | tables[i].offset_new = size_new; |
338 | 512 | if (sfnts_need_copy_table(tables[i].tag)) { |
339 | 384 | num_tables_new++; |
340 | 384 | size_new += |
341 | 384 | (tables[i].length + alignment - 1) / alignment * alignment; |
342 | 384 | } |
343 | 512 | } |
344 | 64 | if (r->error < 0) |
345 | 0 | return r->error; |
346 | 64 | size_new += num_tables_new * 16; |
347 | 64 | if (w == 0) { |
348 | 32 | return size_new; |
349 | 32 | } |
350 | 32 | searchRange = v = num_tables_new * 16; |
351 | 256 | for (i = 0; v; i++) { |
352 | 224 | v >>= 1; |
353 | 224 | searchRange |= v; |
354 | 224 | entrySelector++; |
355 | 224 | } |
356 | 32 | searchRange -= searchRange >> 1; |
357 | 32 | rangeShift = num_tables_new * 16 - searchRange; |
358 | | |
359 | 32 | w->wlong(w, version); |
360 | 32 | w->wword(w, num_tables_new); |
361 | 32 | w->wword(w, searchRange); |
362 | 32 | w->wword(w, entrySelector); |
363 | 32 | w->wword(w, rangeShift); |
364 | 288 | for (i = 0; i < num_tables; i++) { |
365 | 256 | if (sfnts_need_copy_table(tables[i].tag)) { |
366 | 192 | w->wstring(w, tables[i].tag, 4); |
367 | 192 | w->wlong(w, tables[i].checkSum); |
368 | 192 | w->wlong(w, tables[i].offset_new + num_tables_new * 16); |
369 | 192 | w->wlong(w, tables[i].length); |
370 | 192 | } |
371 | 256 | } |
372 | 78 | for (i = 0; i < num_tables && r->error >= 0; i++) { |
373 | 46 | if (sfnts_need_copy_table(tables[i].tag)) { |
374 | 42 | int k = tables[i].length; |
375 | | |
376 | 42 | r->seek(r, tables[i].offset); |
377 | | |
378 | 42 | if (w->p - w->buf != tables[i].offset_new + num_tables_new * 16) { |
379 | 0 | r->error = gs_error_invalidfont; /* the algorithm consistency check */ |
380 | 0 | continue; |
381 | 0 | } |
382 | 42 | sfnt_copy_table(r, w, tables[i].length); |
383 | 46 | for (; k & (alignment - 1); k++) |
384 | 4 | w->wbyte(w, 0); |
385 | 42 | } |
386 | 46 | } |
387 | 32 | if (r->error < 0) |
388 | 30 | return r->error; |
389 | | |
390 | 2 | return (size_new); |
391 | 32 | } |
392 | | |
393 | | static int |
394 | | true_type_size(const gs_memory_t *mem, ref *pdr, unsigned long int *length) |
395 | 32 | { |
396 | 32 | sfnts_reader r; |
397 | | |
398 | 32 | sfnts_reader_init(mem, &r, pdr); |
399 | 32 | *length = sfnts_copy_except_glyf(&r, 0); |
400 | | |
401 | 32 | return r.error; |
402 | 32 | } |
403 | | |
404 | | static int |
405 | | FAPI_FF_serialize_tt_font(gs_fapi_font *ff, void *buf, int buf_size) |
406 | 32 | { |
407 | 32 | ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2)); |
408 | 32 | sfnts_reader r; |
409 | 32 | sfnts_writer w = sfnts_writer_stub; |
410 | | |
411 | 32 | w.buf_size = buf_size; |
412 | 32 | w.buf = w.p = buf; |
413 | 32 | sfnts_reader_init(ff->memory, &r, pdr); |
414 | 32 | return sfnts_copy_except_glyf(&r, &w); |
415 | 32 | } |
416 | | |
417 | | static inline ushort |
418 | | float_to_ushort(float v) |
419 | 3.89M | { |
420 | 3.89M | return ((ushort) (v * 16)); /* fixme : the scale may depend on renderer */ |
421 | 3.89M | } |
422 | | |
423 | | /* In general, we assumed that the entries we use below have been validated (at least for type) |
424 | | * at definefont time. This means validating each entry only once, rather than on every read |
425 | | * here. Better, for example, for BlendDesignMap which is an array, of arrays, of arrays of |
426 | | * numbers. |
427 | | */ |
428 | | static int |
429 | | FAPI_FF_get_word(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index, unsigned short *ret) |
430 | 7.47M | { |
431 | 7.47M | gs_font_type1 *pfont = (gs_font_type1 *) ff->client_font_data; |
432 | 7.47M | ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2)); |
433 | 7.47M | int code = 0; |
434 | | |
435 | 7.47M | switch ((int)var_id) { |
436 | 0 | case gs_fapi_font_feature_Weight: |
437 | 0 | *ret = 0; /* wrong */ |
438 | 0 | break; |
439 | 0 | case gs_fapi_font_feature_ItalicAngle: |
440 | 0 | *ret = 0; /* wrong */ |
441 | 0 | break; |
442 | 0 | case gs_fapi_font_feature_IsFixedPitch: |
443 | 0 | *ret = 0; /* wrong */ |
444 | 0 | break; |
445 | 0 | case gs_fapi_font_feature_UnderLinePosition: |
446 | 0 | *ret = 0; /* wrong */ |
447 | 0 | break; |
448 | 0 | case gs_fapi_font_feature_UnderlineThickness: |
449 | 0 | *ret = 0; /* wrong */ |
450 | 0 | break; |
451 | 123k | case gs_fapi_font_feature_FontType: |
452 | 123k | *ret = (pfont->FontType == 2 ? 2 : 1); |
453 | 123k | break; |
454 | 987k | case gs_fapi_font_feature_FontBBox: |
455 | 987k | switch (index) { |
456 | 246k | case 0: |
457 | 246k | *ret = ((ushort) pfont->FontBBox.p.x); |
458 | 246k | break; |
459 | 246k | case 1: |
460 | 246k | *ret = ((ushort) pfont->FontBBox.p.y); |
461 | 246k | break; |
462 | 246k | case 2: |
463 | 246k | *ret = ((ushort) pfont->FontBBox.q.x); |
464 | 246k | break; |
465 | 246k | case 3: |
466 | 246k | *ret = ((ushort) pfont->FontBBox.q.y); |
467 | 246k | break; |
468 | 0 | default: |
469 | 0 | code = gs_note_error(gs_error_rangecheck); |
470 | 987k | } |
471 | 987k | break; |
472 | 987k | case gs_fapi_font_feature_BlueValues_count: |
473 | 246k | *ret = pfont->data.BlueValues.count; |
474 | 246k | break; |
475 | 1.92M | case gs_fapi_font_feature_BlueValues: |
476 | 1.92M | *ret = (float_to_ushort(pfont->data.BlueValues.values[index])); |
477 | 1.92M | break; |
478 | 246k | case gs_fapi_font_feature_OtherBlues_count: |
479 | 246k | *ret = pfont->data.OtherBlues.count; |
480 | 246k | break; |
481 | 0 | case gs_fapi_font_feature_OtherBlues: |
482 | 0 | *ret = (float_to_ushort(pfont->data.OtherBlues.values[index])); |
483 | 0 | break; |
484 | 246k | case gs_fapi_font_feature_FamilyBlues_count: |
485 | 246k | *ret = pfont->data.FamilyBlues.count; |
486 | 246k | break; |
487 | 0 | case gs_fapi_font_feature_FamilyBlues: |
488 | 0 | *ret = (float_to_ushort(pfont->data.FamilyBlues.values[index])); |
489 | 0 | break; |
490 | 246k | case gs_fapi_font_feature_FamilyOtherBlues_count: |
491 | 246k | *ret = pfont->data.FamilyOtherBlues.count; |
492 | 246k | break; |
493 | 0 | case gs_fapi_font_feature_FamilyOtherBlues: |
494 | 0 | *ret = (float_to_ushort(pfont->data.FamilyOtherBlues.values[index])); |
495 | 0 | break; |
496 | 246k | case gs_fapi_font_feature_BlueShift: |
497 | 246k | *ret = float_to_ushort(pfont->data.BlueShift); |
498 | 246k | break; |
499 | 246k | case gs_fapi_font_feature_BlueFuzz: |
500 | 246k | *ret = float_to_ushort(pfont->data.BlueShift); |
501 | 246k | break; |
502 | 246k | case gs_fapi_font_feature_StdHW: |
503 | 246k | *ret = (pfont->data.StdHW.count == 0 ? 0 : float_to_ushort(pfont->data.StdHW.values[0])); /* UFST bug ? */ |
504 | 246k | break; |
505 | 246k | case gs_fapi_font_feature_StdVW: |
506 | 246k | *ret = (pfont->data.StdVW.count == 0 ? 0 : float_to_ushort(pfont->data.StdVW.values[0])); /* UFST bug ? */ |
507 | 246k | break; |
508 | 246k | case gs_fapi_font_feature_StemSnapH_count: |
509 | 246k | *ret = pfont->data.StemSnapH.count; |
510 | 246k | break; |
511 | 493k | case gs_fapi_font_feature_StemSnapH: |
512 | 493k | *ret = float_to_ushort(pfont->data.StemSnapH.values[index]); |
513 | 493k | break; |
514 | 246k | case gs_fapi_font_feature_StemSnapV_count: |
515 | 246k | *ret = pfont->data.StemSnapV.count; |
516 | 246k | break; |
517 | 491k | case gs_fapi_font_feature_StemSnapV: |
518 | 491k | *ret = float_to_ushort(pfont->data.StemSnapV.values[index]); |
519 | 491k | break; |
520 | 246k | case gs_fapi_font_feature_ForceBold: |
521 | 246k | *ret = pfont->data.ForceBold; |
522 | 246k | break; |
523 | 0 | case gs_fapi_font_feature_LanguageGroup: |
524 | 0 | *ret = pfont->data.LanguageGroup; |
525 | 0 | break; |
526 | 0 | case gs_fapi_font_feature_lenIV: |
527 | 0 | *ret = ff->need_decrypt ? 0 : pfont->data.lenIV; |
528 | 0 | break; |
529 | 0 | case gs_fapi_font_feature_GlobalSubrs_count: |
530 | 0 | { |
531 | 0 | ref *Private, *GlobalSubrs; |
532 | |
|
533 | 0 | if (pfont->FontType == ft_encrypted2) { |
534 | 0 | if (dict_find_string(pdr, "Private", &Private) <= 0) { |
535 | 0 | *ret = 0; |
536 | 0 | break; |
537 | 0 | } |
538 | 0 | if (dict_find_string(Private, "GlobalSubrs", &GlobalSubrs) <= 0) { |
539 | 0 | *ret = 0; |
540 | 0 | break; |
541 | 0 | } |
542 | 0 | *ret = r_size(GlobalSubrs); |
543 | 0 | break; |
544 | 0 | } |
545 | 0 | *ret = 0; |
546 | 0 | break; |
547 | 0 | } |
548 | 246k | case gs_fapi_font_feature_Subrs_count: |
549 | 246k | { |
550 | 246k | ref *Private, *Subrs; |
551 | | |
552 | 246k | if (dict_find_string(pdr, "Private", &Private) <= 0) { |
553 | 0 | *ret = 0; |
554 | 0 | break; |
555 | 0 | } |
556 | 246k | if (dict_find_string(Private, "Subrs", &Subrs) <= 0) { |
557 | 0 | *ret = 0; |
558 | 0 | break; |
559 | 0 | } |
560 | 246k | *ret = r_size(Subrs); |
561 | 246k | break; |
562 | 246k | } |
563 | 0 | case gs_fapi_font_feature_CharStrings_count: |
564 | 0 | { |
565 | 0 | ref *CharStrings; |
566 | |
|
567 | 0 | if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0) |
568 | 0 | *ret = 0; |
569 | 0 | else |
570 | 0 | *ret = dict_maxlength(CharStrings); |
571 | 0 | break; |
572 | 246k | } |
573 | | /* Multiple Master specific */ |
574 | 493k | case gs_fapi_font_feature_DollarBlend: |
575 | 493k | { |
576 | 493k | ref *DBlend; |
577 | | |
578 | 493k | if (dict_find_string(pdr, "$Blend", &DBlend) <= 0) |
579 | 493k | *ret = 0; |
580 | 4 | else |
581 | 4 | *ret = 1; |
582 | 493k | break; |
583 | 246k | } |
584 | 6 | case gs_fapi_font_feature_BlendAxisTypes_count: |
585 | 6 | { |
586 | 6 | ref *Info, *Axes; |
587 | | |
588 | 6 | if (dict_find_string(pdr, "FontInfo", &Info) <= 0) { |
589 | 0 | *ret = 0; |
590 | 0 | break; |
591 | 0 | } |
592 | 6 | if (dict_find_string(Info, "BlendAxisTypes", &Axes) <= 0) { |
593 | 0 | *ret = 0; |
594 | 0 | break; |
595 | 0 | } |
596 | 6 | *ret = r_size(Axes); |
597 | 6 | break; |
598 | 6 | } |
599 | 0 | case gs_fapi_font_feature_BlendFontInfo_count: |
600 | 0 | { |
601 | 0 | ref *Info, *FontInfo; |
602 | |
|
603 | 0 | if (dict_find_string(pdr, "Blend", &Info) <= 0) { |
604 | 0 | *ret = 0; |
605 | 0 | break; |
606 | 0 | } |
607 | 0 | if (dict_find_string(Info, "FontInfo", &FontInfo) <= 0) { |
608 | 0 | *ret = 0; |
609 | 0 | break; |
610 | 0 | } |
611 | 0 | *ret = dict_length(FontInfo); |
612 | 0 | break; |
613 | 0 | } |
614 | 0 | case gs_fapi_font_feature_BlendPrivate_count: |
615 | 0 | { |
616 | 0 | ref *Info, *Private; |
617 | |
|
618 | 0 | if (dict_find_string(pdr, "Blend", &Info) <= 0) { |
619 | 0 | *ret = 0; |
620 | 0 | break; |
621 | 0 | } |
622 | 0 | if (dict_find_string(Info, "Private", &Private) <= 0) { |
623 | 0 | *ret = 0; |
624 | 0 | break; |
625 | 0 | } |
626 | 0 | *ret = dict_length(Private); |
627 | 0 | break; |
628 | 0 | } |
629 | 2 | case gs_fapi_font_feature_WeightVector_count: |
630 | 2 | { |
631 | 2 | *ret = pfont->data.WeightVector.count; |
632 | 2 | break; |
633 | 0 | } |
634 | 4 | case gs_fapi_font_feature_BlendDesignPositionsArrays_count: |
635 | 4 | { |
636 | 4 | ref *Info, *Array; |
637 | | |
638 | 4 | if (dict_find_string(pdr, "FontInfo", &Info) <= 0) { |
639 | 0 | *ret = 0; |
640 | 0 | break; |
641 | 0 | } |
642 | 4 | if (dict_find_string(Info, "BlendDesignPositions", &Array) <= 0) { |
643 | 0 | *ret = 0; |
644 | 0 | break; |
645 | 0 | } |
646 | 4 | *ret = r_size(Array); |
647 | 4 | break; |
648 | 4 | } |
649 | 4 | case gs_fapi_font_feature_BlendDesignMapArrays_count: |
650 | 4 | { |
651 | 4 | ref *Info, *Array; |
652 | | |
653 | 4 | if (dict_find_string(pdr, "FontInfo", &Info) <= 0) { |
654 | 0 | *ret = 0; |
655 | 0 | break; |
656 | 0 | } |
657 | 4 | if (dict_find_string(Info, "BlendDesignMap", &Array) <= 0) { |
658 | 0 | *ret = 0; |
659 | 0 | break; |
660 | 0 | } |
661 | 4 | *ret = r_size(Array); |
662 | 4 | break; |
663 | 4 | } |
664 | 2 | case gs_fapi_font_feature_BlendDesignMapSubArrays_count: |
665 | 2 | { |
666 | 2 | ref *Info, *Array, SubArray; |
667 | | |
668 | 2 | if (dict_find_string(pdr, "FontInfo", &Info) <= 0) { |
669 | 0 | *ret = 0; |
670 | 0 | break; |
671 | 0 | } |
672 | 2 | if (dict_find_string(Info, "BlendDesignMap", &Array) <= 0) { |
673 | 0 | *ret = 0; |
674 | 0 | break; |
675 | 0 | } |
676 | 2 | if (array_get(ff->memory, Array, index, &SubArray) < 0) { |
677 | 0 | *ret = 0; |
678 | 0 | break; |
679 | 0 | } |
680 | 2 | *ret = r_size(&SubArray); |
681 | 2 | break; |
682 | 2 | } |
683 | 2 | case gs_fapi_font_feature_DollarBlend_length: |
684 | 2 | { |
685 | 2 | ref *DBlend, Element, string; |
686 | 2 | int i, length = 0; |
687 | 2 | char Buffer[32]; |
688 | | |
689 | 2 | if (dict_find_string(pdr, "$Blend", &DBlend) <= 0) { |
690 | 0 | *ret = 0; |
691 | 0 | break; |
692 | 0 | } |
693 | 8 | for (i = 0; i < r_size(DBlend); i++) { |
694 | | /* When reading the real proc, we add a space between each entry */ |
695 | 6 | length++; |
696 | 6 | if (array_get(ff->memory, DBlend, i, &Element) < 0) { |
697 | 0 | length = 0; |
698 | 0 | break; |
699 | 0 | } |
700 | 6 | switch (r_btype(&Element)) { |
701 | 0 | case t_name: |
702 | 0 | name_string_ref(ff->memory, &Element, &string); |
703 | 0 | length += r_size(&string); |
704 | 0 | break; |
705 | 2 | case t_real: |
706 | 2 | gs_snprintf(Buffer, sizeof(Buffer), "%f", Element.value.realval); |
707 | 2 | length += strlen(Buffer); |
708 | 2 | break; |
709 | 0 | case t_integer: |
710 | 0 | gs_snprintf(Buffer, sizeof(Buffer), "%"PRIpsint, Element.value.intval); |
711 | 0 | length += strlen(Buffer); |
712 | 0 | break; |
713 | 4 | case t_operator: |
714 | 4 | { |
715 | 4 | op_def const *op; |
716 | | |
717 | 4 | op = op_index_def(r_size(&Element)); |
718 | 4 | length += strlen(op->oname + 1); |
719 | 4 | } |
720 | 4 | break; |
721 | 0 | default: |
722 | 0 | break; |
723 | 6 | } |
724 | | |
725 | 6 | if (length > max_ushort) { |
726 | 0 | length = 0; |
727 | 0 | break; |
728 | 0 | } |
729 | 6 | } |
730 | 2 | *ret = length; |
731 | 2 | break; |
732 | 2 | } |
733 | 2 | case gs_fapi_font_feature_BlendFontBBox_length: |
734 | 2 | { |
735 | 2 | ref *Blend, *bfbbox, bfbbox0; |
736 | 2 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
737 | 0 | *ret = 0; |
738 | 0 | break; |
739 | 0 | } |
740 | | |
741 | 2 | if (dict_find_string(Blend, "FontBBox", &bfbbox) <= 0) { |
742 | 0 | *ret = 0; |
743 | 0 | break; |
744 | 0 | } |
745 | 2 | if (!r_has_type(bfbbox, t_array) || array_get(ff->memory, bfbbox, 0, &bfbbox0) < 0) { |
746 | 0 | *ret = 0; |
747 | 0 | break; |
748 | 0 | } |
749 | 2 | *ret = (ushort)r_size(&bfbbox0); |
750 | 2 | break; |
751 | 2 | } |
752 | 16 | case gs_fapi_font_feature_BlendFontBBox: |
753 | 16 | { |
754 | 16 | ref *Blend, *bfbbox, subbfbbox, val; |
755 | 16 | int aind, ind; |
756 | 16 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
757 | 0 | *ret = 0; |
758 | 0 | break; |
759 | 0 | } |
760 | 16 | if (dict_find_string(Blend, "FontBBox", &bfbbox) <= 0) { |
761 | 0 | *ret = 0; |
762 | 0 | break; |
763 | 0 | } |
764 | 16 | ind = index % 4; |
765 | 16 | aind = (index - ind) /4; |
766 | 16 | if (array_get(ff->memory, bfbbox, aind, &subbfbbox) < 0) { |
767 | 0 | *ret = 0; |
768 | 0 | break; |
769 | 0 | } |
770 | 16 | if (array_get(ff->memory, &subbfbbox, ind, &val) < 0) { |
771 | 0 | *ret = 0; |
772 | 0 | break; |
773 | 0 | } |
774 | | |
775 | 16 | *ret = (ushort)val.value.intval; |
776 | 16 | break; |
777 | 16 | } |
778 | 2 | case gs_fapi_font_feature_BlendBlueValues_length: |
779 | 2 | { |
780 | 2 | ref *Priv, *Blend, *bbv; |
781 | 2 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
782 | 0 | *ret = 0; |
783 | 0 | break; |
784 | 0 | } |
785 | 2 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
786 | 0 | *ret = 0; |
787 | 0 | break; |
788 | 0 | } |
789 | 2 | if (dict_find_string(Priv, "BlueValues", &bbv) <= 0) { |
790 | 2 | *ret = 0; |
791 | 2 | break; |
792 | 2 | } |
793 | 0 | *ret = (ushort)r_size(bbv); |
794 | 0 | break; |
795 | 2 | } |
796 | 0 | case gs_fapi_font_feature_BlendBlueValues_count: |
797 | 0 | { |
798 | 0 | ref *Priv, *Blend, *bbv, sub; |
799 | |
|
800 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
801 | 0 | *ret = 0; |
802 | 0 | break; |
803 | 0 | } |
804 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
805 | 0 | *ret = 0; |
806 | 0 | break; |
807 | 0 | } |
808 | 0 | if (dict_find_string(Priv, "BlueValues", &bbv) <= 0) { |
809 | 0 | *ret = 0; |
810 | 0 | break; |
811 | 0 | } |
812 | 0 | if (array_get(ff->memory, bbv, index, &sub) < 0) { |
813 | 0 | *ret = 0; |
814 | 0 | break; |
815 | 0 | } |
816 | 0 | *ret = (ushort)r_size(&sub); |
817 | 0 | break; |
818 | 0 | } |
819 | 0 | case gs_fapi_font_feature_BlendBlueValues: |
820 | 0 | { |
821 | 0 | ref *Priv, *Blend, *bbv, sub, r; |
822 | 0 | int aind = 0; |
823 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
824 | 0 | *ret = 0; |
825 | 0 | break; |
826 | 0 | } |
827 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
828 | 0 | *ret = 0; |
829 | 0 | break; |
830 | 0 | } |
831 | 0 | if (dict_find_string(Priv, "BlueValues", &bbv) <= 0) { |
832 | 0 | *ret = 0; |
833 | 0 | break; |
834 | 0 | } |
835 | | |
836 | 0 | while (1) { |
837 | 0 | if ((code = array_get(ff->memory, bbv, aind++, &sub)) < 0) { |
838 | 0 | *ret = 0; |
839 | 0 | break; |
840 | 0 | } |
841 | 0 | if (index - (int)r_size(&sub) < 0) { |
842 | 0 | break; |
843 | 0 | } |
844 | 0 | index -= r_size(&sub); |
845 | 0 | } |
846 | 0 | if (code < 0) |
847 | 0 | break; |
848 | | |
849 | 0 | if (array_get(ff->memory, &sub, index, &r) < 0) { |
850 | 0 | *ret = 0; |
851 | 0 | break; |
852 | 0 | } |
853 | | |
854 | 0 | *ret = (ushort)r.value.intval; |
855 | 0 | break; |
856 | 0 | } |
857 | 2 | case gs_fapi_font_feature_BlendOtherBlues_length: |
858 | 2 | { |
859 | 2 | ref *Priv, *Blend, *bob; |
860 | 2 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
861 | 0 | *ret = 0; |
862 | 0 | break; |
863 | 0 | } |
864 | 2 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
865 | 0 | *ret = 0; |
866 | 0 | break; |
867 | 0 | } |
868 | 2 | if (dict_find_string(Priv, "OtherBlues", &bob) <= 0) { |
869 | 2 | *ret = 0; |
870 | 2 | break; |
871 | 2 | } |
872 | 0 | *ret = (ushort)r_size(bob); |
873 | 0 | break; |
874 | 2 | } |
875 | 0 | case gs_fapi_font_feature_BlendOtherBlues_count: |
876 | 0 | { |
877 | 0 | ref *Priv, *Blend, *bob, sub; |
878 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
879 | 0 | *ret = 0; |
880 | 0 | break; |
881 | 0 | } |
882 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
883 | 0 | *ret = 0; |
884 | 0 | break; |
885 | 0 | } |
886 | 0 | if (dict_find_string(Priv, "OtherBlues", &bob) <= 0) { |
887 | 0 | *ret = 0; |
888 | 0 | break; |
889 | 0 | } |
890 | | |
891 | 0 | if (array_get(ff->memory, bob, index, &sub) < 0) { |
892 | 0 | *ret = 0; |
893 | 0 | break; |
894 | 0 | } |
895 | 0 | *ret = (ushort)r_size(&sub); |
896 | 0 | break; |
897 | 0 | } |
898 | 0 | case gs_fapi_font_feature_BlendOtherBlues: |
899 | 0 | { |
900 | 0 | ref *Priv, *Blend, *bob, sub, r; |
901 | 0 | int aind = 0; |
902 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
903 | 0 | *ret = 0; |
904 | 0 | break; |
905 | 0 | } |
906 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
907 | 0 | *ret = 0; |
908 | 0 | break; |
909 | 0 | } |
910 | 0 | if (dict_find_string(Priv, "OtherBlues", &bob) <= 0) { |
911 | 0 | *ret = 0; |
912 | 0 | break; |
913 | 0 | } |
914 | | |
915 | 0 | while (1) { |
916 | 0 | if ((code = array_get(ff->memory, bob, aind++, &sub)) < 0) |
917 | 0 | break; |
918 | 0 | if (index - (int)r_size(&sub) < 0) { |
919 | 0 | break; |
920 | 0 | } |
921 | 0 | index -= r_size(&sub); |
922 | 0 | } |
923 | 0 | if (code < 0) { |
924 | 0 | *ret = 0; |
925 | 0 | break; |
926 | 0 | } |
927 | 0 | if (array_get(ff->memory, &sub, index, &r) < 0) { |
928 | 0 | *ret = 0; |
929 | 0 | break; |
930 | 0 | } |
931 | | |
932 | 0 | *ret = (ushort)r.value.intval; |
933 | 0 | break; |
934 | 0 | } |
935 | 2 | case gs_fapi_font_feature_BlendBlueScale_count: |
936 | 2 | { |
937 | 2 | ref *Priv, *Blend, *bbs; |
938 | 2 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
939 | 0 | *ret = 0; |
940 | 0 | break; |
941 | 0 | } |
942 | 2 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
943 | 0 | *ret = 0; |
944 | 0 | break; |
945 | 0 | } |
946 | 2 | if (dict_find_string(Priv, "BlueScale", &bbs) <= 0) { |
947 | 2 | *ret = 0; |
948 | 2 | break; |
949 | 2 | } |
950 | 0 | *ret = (ushort)r_size(bbs); |
951 | 0 | break; |
952 | 2 | } |
953 | 2 | case gs_fapi_font_feature_BlendBlueShift_count: |
954 | 2 | { |
955 | 2 | ref *Priv, *Blend, *bbs; |
956 | 2 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
957 | 0 | *ret = 0; |
958 | 0 | break; |
959 | 0 | } |
960 | 2 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
961 | 0 | *ret = 0; |
962 | 0 | break; |
963 | 0 | } |
964 | 2 | if (dict_find_string(Priv, "BlueShift", &bbs) <= 0) { |
965 | 2 | *ret = 0; |
966 | 2 | break; |
967 | 2 | } |
968 | 0 | *ret = (ushort)r_size(bbs); |
969 | 0 | break; |
970 | 2 | } |
971 | 0 | case gs_fapi_font_feature_BlendBlueShift: |
972 | 0 | { |
973 | 0 | ref *Priv, *Blend, *bbs, r; |
974 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
975 | 0 | *ret = 0; |
976 | 0 | break; |
977 | 0 | } |
978 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
979 | 0 | *ret = 0; |
980 | 0 | break; |
981 | 0 | } |
982 | 0 | if (dict_find_string(Priv, "BlueShift", &bbs) <= 0) { |
983 | 0 | *ret = 0; |
984 | 0 | break; |
985 | 0 | } |
986 | 0 | if (array_get(ff->memory, bbs, index, &r) < 0) { |
987 | 0 | *ret = 0; |
988 | 0 | break; |
989 | 0 | } |
990 | | |
991 | 0 | *ret = (ushort)r.value.intval; |
992 | 0 | break; |
993 | 0 | } |
994 | 2 | case gs_fapi_font_feature_BlendBlueFuzz_count: |
995 | 2 | { |
996 | 2 | ref *Priv, *Blend, *bbf; |
997 | 2 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
998 | 0 | *ret = 0; |
999 | 0 | break; |
1000 | 0 | } |
1001 | 2 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1002 | 0 | *ret = 0; |
1003 | 0 | break; |
1004 | 0 | } |
1005 | 2 | if (dict_find_string(Priv, "BlueFuzz", &bbf) <= 0) { |
1006 | 2 | *ret = 0; |
1007 | 2 | break; |
1008 | 2 | } |
1009 | 0 | *ret = (ushort)r_size(bbf); |
1010 | 0 | break; |
1011 | 2 | } |
1012 | 0 | case gs_fapi_font_feature_BlendBlueFuzz: |
1013 | 0 | { |
1014 | 0 | ref *Priv, *Blend, *bbf, r; |
1015 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1016 | 0 | *ret = 0; |
1017 | 0 | break; |
1018 | 0 | } |
1019 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1020 | 0 | *ret = 0; |
1021 | 0 | break; |
1022 | 0 | } |
1023 | 0 | if (dict_find_string(Priv, "BlueFuzz", &bbf) <= 0) { |
1024 | 0 | *ret = 0; |
1025 | 0 | break; |
1026 | 0 | } |
1027 | 0 | if (array_get(ff->memory, bbf, index, &r) < 0) { |
1028 | 0 | *ret = 0; |
1029 | 0 | break; |
1030 | 0 | } |
1031 | | |
1032 | 0 | *ret = (ushort)r.value.intval; |
1033 | 0 | break; |
1034 | 0 | } |
1035 | 2 | case gs_fapi_font_feature_BlendForceBold_count: |
1036 | 2 | { |
1037 | 2 | ref *Priv, *Blend, *bfb; |
1038 | 2 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1039 | 0 | *ret = 0; |
1040 | 0 | break; |
1041 | 0 | } |
1042 | 2 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1043 | 0 | *ret = 0; |
1044 | 0 | break; |
1045 | 0 | } |
1046 | 2 | if (dict_find_string(Priv, "ForceBold", &bfb) <= 0) { |
1047 | 2 | *ret = 0; |
1048 | 2 | break; |
1049 | 2 | } |
1050 | 0 | *ret = (ushort)r_size(bfb); |
1051 | 0 | break; |
1052 | 2 | } |
1053 | 0 | case gs_fapi_font_feature_BlendForceBold: |
1054 | 0 | { |
1055 | 0 | ref *Priv, *Blend, *bfb, r; |
1056 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1057 | 0 | *ret = 0; |
1058 | 0 | break; |
1059 | 0 | } |
1060 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1061 | 0 | *ret = 0; |
1062 | 0 | break; |
1063 | 0 | } |
1064 | 0 | if (dict_find_string(Priv, "BlueFuzz", &bfb) <= 0) { |
1065 | 0 | *ret = 0; |
1066 | 0 | break; |
1067 | 0 | } |
1068 | 0 | if (array_get(ff->memory, bfb, index, &r) < 0) { |
1069 | 0 | *ret = 0; |
1070 | 0 | break; |
1071 | 0 | } |
1072 | | |
1073 | 0 | *ret = (ushort)r.value.boolval; |
1074 | 0 | } |
1075 | 2 | case gs_fapi_font_feature_BlendStdHW_length: |
1076 | 2 | { |
1077 | 2 | ref *Priv, *Blend, *stdhw; |
1078 | 2 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1079 | 0 | *ret = 0; |
1080 | 0 | break; |
1081 | 0 | } |
1082 | 2 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1083 | 0 | *ret = 0; |
1084 | 0 | break; |
1085 | 0 | } |
1086 | 2 | if (dict_find_string(Priv, "StdHW", &stdhw) <= 0) { |
1087 | 2 | *ret = 0; |
1088 | 2 | break; |
1089 | 2 | } |
1090 | 0 | *ret = (ushort)r_size(stdhw); |
1091 | 0 | break; |
1092 | 2 | } |
1093 | 0 | case gs_fapi_font_feature_BlendStdHW_count: |
1094 | 0 | { |
1095 | 0 | ref *Priv, *Blend, *stdhw, sub; |
1096 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1097 | 0 | *ret = 0; |
1098 | 0 | break; |
1099 | 0 | } |
1100 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1101 | 0 | *ret = 0; |
1102 | 0 | break; |
1103 | 0 | } |
1104 | 0 | if (dict_find_string(Priv, "StdHW", &stdhw) <= 0) { |
1105 | 0 | *ret = 0; |
1106 | 0 | break; |
1107 | 0 | } |
1108 | | |
1109 | 0 | if (array_get(ff->memory, stdhw, index, &sub) < 0) { |
1110 | 0 | *ret = 0; |
1111 | 0 | break; |
1112 | 0 | } |
1113 | 0 | *ret = (ushort)r_size(&sub); |
1114 | 0 | break; |
1115 | 0 | } |
1116 | 0 | case gs_fapi_font_feature_BlendStdHW: |
1117 | 0 | { |
1118 | 0 | ref *Priv, *Blend, *stdhw, sub, r; |
1119 | 0 | int aind = 0; |
1120 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1121 | 0 | *ret = 0; |
1122 | 0 | break; |
1123 | 0 | } |
1124 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1125 | 0 | *ret = 0; |
1126 | 0 | break; |
1127 | 0 | } |
1128 | 0 | if (dict_find_string(Priv, "StdHW", &stdhw) <= 0) { |
1129 | 0 | *ret = 0; |
1130 | 0 | break; |
1131 | 0 | } |
1132 | | |
1133 | 0 | while (1) { |
1134 | 0 | if ((code = array_get(ff->memory, stdhw, aind++, &sub)) < 0) |
1135 | 0 | break; |
1136 | 0 | if (index - (int)r_size(&sub) < 0) { |
1137 | 0 | break; |
1138 | 0 | } |
1139 | 0 | index -= r_size(&sub); |
1140 | 0 | } |
1141 | 0 | if (code < 0) { |
1142 | 0 | *ret = 0; |
1143 | 0 | break; |
1144 | 0 | } |
1145 | 0 | if (array_get(ff->memory, &sub, index, &r) < 0) { |
1146 | 0 | *ret = 0; |
1147 | 0 | break; |
1148 | 0 | } |
1149 | | |
1150 | 0 | *ret = (ushort)r.value.intval; |
1151 | 0 | break; |
1152 | 0 | } |
1153 | 2 | case gs_fapi_font_feature_BlendStdVW_length: |
1154 | 2 | { |
1155 | 2 | ref *Priv, *Blend, *stdvw; |
1156 | 2 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1157 | 0 | *ret = 0; |
1158 | 0 | break; |
1159 | 0 | } |
1160 | 2 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1161 | 0 | *ret = 0; |
1162 | 0 | break; |
1163 | 0 | } |
1164 | 2 | if (dict_find_string(Priv, "StdVW", &stdvw) <= 0) { |
1165 | 2 | *ret = 0; |
1166 | 2 | break; |
1167 | 2 | } |
1168 | 0 | *ret = (ushort)r_size(stdvw); |
1169 | 0 | break; |
1170 | 2 | } |
1171 | 0 | case gs_fapi_font_feature_BlendStdVW_count: |
1172 | 0 | { |
1173 | 0 | ref *Priv, *Blend, *stdvw, sub; |
1174 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1175 | 0 | *ret = 0; |
1176 | 0 | break; |
1177 | 0 | } |
1178 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1179 | 0 | *ret = 0; |
1180 | 0 | break; |
1181 | 0 | } |
1182 | | |
1183 | 0 | if (dict_find_string(Priv, "StdVW", &stdvw) <= 0) { |
1184 | 0 | *ret = 0; |
1185 | 0 | break; |
1186 | 0 | } |
1187 | | |
1188 | 0 | if (array_get(ff->memory, stdvw, index, &sub) < 0) { |
1189 | 0 | *ret = 0; |
1190 | 0 | break; |
1191 | 0 | } |
1192 | 0 | *ret = (ushort)r_size(&sub); |
1193 | 0 | break; |
1194 | 0 | } |
1195 | 0 | case gs_fapi_font_feature_BlendStdVW: |
1196 | 0 | { |
1197 | 0 | ref *Priv, *Blend, *stdvw, sub, r; |
1198 | 0 | int aind = 0; |
1199 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1200 | 0 | *ret = 0; |
1201 | 0 | break; |
1202 | 0 | } |
1203 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1204 | 0 | *ret = 0; |
1205 | 0 | break; |
1206 | 0 | } |
1207 | 0 | if (dict_find_string(Priv, "StdVW", &stdvw) <= 0) { |
1208 | 0 | *ret = 0; |
1209 | 0 | break; |
1210 | 0 | } |
1211 | | |
1212 | 0 | while (1) { |
1213 | 0 | if ((code = array_get(ff->memory, stdvw, aind++, &sub)) < 0) |
1214 | 0 | break; |
1215 | 0 | if (index - (int)r_size(&sub) < 0) { |
1216 | 0 | break; |
1217 | 0 | } |
1218 | 0 | index -= r_size(&sub); |
1219 | 0 | } |
1220 | 0 | if (code < 0) { |
1221 | 0 | *ret = 0; |
1222 | 0 | break; |
1223 | 0 | } |
1224 | 0 | if (array_get(ff->memory, &sub, index, &r) < 0) { |
1225 | 0 | *ret = 0; |
1226 | 0 | break; |
1227 | 0 | } |
1228 | | |
1229 | 0 | *ret = (ushort)r.value.intval; |
1230 | 0 | break; |
1231 | 0 | } |
1232 | 2 | case gs_fapi_font_feature_BlendStemSnapH_length: |
1233 | 2 | { |
1234 | 2 | ref *Priv, *Blend, *ssh; |
1235 | 2 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1236 | 0 | *ret = 0; |
1237 | 0 | break; |
1238 | 0 | } |
1239 | 2 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1240 | 0 | *ret = 0; |
1241 | 0 | break; |
1242 | 0 | } |
1243 | 2 | if (dict_find_string(Priv, "StemSnapH", &ssh) <= 0) { |
1244 | 2 | *ret = 0; |
1245 | 2 | break; |
1246 | 2 | } |
1247 | 0 | *ret = (ushort)r_size(ssh); |
1248 | 0 | break; |
1249 | 2 | } |
1250 | 0 | case gs_fapi_font_feature_BlendStemSnapH_count: |
1251 | 0 | { |
1252 | 0 | ref *Priv, *Blend, *bssh, sub; |
1253 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1254 | 0 | *ret = 0; |
1255 | 0 | break; |
1256 | 0 | } |
1257 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1258 | 0 | *ret = 0; |
1259 | 0 | break; |
1260 | 0 | } |
1261 | 0 | if (dict_find_string(Priv, "StemSnapH", &bssh) <= 0) { |
1262 | 0 | *ret = 0; |
1263 | 0 | break; |
1264 | 0 | } |
1265 | | |
1266 | 0 | if (array_get(ff->memory, bssh, index, &sub) < 0) { |
1267 | 0 | *ret = 0; |
1268 | 0 | break; |
1269 | 0 | } |
1270 | 0 | *ret = (ushort)r_size(&sub); |
1271 | 0 | break; |
1272 | 0 | } |
1273 | 0 | case gs_fapi_font_feature_BlendStemSnapH: |
1274 | 0 | { |
1275 | 0 | ref *Priv, *Blend, *bssh, sub, r; |
1276 | 0 | int aind = 0; |
1277 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1278 | 0 | *ret = 0; |
1279 | 0 | break; |
1280 | 0 | } |
1281 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1282 | 0 | *ret = 0; |
1283 | 0 | break; |
1284 | 0 | } |
1285 | 0 | if (dict_find_string(Priv, "StemSnapH", &bssh) <= 0) { |
1286 | 0 | *ret = 0; |
1287 | 0 | break; |
1288 | 0 | } |
1289 | | |
1290 | 0 | while (1) { |
1291 | 0 | if ((code = array_get(ff->memory, bssh, aind++, &sub)) < 0) |
1292 | 0 | break; |
1293 | 0 | if (index - (int)r_size(&sub) < 0) { |
1294 | 0 | break; |
1295 | 0 | } |
1296 | 0 | index -= r_size(&sub); |
1297 | 0 | } |
1298 | 0 | if (code < 0) { |
1299 | 0 | *ret = 0; |
1300 | 0 | break; |
1301 | 0 | } |
1302 | 0 | if (array_get(ff->memory, &sub, index, &r) < 0) { |
1303 | 0 | *ret = 0; |
1304 | 0 | break; |
1305 | 0 | } |
1306 | | |
1307 | 0 | *ret = (ushort)r.value.intval; |
1308 | 0 | break; |
1309 | 0 | } |
1310 | 2 | case gs_fapi_font_feature_BlendStemSnapV_length: |
1311 | 2 | { |
1312 | 2 | ref *Priv, *Blend, *ssv; |
1313 | 2 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1314 | 0 | *ret = 0; |
1315 | 0 | break; |
1316 | 0 | } |
1317 | 2 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1318 | 0 | *ret = 0; |
1319 | 0 | break; |
1320 | 0 | } |
1321 | 2 | if (dict_find_string(Priv, "StdHW", &ssv) <= 0) { |
1322 | 2 | *ret = 0; |
1323 | 2 | break; |
1324 | 2 | } |
1325 | 0 | *ret = (ushort)r_size(ssv); |
1326 | 0 | break; |
1327 | 2 | } |
1328 | 0 | case gs_fapi_font_feature_BlendStemSnapV_count: |
1329 | 0 | { |
1330 | 0 | ref *Priv, *Blend, *bssv, sub; |
1331 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1332 | 0 | *ret = 0; |
1333 | 0 | break; |
1334 | 0 | } |
1335 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1336 | 0 | *ret = 0; |
1337 | 0 | break; |
1338 | 0 | } |
1339 | 0 | if (dict_find_string(Priv, "StemSnapV", &bssv) <= 0) { |
1340 | 0 | *ret = 0; |
1341 | 0 | break; |
1342 | 0 | } |
1343 | | |
1344 | 0 | if (array_get(ff->memory, bssv, index, &sub) < 0) { |
1345 | 0 | *ret = 0; |
1346 | 0 | break; |
1347 | 0 | } |
1348 | 0 | *ret = (ushort)r_size(&sub); |
1349 | 0 | break; |
1350 | 0 | } |
1351 | 0 | case gs_fapi_font_feature_BlendStemSnapV: |
1352 | 0 | { |
1353 | 0 | ref *Priv, *Blend, *bssv, sub, r; |
1354 | 0 | int aind = 0; |
1355 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1356 | 0 | *ret = 0; |
1357 | 0 | break; |
1358 | 0 | } |
1359 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1360 | 0 | *ret = 0; |
1361 | 0 | break; |
1362 | 0 | } |
1363 | 0 | if (dict_find_string(Priv, "StemSnapV", &bssv) <= 0) { |
1364 | 0 | *ret = 0; |
1365 | 0 | break; |
1366 | 0 | } |
1367 | | |
1368 | 0 | while (1) { |
1369 | 0 | if ((code = array_get(ff->memory, bssv, aind++, &sub)) < 0) |
1370 | 0 | break; |
1371 | 0 | if (index - (int)r_size(&sub) < 0) { |
1372 | 0 | break; |
1373 | 0 | } |
1374 | 0 | index -= r_size(&sub); |
1375 | 0 | } |
1376 | 0 | if (code < 0) { |
1377 | 0 | *ret = 0; |
1378 | 0 | break; |
1379 | 0 | } |
1380 | 0 | if (array_get(ff->memory, &sub, index, &r) < 0) { |
1381 | 0 | *ret = 0; |
1382 | 0 | break; |
1383 | 0 | } |
1384 | | |
1385 | 0 | *ret = (ushort)r.value.intval; |
1386 | 0 | break; |
1387 | 0 | } |
1388 | | |
1389 | | /* End MM specifics */ |
1390 | 7.47M | } |
1391 | 7.47M | return code; |
1392 | 7.47M | } |
1393 | | |
1394 | | static int |
1395 | | FAPI_FF_get_long(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index, unsigned long *ret) |
1396 | 246k | { |
1397 | 246k | gs_font_type1 *pfont = (gs_font_type1 *) ff->client_font_data; |
1398 | 246k | int code = 0; |
1399 | | |
1400 | 246k | ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2)); |
1401 | | |
1402 | 246k | switch ((int)var_id) { |
1403 | 0 | case gs_fapi_font_feature_UniqueID: |
1404 | 0 | *ret = pfont->UID.id; |
1405 | 0 | break; |
1406 | 246k | case gs_fapi_font_feature_BlueScale: |
1407 | 246k | *ret = (ulong) (pfont->data.BlueScale * 65536); |
1408 | 246k | break; |
1409 | 0 | case gs_fapi_font_feature_Subrs_total_size: |
1410 | 0 | { |
1411 | 0 | ref *Private, *Subrs, v; |
1412 | 0 | int lenIV = max(pfont->data.lenIV, 0), k; |
1413 | 0 | ulong size = 0; |
1414 | 0 | long i; |
1415 | 0 | const char *name[2] = { "Subrs", "GlobalSubrs" }; |
1416 | 0 | if (dict_find_string(pdr, "Private", &Private) <= 0) { |
1417 | 0 | *ret = 0; |
1418 | 0 | break; |
1419 | 0 | } |
1420 | 0 | for (k = 0; k < 2; k++) { |
1421 | 0 | if (dict_find_string(Private, name[k], &Subrs) > 0) |
1422 | 0 | for (i = r_size(Subrs) - 1; i >= 0; i--) { |
1423 | 0 | array_get(pfont->memory, Subrs, i, &v); |
1424 | 0 | if (r_type(&v) == t_string) { |
1425 | 0 | size += r_size(&v) - (ff->need_decrypt ? 0 : lenIV); |
1426 | 0 | } |
1427 | 0 | } |
1428 | 0 | } |
1429 | 0 | *ret = size; |
1430 | 0 | } |
1431 | 0 | break; |
1432 | 32 | case gs_fapi_font_feature_TT_size: |
1433 | 32 | code = true_type_size(ff->memory, pdr, ret); |
1434 | 32 | break; |
1435 | 246k | } |
1436 | 246k | return code; |
1437 | 246k | } |
1438 | | |
1439 | | static int |
1440 | | FAPI_FF_get_float(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index, float *ret) |
1441 | 1.48M | { |
1442 | 1.48M | gs_font_type1 *pfont1 = (gs_font_type1 *) ff->client_font_data; |
1443 | 1.48M | gs_font_base *pbfont = (gs_font_base *) ff->client_font_data2; |
1444 | 1.48M | ref *pdr = pfont_dict(pbfont); |
1445 | 1.48M | int code = 0; |
1446 | 1.48M | gs_fapi_server *I = pbfont->FAPI; |
1447 | | |
1448 | 1.48M | switch ((int)var_id) { |
1449 | 1.48M | case gs_fapi_font_feature_FontMatrix: |
1450 | 1.48M | { |
1451 | 1.48M | double FontMatrix_div; |
1452 | 1.48M | gs_matrix m, *mptr; |
1453 | | |
1454 | 1.48M | if (I && I->get_fontmatrix) { |
1455 | 1.48M | FontMatrix_div = 1; |
1456 | 1.48M | mptr = &m; |
1457 | 1.48M | I->get_fontmatrix(I, mptr); |
1458 | 1.48M | } |
1459 | 0 | else { |
1460 | 0 | FontMatrix_div = |
1461 | 0 | ((ff->is_cid |
1462 | 0 | && (!FAPI_ISCIDFONT(pbfont))) ? 1000 : 1); |
1463 | 0 | mptr = &(pbfont->base->FontMatrix); |
1464 | 0 | } |
1465 | 1.48M | switch (index) { |
1466 | 246k | case 0: |
1467 | 246k | default: |
1468 | 246k | *ret = (mptr->xx / FontMatrix_div); |
1469 | 246k | break; |
1470 | 246k | case 1: |
1471 | 246k | *ret = (mptr->xy / FontMatrix_div); |
1472 | 246k | break; |
1473 | 246k | case 2: |
1474 | 246k | *ret = (mptr->yx / FontMatrix_div); |
1475 | 246k | break; |
1476 | 246k | case 3: |
1477 | 246k | *ret = (mptr->yy / FontMatrix_div); |
1478 | 246k | break; |
1479 | 246k | case 4: |
1480 | 246k | *ret = (mptr->tx / FontMatrix_div); |
1481 | 246k | break; |
1482 | 246k | case 5: |
1483 | 246k | *ret = (mptr->ty / FontMatrix_div); |
1484 | 246k | break; |
1485 | 1.48M | } |
1486 | 1.48M | break; |
1487 | 1.48M | } |
1488 | | |
1489 | 1.48M | case gs_fapi_font_feature_WeightVector: |
1490 | 4 | { |
1491 | 4 | if (index < pfont1->data.WeightVector.count) { |
1492 | 4 | *ret = pfont1->data.WeightVector.values[index]; |
1493 | 4 | } |
1494 | 0 | else { |
1495 | 0 | *ret = 0; |
1496 | 0 | } |
1497 | 4 | } |
1498 | 4 | break; |
1499 | 12 | case gs_fapi_font_feature_BlendDesignPositionsArrayValue: |
1500 | 12 | { |
1501 | 12 | ref *Info, *Array, SubArray, value; |
1502 | 12 | int array_index = index / 8; |
1503 | | |
1504 | 12 | index %= 8; |
1505 | 12 | if (dict_find_string(pdr, "FontInfo", &Info) <= 0) { |
1506 | 0 | *ret = 0; |
1507 | 0 | break; |
1508 | 0 | } |
1509 | 12 | if (dict_find_string(Info, "BlendDesignPositions", &Array) <= 0) { |
1510 | 0 | *ret = 0; |
1511 | 0 | break; |
1512 | 0 | } |
1513 | 12 | if (array_get(ff->memory, Array, array_index, &SubArray) < 0) { |
1514 | 4 | *ret = 0; |
1515 | 4 | break; |
1516 | 4 | } |
1517 | 8 | if (array_get(ff->memory, &SubArray, index, &value) < 0) |
1518 | 2 | return 0; |
1519 | 6 | if (!r_has_type(&value, t_integer)) { |
1520 | 0 | if (r_has_type(&value, t_real)) { |
1521 | 0 | *ret = value.value.realval; |
1522 | 0 | } |
1523 | 0 | else |
1524 | 0 | *ret = 0; |
1525 | 0 | } |
1526 | 6 | else |
1527 | 6 | *ret = ((float)value.value.intval); |
1528 | 6 | } |
1529 | 0 | break; |
1530 | 0 | case gs_fapi_font_feature_BlendDesignMapArrayValue: |
1531 | 0 | { |
1532 | 0 | ref *Info, *Array, SubArray, SubSubArray, value; |
1533 | 0 | int array_index = index / 64; |
1534 | |
|
1535 | 0 | index %= 8; |
1536 | 0 | if (dict_find_string(pdr, "FontInfo", &Info) <= 0) { |
1537 | 0 | *ret = 0; |
1538 | 0 | break; |
1539 | 0 | } |
1540 | 0 | if (dict_find_string(Info, "BlendDesignMap", &Array) <= 0) { |
1541 | 0 | *ret = 0; |
1542 | 0 | break; |
1543 | 0 | } |
1544 | 0 | if (array_get(ff->memory, Array, array_index, &SubArray) < 0) { |
1545 | 0 | *ret = 0; |
1546 | 0 | break; |
1547 | 0 | } |
1548 | 0 | if (array_get(ff->memory, &SubArray, index, &SubSubArray) < 0) { |
1549 | 0 | *ret = 0; |
1550 | 0 | break; |
1551 | 0 | } |
1552 | 0 | if (array_get(ff->memory, &SubSubArray, index, &value) < 0) { |
1553 | 0 | *ret = 0; |
1554 | 0 | break; |
1555 | 0 | } |
1556 | 0 | if (!r_has_type(&value, t_integer)) { |
1557 | 0 | if (r_has_type(&value, t_real)) { |
1558 | 0 | *ret = (value.value.realval); |
1559 | 0 | } |
1560 | 0 | else |
1561 | 0 | *ret = 0; |
1562 | 0 | } |
1563 | 0 | else |
1564 | 0 | *ret = ((float)value.value.intval); |
1565 | 0 | } |
1566 | 0 | break; |
1567 | 0 | case gs_fapi_font_feature_BlendBlueScale: |
1568 | 0 | { |
1569 | 0 | ref *Priv, *Blend, *bbs, r; |
1570 | |
|
1571 | 0 | if (dict_find_string(pdr, "Blend", &Blend) <= 0) { |
1572 | 0 | *ret = 0; |
1573 | 0 | break; |
1574 | 0 | } |
1575 | 0 | if (dict_find_string(Blend, "Private", &Priv) <= 0) { |
1576 | 0 | *ret = 0; |
1577 | 0 | break; |
1578 | 0 | } |
1579 | 0 | if (dict_find_string(Priv, "BlueScale", &bbs) <= 0) { |
1580 | 0 | *ret = 0; |
1581 | 0 | break; |
1582 | 0 | } |
1583 | 0 | if (array_get(ff->memory, bbs, index, &r) < 0) { |
1584 | 0 | *ret = 0; |
1585 | 0 | break; |
1586 | 0 | } |
1587 | 0 | if (r_has_type(&r, t_real)) |
1588 | 0 | *ret = r.value.realval; |
1589 | 0 | else if (r_has_type(&r, t_integer)) |
1590 | 0 | *ret = (float)r.value.intval; |
1591 | 0 | } |
1592 | 0 | break; |
1593 | 1.48M | } |
1594 | 1.48M | return code; |
1595 | 1.48M | } |
1596 | | |
1597 | | static int |
1598 | | FAPI_FF_get_name(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index, |
1599 | | char *Buffer, int len) |
1600 | 2 | { |
1601 | 2 | ref name, string; |
1602 | 2 | ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2)); |
1603 | 2 | int code = 0; |
1604 | | |
1605 | 2 | switch ((int)var_id) { |
1606 | 2 | case gs_fapi_font_feature_BlendAxisTypes: |
1607 | 2 | { |
1608 | 2 | ref *Info, *Axes; |
1609 | | |
1610 | 2 | if (dict_find_string(pdr, "FontInfo", &Info) <= 0) { |
1611 | 0 | code = gs_note_error(gs_error_undefined); |
1612 | 0 | break; |
1613 | 0 | } |
1614 | 2 | if (dict_find_string(Info, "BlendAxisTypes", &Axes) <= 0) { |
1615 | 0 | code = gs_note_error(gs_error_undefined); |
1616 | 0 | break; |
1617 | 0 | } |
1618 | 2 | if (!r_has_type(Axes, t_array)) { |
1619 | 0 | code = gs_note_error(gs_error_undefined); |
1620 | 0 | break; |
1621 | 0 | } |
1622 | 2 | if (array_get(ff->memory, Axes, index, &name) < 0) { |
1623 | 0 | code = gs_note_error(gs_error_undefined); |
1624 | 0 | break; |
1625 | 0 | } |
1626 | 2 | } |
1627 | 2 | } |
1628 | 2 | if (code >= 0) { |
1629 | 2 | name_string_ref(ff->memory, &name, &string); |
1630 | 2 | if (r_size(&string) < len) { |
1631 | 2 | memcpy(Buffer, string.value.const_bytes, r_size(&string)); |
1632 | 2 | Buffer[r_size(&string)] = 0x00; |
1633 | 2 | } |
1634 | 0 | else { |
1635 | 0 | code = gs_note_error(gs_error_unknownerror); |
1636 | 0 | } |
1637 | 2 | } |
1638 | 2 | return code; |
1639 | 2 | } |
1640 | | |
1641 | | /* NOTE: we checked the type of $Blend at definefont time, so we know it is a |
1642 | | * procedure and don't need to check it again here |
1643 | | */ |
1644 | | static int |
1645 | | FAPI_FF_get_proc(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index, |
1646 | | char *Buffer) |
1647 | 2 | { |
1648 | 2 | ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2)); |
1649 | 2 | char *ptr = Buffer; |
1650 | 2 | int code = 0; |
1651 | | |
1652 | 2 | if (!Buffer) |
1653 | 1 | return_error(gs_error_unknownerror); |
1654 | | |
1655 | 1 | switch ((int)var_id) { |
1656 | 1 | case gs_fapi_font_feature_DollarBlend: |
1657 | 1 | { |
1658 | 1 | ref *DBlend, Element, string; |
1659 | 1 | int i; |
1660 | 1 | char Buf[32]; |
1661 | | |
1662 | 1 | if (dict_find_string(pdr, "$Blend", &DBlend) <= 0) { |
1663 | 0 | code = gs_note_error(gs_error_undefined); |
1664 | 0 | break; |
1665 | 0 | } |
1666 | 4 | for (i = 0; i < r_size(DBlend); i++) { |
1667 | 3 | *ptr++ = 0x20; |
1668 | 3 | if (array_get(ff->memory, DBlend, i, &Element) < 0) { |
1669 | 0 | code = gs_note_error(gs_error_undefined); |
1670 | 0 | break; |
1671 | 0 | } |
1672 | 3 | switch (r_btype(&Element)) { |
1673 | 0 | case t_name: |
1674 | 0 | name_string_ref(ff->memory, &Element, &string); |
1675 | |
|
1676 | 0 | strncpy(ptr, (char *)string.value.const_bytes, |
1677 | 0 | r_size(&string)); |
1678 | 0 | ptr += r_size(&string); |
1679 | 0 | break; |
1680 | 1 | case t_real: |
1681 | 1 | gs_snprintf(Buf, sizeof(Buf), "%f", Element.value.realval); |
1682 | 1 | strcpy(ptr, Buf); |
1683 | 1 | ptr += strlen(Buf); |
1684 | 1 | break; |
1685 | 0 | case t_integer: |
1686 | 0 | gs_snprintf(Buf, sizeof(Buf), "%"PRIpsint, Element.value.intval); |
1687 | 0 | strcpy(ptr, Buf); |
1688 | 0 | ptr += strlen(Buf); |
1689 | 0 | break; |
1690 | 2 | case t_operator: |
1691 | 2 | { |
1692 | 2 | op_def const *op; |
1693 | | |
1694 | 2 | op = op_index_def(r_size(&Element)); |
1695 | 2 | strcpy(ptr, op->oname + 1); |
1696 | 2 | ptr += strlen(op->oname + 1); |
1697 | 2 | } |
1698 | 2 | break; |
1699 | 0 | default: |
1700 | 0 | break; |
1701 | 3 | } |
1702 | 3 | } |
1703 | 1 | } |
1704 | 1 | } |
1705 | 1 | return code < 0 ? code : (ptr - Buffer); |
1706 | 1 | } |
1707 | | |
1708 | | static inline void |
1709 | | decode_bytes(byte *p, const byte *s, int l, int lenIV) |
1710 | 2.39M | { |
1711 | 2.39M | ushort state = 4330; |
1712 | | |
1713 | 213M | for (; l; s++, l--) { |
1714 | 211M | uchar c = (*s ^ (state >> 8)); |
1715 | | |
1716 | 211M | state = (*s + state) * crypt_c1 + crypt_c2; |
1717 | 211M | if (lenIV > 0) |
1718 | 9.58M | lenIV--; |
1719 | 201M | else { |
1720 | 201M | *p = c; |
1721 | 201M | p++; |
1722 | 201M | } |
1723 | 211M | } |
1724 | 2.39M | } |
1725 | | |
1726 | | static int |
1727 | | get_type1_data(gs_fapi_font *ff, const ref *type1string, |
1728 | | byte *buf, int buf_length) |
1729 | 3.63M | { |
1730 | 3.63M | gs_font_type1 *pfont = (gs_font_type1 *) ff->client_font_data; |
1731 | 3.63M | int lenIV = max(pfont->data.lenIV, 0); |
1732 | 3.63M | int length = r_size(type1string) - (ff->need_decrypt ? lenIV : 0); |
1733 | | |
1734 | 3.63M | if (buf != 0) { |
1735 | 2.39M | int l = min(length, buf_length); /*safety */ |
1736 | | |
1737 | 2.39M | if (ff->need_decrypt && pfont->data.lenIV >= 0) |
1738 | 2.39M | decode_bytes(buf, type1string->value.const_bytes, l + lenIV, |
1739 | 2.39M | lenIV); |
1740 | 0 | else |
1741 | 0 | memcpy(buf, type1string->value.const_bytes, l); |
1742 | 2.39M | } |
1743 | 3.63M | return length; |
1744 | 3.63M | } |
1745 | | |
1746 | | static int |
1747 | | FAPI_FF_get_gsubr(gs_fapi_font *ff, int index, byte *buf, int buf_length) |
1748 | 0 | { |
1749 | 0 | ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2)); |
1750 | 0 | ref *Private, *GlobalSubrs, subr; |
1751 | |
|
1752 | 0 | if (dict_find_string(pdr, "Private", &Private) <= 0) |
1753 | 0 | return 0; |
1754 | 0 | if (dict_find_string(Private, "GlobalSubrs", &GlobalSubrs) <= 0) |
1755 | 0 | return 0; |
1756 | 0 | if (array_get(ff->memory, |
1757 | 0 | GlobalSubrs, index, &subr) < 0 || r_type(&subr) != t_string) |
1758 | 0 | return 0; |
1759 | 0 | return (get_type1_data(ff, &subr, buf, buf_length)); |
1760 | 0 | } |
1761 | | |
1762 | | static int |
1763 | | FAPI_FF_get_subr(gs_fapi_font *ff, int index, byte *buf, int buf_length) |
1764 | 1.85M | { |
1765 | 1.85M | ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2)); |
1766 | 1.85M | ref *Private, *Subrs, subr; |
1767 | | |
1768 | 1.85M | if (dict_find_string(pdr, "Private", &Private) <= 0) |
1769 | 0 | return 0; |
1770 | 1.85M | if (dict_find_string(Private, "Subrs", &Subrs) <= 0) |
1771 | 0 | return 0; |
1772 | 1.85M | if (array_get(ff->memory, Subrs, index, &subr) < 0 |
1773 | 1.85M | || r_type(&subr) != t_string) |
1774 | 0 | return 0; |
1775 | 1.85M | return (get_type1_data(ff, &subr, buf, buf_length)); |
1776 | 1.85M | } |
1777 | | |
1778 | | static int |
1779 | | FAPI_FF_get_raw_subr(gs_fapi_font *ff, int index, byte *buf, |
1780 | | int buf_length) |
1781 | 0 | { |
1782 | 0 | ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2)); |
1783 | 0 | ref *Private, *Subrs, subr; |
1784 | 0 | int code = 0; |
1785 | |
|
1786 | 0 | do { |
1787 | 0 | if (dict_find_string(pdr, "Private", &Private) <= 0) { |
1788 | 0 | code = gs_note_error(gs_error_undefined); |
1789 | 0 | break; |
1790 | 0 | } |
1791 | 0 | if (dict_find_string(Private, "Subrs", &Subrs) <= 0) { |
1792 | 0 | code = gs_note_error(gs_error_undefined); |
1793 | 0 | break; |
1794 | 0 | } |
1795 | 0 | if (array_get(ff->memory, Subrs, index, &subr) < 0) { |
1796 | 0 | code = gs_note_error(gs_error_undefined); |
1797 | 0 | break; |
1798 | 0 | } |
1799 | 0 | if (r_type(&subr) != t_string) { |
1800 | 0 | code = gs_note_error(gs_error_undefined); |
1801 | 0 | break; |
1802 | 0 | } |
1803 | 0 | if (buf && buf_length && buf_length >= r_size(&subr)) { |
1804 | 0 | memcpy(buf, subr.value.const_bytes, r_size(&subr)); |
1805 | 0 | } |
1806 | 0 | } while(0); |
1807 | | |
1808 | 0 | return code < 0 ? code : r_size(&subr); |
1809 | 0 | } |
1810 | | |
1811 | | /* FAPI_FF_get_charstring_name() and FAPI_FF_get_charstring() |
1812 | | * |
1813 | | * Generally we'd want to use the dictionary content |
1814 | | * enumeration API rather than dict_index_entry(), but |
1815 | | * the FAPI interface doesn't enforce sequential accessing |
1816 | | * of the indices. |
1817 | | * Setting up enumeration and enumerating through the entries |
1818 | | * until we reach the requested valid index is a performance |
1819 | | * hit we don't want to pay. |
1820 | | * |
1821 | | * Luckily, the checks we need for invalid CharString contents |
1822 | | * also handle empty "slots" in the dictionary. |
1823 | | */ |
1824 | | |
1825 | | static int |
1826 | | FAPI_FF_get_charstring_name(gs_fapi_font *ff, int index, byte *buf, |
1827 | | ushort buf_length) |
1828 | 0 | { |
1829 | 0 | int code = 0; |
1830 | 0 | ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2)); |
1831 | 0 | ref *CharStrings, eltp[2], string; |
1832 | |
|
1833 | 0 | do { |
1834 | 0 | if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0) { |
1835 | 0 | code = gs_note_error(gs_error_undefined); |
1836 | 0 | break; |
1837 | 0 | } |
1838 | 0 | if (dict_index_entry(CharStrings, index, eltp) < 0) { |
1839 | 0 | code = gs_note_error(gs_error_undefined); |
1840 | 0 | break; |
1841 | 0 | } |
1842 | 0 | if (r_type(&eltp[0]) != t_name) { |
1843 | 0 | code = gs_note_error(gs_error_undefined); |
1844 | 0 | break; |
1845 | 0 | } |
1846 | 0 | name_string_ref(ff->memory, &eltp[0], &string); |
1847 | 0 | if (r_size(&string) <= buf_length) { |
1848 | 0 | memcpy(buf, string.value.const_bytes, r_size(&string)); |
1849 | 0 | buf[r_size(&string)] = 0x00; |
1850 | 0 | } |
1851 | 0 | } while(0); |
1852 | 0 | return code < 0 ? code : r_size(&string); |
1853 | 0 | } |
1854 | | |
1855 | | static int |
1856 | | FAPI_FF_get_charstring(gs_fapi_font *ff, int index, byte *buf, |
1857 | | ushort buf_length) |
1858 | 0 | { |
1859 | 0 | int code = 0; |
1860 | 0 | ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2)); |
1861 | 0 | ref *CharStrings, eltp[2]; |
1862 | |
|
1863 | 0 | do { |
1864 | 0 | if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0) { |
1865 | 0 | code = gs_note_error(gs_error_undefined); |
1866 | 0 | break; |
1867 | 0 | } |
1868 | 0 | if (dict_index_entry(CharStrings, index, eltp) < 0) { |
1869 | 0 | code = gs_note_error(gs_error_undefined); |
1870 | 0 | break; |
1871 | 0 | } |
1872 | 0 | if (r_type(&eltp[1]) != t_string) { |
1873 | 0 | code = gs_note_error(gs_error_typecheck); |
1874 | 0 | break; |
1875 | 0 | } |
1876 | 0 | if (buf && buf_length && buf_length >= r_size(&eltp[1])) { |
1877 | 0 | memcpy(buf, eltp[1].value.const_bytes, r_size(&eltp[1])); |
1878 | 0 | } |
1879 | 0 | } while(0); |
1880 | | |
1881 | 0 | return code < 0 ? code : r_size(&eltp[1]); |
1882 | 0 | } |
1883 | | |
1884 | | static int |
1885 | | sfnt_get_sfnt_length(ref *pdr, ulong *len) |
1886 | 0 | { |
1887 | 0 | int code = 0; |
1888 | 0 | ref *sfnts, sfnt_elem; |
1889 | 0 | const gs_memory_t *mem = dict_mem(pdr->value.pdict); |
1890 | |
|
1891 | 0 | *len = 0; |
1892 | 0 | if (r_type(pdr) != t_dictionary || |
1893 | 0 | dict_find_string(pdr, "sfnts", &sfnts) <= 0) { |
1894 | 0 | code = gs_error_invalidfont; |
1895 | 0 | } |
1896 | 0 | else { |
1897 | 0 | if (r_type(sfnts) != t_array && r_type(sfnts) != t_string) { |
1898 | 0 | code = gs_error_invalidfont; |
1899 | 0 | } |
1900 | 0 | else { |
1901 | 0 | if (r_type(sfnts) == t_string) { |
1902 | 0 | *len = r_size(sfnts); |
1903 | 0 | } |
1904 | 0 | else { |
1905 | 0 | int i; |
1906 | 0 | for (i = 0; i < r_size(sfnts); i++) { |
1907 | 0 | code = array_get(mem, sfnts, i, &sfnt_elem); |
1908 | 0 | if (code < 0) break; |
1909 | 0 | *len += r_size(&sfnt_elem); |
1910 | 0 | } |
1911 | 0 | } |
1912 | 0 | } |
1913 | 0 | } |
1914 | 0 | return code; |
1915 | 0 | } |
1916 | | |
1917 | | static int |
1918 | | sfnt_get_glyph_offset(ref *pdr, gs_font_type42 *pfont42, int index, |
1919 | | ulong *offset0) |
1920 | 0 | { /* Note : TTC is not supported and probably is unuseful for Type 42. */ |
1921 | 0 | sfnts_reader r; |
1922 | 0 | int glyf_elem_size = (pfont42->data.indexToLocFormat) ? 4 : 2; |
1923 | 0 | ulong fullsize; |
1924 | |
|
1925 | 0 | if (index < pfont42->data.trueNumGlyphs) { |
1926 | 0 | sfnts_reader_init(pfont42->memory, &r, pdr); |
1927 | 0 | r.seek(&r, pfont42->data.loca + index * (ulong)glyf_elem_size); |
1928 | 0 | *offset0 = |
1929 | 0 | pfont42->data.glyf + (glyf_elem_size == |
1930 | 0 | 2 ? r.rword(&r) * 2 : r.rlong(&r)); |
1931 | 0 | r.error = sfnt_get_sfnt_length(pdr, &fullsize); |
1932 | 0 | if (r.error < 0 || *offset0 > fullsize) { |
1933 | 0 | r.error = gs_note_error(gs_error_invalidaccess); |
1934 | 0 | } |
1935 | 0 | } |
1936 | 0 | else { |
1937 | 0 | r.error = gs_note_error(gs_error_rangecheck); |
1938 | 0 | } |
1939 | 0 | return (r.error); |
1940 | 0 | } |
1941 | | |
1942 | | static int |
1943 | | ps_get_GlyphDirectory_data_ptr(gs_fapi_font *ff, int char_code, |
1944 | | const byte **ptr) |
1945 | 0 | { |
1946 | 0 | ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2)); |
1947 | 0 | ref *GlyphDirectory, glyph0, *glyph = &glyph0, glyph_index; |
1948 | |
|
1949 | 0 | if (dict_find_string(pdr, "GlyphDirectory", &GlyphDirectory) > 0) { |
1950 | 0 | if (((r_type(GlyphDirectory) == t_dictionary && |
1951 | 0 | (make_int(&glyph_index, char_code), |
1952 | 0 | dict_find(GlyphDirectory, &glyph_index, &glyph) > 0)) || |
1953 | 0 | (r_type(GlyphDirectory) == t_array && |
1954 | 0 | array_get(ff->memory, GlyphDirectory, char_code, &glyph0) >= 0) |
1955 | 0 | ) |
1956 | 0 | && r_type(glyph) == t_string) { |
1957 | 0 | *ptr = glyph->value.const_bytes; |
1958 | 0 | return (r_size(glyph)); |
1959 | 0 | } |
1960 | 0 | else |
1961 | | /* We have a GlyphDirectory, but couldn't find the glyph. If we |
1962 | | * return -1 then we will attempt to use glyf and loca which |
1963 | | * will fail. Instead return 0, so we execute an 'empty' glyph. |
1964 | | */ |
1965 | 0 | return 0; |
1966 | 0 | } |
1967 | 0 | return -1; |
1968 | 0 | } |
1969 | | |
1970 | | static int |
1971 | | get_charstring(gs_fapi_font *ff, int char_code, ref **proc, ref *char_name) |
1972 | 0 | { |
1973 | 0 | ref *CharStrings; |
1974 | 0 | ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2)); |
1975 | |
|
1976 | 0 | if (ff->is_type1) { |
1977 | 0 | if (ff->is_cid) |
1978 | 0 | return -1; |
1979 | 0 | if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0) |
1980 | 0 | return -1; |
1981 | | |
1982 | 0 | if (ff->char_data != NULL) { |
1983 | | /* |
1984 | | * Can't use char_code in this case because hooked Type 1 fonts |
1985 | | * with 'glyphshow' may render a character which has no |
1986 | | * Encoding entry. |
1987 | | */ |
1988 | 0 | if (name_ref |
1989 | 0 | (ff->memory, ff->char_data, ff->char_data_len, char_name, |
1990 | 0 | -1) < 0) |
1991 | 0 | return -1; |
1992 | 0 | } |
1993 | 0 | else { /* seac */ |
1994 | 0 | i_ctx_t *i_ctx_p = (i_ctx_t *) ff->client_ctx_p; |
1995 | 0 | ref *StandardEncoding; |
1996 | |
|
1997 | 0 | if (dict_find_string |
1998 | 0 | (systemdict, "StandardEncoding", &StandardEncoding) <= 0 |
1999 | 0 | || array_get(ff->memory, StandardEncoding, char_code, |
2000 | 0 | char_name) < 0) { |
2001 | 0 | if (name_ref |
2002 | 0 | (ff->memory, (const byte *)".notdef", 7, char_name, |
2003 | 0 | -1) < 0) |
2004 | 0 | return -1; |
2005 | 0 | } |
2006 | 0 | } |
2007 | 0 | if (dict_find(CharStrings, char_name, (ref **) proc) <= 0) |
2008 | 0 | return -1; |
2009 | 0 | } |
2010 | 0 | return 0; |
2011 | 0 | } |
2012 | | |
2013 | | static int |
2014 | | FAPI_FF_get_glyph(gs_fapi_font *ff, gs_glyph char_code, byte *buf, int buf_length) |
2015 | 1.78M | { |
2016 | | /* |
2017 | | * We assume that renderer requests glyph data with multiple |
2018 | | * consecutive calls to this function. |
2019 | | * |
2020 | | * For a simple glyph it calls this function exactly twice: first |
2021 | | * with buf == NULL for requesting the necessary buffer length, and |
2022 | | * second with buf != NULL for requesting the data (the second call |
2023 | | * may be skipped if the renderer discontinues the rendering). |
2024 | | * |
2025 | | * For a composite glyph it calls this function 2 * (N + 1) |
2026 | | * times: 2 calls for the main glyph (same as above) followed with |
2027 | | * 2 * N calls for subglyphs, where N is less or equal to the number |
2028 | | * of subglyphs (N may be less if the renderer caches glyph data, |
2029 | | * or discontinues rendering on an exception). |
2030 | | */ |
2031 | 1.78M | ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2)); |
2032 | | |
2033 | 1.78M | int glyph_length; |
2034 | 1.78M | i_ctx_t *i_ctx_p = (i_ctx_t *) ff->client_ctx_p; |
2035 | | |
2036 | 1.78M | if (ff->is_type1) { |
2037 | 1.78M | if (ff->is_cid) { |
2038 | 0 | const gs_string *char_str = (const gs_string *)ff->char_data; |
2039 | 0 | ref glyph; |
2040 | |
|
2041 | 0 | make_string(&glyph, avm_foreign | a_readonly, char_str->size, |
2042 | 0 | char_str->data); |
2043 | |
|
2044 | 0 | glyph_length = get_type1_data(ff, &glyph, buf, buf_length); |
2045 | 0 | } |
2046 | 1.78M | else { |
2047 | 1.78M | ref *CharStrings, *CFFCharStrings, char_name, *glyph; |
2048 | | |
2049 | 1.78M | if (ff->char_data != NULL) { |
2050 | | /* |
2051 | | * Can't use char_code in this case because hooked Type 1 fonts |
2052 | | * with 'glyphshow' may render a character which has no |
2053 | | * Encoding entry. |
2054 | | */ |
2055 | 1.78M | if (name_ref(ff->memory, ff->char_data, |
2056 | 1.78M | ff->char_data_len, &char_name, -1) < 0) |
2057 | 0 | return gs_fapi_glyph_invalid_format; |
2058 | 1.78M | if (buf != NULL) { |
2059 | | /* |
2060 | | * Trigger the next call to the 'seac' case below. |
2061 | | * Here we use the assumption about call sequence |
2062 | | * being documented above. |
2063 | | */ |
2064 | 1.77M | ff->char_data = NULL; |
2065 | 1.77M | } |
2066 | 1.78M | } |
2067 | 0 | else { /* seac */ |
2068 | 0 | ref *StandardEncoding; |
2069 | |
|
2070 | 0 | if (dict_find_string |
2071 | 0 | (systemdict, "StandardEncoding", &StandardEncoding) <= 0 |
2072 | 0 | || array_get(ff->memory, StandardEncoding, char_code, |
2073 | 0 | &char_name) < 0) |
2074 | 0 | if (name_ref |
2075 | 0 | (ff->memory, (const byte *)".notdef", 7, &char_name, -1) < 0) |
2076 | 0 | return gs_fapi_glyph_invalid_format; |
2077 | 0 | } |
2078 | 1.78M | if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0) |
2079 | 0 | return gs_fapi_glyph_invalid_format; |
2080 | | |
2081 | 1.78M | if (dict_find(CharStrings, &char_name, &glyph) <= 0) { |
2082 | 0 | if (name_ref |
2083 | 0 | (ff->memory, (const byte *)".notdef", 7, &char_name, -1) < 0) { |
2084 | 0 | return gs_fapi_glyph_invalid_format; |
2085 | 0 | } |
2086 | 0 | if (dict_find(CharStrings, &char_name, &glyph) <= 0) { |
2087 | 0 | return gs_fapi_glyph_invalid_format; |
2088 | 0 | } |
2089 | 0 | } |
2090 | 1.78M | if (r_has_type(glyph, t_array) || r_has_type(glyph, t_mixedarray)) |
2091 | 0 | return gs_fapi_glyph_invalid_format; |
2092 | | |
2093 | 1.78M | if (r_has_type(glyph, t_integer) |
2094 | 1.78M | && dict_find_string(pdr, "CFFCharStrings", &CFFCharStrings) > 0) { |
2095 | 0 | ref *g2; |
2096 | 0 | if (dict_find(CFFCharStrings, glyph, &g2) <= 0) { |
2097 | 0 | ref nd; |
2098 | 0 | make_int(&nd, 0); |
2099 | 0 | if (dict_find(CFFCharStrings, &nd, &g2) <= 0) { |
2100 | 0 | return gs_fapi_glyph_invalid_format; |
2101 | 0 | } |
2102 | 0 | } |
2103 | 0 | glyph = g2; |
2104 | 0 | } |
2105 | | |
2106 | 1.78M | if (!r_has_type(glyph, t_string)) |
2107 | 0 | return 0; |
2108 | 1.78M | glyph_length = get_type1_data(ff, glyph, buf, buf_length); |
2109 | 1.78M | } |
2110 | 1.78M | } |
2111 | 0 | else { /* type 42 */ |
2112 | 0 | const byte *data_ptr; |
2113 | 0 | int l = ff->get_glyphdirectory_data(ff, char_code, &data_ptr); |
2114 | 0 | ref *render_notdef_ref; |
2115 | 0 | bool render_notdef = true; |
2116 | |
|
2117 | 0 | if (dict_find_string(pdr, ".render_notdef", &render_notdef_ref) > 0 |
2118 | 0 | && r_has_type(render_notdef_ref, t_boolean)) { |
2119 | 0 | render_notdef = render_notdef_ref->value.boolval; |
2120 | 0 | } |
2121 | 0 | else { |
2122 | 0 | render_notdef = i_ctx_p->RenderTTNotdef; |
2123 | 0 | } |
2124 | | |
2125 | | /* We should only render the TT notdef if we've been told to - logic lifted from zchar42.c */ |
2126 | 0 | if (!render_notdef |
2127 | 0 | && |
2128 | 0 | ((ff->char_data_len == 7 |
2129 | 0 | && strncmp((const char *)ff->char_data, ".notdef", 7) == 0) |
2130 | 0 | || (ff->char_data_len > 9 |
2131 | 0 | && strncmp((const char *)ff->char_data, ".notdef~GS", |
2132 | 0 | 10) == 0))) { |
2133 | 0 | glyph_length = 0; |
2134 | 0 | } |
2135 | 0 | else { |
2136 | 0 | if (l >= 0) { |
2137 | 0 | int MetricsCount = gs_fapi_get_metrics_count(ff), mc = |
2138 | 0 | MetricsCount << 1; |
2139 | |
|
2140 | 0 | glyph_length = max((ushort) (l - mc), 0); /* safety */ |
2141 | 0 | if (buf != 0 && glyph_length > 0) |
2142 | 0 | memcpy(buf, data_ptr + mc, |
2143 | 0 | min(glyph_length, buf_length) /* safety */ ); |
2144 | 0 | } |
2145 | 0 | else { |
2146 | 0 | gs_font_type42 *pfont42 = (gs_font_type42 *) ff->client_font_data; |
2147 | 0 | ulong offset0, length_read; |
2148 | 0 | int error = sfnt_get_glyph_offset(pdr, pfont42, char_code, &offset0); |
2149 | |
|
2150 | 0 | if (error < 0) { |
2151 | 0 | glyph_length = gs_fapi_glyph_invalid_index; |
2152 | 0 | } |
2153 | 0 | else if (pfont42->data.len_glyphs) { |
2154 | 0 | if (char_code <= pfont42->data.numGlyphs) |
2155 | 0 | glyph_length = pfont42->data.len_glyphs[char_code]; |
2156 | 0 | else |
2157 | 0 | glyph_length = gs_fapi_glyph_invalid_index; |
2158 | 0 | } |
2159 | 0 | else { |
2160 | 0 | ulong noffs, endoffs; |
2161 | | /* If we haven't got a len_glyphs array, try using the offset of the next glyph offset |
2162 | | * to work out the length |
2163 | | */ |
2164 | 0 | error = sfnt_get_glyph_offset(pdr, pfont42, char_code + 1, &noffs); |
2165 | 0 | if (error == 0) { |
2166 | 0 | glyph_length = noffs - offset0; |
2167 | 0 | error = sfnt_get_sfnt_length(pdr, &endoffs); |
2168 | 0 | if (error < 0) { |
2169 | 0 | glyph_length = gs_fapi_glyph_invalid_index; |
2170 | 0 | } |
2171 | 0 | else { |
2172 | 0 | if (glyph_length + offset0 > endoffs) { |
2173 | 0 | glyph_length = gs_fapi_glyph_invalid_index; |
2174 | 0 | } |
2175 | 0 | } |
2176 | 0 | } |
2177 | 0 | else { |
2178 | | /* And if we can't get the next glyph offset, use the end of the sfnt data |
2179 | | * to work out the length. |
2180 | | */ |
2181 | 0 | error = sfnt_get_sfnt_length(pdr, &noffs); |
2182 | 0 | if (error < 0) { |
2183 | 0 | glyph_length = gs_fapi_glyph_invalid_index; |
2184 | 0 | } |
2185 | 0 | else { |
2186 | 0 | glyph_length = noffs - offset0; |
2187 | 0 | } |
2188 | 0 | } |
2189 | 0 | } |
2190 | |
|
2191 | 0 | if (buf != 0 && !error) { |
2192 | 0 | sfnts_reader r; |
2193 | |
|
2194 | 0 | sfnts_reader_init(pfont42->memory, &r, pdr); |
2195 | |
|
2196 | 0 | r.seek(&r, offset0); |
2197 | 0 | length_read = |
2198 | 0 | r.rstring(&r, buf, |
2199 | 0 | min(glyph_length, |
2200 | 0 | buf_length) /* safety */ ); |
2201 | 0 | if (r.error == 1) { |
2202 | 0 | glyph_length = gs_fapi_glyph_invalid_index; |
2203 | 0 | } |
2204 | | /* r.error == 2 means a rangecheck, and probably means that the |
2205 | | * font is broken, and the final glyph length is longer than the data available for it. |
2206 | | * In which case we need to return the number of bytes read. |
2207 | | */ |
2208 | 0 | if (r.error == 2) { |
2209 | 0 | glyph_length = length_read; |
2210 | 0 | } |
2211 | 0 | } |
2212 | 0 | } |
2213 | 0 | } |
2214 | 0 | } |
2215 | 1.78M | return glyph_length; |
2216 | 1.78M | } |
2217 | | |
2218 | | static int |
2219 | | ps_fapi_get_metrics(gs_fapi_font *ff, gs_string *char_name, gs_glyph cid, double *m, bool vertical) |
2220 | 1.77M | { |
2221 | 1.77M | ref glyph; |
2222 | 1.77M | int code; |
2223 | 1.77M | gs_font_base *pbfont = ((gs_font_base *) ff->client_font_data2); |
2224 | | |
2225 | 1.77M | if (char_name->data != NULL) { |
2226 | 1.77M | make_string(&glyph, avm_foreign | a_readonly, char_name->size, char_name->data); |
2227 | 1.77M | } |
2228 | 0 | else { |
2229 | 0 | make_int(&glyph, cid); |
2230 | 0 | } |
2231 | | |
2232 | 1.77M | if (vertical) { |
2233 | 0 | code = zchar_get_metrics2(pbfont, &glyph, m); |
2234 | 0 | } |
2235 | 1.77M | else { |
2236 | 1.77M | code = zchar_get_metrics(pbfont, &glyph, m); |
2237 | 1.77M | } |
2238 | | |
2239 | 1.77M | make_null(&glyph); |
2240 | | |
2241 | 1.77M | return (code); |
2242 | 1.77M | } |
2243 | | |
2244 | | |
2245 | | /* forward declaration for the ps_ff_stub assignment */ |
2246 | | static int ps_get_glyphname_or_cid(gs_text_enum_t *penum, |
2247 | | gs_font_base *pbfont, |
2248 | | gs_string *charstring, gs_string *name, |
2249 | | gs_glyph ccode, gs_string *enc_char_name, |
2250 | | char *font_file_path, |
2251 | | gs_fapi_char_ref *cr, bool bCID); |
2252 | | |
2253 | | static int ps_fapi_set_cache(gs_text_enum_t *penum, |
2254 | | const gs_font_base *pbfont, |
2255 | | const gs_string *char_name, gs_glyph cid, |
2256 | | const double pwidth[2], const gs_rect *pbbox, |
2257 | | const double Metrics2_sbw_default[4], |
2258 | | bool *imagenow); |
2259 | | |
2260 | | static const gs_fapi_font ps_ff_stub = { |
2261 | | 0, /* server_font_data */ |
2262 | | 0, /* need_decrypt */ |
2263 | | NULL, /* const gs_memory_t */ |
2264 | | 0, /* font_file_path */ |
2265 | | 0, /* full_font_buf */ |
2266 | | 0, /* full_font_buf_len */ |
2267 | | 0, /* subfont */ |
2268 | | false, /* is_type1 */ |
2269 | | false, /* is_cid */ |
2270 | | false, /* is_outline_font */ |
2271 | | false, /* is_mtx_skipped */ |
2272 | | false, /* is_vertical */ |
2273 | | false, /* metrics_only */ |
2274 | | {{-1, -1}}, /* ttf_cmap_req */ |
2275 | | {-1, -1}, /* ttf_cmap_selected */ |
2276 | | 0, /* client_ctx_p */ |
2277 | | 0, /* client_font_data */ |
2278 | | 0, /* client_font_data2 */ |
2279 | | 0, /* char_data */ |
2280 | | 0, /* char_data_len */ |
2281 | | 0, /* embolden */ |
2282 | | FAPI_FF_get_word, |
2283 | | FAPI_FF_get_long, |
2284 | | FAPI_FF_get_float, |
2285 | | FAPI_FF_get_name, |
2286 | | FAPI_FF_get_proc, |
2287 | | FAPI_FF_get_gsubr, |
2288 | | FAPI_FF_get_subr, |
2289 | | FAPI_FF_get_raw_subr, |
2290 | | FAPI_FF_get_glyph, |
2291 | | FAPI_FF_serialize_tt_font, |
2292 | | NULL, /* retrieve_tt_font */ |
2293 | | FAPI_FF_get_charstring, |
2294 | | FAPI_FF_get_charstring_name, |
2295 | | ps_get_GlyphDirectory_data_ptr, |
2296 | | ps_get_glyphname_or_cid, |
2297 | | ps_fapi_get_metrics, |
2298 | | ps_fapi_set_cache |
2299 | | }; |
2300 | | |
2301 | | static int |
2302 | | FAPI_get_xlatmap(i_ctx_t *i_ctx_p, char **xlatmap) |
2303 | 13.0k | { |
2304 | 13.0k | ref *pref; |
2305 | 13.0k | int code; |
2306 | | |
2307 | 13.0k | if ((code = dict_find_string(systemdict, ".xlatmap", &pref)) < 0) |
2308 | 0 | return code; |
2309 | 13.0k | if (code == 0) |
2310 | 0 | return_error(gs_error_undefined); |
2311 | | |
2312 | 13.0k | if (r_type(pref) != t_string) |
2313 | 0 | return_error(gs_error_typecheck); |
2314 | 13.0k | *xlatmap = (char *)pref->value.bytes; |
2315 | | /* Note : this supposes that xlatmap doesn't move in virtual memory. |
2316 | | Garbager must not be called while plugin executes get_scaled_font, get_decodingID. |
2317 | | Fix some day with making copy of xlatmap in system memory. |
2318 | | */ |
2319 | 13.0k | return 0; |
2320 | 13.0k | } |
2321 | | |
2322 | | static int |
2323 | | renderer_retcode(gs_memory_t *mem, gs_fapi_server *I, gs_fapi_retcode rc) |
2324 | 0 | { |
2325 | 0 | if (rc == 0) |
2326 | 0 | return 0; |
2327 | 0 | emprintf2(mem, |
2328 | 0 | "Error: Font Renderer Plugin ( %s ) return code = %d\n", |
2329 | 0 | I->ig.d->subtype, rc); |
2330 | 0 | return rc < 0 ? rc : gs_error_invalidfont; |
2331 | 0 | } |
2332 | | |
2333 | | /* <server name>/<null> object .FAPIavailable bool */ |
2334 | | static int |
2335 | | zFAPIavailable(i_ctx_t *i_ctx_p) |
2336 | 324k | { |
2337 | 324k | os_ptr op = osp; |
2338 | 324k | char *serv_name = NULL; |
2339 | 324k | ref name_ref; |
2340 | | |
2341 | 324k | check_op(1); |
2342 | 324k | if (r_has_type(op, t_name)) { |
2343 | 162k | name_string_ref(imemory, op, &name_ref); |
2344 | | |
2345 | 162k | serv_name = |
2346 | 162k | (char *) ref_to_string(&name_ref, imemory, "zFAPIavailable"); |
2347 | 162k | if (!serv_name) { |
2348 | 0 | return_error(gs_error_VMerror); |
2349 | 0 | } |
2350 | 162k | } |
2351 | | |
2352 | 324k | make_bool(op, gs_fapi_available(imemory, serv_name)); |
2353 | | |
2354 | 324k | if (serv_name) { |
2355 | 162k | gs_free_string(imemory, (byte *) serv_name, |
2356 | 162k | strlen((char *)serv_name) + 1, "zFAPIavailable"); |
2357 | 162k | } |
2358 | 324k | return (0); |
2359 | 324k | } |
2360 | | |
2361 | | static int |
2362 | | ps_get_server_param(gs_fapi_server *I, const char *subtype, char **server_param, int *server_param_size) |
2363 | | |
2364 | 123k | { |
2365 | 123k | ref *FAPIconfig, *options, *server_options; |
2366 | 123k | i_ctx_t *i_ctx_p = (i_ctx_t *) I->client_ctx_p; |
2367 | | |
2368 | 123k | if (dict_find_string(systemdict, ".FAPIconfig", &FAPIconfig) > 0 |
2369 | 123k | && r_has_type(FAPIconfig, t_dictionary)) { |
2370 | 123k | if (dict_find_string(FAPIconfig, "ServerOptions", &options) > 0 |
2371 | 123k | && r_has_type(options, t_dictionary)) { |
2372 | 123k | if (dict_find_string(options, (char *)subtype, &server_options) > |
2373 | 123k | 0 && r_has_type(server_options, t_string)) { |
2374 | 0 | *server_param = (char *) server_options->value.const_bytes; |
2375 | 0 | *server_param_size = r_size(server_options); |
2376 | 0 | } |
2377 | 123k | } |
2378 | 123k | } |
2379 | 123k | return 1; |
2380 | 123k | } |
2381 | | |
2382 | | static int |
2383 | | FAPI_refine_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font *pfont, |
2384 | | int subfont, const char *font_file_path) |
2385 | 123k | { |
2386 | 123k | ref *pdr = op; /* font dict */ |
2387 | 123k | const char *decodingID = NULL; |
2388 | 123k | char *xlatmap = NULL; |
2389 | 123k | gs_font_base *pbfont = (gs_font_base *)pfont; |
2390 | 123k | gs_fapi_server *I = pbfont->FAPI; |
2391 | 123k | ref *Decoding_old; |
2392 | 123k | int code; |
2393 | | |
2394 | 123k | if (font_file_path != NULL && pbfont->FAPI_font_data == NULL) |
2395 | 0 | if ((code = FAPI_get_xlatmap(i_ctx_p, &xlatmap)) < 0) |
2396 | 0 | return code; |
2397 | | |
2398 | 123k | gs_fapi_set_servers_client_data(imemory, NULL, i_ctx_p); |
2399 | | |
2400 | 123k | code = |
2401 | 123k | gs_fapi_prepare_font(pfont, I, subfont, font_file_path, |
2402 | 123k | NULL, xlatmap, &decodingID); |
2403 | 123k | if (code < 0) |
2404 | 0 | return code; |
2405 | | |
2406 | 123k | if (code > 0) { |
2407 | | /* save refined FontBBox back to PS world */ |
2408 | 0 | ref *v, mat[4], arr; |
2409 | 0 | int attrs; |
2410 | |
|
2411 | 0 | if (dict_find_string(op, "FontBBox", &v) > 0) { |
2412 | 0 | if (!r_has_type(v, t_array) && !r_has_type(v, t_shortarray) |
2413 | 0 | && !r_has_type(v, t_mixedarray)) |
2414 | 0 | return_error(gs_error_invalidfont); |
2415 | 0 | make_real(&mat[0], pbfont->FontBBox.p.x); |
2416 | 0 | make_real(&mat[1], pbfont->FontBBox.p.y); |
2417 | 0 | make_real(&mat[2], pbfont->FontBBox.q.x); |
2418 | 0 | make_real(&mat[3], pbfont->FontBBox.q.y); |
2419 | 0 | if (r_has_type(v, t_shortarray) || r_has_type(v, t_mixedarray) |
2420 | 0 | || r_size(v) < 4) { |
2421 | | /* Create a new full blown array in case the values are reals */ |
2422 | 0 | code = ialloc_ref_array(&arr, a_all, 4, "array"); |
2423 | 0 | if (code < 0) |
2424 | 0 | return code; |
2425 | 0 | v = &arr; |
2426 | 0 | code = idict_put_string(op, "FontBBox", &arr); |
2427 | 0 | if (code < 0) |
2428 | 0 | return code; |
2429 | 0 | ref_assign_new(v->value.refs + 0, &mat[0]); |
2430 | 0 | ref_assign_new(v->value.refs + 1, &mat[1]); |
2431 | 0 | ref_assign_new(v->value.refs + 2, &mat[2]); |
2432 | 0 | ref_assign_new(v->value.refs + 3, &mat[3]); |
2433 | 0 | } |
2434 | 0 | else { |
2435 | 0 | ref_assign_old(v, v->value.refs + 0, &mat[0], |
2436 | 0 | "FAPI_refine_font_BBox"); |
2437 | 0 | ref_assign_old(v, v->value.refs + 1, &mat[1], |
2438 | 0 | "FAPI_refine_font_BBox"); |
2439 | 0 | ref_assign_old(v, v->value.refs + 2, &mat[2], |
2440 | 0 | "FAPI_refine_font_BBox"); |
2441 | 0 | ref_assign_old(v, v->value.refs + 3, &mat[3], |
2442 | 0 | "FAPI_refine_font_BBox"); |
2443 | 0 | } |
2444 | 0 | attrs = v->tas.type_attrs; |
2445 | 0 | r_clear_attrs(v, a_all); |
2446 | 0 | r_set_attrs(v, attrs | a_execute); |
2447 | 0 | } |
2448 | 0 | } |
2449 | | |
2450 | | /* Assign a Decoding : */ |
2451 | 123k | if (decodingID != 0 && *decodingID |
2452 | 123k | && dict_find_string(pdr, "Decoding", &Decoding_old) <= 0) { |
2453 | 0 | ref Decoding; |
2454 | |
|
2455 | 0 | if (FAPI_ISCIDFONT(pbfont)) { |
2456 | 0 | ref *CIDSystemInfo, *Ordering, SubstNWP; |
2457 | 0 | byte buf[30]; |
2458 | 0 | int ordering_length, decodingID_length = |
2459 | 0 | min(strlen(decodingID), sizeof(buf) - 2); |
2460 | |
|
2461 | 0 | if (dict_find_string(pdr, "CIDSystemInfo", &CIDSystemInfo) <= 0 |
2462 | 0 | || !r_has_type(CIDSystemInfo, t_dictionary)) |
2463 | 0 | return_error(gs_error_invalidfont); |
2464 | | |
2465 | 0 | if (dict_find_string(CIDSystemInfo, "Ordering", &Ordering) <= 0 |
2466 | 0 | || !r_has_type(Ordering, t_string)) { |
2467 | 0 | return_error(gs_error_invalidfont); |
2468 | 0 | } |
2469 | | |
2470 | 0 | ordering_length = |
2471 | 0 | min(r_size(Ordering), sizeof(buf) - 2 - decodingID_length); |
2472 | 0 | memcpy(buf, Ordering->value.const_bytes, ordering_length); |
2473 | 0 | if ((code = |
2474 | 0 | name_ref(imemory, buf, ordering_length, &SubstNWP, 0)) < 0) |
2475 | 0 | return code; |
2476 | 0 | if ((code = |
2477 | 0 | dict_put_string(pdr, "SubstNWP", &SubstNWP, NULL)) < 0) |
2478 | 0 | return code; |
2479 | 0 | buf[ordering_length] = '.'; |
2480 | 0 | memcpy(buf + ordering_length + 1, decodingID, decodingID_length); |
2481 | 0 | buf[decodingID_length + 1 + ordering_length] = 0; /* Debug purpose only */ |
2482 | 0 | if ((code = name_ref(imemory, buf, |
2483 | 0 | decodingID_length + 1 + ordering_length, |
2484 | 0 | &Decoding, 0)) < 0) |
2485 | 0 | return code; |
2486 | 0 | } |
2487 | 0 | else if ((code = name_ref(imemory, (const byte *)decodingID, |
2488 | 0 | strlen(decodingID), &Decoding, 0)) < 0) |
2489 | 0 | return code; |
2490 | 0 | if ((code = dict_put_string(pdr, "Decoding", &Decoding, NULL)) < 0) |
2491 | 0 | return code; |
2492 | 0 | } |
2493 | 123k | return 0; |
2494 | 123k | } |
2495 | | |
2496 | | /* <string|name> <font> <is_disk_font> .rebuildfontFAPI <string|name> <font> */ |
2497 | | /* Rebuild a font for handling it with an external renderer. |
2498 | | |
2499 | | The font was built as a native GS font to allow easy access |
2500 | | to font features. Then zFAPIrebuildfont sets FAPI entry |
2501 | | into gx_font_base and replaces BuildGlyph and BuildChar |
2502 | | to enforce the FAPI handling. |
2503 | | |
2504 | | This operator must not be called with devices which embed fonts. |
2505 | | |
2506 | | */ |
2507 | | static int |
2508 | | zFAPIrebuildfont(i_ctx_t *i_ctx_p) |
2509 | 123k | { |
2510 | 123k | os_ptr op = osp; |
2511 | 123k | build_proc_refs build; |
2512 | 123k | gs_font *pfont; |
2513 | 123k | int code; |
2514 | 123k | gs_font_base *pbfont; |
2515 | 123k | ref *v; |
2516 | 123k | char *font_file_path = NULL; |
2517 | 123k | char FAPI_ID[20]; |
2518 | 123k | const byte *pchars; |
2519 | 123k | uint len; |
2520 | 123k | font_data *pdata; |
2521 | 123k | gs_fapi_server *I; |
2522 | 123k | bool has_buildglyph; |
2523 | 123k | bool has_buildchar; |
2524 | 123k | int subfont; |
2525 | | |
2526 | 123k | check_op(3); |
2527 | 123k | code = font_param(op - 1, &pfont); |
2528 | 123k | if (code < 0) |
2529 | 0 | return code; |
2530 | | |
2531 | 123k | pbfont = (gs_font_base *) pfont; |
2532 | | |
2533 | 123k | check_type(*op, t_boolean); |
2534 | | /* If someone has copied the font dictionary, we may still |
2535 | | * have the FAPI entry in the dict, but not have the FAPI |
2536 | | * server assigned in the font object. |
2537 | | */ |
2538 | 123k | if (pbfont->FAPI == NULL) { |
2539 | 110k | if (dict_find_string(op - 1, "FAPI", &v) <= 0 |
2540 | 110k | || !r_has_type(v, t_name)) |
2541 | 0 | return_error(gs_error_invalidfont); |
2542 | 110k | obj_string_data(imemory, v, &pchars, &len); |
2543 | 110k | len = min(len, sizeof(FAPI_ID) - 1); |
2544 | 110k | strncpy((char *)FAPI_ID, (const char *)pchars, len); |
2545 | 110k | FAPI_ID[len] = 0; |
2546 | | |
2547 | 110k | gs_fapi_set_servers_client_data(imemory, &ps_ff_stub, i_ctx_p); |
2548 | | |
2549 | 110k | code = |
2550 | 110k | gs_fapi_find_server(imemory, FAPI_ID, |
2551 | 110k | (gs_fapi_server **) & (pbfont->FAPI), ps_get_server_param); |
2552 | 110k | if (!pbfont->FAPI || code < 0) { |
2553 | 0 | return_error(gs_error_invalidfont); |
2554 | 0 | } |
2555 | 110k | } |
2556 | | |
2557 | 123k | pdata = (font_data *) pfont->client_data; |
2558 | 123k | I = pbfont->FAPI; |
2559 | | |
2560 | 123k | if (dict_find_string((op - 1), "SubfontId", &v) > 0 |
2561 | 123k | && r_has_type(v, t_integer)) |
2562 | 0 | subfont = v->value.intval; |
2563 | 123k | else |
2564 | 123k | subfont = 0; |
2565 | | |
2566 | | |
2567 | 123k | if (r_type(&(pdata->BuildGlyph)) != t_null) { |
2568 | 123k | has_buildglyph = true; |
2569 | 123k | } |
2570 | 0 | else { |
2571 | 0 | has_buildglyph = false; |
2572 | 0 | } |
2573 | | |
2574 | 123k | if (r_type(&(pdata->BuildChar)) != t_null) { |
2575 | 123k | has_buildchar = true; |
2576 | 123k | } |
2577 | 1 | else { |
2578 | 1 | has_buildchar = false; |
2579 | 1 | } |
2580 | | |
2581 | | /* This shouldn't happen, but just in case */ |
2582 | 123k | if (has_buildglyph == false && has_buildchar == false) { |
2583 | 0 | has_buildglyph = true; |
2584 | 0 | } |
2585 | | |
2586 | 123k | if (dict_find_string(op - 1, "Path", &v) <= 0 || !r_has_type(v, t_string)) { |
2587 | 123k | v = NULL; |
2588 | 123k | } |
2589 | | |
2590 | 123k | if (pfont->FontType == ft_CID_encrypted && v == NULL) { |
2591 | 1 | if ((code = build_proc_name_refs(imemory, &build, ".FAPIBuildGlyph9", |
2592 | 1 | ".FAPIBuildGlyph9")) < 0) { |
2593 | 0 | return code; |
2594 | 0 | } |
2595 | 1 | } |
2596 | 123k | else { |
2597 | 123k | if ((code = build_proc_name_refs(imemory, &build, ".FAPIBuildChar", |
2598 | 123k | ".FAPIBuildGlyph")) < 0) { |
2599 | 0 | return code; |
2600 | 0 | } |
2601 | 123k | } |
2602 | | |
2603 | 123k | if (! |
2604 | 123k | ((r_type(&(pdata->BuildChar)) != t_null |
2605 | 123k | && pdata->BuildChar.value.pname && build.BuildChar.value.pname |
2606 | 123k | && name_index(imemory, &pdata->BuildChar) == name_index(imemory, |
2607 | 123k | &build. |
2608 | 123k | BuildChar)) |
2609 | 123k | || (r_type(&(pdata->BuildGlyph)) != t_null |
2610 | 123k | && pdata->BuildGlyph.value.pname && build.BuildGlyph.value.pname |
2611 | 123k | && name_index(imemory, &pdata->BuildGlyph) == name_index(imemory, |
2612 | 123k | &build. |
2613 | 123k | BuildGlyph)))) |
2614 | 123k | { |
2615 | | |
2616 | 123k | if (has_buildchar == true) { |
2617 | 123k | ref_assign_new(&pdata->BuildChar, &build.BuildChar); |
2618 | 123k | } |
2619 | 1 | else { |
2620 | 1 | make_null(&pdata->BuildChar); |
2621 | 1 | } |
2622 | | |
2623 | 123k | if (has_buildglyph == true) { |
2624 | 123k | ref_assign_new(&pdata->BuildGlyph, &build.BuildGlyph); |
2625 | 123k | } |
2626 | 0 | else { |
2627 | 0 | make_null(&pdata->BuildGlyph); |
2628 | 0 | } |
2629 | 123k | if (v != NULL) { |
2630 | 0 | font_file_path = |
2631 | 0 | ref_to_string(v, imemory_global, "font file path"); |
2632 | 0 | } |
2633 | | |
2634 | 123k | code = |
2635 | 123k | FAPI_refine_font(i_ctx_p, op - 1, pfont, subfont, |
2636 | 123k | font_file_path); |
2637 | | |
2638 | 123k | memcpy(&I->initial_FontMatrix, &pbfont->FontMatrix, |
2639 | 123k | sizeof(gs_matrix)); |
2640 | | |
2641 | 123k | if (font_file_path != NULL) { |
2642 | 0 | gs_free_string(imemory_global, (byte *) font_file_path, |
2643 | 0 | r_size(v) + 1, "font file path"); |
2644 | 0 | } |
2645 | 123k | } |
2646 | 123k | pop(1); |
2647 | 123k | return code; |
2648 | 123k | } |
2649 | | |
2650 | | static ulong |
2651 | | array_find(const gs_memory_t *mem, ref *Encoding, ref *char_name) |
2652 | 0 | { |
2653 | 0 | ulong n = r_size(Encoding), i; |
2654 | 0 | ref v; |
2655 | |
|
2656 | 0 | for (i = 0; i < n; i++) |
2657 | 0 | if (array_get(mem, Encoding, i, &v) < 0) |
2658 | 0 | break; |
2659 | 0 | else if (r_type(char_name) == r_type(&v) |
2660 | 0 | && char_name->value.const_pname == v.value.const_pname) |
2661 | 0 | return i; |
2662 | 0 | return 0; |
2663 | 0 | } |
2664 | | |
2665 | | static int |
2666 | | zfapi_finish_render(i_ctx_t *i_ctx_p) |
2667 | 0 | { |
2668 | 0 | os_ptr op = osp; |
2669 | 0 | gs_font *pfont; |
2670 | 0 | int code = font_param(op - 1, &pfont); |
2671 | |
|
2672 | 0 | if (code == 0) { |
2673 | 0 | gs_font_base *pbfont = (gs_font_base *) pfont; |
2674 | 0 | gs_fapi_server *I = pbfont->FAPI; |
2675 | 0 | gs_text_enum_t *penum = op_show_find(i_ctx_p); |
2676 | |
|
2677 | 0 | gs_fapi_set_servers_client_data(imemory, NULL, i_ctx_p); |
2678 | |
|
2679 | 0 | code = gs_fapi_finish_render(pfont, igs, penum, I); |
2680 | 0 | pop(2); |
2681 | 0 | I->release_char_data(I); |
2682 | 0 | } |
2683 | 0 | return code; |
2684 | 0 | } |
2685 | | |
2686 | | static int |
2687 | | ps_fapi_set_cache(gs_text_enum_t *penum, const gs_font_base *pbfont, |
2688 | | const gs_string *char_name, gs_glyph cid, |
2689 | | const double pwidth[2], const gs_rect *pbbox, |
2690 | | const double Metrics2_sbw_default[4], bool *imagenow) |
2691 | 1.50M | { |
2692 | 1.50M | i_ctx_t *i_ctx_p = (i_ctx_t *) pbfont->FAPI->client_ctx_p; |
2693 | 1.50M | op_proc_t exec_cont = 0; /* dummy - see below */ |
2694 | 1.50M | int code = 0; |
2695 | | |
2696 | 1.50M | if (cid < GS_MIN_CID_GLYPH) { |
2697 | 1.50M | ref cname; |
2698 | | |
2699 | 1.50M | make_string(&cname, avm_foreign | a_readonly, char_name->size, |
2700 | 1.50M | char_name->data); |
2701 | 1.50M | code = |
2702 | 1.50M | zchar_set_cache(i_ctx_p, pbfont, &cname, NULL, pwidth, pbbox, |
2703 | 1.50M | zfapi_finish_render, &exec_cont, |
2704 | 1.50M | Metrics2_sbw_default); |
2705 | 1.50M | } |
2706 | 0 | else { |
2707 | 0 | ref cidref; |
2708 | |
|
2709 | 0 | make_int(&cidref, (cid - GS_MIN_CID_GLYPH)); |
2710 | 0 | code = zchar_set_cache(i_ctx_p, pbfont, &cidref, NULL, pwidth, pbbox, |
2711 | 0 | zfapi_finish_render, &exec_cont, |
2712 | 0 | Metrics2_sbw_default); |
2713 | 0 | } |
2714 | | |
2715 | 1.50M | if (code >= 0 && exec_cont != NULL) { |
2716 | 1.50M | *imagenow = true; |
2717 | 1.50M | } |
2718 | 680 | else { |
2719 | 680 | *imagenow = false; |
2720 | 680 | } |
2721 | | /* We ignore the value of exec_cont here, and leave it up to |
2722 | | * gs_fapi_do_char() to do the "right" thing based on the |
2723 | | * return value |
2724 | | */ |
2725 | 1.50M | return (code); |
2726 | 1.50M | } |
2727 | | |
2728 | | |
2729 | | static const byte * |
2730 | | find_substring(const byte *where, int length, const char *what) |
2731 | 0 | { |
2732 | 0 | int l = strlen(what); |
2733 | 0 | int n = length - l; |
2734 | 0 | const byte *p = where; |
2735 | |
|
2736 | 0 | for (; n >= 0; n--, p++) |
2737 | 0 | if (!memcmp(p, what, l)) |
2738 | 0 | return p; |
2739 | 0 | return NULL; |
2740 | 0 | } |
2741 | | |
2742 | | static int |
2743 | | ps_get_glyphname_or_cid(gs_text_enum_t *penum, |
2744 | | gs_font_base *pbfont, gs_string *charstring, |
2745 | | gs_string *name, gs_glyph ccode, |
2746 | | gs_string *enc_char_name, char *font_file_path, |
2747 | | gs_fapi_char_ref *cr, bool bCID) |
2748 | 1.77M | { |
2749 | 1.77M | ref *pdr = pfont_dict(pbfont); |
2750 | 1.77M | int client_char_code = ccode; |
2751 | 1.77M | ref char_name, cname_str; |
2752 | 1.77M | int code = 0; |
2753 | 1.77M | gs_fapi_server *I = pbfont->FAPI; |
2754 | 1.77M | bool is_TT_from_type42 = (pbfont->FontType == ft_TrueType && font_file_path == NULL); |
2755 | 1.77M | bool is_glyph_index = false; |
2756 | 1.77M | bool is_embedded_type1 = |
2757 | 1.77M | ((pbfont->FontType == ft_encrypted |
2758 | 1.77M | || pbfont->FontType == ft_encrypted2) && font_file_path == NULL); |
2759 | 1.77M | i_ctx_t *i_ctx_p = (i_ctx_t *) I->client_ctx_p; |
2760 | 1.77M | bool unicode_cp = false; |
2761 | | |
2762 | | /* Obtain the character name : */ |
2763 | 1.77M | if (bCID) { |
2764 | 0 | if (pbfont->FontType == ft_CID_TrueType && font_file_path) { |
2765 | 0 | ref *pdr2, *fidr, *dummy; |
2766 | 0 | pdr2 = pfont_dict(gs_rootfont(igs)); |
2767 | 0 | if (dict_find_string(pdr2, "FontInfo", &fidr) > 0 && |
2768 | 0 | dict_find_string(fidr, "GlyphNames2Unicode", &dummy) > 0) |
2769 | 0 | { |
2770 | 0 | unsigned char uc[4] = {0}; |
2771 | 0 | unsigned int cc = 0; |
2772 | 0 | int i, l; |
2773 | 0 | if (penum->text.operation & TEXT_FROM_SINGLE_CHAR) { |
2774 | 0 | cc = penum->text.data.d_char; |
2775 | 0 | } else if (penum->text.operation & TEXT_FROM_SINGLE_GLYPH) { |
2776 | 0 | cc = penum->text.data.d_glyph - GS_MIN_CID_GLYPH; |
2777 | 0 | } |
2778 | 0 | else { |
2779 | 0 | byte *c = (byte *)&penum->text.data.bytes[penum->index - penum->bytes_decoded]; |
2780 | 0 | for (i = 0; i < penum->bytes_decoded ; i++) { |
2781 | 0 | cc |= c[i] << ((penum->bytes_decoded - 1) - i) * 8; |
2782 | 0 | } |
2783 | 0 | } |
2784 | 0 | l = ((gs_font_base *)gs_rootfont(igs))->procs.decode_glyph(gs_rootfont(igs), cc + GS_MIN_CID_GLYPH, ccode, (unsigned short *)uc, sizeof(uc)); |
2785 | 0 | if (l > 0 && l < sizeof(uc)) { |
2786 | 0 | cc = 0; |
2787 | 0 | for (i = 0; i < l; i++) { |
2788 | 0 | cc |= uc[l - 1 - i] << (i * 8); |
2789 | 0 | } |
2790 | 0 | ccode = cc; |
2791 | 0 | unicode_cp = true; |
2792 | 0 | } |
2793 | 0 | } |
2794 | 0 | } |
2795 | 0 | client_char_code = ccode; |
2796 | 0 | make_null(&char_name); |
2797 | 0 | enc_char_name->data = NULL; |
2798 | 0 | enc_char_name->size = 0; |
2799 | 0 | } |
2800 | 1.77M | else { |
2801 | 1.77M | if (ccode != GS_NO_CHAR) { |
2802 | | /* Translate from PS encoding to char name : */ |
2803 | 1.77M | ref *Encoding; |
2804 | | |
2805 | 1.77M | client_char_code = ccode; |
2806 | 1.77M | if (dict_find_string(pdr, "Encoding", &Encoding) > 0 && |
2807 | 1.77M | (r_has_type(Encoding, t_array) || |
2808 | 1.77M | r_has_type(Encoding, t_shortarray) |
2809 | 1.77M | || r_has_type(Encoding, t_mixedarray))) { |
2810 | 1.77M | if (array_get(imemory, Encoding, client_char_code, &char_name) |
2811 | 1.77M | < 0) |
2812 | 0 | if ((code = |
2813 | 0 | name_ref(imemory, (const byte *)".notdef", 7, |
2814 | 0 | &char_name, -1)) < 0) |
2815 | 0 | return code; |
2816 | 1.77M | } |
2817 | 0 | else { |
2818 | 0 | return_error(gs_error_invalidfont); |
2819 | 0 | } |
2820 | 1.77M | } |
2821 | 0 | else { |
2822 | 0 | code = |
2823 | 0 | names_ref(imemory->gs_lib_ctx->gs_name_table, |
2824 | 0 | (const byte *)name->data, name->size, &char_name, |
2825 | 0 | 0); |
2826 | |
|
2827 | 0 | } |
2828 | | /* We need to store the name as we get it (from the Encoding array), in case it's |
2829 | | * had the name extended (with "~GS~xx"), we'll remove the extension before passing |
2830 | | * it to the renderer for a disk based font. But the metrics dictionary may have |
2831 | | * been constructed using the extended name.... |
2832 | | */ |
2833 | 1.77M | if (!r_has_type(&char_name, t_name)) |
2834 | 0 | return_error(gs_error_invalidfont); |
2835 | 1.77M | name_string_ref(imemory, &char_name, &cname_str); |
2836 | 1.77M | enc_char_name->data = cname_str.value.bytes; |
2837 | 1.77M | enc_char_name->size = r_size(&cname_str); |
2838 | 1.77M | } |
2839 | | |
2840 | | /* Obtain the character code or glyph index : */ |
2841 | 1.77M | cr->char_codes_count = 1; |
2842 | 1.77M | if (bCID) { |
2843 | 0 | if (font_file_path != NULL) { |
2844 | 0 | ref *Decoding, *TT_cmap = NULL, *SubstNWP; |
2845 | 0 | ref src_type, dst_type; |
2846 | 0 | uint c = 0; |
2847 | |
|
2848 | 0 | is_glyph_index = true; |
2849 | |
|
2850 | 0 | if (dict_find_string(pdr, "Decoding", &Decoding) <= 0 |
2851 | 0 | || !r_has_type(Decoding, t_dictionary)) |
2852 | 0 | return_error(gs_error_invalidfont); |
2853 | 0 | if (dict_find_string(pdr, "SubstNWP", &SubstNWP) <= 0 |
2854 | 0 | || !r_has_type(SubstNWP, t_array)) |
2855 | 0 | return_error(gs_error_invalidfont); |
2856 | 0 | if (dict_find_string(pdr, "TT_cmap", &TT_cmap) <= 0 |
2857 | 0 | || !r_has_type(TT_cmap, t_dictionary)) { |
2858 | 0 | ref *DecodingArray, char_code, char_code1, ih; |
2859 | 0 | int i = client_char_code % 256, n; |
2860 | |
|
2861 | 0 | make_int(&ih, client_char_code / 256); |
2862 | | /* Check the Decoding array for this block of CIDs */ |
2863 | 0 | if (dict_find(Decoding, &ih, &DecodingArray) <= 0 |
2864 | 0 | || !r_has_type(DecodingArray, t_array) |
2865 | 0 | || array_get(imemory, DecodingArray, i, &char_code) < 0) { |
2866 | 0 | return_error(gs_error_invalidfont); |
2867 | 0 | } |
2868 | | |
2869 | | /* Check the Decoding entry */ |
2870 | 0 | if (r_has_type(&char_code, t_integer)) { |
2871 | 0 | n = 1; |
2872 | 0 | } |
2873 | 0 | else if (r_has_type(&char_code, t_array)) { |
2874 | 0 | DecodingArray = &char_code; |
2875 | 0 | i = 0; |
2876 | 0 | n = r_size(DecodingArray); |
2877 | 0 | } |
2878 | 0 | else { |
2879 | 0 | return_error(gs_error_invalidfont); |
2880 | 0 | } |
2881 | | |
2882 | 0 | for (; n--; i++) { |
2883 | 0 | if (array_get(imemory, DecodingArray, i, &char_code1) < 0 |
2884 | 0 | || !r_has_type(&char_code1, t_integer)) { |
2885 | 0 | return_error(gs_error_invalidfont); |
2886 | 0 | } |
2887 | | |
2888 | 0 | c = char_code1.value.intval; |
2889 | 0 | I->check_cmap_for_GID(I, &c); |
2890 | 0 | if (c != 0) |
2891 | 0 | break; |
2892 | 0 | } |
2893 | 0 | } |
2894 | 0 | else { |
2895 | 0 | ref *CIDSystemInfo; |
2896 | 0 | ref *Ordering; |
2897 | 0 | ref *fdict, *CMapDict, *CMapName, *WMode, CMapNameStr; |
2898 | 0 | char *cmapnm = NULL; |
2899 | 0 | int cmapnmlen = 0; |
2900 | 0 | int wmode = 0; |
2901 | | /* leave off the -H or -V */ |
2902 | 0 | const char * const utfcmap = "Identity-UTF16"; |
2903 | 0 | int utfcmaplen = strlen(utfcmap); |
2904 | |
|
2905 | 0 | fdict = pfont_dict(gs_rootfont(igs)); |
2906 | 0 | code = dict_find_string(fdict, "CMap", &CMapDict); |
2907 | 0 | if (code > 0 && r_has_type(CMapDict, t_dictionary)) { |
2908 | 0 | code = dict_find_string(CMapDict, "WMode", &WMode); |
2909 | 0 | if (code > 0 && r_has_type(WMode, t_integer)) { |
2910 | 0 | wmode = WMode->value.intval; |
2911 | 0 | } |
2912 | 0 | code = dict_find_string(CMapDict, "CMapName", &CMapName); |
2913 | 0 | if (code > 0 && r_has_type(CMapName, t_name)) { |
2914 | 0 | name_string_ref(imemory, CMapName, &CMapNameStr); |
2915 | 0 | cmapnm = (char *)CMapNameStr.value.bytes; |
2916 | 0 | cmapnmlen = r_size(&CMapNameStr); |
2917 | 0 | } |
2918 | 0 | } |
2919 | | /* We only have to lookup the char code if we're *not* using an identity ordering |
2920 | | with the exception of Identity-UTF16 which is a different beast altogether */ |
2921 | 0 | if (unicode_cp || (cmapnmlen > 0 && !strncmp(cmapnm, utfcmap, cmapnmlen > utfcmaplen ? utfcmaplen : cmapnmlen)) |
2922 | 0 | || (dict_find_string(pdr, "CIDSystemInfo", &CIDSystemInfo) > 0 |
2923 | 0 | && r_has_type(CIDSystemInfo, t_dictionary) |
2924 | 0 | && dict_find_string(CIDSystemInfo, "Ordering", |
2925 | 0 | &Ordering) > 0 |
2926 | 0 | && r_has_type(Ordering, t_string) |
2927 | 0 | && strncmp((const char *)Ordering->value.bytes, |
2928 | 0 | "Identity", 8) != 0)) { |
2929 | |
|
2930 | 0 | if ((code = |
2931 | 0 | cid_to_TT_charcode(imemory, Decoding, TT_cmap, |
2932 | 0 | SubstNWP, client_char_code, &c, |
2933 | 0 | &src_type, &dst_type)) < 0) { |
2934 | 0 | return code; |
2935 | 0 | } |
2936 | 0 | } |
2937 | 0 | else { |
2938 | 0 | if (pbfont->FontType == ft_CID_TrueType) { |
2939 | 0 | c = ((gs_font_cid2 *)pbfont)->cidata.CIDMap_proc(((gs_font_cid2 *)pbfont), |
2940 | 0 | client_char_code + GS_MIN_CID_GLYPH); |
2941 | 0 | } |
2942 | 0 | else { |
2943 | 0 | c = client_char_code; |
2944 | 0 | } |
2945 | 0 | } |
2946 | 0 | if (pbfont->FontType == ft_CID_TrueType) |
2947 | 0 | c = ((gs_font_cid2 *)pbfont)->data.substitute_glyph_index_vertical((gs_font_type42 *)pbfont, c, wmode, ccode); |
2948 | 0 | } |
2949 | 0 | if (pbfont->FontType == ft_CID_TrueType && c == 0 && TT_cmap) { |
2950 | 0 | ref cc32; |
2951 | 0 | ref *gid; |
2952 | 0 | make_int(&cc32, 32); |
2953 | 0 | if (dict_find(TT_cmap, &cc32, &gid) > 0) |
2954 | 0 | c = gid->value.intval; |
2955 | 0 | } |
2956 | 0 | cr->char_codes[0] = c; |
2957 | | /* fixme : process the narrow/wide/proportional mapping type, |
2958 | | using src_type, dst_type. Should adjust the 'matrix' above. |
2959 | | Call get_font_proportional_feature for proper choice. |
2960 | | */ |
2961 | 0 | } |
2962 | 0 | else { |
2963 | 0 | ref *CIDMap; |
2964 | 0 | byte *Map; |
2965 | 0 | int c_code = client_char_code; |
2966 | 0 | int gdb = 2; |
2967 | 0 | int i; |
2968 | 0 | ref *GDBytes = NULL; |
2969 | |
|
2970 | 0 | if ((dict_find_string(pdr, "GDBytes", &GDBytes) > 0) |
2971 | 0 | && r_has_type(GDBytes, t_integer)) { |
2972 | 0 | gdb = GDBytes->value.intval; |
2973 | 0 | } |
2974 | | |
2975 | | /* The PDF Reference says that we should use a CIDToGIDMap, but the PDF |
2976 | | * interpreter converts this into a CIDMap (see pdf_font.ps, processCIDToGIDMap) |
2977 | | */ |
2978 | 0 | if (dict_find_string(pdr, "CIDMap", &CIDMap) > 0 |
2979 | 0 | && !r_has_type(CIDMap, t_name) && (r_has_type(CIDMap, t_array) |
2980 | 0 | || r_has_type(CIDMap, |
2981 | 0 | t_string))) { |
2982 | |
|
2983 | 0 | if (r_has_type(CIDMap, t_array)) { |
2984 | | |
2985 | | /* Too big for single string, so its an array of 2 strings */ |
2986 | 0 | code = string_array_access_proc(pbfont->memory, CIDMap, 1, |
2987 | 0 | client_char_code * (ulong)gdb, |
2988 | 0 | gdb, NULL, NULL, |
2989 | 0 | (const byte **)&Map); |
2990 | 0 | } |
2991 | 0 | else { |
2992 | 0 | if (CIDMap->tas.rsize <= c_code * gdb) { |
2993 | 0 | c_code = 0; |
2994 | 0 | } |
2995 | 0 | Map = &CIDMap->value.bytes[c_code * gdb]; |
2996 | 0 | } |
2997 | 0 | cr->char_codes[0] = 0; |
2998 | 0 | is_glyph_index = true; |
2999 | 0 | if (code >= 0) { |
3000 | 0 | for (i = 0; i < gdb; i++) { |
3001 | 0 | cr->char_codes[0] = (cr->char_codes[0] << 8) + Map[i]; |
3002 | 0 | } |
3003 | 0 | } |
3004 | 0 | else { |
3005 | 0 | ref *cstr, *refcode; |
3006 | 0 | code = dict_find_string(pdr, "CharStrings", &cstr); |
3007 | 0 | if (code > 0) { |
3008 | 0 | code = dict_find_string(cstr, ".notdef", &refcode); |
3009 | 0 | if (code > 0) { |
3010 | 0 | cr->char_codes[0] = refcode->value.intval; |
3011 | 0 | } |
3012 | 0 | } |
3013 | 0 | } |
3014 | 0 | } |
3015 | 0 | else |
3016 | 0 | cr->char_codes[0] = client_char_code; |
3017 | 0 | } |
3018 | 0 | } |
3019 | 1.77M | else if (is_TT_from_type42) { |
3020 | | /* This font must not use 'cmap', so compute glyph index from CharStrings : */ |
3021 | 0 | ref *CharStrings, *glyph_index, *cmaptab; |
3022 | |
|
3023 | 0 | if (dict_find_string(pdr, "TT_cmap", &cmaptab) > 0 && |
3024 | 0 | r_has_type(cmaptab, t_dictionary)) { |
3025 | 0 | const char *nd = ".notdef"; |
3026 | |
|
3027 | 0 | if (enc_char_name->size >= strlen(nd) && |
3028 | 0 | enc_char_name->data[0] == nd[0] && |
3029 | 0 | !memcmp(enc_char_name->data, nd, strlen(nd))) { |
3030 | 0 | ref ccref, *gidref, boolref; |
3031 | 0 | make_int(&ccref, ccode); |
3032 | 0 | if (dict_find(cmaptab, &ccref, &gidref) > 0 && |
3033 | 0 | r_has_type(gidref, t_integer) && |
3034 | 0 | gidref->value.intval == 0) { |
3035 | 0 | make_bool(&boolref, true); |
3036 | 0 | } |
3037 | 0 | else { |
3038 | 0 | make_bool(&boolref, false); |
3039 | 0 | } |
3040 | 0 | dict_put_string(pdr, ".render_notdef", &boolref, NULL); |
3041 | 0 | } |
3042 | 0 | } |
3043 | |
|
3044 | 0 | if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0 |
3045 | 0 | || !r_has_type(CharStrings, t_dictionary)) |
3046 | 0 | return_error(gs_error_invalidfont); |
3047 | 0 | if ((dict_find(CharStrings, &char_name, &glyph_index) <= 0) |
3048 | 0 | || r_has_type(glyph_index, t_null)) { |
3049 | | #ifdef DEBUG |
3050 | | ref *pvalue; |
3051 | | |
3052 | | if (gs_debug_c('1') |
3053 | | && (dict_find_string(systemdict, "QUIET", &pvalue)) > 0 |
3054 | | && (r_has_type(pvalue, t_boolean) |
3055 | | && pvalue->value.boolval == false)) { |
3056 | | char *glyphn; |
3057 | | |
3058 | | name_string_ref(imemory, &char_name, &char_name); |
3059 | | |
3060 | | glyphn = |
3061 | | ref_to_string(&char_name, imemory, |
3062 | | "ps_get_glyphname_or_cid"); |
3063 | | if (glyphn) { |
3064 | | dmprintf2(imemory, " Substituting .notdef for %s in the font %s \n", |
3065 | | glyphn, pbfont->font_name.chars); |
3066 | | gs_free_string(imemory, (byte *) glyphn, |
3067 | | strlen(glyphn) + 1, |
3068 | | "ps_get_glyphname_or_cid"); |
3069 | | } |
3070 | | } |
3071 | | #endif |
3072 | |
|
3073 | 0 | cr->char_codes[0] = 0; /* .notdef */ |
3074 | 0 | if ((code = |
3075 | 0 | name_ref(imemory, (const byte *)".notdef", 7, &char_name, |
3076 | 0 | -1)) < 0) |
3077 | 0 | return code; |
3078 | 0 | } |
3079 | 0 | else if (r_has_type(glyph_index, t_integer)) { |
3080 | 0 | cr->char_codes[0] = glyph_index->value.intval; |
3081 | 0 | } |
3082 | 0 | else { |
3083 | 0 | #if 1 /* I can't find this ever being used, no idea what it's for..... */ |
3084 | 0 | os_ptr op = osp; |
3085 | | |
3086 | | /* Check execution stack has space for BuldChar proc and finish_render */ |
3087 | 0 | check_estack(2); |
3088 | | /* check space and duplicate the glyph index for BuildChar */ |
3089 | 0 | check_op(1); |
3090 | 0 | push(1); |
3091 | 0 | ref_assign_inline(op, op - 1); |
3092 | | /* Come back to fapi_finish_render after running the BuildChar */ |
3093 | 0 | push_op_estack(zfapi_finish_render); |
3094 | 0 | ++esp; |
3095 | 0 | ref_assign(esp, glyph_index); |
3096 | 0 | return o_push_estack; |
3097 | | #else |
3098 | | return (gs_error_invalidfont); |
3099 | | #endif |
3100 | 0 | } |
3101 | 0 | is_glyph_index = true; |
3102 | 0 | } |
3103 | 1.77M | else if (is_embedded_type1) { |
3104 | | /* Since the client passes charstring by callback using I->ff.char_data, |
3105 | | the client doesn't need to provide a good cr here. |
3106 | | Perhaps since UFST uses char codes as glyph cache keys (UFST 4.2 cannot use names), |
3107 | | we provide font char codes equal to document's char codes. |
3108 | | This trick assumes that Encoding can't point different glyphs |
3109 | | for same char code. The last should be true due to |
3110 | | PLRM3, "5.9.4 Subsetting and Incremental Definition of Glyphs". |
3111 | | */ |
3112 | 1.77M | if (ccode != GS_NO_CHAR) { |
3113 | 1.77M | cr->char_codes[0] = client_char_code; |
3114 | 1.77M | } |
3115 | 0 | else { |
3116 | | /* |
3117 | | * Reverse Encoding here, because it can be an incremental one. |
3118 | | * Note that this can cause problems with UFST (see the comment above), |
3119 | | * if the encoding doesn't contain the glyph name rendered with glyphshow. |
3120 | | */ |
3121 | 0 | ref *Encoding; |
3122 | 0 | ref glyph; |
3123 | |
|
3124 | 0 | if ((code = name_ref(pbfont->memory, name->data, name->size, &glyph, false)) < 0) |
3125 | 0 | return code; |
3126 | | |
3127 | 0 | if (dict_find_string(osp - 1, "Encoding", &Encoding) > 0) { |
3128 | 0 | cr->char_codes[0] = |
3129 | 0 | (uint) array_find(imemory, Encoding, &glyph); |
3130 | 0 | } |
3131 | 0 | else |
3132 | 0 | return_error(gs_error_invalidfont); |
3133 | 0 | } |
3134 | 1.77M | } |
3135 | 0 | else { /* a non-embedded font, i.e. a disk font */ |
3136 | 0 | bool can_retrieve_char_by_name = false; |
3137 | 0 | const byte *p; |
3138 | |
|
3139 | 0 | obj_string_data(imemory, &char_name, &cr->char_name, |
3140 | 0 | &cr->char_name_length); |
3141 | 0 | p = find_substring(cr->char_name, cr->char_name_length, |
3142 | 0 | gx_extendeg_glyph_name_separator); |
3143 | 0 | if (p != NULL) { |
3144 | 0 | cr->char_name_length = p - cr->char_name; |
3145 | 0 | if ((code = name_ref(pbfont->memory, cr->char_name, |
3146 | 0 | cr->char_name_length, &char_name, true)) < 0) |
3147 | 0 | return code; |
3148 | 0 | } |
3149 | 0 | if ((code = |
3150 | 0 | renderer_retcode(imemory, I, |
3151 | 0 | I->can_retrieve_char_by_name(I, &I->ff, cr, |
3152 | 0 | &can_retrieve_char_by_name))) |
3153 | 0 | < 0) |
3154 | 0 | return code; |
3155 | | |
3156 | 0 | if (!can_retrieve_char_by_name) { |
3157 | | /* Translate from char name to encoding used with 3d party font technology : */ |
3158 | 0 | ref *Decoding, *char_code; |
3159 | |
|
3160 | 0 | if (dict_find_string(osp - 1, "Decoding", &Decoding) > 0 |
3161 | 0 | && r_has_type(Decoding, t_dictionary)) { |
3162 | 0 | if (dict_find(Decoding, &char_name, &char_code) > 0) { |
3163 | 0 | code = 0; |
3164 | 0 | if (r_has_type(char_code, t_integer)) { |
3165 | 0 | int c_code; |
3166 | 0 | int_param(char_code, 0xFFFF, &c_code); |
3167 | 0 | cr->char_codes[0] = (gs_glyph)c_code; |
3168 | 0 | } |
3169 | 0 | else if (r_has_type(char_code, t_array) |
3170 | 0 | || r_has_type(char_code, t_shortarray)) { |
3171 | 0 | int i; |
3172 | 0 | ref v; |
3173 | |
|
3174 | 0 | cr->char_codes_count = r_size(char_code); |
3175 | 0 | if (cr->char_codes_count > count_of(cr->char_codes)) |
3176 | 0 | code = gs_note_error(gs_error_rangecheck); |
3177 | 0 | if (code >= 0) { |
3178 | 0 | for (i = 0; i < cr->char_codes_count; i++) { |
3179 | 0 | code = array_get(imemory, char_code, i, &v); |
3180 | 0 | if (code < 0) |
3181 | 0 | break; |
3182 | 0 | if (!r_has_type(char_code, t_integer)) { |
3183 | 0 | code = gs_note_error(gs_error_rangecheck); |
3184 | 0 | break; |
3185 | 0 | } |
3186 | 0 | cr->char_codes[i] = v.value.intval; |
3187 | 0 | } |
3188 | 0 | } |
3189 | 0 | } |
3190 | 0 | else { |
3191 | 0 | code = gs_note_error(gs_error_rangecheck); |
3192 | 0 | } |
3193 | 0 | if (code < 0) { |
3194 | 0 | char buf[16]; |
3195 | 0 | int l = cr->char_name_length; |
3196 | |
|
3197 | 0 | if (l > sizeof(buf) - 1) { |
3198 | 0 | l = sizeof(buf) - 1; |
3199 | 0 | } |
3200 | 0 | memcpy(buf, cr->char_name, l); |
3201 | 0 | buf[l] = 0; |
3202 | 0 | emprintf1(imemory, |
3203 | 0 | "Wrong decoding entry for the character '%s'.\n", |
3204 | 0 | buf); |
3205 | 0 | return_error(gs_error_rangecheck); |
3206 | 0 | } |
3207 | 0 | } |
3208 | 0 | } |
3209 | 0 | } |
3210 | 0 | } |
3211 | | |
3212 | | /* Provide glyph data for renderer : */ |
3213 | | /* Occasionally, char_name is already a glyph index to pass to the rendering engine |
3214 | | * so don't treat it as a name object. |
3215 | | * I believe this will only happen with a TTF/Type42, but checking the object type |
3216 | | * is cheap, and covers all font type eventualities. |
3217 | | */ |
3218 | 1.77M | if (!I->ff.is_cid && r_has_type(&char_name, t_name)) { |
3219 | 1.77M | ref sname; |
3220 | | |
3221 | 1.77M | name_string_ref(imemory, &char_name, &sname); |
3222 | 1.77M | I->ff.char_data = sname.value.const_bytes; |
3223 | 1.77M | I->ff.char_data_len = r_size(&sname); |
3224 | 1.77M | } |
3225 | 0 | else if (I->ff.is_type1) { |
3226 | 0 | I->ff.char_data = charstring; |
3227 | 0 | } |
3228 | | |
3229 | 1.77M | cr->is_glyph_index = is_glyph_index; |
3230 | 1.77M | cr->client_char_code = client_char_code; |
3231 | | |
3232 | 1.77M | return (code); |
3233 | 1.77M | } |
3234 | | |
3235 | | |
3236 | | static int |
3237 | | FAPI_char(i_ctx_t *i_ctx_p, bool bBuildGlyph, ref *charstring) |
3238 | 1.50M | { /* Stack : <font> <code|name> --> - */ |
3239 | 1.50M | os_ptr op = osp; |
3240 | 1.50M | ref *pdr = op - 1; |
3241 | 1.50M | ref *v; |
3242 | 1.50M | char *font_file_path = NULL; |
3243 | 1.50M | gs_font *pfont; |
3244 | 1.50M | int code; |
3245 | | |
3246 | 1.50M | check_op(2); |
3247 | 1.50M | code = font_param(osp - 1, &pfont); |
3248 | | |
3249 | 1.50M | if (code == 0) { |
3250 | 1.50M | gs_font_base *pbfont = (gs_font_base *) pfont; |
3251 | 1.50M | bool bCID = (FAPI_ISCIDFONT(pbfont) || charstring != NULL); |
3252 | 1.50M | int subfont; |
3253 | 1.50M | gs_fapi_server *I = pbfont->FAPI; |
3254 | 1.50M | gs_text_enum_t *penum = op_show_find(i_ctx_p); |
3255 | 1.50M | gs_string char_string, *c_string_p = NULL; |
3256 | 1.50M | gs_string char_name, *c_name_p = NULL; |
3257 | 1.50M | gs_glyph cindex = GS_NO_CHAR; |
3258 | 1.50M | ref gname; |
3259 | | |
3260 | 1.50M | if (I == NULL) |
3261 | 0 | return_error(gs_error_invalidfont); |
3262 | | |
3263 | | /* initialise the FAPI font, this includes language specific stuff */ |
3264 | 1.50M | I->ff = ps_ff_stub; |
3265 | | |
3266 | 1.50M | I->client_ctx_p = i_ctx_p; |
3267 | | |
3268 | 1.50M | if (bBuildGlyph && !bCID) { |
3269 | 0 | if (r_type(op) != t_name) { |
3270 | 0 | name_enter_string(imemory, ".notdef", op); |
3271 | 0 | } |
3272 | 0 | check_type(*op, t_name); |
3273 | | |
3274 | 0 | name_string_ref(imemory, op, &gname); |
3275 | 0 | c_name_p = &char_name; |
3276 | 0 | c_name_p->data = gname.value.bytes; |
3277 | 0 | c_name_p->size = r_size(&gname); |
3278 | |
|
3279 | 0 | } |
3280 | 1.50M | else { |
3281 | 1.50M | int chint; |
3282 | 1.50M | if (bBuildGlyph && pbfont->FontType == ft_CID_TrueType |
3283 | 1.50M | && r_has_type(op, t_name)) { |
3284 | 0 | ref *chstrs, *chs; |
3285 | | |
3286 | | /* This logic is lifted from %Type11BuildGlyph in gs_cidfn.ps |
3287 | | * Note we only have to deal with mistakenly being given a name object |
3288 | | * here, the out of range CID is handled later |
3289 | | */ |
3290 | 0 | if ((dict_find_string(op - 1, "CharStrings", &chstrs)) <= 0) { |
3291 | 0 | return_error(gs_error_undefined); |
3292 | 0 | } |
3293 | | |
3294 | 0 | if ((dict_find_string(chstrs, ".notdef", &chs)) <= 0) { |
3295 | 0 | return_error(gs_error_undefined); |
3296 | 0 | } |
3297 | 0 | ref_assign_inline(op, chs); |
3298 | 0 | } |
3299 | | |
3300 | 1.50M | make_null(&gname); |
3301 | 1.50M | check_type(*op, t_integer); |
3302 | 1.50M | int_param(op, 0xFFFF, (int *)&chint); |
3303 | 1.50M | cindex = chint; |
3304 | 1.50M | } |
3305 | | |
3306 | 1.50M | if (dict_find_string(pdr, "SubfontId", &v) > 0 |
3307 | 1.50M | && r_has_type(v, t_integer)) |
3308 | 0 | subfont = v->value.intval; |
3309 | 1.50M | else |
3310 | 1.50M | subfont = 0; |
3311 | | |
3312 | 1.50M | if (dict_find_string(osp - 1, "Path", &v) > 0 |
3313 | 1.50M | && r_has_type(v, t_string)) { |
3314 | 0 | font_file_path = ref_to_string(v, imemory, "font file path"); |
3315 | 0 | } |
3316 | | |
3317 | 1.50M | if (charstring) { |
3318 | 0 | c_string_p = &char_string; |
3319 | 0 | c_string_p->data = charstring->value.bytes; |
3320 | 0 | c_string_p->size = r_size(charstring); |
3321 | 0 | } |
3322 | | |
3323 | 1.50M | code = |
3324 | 1.50M | gs_fapi_do_char(pfont, igs, penum, font_file_path, |
3325 | 1.50M | bBuildGlyph, c_string_p, c_name_p, (gs_char)cindex, cindex, |
3326 | 1.50M | subfont); |
3327 | 1.50M | if (font_file_path != NULL) { |
3328 | 0 | gs_free_string(imemory, (byte *) font_file_path, r_size(v) + 1, |
3329 | 0 | "font file path"); |
3330 | 0 | } |
3331 | | /* This handles the situation where a charstring has been replaced with a PS procedure. |
3332 | | * against the rules, but not *that* rare. |
3333 | | * It's also something that GS does internally to simulate font styles. |
3334 | | */ |
3335 | 1.50M | if (code == gs_error_unregistered) { |
3336 | 0 | os_ptr op = osp; |
3337 | 0 | ref *proc = NULL, gname; |
3338 | |
|
3339 | 0 | if (I->ff.is_type1 |
3340 | 0 | && (get_charstring(&I->ff, cindex, &proc, &gname) >= 0) |
3341 | 0 | && proc != NULL && (r_has_type(proc, t_array) |
3342 | 0 | || r_has_type(proc, t_mixedarray))) { |
3343 | 0 | push(2); |
3344 | 0 | ref_assign(op - 1, &gname); |
3345 | 0 | ref_assign(op, proc); |
3346 | 0 | return (zchar_exec_char_proc(i_ctx_p)); |
3347 | 0 | } |
3348 | 0 | else { |
3349 | 0 | return_error(gs_error_invalidfont); |
3350 | 0 | } |
3351 | 0 | } |
3352 | 1.50M | } |
3353 | | /* We've already imaged teh glyph, pop the operands */ |
3354 | 1.50M | if (code == 0) |
3355 | 1.50M | pop(2); |
3356 | 1.50M | return code; |
3357 | 1.50M | } |
3358 | | |
3359 | | static int |
3360 | | zFAPIBuildGlyph9(i_ctx_t *i_ctx_p) |
3361 | 0 | { |
3362 | | /* The alghorithm is taken from %Type9BuildGlyph - see gs_cidfn.ps . */ |
3363 | 0 | os_ptr lop, op = osp; |
3364 | 0 | int cid, code; |
3365 | 0 | avm_space s = ialloc_space(idmemory); |
3366 | 0 | ref font9 = *pfont_dict(gs_currentfont(igs)); |
3367 | 0 | ref *rFDArray, f; |
3368 | 0 | int font_index; |
3369 | |
|
3370 | 0 | check_op(2); |
3371 | 0 | check_type(op[0], t_integer); |
3372 | 0 | check_type(op[-1], t_dictionary); |
3373 | 0 | cid = op[0].value.intval; |
3374 | 0 | push(2); |
3375 | 0 | op[-1] = *pfont_dict(gs_currentfont(igs)); |
3376 | 0 | op[0] = op[-2]; /* <font0> <cid> <font9> <cid> */ |
3377 | 0 | ialloc_set_space(idmemory, (r_is_local(op - 3) ? avm_global : avm_local)); /* for ztype9mapcid */ |
3378 | | |
3379 | | /* stack: <font0> <cid> <font9> <cid> */ |
3380 | 0 | if ((code = ztype9mapcid(i_ctx_p)) < 0) |
3381 | 0 | return code; /* <font0> <cid> <charstring> <font_index> */ |
3382 | | /* fixme: what happens if the charstring is absent ? |
3383 | | Can FDArray contain 'null' (see %Type9BuildGlyph in gs_cidfn.ps)? */ |
3384 | 0 | font_index = op[0].value.intval; |
3385 | 0 | if (dict_find_string(&font9, "FDArray", &rFDArray) <= 0 |
3386 | 0 | || r_type(rFDArray) != t_array) |
3387 | 0 | return_error(gs_error_invalidfont); |
3388 | 0 | if (array_get(imemory, rFDArray, font_index, &f) < 0 |
3389 | 0 | || r_type(&f) != t_dictionary) |
3390 | 0 | return_error(gs_error_invalidfont); |
3391 | | |
3392 | 0 | op[0] = op[-2]; |
3393 | 0 | op[-2] = op[-1]; /* Keep the charstring on ostack for the garbager. */ |
3394 | 0 | op[-1] = f; /* <font0> <charstring> <subfont> <cid> */ |
3395 | 0 | if ((code = FAPI_char(i_ctx_p, true, op - 2)) < 0) |
3396 | 0 | return code; |
3397 | | /* stack: <font0> <charstring> */ |
3398 | | |
3399 | 0 | lop = osp; |
3400 | 0 | if (code == 5) { |
3401 | 0 | int i, ind = (lop - op); |
3402 | |
|
3403 | 0 | op = osp; |
3404 | |
|
3405 | 0 | for (i = ind; i >= 0; i--) { |
3406 | 0 | op[-i - 2] = op[-i]; |
3407 | 0 | } |
3408 | 0 | pop(2); |
3409 | 0 | } |
3410 | 0 | else if (code < 0) { /* <font0> <dirty> <dirty> <dirty> */ |
3411 | | /* Adjust ostack for the correct error handling : */ |
3412 | 0 | make_int(op - 2, cid); |
3413 | 0 | pop(2); /* <font0> <cid> */ |
3414 | 0 | } |
3415 | 0 | else if (code != 5) { /* <font0> <dirty> */ |
3416 | | |
3417 | |
|
3418 | 0 | pop(2); /* */ |
3419 | | /* Note that this releases the charstring, and it may be garbage-collected |
3420 | | before the interpreter calls fapi_finish_render. This requires the server |
3421 | | to keep glyph raster internally between calls to get_char_raster_metrics |
3422 | | and get_char_raster. Perhaps UFST cannot provide metrics without |
3423 | | building a raster, so this constraint actually goes from UFST. |
3424 | | */ |
3425 | 0 | } |
3426 | 0 | ialloc_set_space(idmemory, s); |
3427 | 0 | return code; |
3428 | 0 | } |
3429 | | |
3430 | | /* <font> <code> .FAPIBuildChar - */ |
3431 | | static int |
3432 | | zFAPIBuildChar(i_ctx_t *i_ctx_p) |
3433 | 1.50M | { |
3434 | 1.50M | return FAPI_char(i_ctx_p, false, NULL); |
3435 | 1.50M | } |
3436 | | |
3437 | | /* non-CID : <font> <code> .FAPIBuildGlyph - */ |
3438 | | /* CID : <font> <name> .FAPIBuildGlyph - */ |
3439 | | static int |
3440 | | zFAPIBuildGlyph(i_ctx_t *i_ctx_p) |
3441 | 7 | { |
3442 | 7 | return FAPI_char(i_ctx_p, true, NULL); |
3443 | 7 | } |
3444 | | |
3445 | | |
3446 | | /* <font_dict> .FAPIpassfont bool <font_dict> */ |
3447 | | /* must insert /FAPI to font dictionary */ |
3448 | | static int |
3449 | | zFAPIpassfont(i_ctx_t *i_ctx_p) |
3450 | 13.0k | { |
3451 | 13.0k | os_ptr op = osp; |
3452 | 13.0k | gs_font *pfont; |
3453 | 13.0k | int code; |
3454 | 13.0k | char *font_file_path = NULL; |
3455 | 13.0k | ref *v; |
3456 | 13.0k | char *xlatmap = NULL; |
3457 | 13.0k | char *fapi_request = NULL; |
3458 | 13.0k | char *fapi_id = NULL; |
3459 | 13.0k | ref reqstr; |
3460 | 13.0k | int subfont; |
3461 | | |
3462 | 13.0k | check_op(1); |
3463 | | /* Normally embedded fonts have no Path, but if a CID font is |
3464 | | * emulated with a TT font, and it is hooked with FAPI, |
3465 | | * the path presents and is neccessary to access the full font data. |
3466 | | */ |
3467 | 13.0k | check_type(*op, t_dictionary); |
3468 | | |
3469 | 13.0k | code = font_param(osp, &pfont); |
3470 | 13.0k | if (code < 0) |
3471 | 0 | return code; |
3472 | | |
3473 | 13.0k | if (dict_find_string(op, "SubfontId", &v) > 0 |
3474 | 13.0k | && r_has_type(v, t_integer)) |
3475 | 0 | subfont = v->value.intval; |
3476 | 13.0k | else |
3477 | 13.0k | subfont = 0; |
3478 | | |
3479 | 13.0k | code = FAPI_get_xlatmap(i_ctx_p, &xlatmap); /* Useful for emulated fonts hooked with FAPI. */ |
3480 | 13.0k | if (code < 0) |
3481 | 0 | return code; |
3482 | | |
3483 | | /* If the font dictionary contains a FAPIPlugInReq key, the the PS world wants us |
3484 | | * to try to use a specific FAPI plugin, so find it, and try it.... |
3485 | | */ |
3486 | 13.0k | if (dict_find_string(op, "FAPIPlugInReq", &v) > 0 && r_type(v) == t_name) { |
3487 | |
|
3488 | 0 | name_string_ref(imemory, v, &reqstr); |
3489 | |
|
3490 | 0 | fapi_request = ref_to_string(&reqstr, imemory, "zFAPIpassfont"); |
3491 | 0 | } |
3492 | | |
3493 | 13.0k | if (dict_find_string(op, "Path", &v) > 0 && r_has_type(v, t_string)) |
3494 | 0 | font_file_path = ref_to_string(v, imemory_global, "font file path"); |
3495 | | |
3496 | 13.0k | gs_fapi_set_servers_client_data(imemory, &ps_ff_stub, i_ctx_p); |
3497 | | |
3498 | 13.0k | code = |
3499 | 13.0k | gs_fapi_passfont(pfont, subfont, font_file_path, NULL, fapi_request, xlatmap, |
3500 | 13.0k | &fapi_id, NULL, ps_get_server_param); |
3501 | | |
3502 | 13.0k | if (font_file_path != NULL) |
3503 | 0 | gs_free_string(imemory_global, (byte *) font_file_path, r_size(v) + 1, |
3504 | 13.0k | "font file path"); |
3505 | | |
3506 | 13.0k | if (fapi_request != NULL) |
3507 | 0 | gs_free_string(imemory, (byte *) fapi_request, |
3508 | 13.0k | strlen(fapi_request) + 1, "do_FAPIpassfont"); |
3509 | 13.0k | if (code < 0 && code != gs_error_invalidaccess) |
3510 | 15 | return code; |
3511 | | |
3512 | 13.0k | if (code >= 0 && fapi_id != NULL) { |
3513 | 13.0k | ref FAPI_ID; |
3514 | | |
3515 | 13.0k | if ((code = |
3516 | 13.0k | name_ref(imemory, (const byte *)fapi_id, |
3517 | 13.0k | strlen(fapi_id), &FAPI_ID, false)) < 0) |
3518 | 0 | return code; |
3519 | 13.0k | if ((code = dict_put_string(op, "FAPI", &FAPI_ID, NULL)) < 0) |
3520 | 0 | return code; /* Insert FAPI entry to font dictionary. */ |
3521 | 13.0k | } |
3522 | 13.0k | push(1); |
3523 | 13.0k | make_bool(op, (fapi_id != NULL)); |
3524 | 13.0k | return 0; |
3525 | 13.0k | } |
3526 | | |
3527 | | const op_def zfapi_op_defs[] = { |
3528 | | {"1.FAPIavailable", zFAPIavailable}, |
3529 | | {"2.FAPIpassfont", zFAPIpassfont}, |
3530 | | {"2.FAPIrebuildfont", zFAPIrebuildfont}, |
3531 | | {"2.FAPIBuildChar", zFAPIBuildChar}, |
3532 | | {"2.FAPIBuildGlyph", zFAPIBuildGlyph}, |
3533 | | {"2.FAPIBuildGlyph9", zFAPIBuildGlyph9}, |
3534 | | op_def_end(0) |
3535 | | }; |