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