/src/ghostpdl/psi/zfont.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2021 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., 1305 Grant Avenue - Suite 200, Novato, |
13 | | CA 94945, U.S.A., +1(415)492-9861, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Generic font operators */ |
18 | | #include "ghost.h" |
19 | | #include "oper.h" |
20 | | #include "gsstruct.h" /* for registering root */ |
21 | | #include "gzstate.h" /* must precede gxdevice */ |
22 | | #include "gxdevice.h" /* must precede gxfont */ |
23 | | #include "gxfont.h" |
24 | | #include "gxfcache.h" |
25 | | #include "bfont.h" |
26 | | #include "ialloc.h" |
27 | | #include "iddict.h" |
28 | | #include "igstate.h" |
29 | | #include "iname.h" /* for name_mark_index */ |
30 | | #include "isave.h" |
31 | | #include "store.h" |
32 | | #include "ivmspace.h" |
33 | | #include "gscencs.h" |
34 | | |
35 | | /* Forward references */ |
36 | | static int make_font(i_ctx_t *, const gs_matrix *); |
37 | | static void make_uint_array(os_ptr, const uint *, int); |
38 | | static int setup_unicode_decoder(i_ctx_t *i_ctx_p, ref *Decoding); |
39 | | |
40 | | /* Mark a glyph as a PostScript name (if it isn't a CID). */ |
41 | | bool |
42 | | zfont_mark_glyph_name(const gs_memory_t *mem, gs_glyph glyph, void *ignore_data) |
43 | 1.02M | { |
44 | 1.02M | if (glyph == GS_NO_GLYPH) |
45 | 0 | return false; |
46 | 1.02M | if (glyph >= gs_c_min_std_encoding_glyph) |
47 | 0 | return false; |
48 | 1.02M | return name_mark_index(mem, (uint) glyph); |
49 | 1.02M | } |
50 | | |
51 | | /* Get a global glyph code. */ |
52 | | static int |
53 | | zfont_global_glyph_code(const gs_font *pbfont, gs_const_string *gstr, gs_glyph *pglyph) |
54 | 0 | { |
55 | 0 | ref v; |
56 | 0 | int code = name_ref(pbfont->memory, gstr->data, gstr->size, &v, 0); |
57 | |
|
58 | 0 | if (code < 0) |
59 | 0 | return code; |
60 | 0 | *pglyph = (gs_glyph)name_index(pbfont->memory, &v); |
61 | 0 | return 0; |
62 | 0 | } |
63 | | |
64 | | /* Initialize the font operators */ |
65 | | static int |
66 | | zfont_init(i_ctx_t *i_ctx_p) |
67 | 89.2k | { |
68 | 89.2k | ifont_dir = gs_font_dir_alloc2(imemory->stable_memory, imemory->non_gc_memory); |
69 | 89.2k | if (ifont_dir == NULL) |
70 | 0 | return gs_error_VMerror; |
71 | 89.2k | ifont_dir->ccache.mark_glyph = zfont_mark_glyph_name; |
72 | 89.2k | ifont_dir->global_glyph_code = zfont_global_glyph_code; |
73 | 89.2k | return gs_register_struct_root(imemory, &imemory->gs_lib_ctx->font_dir_root, |
74 | 89.2k | (void **)&ifont_dir, "ifont_dir"); |
75 | 89.2k | } |
76 | | |
77 | | /* <font> <scale> scalefont <new_font> */ |
78 | | static int |
79 | | zscalefont(i_ctx_t *i_ctx_p) |
80 | 9.97k | { |
81 | 9.97k | os_ptr op = osp; |
82 | 9.97k | int code; |
83 | 9.97k | double scale; |
84 | 9.97k | gs_matrix mat; |
85 | | |
86 | 9.97k | if ((code = real_param(op, &scale)) < 0) |
87 | 143 | return code; |
88 | 9.83k | if ((code = gs_make_scaling(scale, scale, &mat)) < 0) |
89 | 0 | return code; |
90 | 9.83k | return make_font(i_ctx_p, &mat); |
91 | 9.83k | } |
92 | | |
93 | | /* <font> <matrix> makefont <new_font> */ |
94 | | static int |
95 | | zmakefont(i_ctx_t *i_ctx_p) |
96 | 13 | { |
97 | 13 | os_ptr op = osp; |
98 | 13 | int code; |
99 | 13 | gs_matrix mat; |
100 | | |
101 | 13 | if ((code = read_matrix(imemory, op, &mat)) < 0) |
102 | 12 | return code; |
103 | 1 | return make_font(i_ctx_p, &mat); |
104 | 13 | } |
105 | | |
106 | | /* <font> setfont - */ |
107 | | int |
108 | | zsetfont(i_ctx_t *i_ctx_p) |
109 | 98.5k | { |
110 | 98.5k | os_ptr op = osp; |
111 | 98.5k | gs_font *pfont; |
112 | 98.5k | int code = font_param(op, &pfont); |
113 | | |
114 | 98.5k | if (code < 0 || (code = gs_setfont(igs, pfont)) < 0) |
115 | 15 | return code; |
116 | 98.5k | pop(1); |
117 | 98.5k | return code; |
118 | 98.5k | } |
119 | | |
120 | | /* - currentfont <font> */ |
121 | | static int |
122 | | zcurrentfont(i_ctx_t *i_ctx_p) |
123 | 97.0k | { |
124 | 97.0k | os_ptr op = osp; |
125 | | |
126 | 97.0k | push(1); |
127 | 97.0k | *op = *pfont_dict(gs_currentfont(igs)); |
128 | 97.0k | return 0; |
129 | 97.0k | } |
130 | | |
131 | | /* - cachestatus <mark> <bsize> <bmax> <msize> <mmax> <csize> <cmax> <blimit> */ |
132 | | static int |
133 | | zcachestatus(i_ctx_t *i_ctx_p) |
134 | 89.2k | { |
135 | 89.2k | os_ptr op = osp; |
136 | 89.2k | uint status[7]; |
137 | | |
138 | 89.2k | gs_cachestatus(ifont_dir, status); |
139 | 89.2k | push(7); |
140 | 89.2k | make_uint_array(op - 6, status, 7); |
141 | 89.2k | return 0; |
142 | 89.2k | } |
143 | | |
144 | | /* <blimit> setcachelimit - */ |
145 | | static int |
146 | | zsetcachelimit(i_ctx_t *i_ctx_p) |
147 | 0 | { |
148 | 0 | os_ptr op = osp; |
149 | |
|
150 | 0 | check_int_leu(*op, max_uint); |
151 | 0 | gs_setcachelimit(ifont_dir, (uint) op->value.intval); |
152 | 0 | pop(1); |
153 | 0 | return 0; |
154 | 0 | } |
155 | | |
156 | | /* <mark> <size> <lower> <upper> setcacheparams - */ |
157 | | static int |
158 | | zsetcacheparams(i_ctx_t *i_ctx_p) |
159 | 89.2k | { |
160 | 89.2k | os_ptr op = osp; |
161 | 89.2k | uint params[3]; |
162 | 89.2k | int i, code; |
163 | 89.2k | os_ptr opp = op; |
164 | | |
165 | 267k | for (i = 0; i < 3 && !r_has_type(opp, t_mark); i++, opp--) { |
166 | 178k | check_int_leu(*opp, max_uint); |
167 | 178k | params[i] = opp->value.intval; |
168 | 178k | } |
169 | 89.2k | switch (i) { |
170 | 0 | case 3: |
171 | 0 | if ((code = gs_setcachesize(igs, ifont_dir, params[2])) < 0) |
172 | 0 | return code; |
173 | 89.2k | case 2: |
174 | 89.2k | if ((code = gs_setcachelower(ifont_dir, params[1])) < 0) |
175 | 0 | return code; |
176 | 89.2k | case 1: |
177 | 89.2k | if ((code = gs_setcacheupper(ifont_dir, params[0])) < 0) |
178 | 0 | return code; |
179 | 89.2k | case 0:; |
180 | 89.2k | } |
181 | 89.2k | return zcleartomark(i_ctx_p); |
182 | 89.2k | } |
183 | | |
184 | | /* - currentcacheparams <mark> <size> <lower> <upper> */ |
185 | | static int |
186 | | zcurrentcacheparams(i_ctx_t *i_ctx_p) |
187 | 89.2k | { |
188 | 89.2k | os_ptr op = osp; |
189 | 89.2k | uint params[3]; |
190 | | |
191 | 89.2k | params[0] = gs_currentcachesize(ifont_dir); |
192 | 89.2k | params[1] = gs_currentcachelower(ifont_dir); |
193 | 89.2k | params[2] = gs_currentcacheupper(ifont_dir); |
194 | 89.2k | push(4); |
195 | 89.2k | make_mark(op - 3); |
196 | 89.2k | make_uint_array(op - 2, params, 3); |
197 | 89.2k | return 0; |
198 | 89.2k | } |
199 | | |
200 | | /* <font> .registerfont - */ |
201 | | static int |
202 | | zregisterfont(i_ctx_t *i_ctx_p) |
203 | 43.8k | { |
204 | 43.8k | os_ptr op = osp; |
205 | 43.8k | gs_font *pfont; |
206 | 43.8k | int code = font_param(op, &pfont); |
207 | | |
208 | 43.8k | if (code < 0) |
209 | 0 | return code; |
210 | 43.8k | pfont->is_resource = true; |
211 | 43.8k | pop(1); |
212 | 43.8k | return 0; |
213 | 43.8k | } |
214 | | |
215 | | /* <Decoding> .setupUnicodeDecoder - */ |
216 | | static int |
217 | | zsetupUnicodeDecoder(i_ctx_t *i_ctx_p) |
218 | 11.2k | { /* The allocation mode must be global. */ |
219 | 11.2k | os_ptr op = osp; |
220 | 11.2k | int code; |
221 | | |
222 | 11.2k | check_type(*op, t_dictionary); |
223 | 11.2k | code = setup_unicode_decoder(i_ctx_p, op); |
224 | 11.2k | if (code < 0) |
225 | 0 | return code; |
226 | 11.2k | pop(1); |
227 | 11.2k | return 0; |
228 | 11.2k | } |
229 | | |
230 | | /* ------ Initialization procedure ------ */ |
231 | | |
232 | | const op_def zfont_op_defs[] = |
233 | | { |
234 | | {"0currentfont", zcurrentfont}, |
235 | | {"2makefont", zmakefont}, |
236 | | {"2scalefont", zscalefont}, |
237 | | {"1setfont", zsetfont}, |
238 | | {"0cachestatus", zcachestatus}, |
239 | | {"1setcachelimit", zsetcachelimit}, |
240 | | {"1setcacheparams", zsetcacheparams}, |
241 | | {"0currentcacheparams", zcurrentcacheparams}, |
242 | | {"1.registerfont", zregisterfont}, |
243 | | {"1.setupUnicodeDecoder", zsetupUnicodeDecoder}, |
244 | | op_def_end(zfont_init) |
245 | | }; |
246 | | |
247 | | /* ------ Subroutines ------ */ |
248 | | |
249 | | /* Validate a font parameter. */ |
250 | | int |
251 | | font_param(const ref * pfdict, gs_font ** ppfont) |
252 | 1.16M | { /* |
253 | | * Check that pfdict is a read-only dictionary, that it has a FID |
254 | | * entry whose value is a fontID, and that the fontID points to a |
255 | | * gs_font structure whose associated PostScript dictionary is |
256 | | * pfdict. |
257 | | */ |
258 | 1.16M | ref *pid; |
259 | 1.16M | gs_font *pfont; |
260 | 1.16M | const font_data *pdata; |
261 | | |
262 | 1.16M | check_type(*pfdict, t_dictionary); |
263 | 1.16M | if (dict_find_string(pfdict, "FID", &pid) <= 0 || |
264 | 1.16M | !r_has_type(pid, t_fontID) |
265 | 1.16M | ) |
266 | 4 | return_error(gs_error_invalidfont); |
267 | 1.16M | pfont = r_ptr(pid, gs_font); |
268 | 1.16M | if (pfont == 0) |
269 | 0 | return_error(gs_error_invalidfont); /* unregistered font */ |
270 | 1.16M | pdata = pfont->client_data; |
271 | 1.16M | if (!obj_eq(pfont->memory, &pdata->dict, pfdict)) |
272 | 0 | return_error(gs_error_invalidfont); |
273 | 1.16M | *ppfont = pfont; |
274 | 1.16M | return 0; |
275 | 1.16M | } |
276 | | |
277 | | /* Add the FID entry to a font dictionary. */ |
278 | | /* Note that i_ctx_p may be NULL. */ |
279 | | int |
280 | | add_FID(i_ctx_t *i_ctx_p, ref * fp /* t_dictionary */ , gs_font * pfont, |
281 | | gs_ref_memory_t *imem) |
282 | 141k | { |
283 | 141k | ref fid; |
284 | | |
285 | 141k | make_tav(&fid, t_fontID, |
286 | 141k | a_readonly | imemory_space(imem) | imemory_new_mask(imem), |
287 | 141k | pstruct, (void *)pfont); |
288 | 141k | return (i_ctx_p ? idict_put_string(fp, "FID", &fid) : |
289 | 141k | dict_put_string(fp, "FID", &fid, NULL)); |
290 | 141k | } |
291 | | |
292 | | /* Make a transformed font (common code for makefont/scalefont). */ |
293 | | static int |
294 | | make_font(i_ctx_t *i_ctx_p, const gs_matrix * pmat) |
295 | 9.83k | { |
296 | 9.83k | os_ptr op = osp; |
297 | 9.83k | os_ptr fp = op - 1; |
298 | 9.83k | gs_font *oldfont, *newfont; |
299 | 9.83k | int code; |
300 | 9.83k | ref *pencoding = 0; |
301 | | |
302 | 9.83k | code = font_param(fp, &oldfont); |
303 | 9.83k | if (code < 0) |
304 | 16 | return code; |
305 | 9.81k | { |
306 | 9.81k | uint space = ialloc_space(idmemory); |
307 | | |
308 | 9.81k | ialloc_set_space(idmemory, r_space(fp)); |
309 | 9.81k | if (dict_find_string(fp, "Encoding", &pencoding) > 0 && |
310 | 9.81k | !r_is_array(pencoding) |
311 | 9.81k | ) |
312 | 0 | code = gs_note_error(gs_error_invalidfont); |
313 | 9.81k | else { |
314 | | /* |
315 | | * Temporarily substitute the new dictionary |
316 | | * for the old one, in case the Encoding changed. |
317 | | */ |
318 | 9.81k | ref olddict; |
319 | | |
320 | 9.81k | olddict = *pfont_dict(oldfont); |
321 | 9.81k | *pfont_dict(oldfont) = *fp; |
322 | 9.81k | code = gs_makefont(ifont_dir, oldfont, pmat, &newfont); |
323 | 9.81k | *pfont_dict(oldfont) = olddict; |
324 | 9.81k | } |
325 | 9.81k | ialloc_set_space(idmemory, space); |
326 | 9.81k | } |
327 | 9.81k | if (code < 0) |
328 | 0 | return code; |
329 | | /* |
330 | | * We have to allow for the possibility that the font's Encoding |
331 | | * is different from that of the base font. Note that the |
332 | | * font_data of the new font was simply copied from the old one. |
333 | | */ |
334 | 9.81k | if (pencoding != 0 && |
335 | 9.81k | !obj_eq(imemory, pencoding, &pfont_data(newfont)->Encoding) |
336 | 9.81k | ) { |
337 | 0 | if (newfont->FontType == ft_composite) |
338 | 0 | return_error(gs_error_rangecheck); |
339 | | /* We should really do validity checking here.... */ |
340 | 0 | ref_assign(&pfont_data(newfont)->Encoding, pencoding); |
341 | 0 | lookup_gs_simple_font_encoding((gs_font_base *) newfont); |
342 | 0 | } |
343 | 9.81k | *fp = *pfont_dict(newfont); |
344 | 9.81k | pop(1); |
345 | 9.81k | return 0; |
346 | 9.81k | } |
347 | | /* Create the transformed font dictionary. */ |
348 | | /* This is the make_font completion procedure for all non-composite fonts */ |
349 | | /* created at the interpreter level (see build_gs_simple_font in zbfont.c.) */ |
350 | | int |
351 | | zbase_make_font(gs_font_dir * pdir, const gs_font * oldfont, |
352 | | const gs_matrix * pmat, gs_font ** ppfont) |
353 | 8.21k | { |
354 | | /* |
355 | | * We must call gs_base_make_font so that the XUID gets copied |
356 | | * if necessary. |
357 | | */ |
358 | 8.21k | int code = gs_base_make_font(pdir, oldfont, pmat, ppfont); |
359 | | |
360 | 8.21k | if (code < 0) |
361 | 0 | return code; |
362 | 8.21k | return zdefault_make_font(pdir, oldfont, pmat, ppfont); |
363 | 8.21k | } |
364 | | int |
365 | | zdefault_make_font(gs_font_dir * pdir, const gs_font * oldfont, |
366 | | const gs_matrix * pmat, gs_font ** ppfont) |
367 | 8.21k | { |
368 | 8.21k | gs_font *newfont = *ppfont; |
369 | 8.21k | gs_memory_t *mem = newfont->memory; |
370 | | /* HACK: we know this font was allocated by the interpreter. */ |
371 | 8.21k | gs_ref_memory_t *imem = (gs_ref_memory_t *)mem; |
372 | 8.21k | ref *fp = pfont_dict(oldfont); |
373 | 8.21k | font_data *pdata; |
374 | 8.21k | ref newdict, newmat, scalemat; |
375 | 8.21k | uint dlen = dict_maxlength(fp); |
376 | 8.21k | uint mlen = dict_length(fp) + 3; /* FontID, OrigFont, ScaleMatrix */ |
377 | 8.21k | int code; |
378 | | |
379 | 8.21k | if (dlen < mlen) |
380 | 7.80k | dlen = mlen; |
381 | 8.21k | if ((pdata = gs_alloc_struct(mem, font_data, &st_font_data, |
382 | 8.21k | "make_font(font_data)")) == 0 |
383 | 8.21k | ) |
384 | 0 | return_error(gs_error_VMerror); |
385 | | /* |
386 | | * This dictionary is newly created: it's safe to pass NULL as the |
387 | | * dstack pointer to dict_copy and dict_put_string. |
388 | | */ |
389 | 8.21k | if ((code = dict_alloc(imem, dlen, &newdict)) < 0 || |
390 | 8.21k | (code = dict_copy(fp, &newdict, NULL)) < 0 || |
391 | 8.21k | (code = gs_alloc_ref_array(imem, &newmat, a_all, 12, |
392 | 8.21k | "make_font(matrices)")) < 0 |
393 | 8.21k | ) |
394 | 0 | return code; |
395 | 8.21k | refset_null_new(newmat.value.refs, 12, imemory_new_mask(imem)); |
396 | 8.21k | ref_assign(&scalemat, &newmat); |
397 | 8.21k | r_set_size(&scalemat, 6); |
398 | 8.21k | scalemat.value.refs += 6; |
399 | | /* |
400 | | * Create the scaling matrix. We could do this several different |
401 | | * ways: by "dividing" the new FontMatrix by the base FontMatrix, by |
402 | | * multiplying the current scaling matrix by a ScaleMatrix kept in |
403 | | * the gs_font, or by multiplying the current scaling matrix by the |
404 | | * ScaleMatrix from the font dictionary. We opt for the last of |
405 | | * these. |
406 | | */ |
407 | 8.21k | { |
408 | 8.21k | gs_matrix scale, prev_scale; |
409 | 8.21k | ref *ppsm; |
410 | | |
411 | 8.21k | if (!(dict_find_string(fp, "ScaleMatrix", &ppsm) > 0 && |
412 | 8.21k | read_matrix(mem, ppsm, &prev_scale) >= 0 && |
413 | 8.21k | gs_matrix_multiply(pmat, &prev_scale, &scale) >= 0) |
414 | 8.21k | ) |
415 | 7.83k | scale = *pmat; |
416 | 8.21k | write_matrix_new(&scalemat, &scale, imem); |
417 | 8.21k | } |
418 | 8.21k | r_clear_attrs(&scalemat, a_write); |
419 | 8.21k | r_set_size(&newmat, 6); |
420 | 8.21k | write_matrix_new(&newmat, &newfont->FontMatrix, imem); |
421 | 8.21k | r_clear_attrs(&newmat, a_write); |
422 | 8.21k | if ((code = dict_put_string(&newdict, "FontMatrix", &newmat, NULL)) < 0 || |
423 | 8.21k | (code = dict_put_string(&newdict, "OrigFont", pfont_dict(oldfont->base), NULL)) < 0 || |
424 | 8.21k | (code = dict_put_string(&newdict, "ScaleMatrix", &scalemat, NULL)) < 0 || |
425 | 8.21k | (code = add_FID(NULL, &newdict, newfont, imem)) < 0 |
426 | 8.21k | ) |
427 | 0 | return code; |
428 | 8.21k | newfont->client_data = pdata; |
429 | 8.21k | *pdata = *pfont_data(oldfont); |
430 | 8.21k | pdata->dict = newdict; |
431 | 8.21k | r_clear_attrs(dict_access_ref(&newdict), a_write); |
432 | 8.21k | return 0; |
433 | 8.21k | } |
434 | | |
435 | | /* Convert an array of (unsigned) integers to stack form. */ |
436 | | static void |
437 | | make_uint_array(register os_ptr op, const uint * intp, int count) |
438 | 178k | { |
439 | 178k | int i; |
440 | | |
441 | 1.07M | for (i = 0; i < count; i++, op++, intp++) |
442 | 892k | make_int(op, *intp); |
443 | 178k | } |
444 | | |
445 | | /* Remove scaled font and character cache entries that would be */ |
446 | | /* invalidated by a restore. */ |
447 | | static bool |
448 | | purge_if_name_removed(const gs_memory_t *mem, cached_char * cc, void *vsave) |
449 | 0 | { |
450 | 0 | return alloc_name_index_is_since_save(mem, cc->code, vsave); |
451 | 0 | } |
452 | | |
453 | | /* Remove entries from font and character caches. */ |
454 | | int |
455 | | font_restore(const alloc_save_t * save) |
456 | 378k | { |
457 | | |
458 | 378k | gs_memory_t *smem = gs_save_any_memory(save); |
459 | 378k | gs_font_dir *pdir = smem->gs_lib_ctx->font_dir; |
460 | 378k | int code; |
461 | | |
462 | 378k | if (pdir == 0) /* not initialized yet */ |
463 | 89.2k | return 0; |
464 | | |
465 | | /* Purge original (unscaled) fonts. */ |
466 | | |
467 | 288k | { |
468 | 288k | gs_font *pfont; |
469 | | |
470 | 377k | otop: |
471 | 741k | for (pfont = pdir->orig_fonts; pfont != 0; |
472 | 377k | pfont = pfont->next |
473 | 452k | ) { |
474 | 452k | if (alloc_is_since_save((char *)pfont, save)) { |
475 | 89.2k | code = gs_purge_font(pfont); |
476 | 89.2k | if (code < 0) |
477 | 0 | return code; |
478 | 89.2k | goto otop; |
479 | 89.2k | } |
480 | 452k | } |
481 | 377k | } |
482 | | |
483 | | /* Purge cached scaled fonts. */ |
484 | | |
485 | 288k | { |
486 | 288k | gs_font *pfont; |
487 | | |
488 | 288k | top: |
489 | 339k | for (pfont = pdir->scaled_fonts; pfont != 0; |
490 | 288k | pfont = pfont->next |
491 | 288k | ) { |
492 | 51.1k | if (alloc_is_since_save((char *)pfont, save)) { |
493 | 0 | code = gs_purge_font(pfont); |
494 | 0 | if (code < 0) |
495 | 0 | return code; |
496 | 0 | goto top; |
497 | 0 | } |
498 | 51.1k | } |
499 | 288k | } |
500 | | |
501 | | /* Purge xfonts and uncached scaled fonts. */ |
502 | | |
503 | 288k | { |
504 | 288k | cached_fm_pair *pair; |
505 | 288k | uint n; |
506 | | |
507 | 288k | for (pair = pdir->fmcache.mdata, n = pdir->fmcache.mmax; |
508 | 58.0M | n > 0; pair++, n-- |
509 | 288k | ) |
510 | 57.7M | if (!fm_pair_is_free(pair)) { |
511 | | #if 0 |
512 | | /* We disabled this code portion because |
513 | | gx_add_fm_pair now copied xvalues |
514 | | into a stable memory. |
515 | | */ |
516 | | if ((uid_is_XUID(&pair->UID) && |
517 | | alloc_is_since_save((char *)pair->UID.xvalues, |
518 | | save)) |
519 | | ) { |
520 | | code = gs_purge_fm_pair(pdir, pair, 0); |
521 | | if (code < 0) |
522 | | return code; |
523 | | continue; |
524 | | } |
525 | | #endif |
526 | 163k | if (pair->font != 0 && |
527 | 163k | alloc_is_since_save((char *)pair->font, save) |
528 | 163k | ) { |
529 | 0 | if (!uid_is_valid(&pair->UID)) |
530 | 0 | gs_clean_fm_pair(pdir, pair); |
531 | | /* Don't discard pairs with a surviving UID. */ |
532 | 0 | pair->font = 0; |
533 | 0 | } |
534 | 163k | if (pair->xfont != 0 && |
535 | 163k | alloc_is_since_save((char *)pair->xfont, save) |
536 | 163k | ) { |
537 | 0 | code = gs_purge_fm_pair(pdir, pair, 1); |
538 | 0 | if (code < 0) |
539 | 0 | return code; |
540 | 0 | } |
541 | 163k | } |
542 | 288k | } |
543 | | |
544 | | /* Purge characters with names about to be removed. */ |
545 | | /* We only need to do this if any new names have been created */ |
546 | | /* since the save. */ |
547 | | |
548 | 288k | if (alloc_any_names_since_save(save)) |
549 | 0 | gx_purge_selected_cached_chars(pdir, purge_if_name_removed, |
550 | 0 | (void *)save); |
551 | 288k | return 0; |
552 | 288k | } |
553 | | |
554 | | /* ------ Font procedures for PostScript fonts ------ */ |
555 | | |
556 | | /* font_info procedure */ |
557 | | static bool |
558 | | zfont_info_has(const ref *pfidict, const char *key, gs_const_string *pmember) |
559 | 2.50k | { |
560 | 2.50k | ref *pvalue; |
561 | | |
562 | 2.50k | if (dict_find_string(pfidict, key, &pvalue) > 0 && |
563 | 2.50k | r_has_type(pvalue, t_string) |
564 | 2.50k | ) { |
565 | 2.50k | pmember->data = pvalue->value.const_bytes; |
566 | 2.50k | pmember->size = r_size(pvalue); |
567 | 2.50k | return true; |
568 | 2.50k | } |
569 | 0 | return false; |
570 | 2.50k | } |
571 | | int |
572 | | zfont_info(gs_font *font, const gs_point *pscale, int members, |
573 | | gs_font_info_t *info) |
574 | 1.25k | { |
575 | 1.25k | int code = gs_default_font_info(font, pscale, members & |
576 | 1.25k | ~(FONT_INFO_COPYRIGHT | FONT_INFO_NOTICE | |
577 | 1.25k | FONT_INFO_FAMILY_NAME | FONT_INFO_FULL_NAME), |
578 | 1.25k | info); |
579 | 1.25k | const ref *pfdict; |
580 | 1.25k | ref *pfontinfo, *pvalue; |
581 | | |
582 | 1.25k | if (code < 0) |
583 | 0 | return code; |
584 | 1.25k | pfdict = &pfont_data(font)->dict; |
585 | 1.25k | if (dict_find_string(pfdict, "FontInfo", &pfontinfo) <= 0 || |
586 | 1.25k | !r_has_type(pfontinfo, t_dictionary)) |
587 | 96 | return 0; |
588 | 1.16k | if ((members & FONT_INFO_COPYRIGHT) && |
589 | 1.16k | zfont_info_has(pfontinfo, "Copyright", &info->Copyright)) |
590 | 625 | info->members |= FONT_INFO_COPYRIGHT; |
591 | 1.16k | if ((members & FONT_INFO_NOTICE) && |
592 | 1.16k | zfont_info_has(pfontinfo, "Notice", &info->Notice)) |
593 | 625 | info->members |= FONT_INFO_NOTICE; |
594 | 1.16k | if ((members & FONT_INFO_FAMILY_NAME) && |
595 | 1.16k | zfont_info_has(pfontinfo, "FamilyName", &info->FamilyName)) |
596 | 625 | info->members |= FONT_INFO_FAMILY_NAME; |
597 | 1.16k | if ((members & FONT_INFO_FULL_NAME) && |
598 | 1.16k | zfont_info_has(pfontinfo, "FullName", &info->FullName)) |
599 | 625 | info->members |= FONT_INFO_FULL_NAME; |
600 | 1.16k | if ((members & FONT_INFO_EMBEDDING_RIGHTS) |
601 | 1.16k | && (dict_find_string(pfontinfo, "FSType", &pvalue) > 0)) { |
602 | 0 | if (r_type(pvalue) != t_integer) |
603 | 0 | return gs_note_error(gs_error_typecheck); |
604 | | |
605 | 0 | info->EmbeddingRights = pvalue->value.intval; |
606 | 0 | info->members |= FONT_INFO_EMBEDDING_RIGHTS; |
607 | 0 | } |
608 | 1.16k | return code; |
609 | 1.16k | } |
610 | | |
611 | | /* -------------------- Utilities --------------*/ |
612 | | |
613 | | typedef struct gs_unicode_decoder_s { |
614 | | ref data; |
615 | | } gs_unicode_decoder; |
616 | | |
617 | | /* GC procedures */ |
618 | | static |
619 | | CLEAR_MARKS_PROC(unicode_decoder_clear_marks) |
620 | 23.2k | { gs_unicode_decoder *const pptr = vptr; |
621 | | |
622 | 23.2k | r_clear_attrs(&pptr->data, l_mark); |
623 | 23.2k | } |
624 | | static |
625 | 45.7k | ENUM_PTRS_WITH(unicode_decoder_enum_ptrs, gs_unicode_decoder *pptr) return 0; |
626 | 22.8k | case 0: |
627 | 22.8k | ENUM_RETURN_REF(&pptr->data); |
628 | 45.7k | ENUM_PTRS_END |
629 | 22.8k | static RELOC_PTRS_WITH(unicode_decoder_reloc_ptrs, gs_unicode_decoder *pptr); |
630 | 22.8k | RELOC_REF_VAR(pptr->data); |
631 | 22.8k | r_clear_attrs(&pptr->data, l_mark); |
632 | 22.8k | RELOC_PTRS_END |
633 | | |
634 | | gs_private_st_complex_only(st_unicode_decoder, gs_unicode_decoder,\ |
635 | | "unicode_decoder", unicode_decoder_clear_marks, unicode_decoder_enum_ptrs, |
636 | | unicode_decoder_reloc_ptrs, 0); |
637 | | |
638 | | /* Get the Unicode value for a glyph. */ |
639 | | const ref * |
640 | | zfont_get_to_unicode_map(gs_font_dir *dir) |
641 | 25.4k | { |
642 | 25.4k | const gs_unicode_decoder *pud = (gs_unicode_decoder *)dir->glyph_to_unicode_table; |
643 | | |
644 | 25.4k | return (pud == NULL ? NULL : &pud->data); |
645 | 25.4k | } |
646 | | |
647 | | static int |
648 | | setup_unicode_decoder(i_ctx_t *i_ctx_p, ref *Decoding) |
649 | 11.2k | { |
650 | 11.2k | gs_unicode_decoder *pud = gs_alloc_struct(imemory, gs_unicode_decoder, |
651 | 11.2k | &st_unicode_decoder, "setup_unicode_decoder"); |
652 | 11.2k | if (pud == NULL) |
653 | 0 | return_error(gs_error_VMerror); |
654 | 11.2k | ref_assign_new(&pud->data, Decoding); |
655 | 11.2k | ifont_dir->glyph_to_unicode_table = pud; |
656 | 11.2k | return 0; |
657 | 11.2k | } |