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