xref: /plan9/sys/src/cmd/gs/src/zbfont.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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: zbfont.c,v 1.30 2005/07/27 11:24:38 igor Exp $ */
18 /* Font creation utilities */
19 #include "memory_.h"
20 #include "string_.h"
21 #include "ghost.h"
22 #include "oper.h"
23 #include "gxfixed.h"
24 #include "gscencs.h"
25 #include "gsmatrix.h"
26 #include "gxdevice.h"
27 #include "gxfont.h"
28 #include "bfont.h"
29 #include "ialloc.h"
30 #include "idict.h"
31 #include "idparam.h"
32 #include "ilevel.h"
33 #include "iname.h"
34 #include "inamedef.h"		/* for inlining name_index */
35 #include "interp.h"		/* for initial_enter_name */
36 #include "ipacked.h"
37 #include "istruct.h"
38 #include "store.h"
39 
40 /* Structure descriptor */
41 public_st_font_data();
42 
43 /* <string|name> <font_dict> .buildfont3 <string|name> <font> */
44 /* Build a type 3 (user-defined) font. */
45 private int
zbuildfont3(i_ctx_t * i_ctx_p)46 zbuildfont3(i_ctx_t *i_ctx_p)
47 {
48     os_ptr op = osp;
49     int code;
50     build_proc_refs build;
51     gs_font_base *pfont;
52 
53     check_type(*op, t_dictionary);
54     code = build_gs_font_procs(op, &build);
55     if (code < 0)
56 	return code;
57     code = build_gs_simple_font(i_ctx_p, op, &pfont, ft_user_defined,
58 				&st_gs_font_base, &build, bf_options_none);
59     if (code < 0)
60 	return code;
61     return define_gs_font((gs_font *) pfont);
62 }
63 
64 /* Encode a character. */
65 gs_glyph
zfont_encode_char(gs_font * pfont,gs_char chr,gs_glyph_space_t gspace)66 zfont_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t gspace)
67 {
68     font_data *pdata = pfont_data(pfont);
69     const ref *pencoding = &pdata->Encoding;
70     ulong index = chr;	/* work around VAX widening bug */
71     ref cname;
72     int code = array_get(pfont->memory, pencoding, (long)index, &cname);
73 
74     if (code < 0 || !r_has_type(&cname, t_name))
75 	return gs_no_glyph;
76     if (pfont->FontType == ft_user_defined && r_type(&pdata->BuildGlyph) == t_null) {
77 	ref nsref, tname;
78 
79 	name_string_ref(pfont->memory, &cname, &nsref);
80 	if (r_size(&nsref) == 7 &&
81 	    !memcmp(nsref.value.const_bytes, ".notdef", r_size(&nsref))) {
82 	    /* A special support for high level devices.
83 	       They need a glyph name but the font doesn't provide one
84 	       due to an instandard BuildChar.
85 	       Such fonts don't conform to PLRM section 5.3.7,
86 	       but we've got real examples that we want to handle (Bug 686982).
87 	       Construct a name here.
88 	       Low level devices don't pass here, because regular PS interpretation
89 	       doesn't need such names.
90 	    */
91 	    char buf[20];
92 	    int code;
93 
94 	    if (gspace == GLYPH_SPACE_NOGEN)
95 		return gs_no_glyph;
96 	    sprintf(buf, "j%ld", chr); /* 'j' is arbutrary. */
97 	    code = name_ref(pfont->memory, (const byte *)buf, strlen(buf), &tname, 1);
98 	    if (code < 0) {
99 		/* Can't propagate the error due to interface limitation,
100 		   return with .notdef */
101 	    } else
102 		cname = tname;
103 	}
104     }
105     return (gs_glyph)name_index(pfont->memory, &cname);
106 }
107 
108 /* Get the name of a glyph. */
109 private int
zfont_glyph_name(gs_font * font,gs_glyph index,gs_const_string * pstr)110 zfont_glyph_name(gs_font *font, gs_glyph index, gs_const_string *pstr)
111 {
112     ref nref, sref;
113 
114     if (index >= gs_min_cid_glyph) {	/* Fabricate a numeric name. */
115 	char cid_name[sizeof(gs_glyph) * 3 + 1];
116 	int code;
117 
118 	sprintf(cid_name, "%lu", (ulong) index);
119 	code = name_ref(font->memory, (const byte *)cid_name, strlen(cid_name),
120 			&nref, 1);
121 	if (code < 0)
122 	    return code;
123     } else
124 	name_index_ref(font->memory, index, &nref);
125     name_string_ref(font->memory, &nref, &sref);
126     pstr->data = sref.value.const_bytes;
127     pstr->size = r_size(&sref);
128     return 0;
129 }
130 
131 private gs_char
gs_font_map_glyph_by_dict(const gs_memory_t * mem,const ref * map,gs_glyph glyph)132 gs_font_map_glyph_by_dict(const gs_memory_t *mem, const ref *map, gs_glyph glyph)
133 {
134     ref *v, n;
135     if (glyph >= gs_min_cid_glyph) {
136 	uint cid = glyph - gs_min_cid_glyph;
137 
138 	if (dict_find_string(map, "CIDCount", &v) > 0) {
139 	    /* This is a CIDDEcoding resource. */
140 	    make_int(&n, cid / 256);
141 	    if (dict_find(map, &n, &v) > 0) {
142 		ref vv;
143 
144 		if (array_get(mem, v, cid % 256, &vv) == 0 && r_type(&vv) == t_integer)
145 		    return vv.value.intval;
146 	    }
147 	    return GS_NO_CHAR; /* Absent in the map. */
148 	}
149 	/* This is GlyphNames2Unicode dictionary. */
150 	make_int(&n, cid);
151     } else
152 	name_index_ref(mem, glyph, &n);
153     if (dict_find(map, &n, &v) > 0) {
154 	if (r_has_type(v, t_string)) {
155 	    int i, l = r_size(v);
156 	    gs_char c = 0;
157 
158 	    for (i = 0; i < l; i++)
159 		c = (c << 8) | v->value.const_bytes[i];
160 	    return c;
161 	}
162 	if (r_type(v) == t_integer)
163 	    return v->value.intval;
164     }
165     return GS_NO_CHAR; /* Absent in the map. */
166 }
167 
168 /* Get Unicode UTF-16 code for a glyph. */
169 gs_char
gs_font_map_glyph_to_unicode(gs_font * font,gs_glyph glyph)170 gs_font_map_glyph_to_unicode(gs_font *font, gs_glyph glyph)
171 {
172     font_data *pdata = pfont_data(font);
173     const ref *UnicodeDecoding;
174 
175     if (r_type(&pdata->GlyphNames2Unicode) == t_dictionary) {
176 	gs_char c = gs_font_map_glyph_by_dict(font->memory,
177 					      &pdata->GlyphNames2Unicode, glyph);
178 
179 	if (c != GS_NO_CHAR)
180 	    return c;
181 	/*
182 	 * Fall through, because test.ps for SF bug #529103 requres
183 	 * to examine both tables. Due to that the Unicode Decoding resource
184 	 * can't be a default value for FontInfo.GlyphNames2Unicode .
185 	 */
186     }
187     UnicodeDecoding = zfont_get_to_unicode_map(font->dir);
188     if (UnicodeDecoding != NULL && r_type(UnicodeDecoding) == t_dictionary)
189 	return gs_font_map_glyph_by_dict(font->memory, UnicodeDecoding, glyph);
190     return GS_NO_CHAR; /* No map. */
191 }
192 
193 /* ------ Initialization procedure ------ */
194 
195 const op_def zbfont_op_defs[] =
196 {
197     {"2.buildfont3", zbuildfont3},
198     op_def_end(0)
199 };
200 
201 /* ------ Subroutines ------ */
202 
203 /* Convert strings to executable names for build_proc_refs. */
204 int
build_proc_name_refs(const gs_memory_t * mem,build_proc_refs * pbuild,const char * bcstr,const char * bgstr)205 build_proc_name_refs(const gs_memory_t *mem, build_proc_refs * pbuild,
206 		     const char *bcstr, const char *bgstr)
207 {
208     int code;
209 
210     if (!bcstr)
211 	make_null(&pbuild->BuildChar);
212     else {
213 	if ((code = name_ref(mem, (const byte *)bcstr,
214 			     strlen(bcstr), &pbuild->BuildChar, 0)) < 0)
215 	    return code;
216 	r_set_attrs(&pbuild->BuildChar, a_executable);
217     }
218     if (!bgstr)
219 	make_null(&pbuild->BuildGlyph);
220     else {
221 	if ((code = name_ref(mem, (const byte *)bgstr,
222 			     strlen(bgstr), &pbuild->BuildGlyph, 0)) < 0)
223 	    return code;
224 	r_set_attrs(&pbuild->BuildGlyph, a_executable);
225     }
226     return 0;
227 }
228 
229 /* Get the BuildChar and/or BuildGlyph routines from a (base) font. */
230 int
build_gs_font_procs(os_ptr op,build_proc_refs * pbuild)231 build_gs_font_procs(os_ptr op, build_proc_refs * pbuild)
232 {
233     int ccode, gcode;
234     ref *pBuildChar;
235     ref *pBuildGlyph;
236 
237     check_type(*op, t_dictionary);
238     ccode = dict_find_string(op, "BuildChar", &pBuildChar);
239     gcode = dict_find_string(op, "BuildGlyph", &pBuildGlyph);
240     if (ccode <= 0) {
241 	if (gcode <= 0)
242 	    return_error(e_invalidfont);
243 	make_null(&pbuild->BuildChar);
244     } else {
245 	check_proc(*pBuildChar);
246 	pbuild->BuildChar = *pBuildChar;
247     }
248     if (gcode <= 0)
249 	make_null(&pbuild->BuildGlyph);
250     else {
251 	check_proc(*pBuildGlyph);
252 	pbuild->BuildGlyph = *pBuildGlyph;
253     }
254     return 0;
255 }
256 
font_with_same_UID_and_another_metrics(const gs_font * pfont0,const gs_font * pfont1)257 private int font_with_same_UID_and_another_metrics(const gs_font *pfont0, const gs_font *pfont1)
258 {
259     const gs_font_base *pbfont0 = (const gs_font_base *)pfont0;
260     const gs_font_base *pbfont1 = (const gs_font_base *)pfont1;
261 
262 
263     if (uid_equal(&pbfont0->UID, &pbfont1->UID)) {
264 	const ref *pfdict0 = &pfont_data(gs_font_parent(pbfont0))->dict;
265 	const ref *pfdict1 = &pfont_data(gs_font_parent(pbfont1))->dict;
266 	ref *pmdict0, *pmdict1;
267 
268 	if (pbfont0->WMode || dict_find_string(pfdict0, "Metrics", &pmdict0) <= 0)
269 	    pmdict0 = NULL;
270 	if (pbfont1->WMode || dict_find_string(pfdict1, "Metrics", &pmdict1) <= 0)
271 	    pmdict1 = NULL;
272 	if (!pmdict0 != !pmdict1)
273 	    return 1;
274 	if (pmdict0 != NULL && !obj_eq(pfont0->memory, pmdict0, pmdict1))
275 	    return 1;
276 	if (!pbfont0->WMode || dict_find_string(pfdict0, "Metrics2", &pmdict0) <= 0)
277 	    pmdict0 = NULL;
278 	if (!pbfont0->WMode || dict_find_string(pfdict1, "Metrics2", &pmdict1) <= 0)
279 	    pmdict1 = NULL;
280 	if (!pmdict0 != !pmdict1)
281 	    return 1;
282 	if (pmdict0 != NULL && !obj_eq(pfont0->memory, pmdict0, pmdict1))
283 	    return 1;
284     }
285     return 0;
286 }
287 
288 /* Do the common work for building a primitive font -- one whose execution */
289 /* algorithm is implemented in C (Type 1, Type 2, Type 4, or Type 42). */
290 /* The caller guarantees that *op is a dictionary. */
291 int
build_gs_primitive_font(i_ctx_t * i_ctx_p,os_ptr op,gs_font_base ** ppfont,font_type ftype,gs_memory_type_ptr_t pstype,const build_proc_refs * pbuild,build_font_options_t options)292 build_gs_primitive_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font_base ** ppfont,
293 			font_type ftype, gs_memory_type_ptr_t pstype,
294 			const build_proc_refs * pbuild,
295 			build_font_options_t options)
296 {
297     ref *pcharstrings = 0;
298     ref CharStrings;
299     gs_font_base *pfont;
300     font_data *pdata;
301     int code;
302 
303     if (dict_find_string(op, "CharStrings", &pcharstrings) <= 0) {
304 	if (!(options & bf_CharStrings_optional))
305 	    return_error(e_invalidfont);
306     } else {
307 	ref *ignore;
308 
309 	if (!r_has_type(pcharstrings, t_dictionary))
310 	    return_error(e_invalidfont);
311 	if ((options & bf_notdef_required) != 0 &&
312 	    dict_find_string(pcharstrings, ".notdef", &ignore) <= 0
313 	    )
314 	    return_error(e_invalidfont);
315 	/*
316 	 * Since build_gs_simple_font may resize the dictionary and cause
317 	 * pointers to become invalid, save CharStrings.
318 	 */
319 	CharStrings = *pcharstrings;
320     }
321     code = build_gs_outline_font(i_ctx_p, op, ppfont, ftype, pstype, pbuild,
322 				 options, build_gs_simple_font);
323     if (code != 0)
324 	return code;
325     pfont = *ppfont;
326     pdata = pfont_data(pfont);
327     if (pcharstrings)
328 	ref_assign(&pdata->CharStrings, &CharStrings);
329     else
330 	make_null(&pdata->CharStrings);
331     /* Check that the UniqueIDs match.  This is part of the */
332     /* Adobe protection scheme, but we may as well emulate it. */
333     if (uid_is_valid(&pfont->UID) &&
334 	!dict_check_uid_param(op, &pfont->UID)
335 	)
336 	uid_set_invalid(&pfont->UID);
337     if (uid_is_valid(&pfont->UID)) {
338 	const gs_font *pfont0 = (const gs_font *)pfont;
339 
340 	code = gs_font_find_similar(ifont_dir, &pfont0,
341 		       font_with_same_UID_and_another_metrics);
342 	if (code < 0)
343 	    return code; /* Must not happen. */
344 	if (code)
345 	    uid_set_invalid(&pfont->UID);
346     }
347     return 0;
348 }
349 
350 /* Build a FDArray entry for a CIDFontType 0 font. */
351 /* Note that as of Adobe PostScript version 3011, this may be either */
352 /* a Type 1 or Type 2 font. */
353 private int
build_FDArray_sub_font(i_ctx_t * i_ctx_p,ref * op,gs_font_base ** ppfont,font_type ftype,gs_memory_type_ptr_t pstype,const build_proc_refs * pbuild,build_font_options_t ignore_options)354 build_FDArray_sub_font(i_ctx_t *i_ctx_p, ref *op,
355 		       gs_font_base **ppfont,
356 		       font_type ftype, gs_memory_type_ptr_t pstype,
357 		       const build_proc_refs * pbuild,
358 		       build_font_options_t ignore_options)
359 {
360     gs_font *pfont;
361     int code = build_gs_sub_font(i_ctx_p, op, &pfont, ftype, pstype, pbuild,
362 				 NULL, op);
363 
364     if (code >= 0)
365 	*ppfont = (gs_font_base *)pfont;
366     return code;
367 }
368 int
build_gs_FDArray_font(i_ctx_t * i_ctx_p,ref * op,gs_font_base ** ppfont,font_type ftype,gs_memory_type_ptr_t pstype,const build_proc_refs * pbuild)369 build_gs_FDArray_font(i_ctx_t *i_ctx_p, ref *op,
370 		      gs_font_base **ppfont,
371 		      font_type ftype, gs_memory_type_ptr_t pstype,
372 		      const build_proc_refs * pbuild)
373 {
374     gs_font_base *pfont;
375     font_data *pdata;
376     int code = build_gs_outline_font(i_ctx_p, op, &pfont, ftype, pstype,
377 				     pbuild, bf_options_none,
378 				     build_FDArray_sub_font);
379     static const double bbox[4] = { 0, 0, 0, 0 };
380     gs_uid uid;
381 
382     if (code < 0)
383 	return code;
384     pdata = pfont_data(pfont);
385     /* Fill in members normally set by build_gs_primitive_font. */
386     make_null(&pdata->CharStrings);
387     /* Fill in members normally set by build_gs_simple_font. */
388     uid_set_invalid(&uid);
389     init_gs_simple_font(pfont, bbox, &uid);
390     pfont->encoding_index = ENCODING_INDEX_UNKNOWN;
391     pfont->nearest_encoding_index = ENCODING_INDEX_UNKNOWN;
392     /* Fill in members normally set by build_gs_font. */
393     pfont->key_name = pfont->font_name;
394     *ppfont = pfont;
395     return 0;
396 }
397 
398 /* Do the common work for building an outline font -- a non-composite font */
399 /* for which PaintType and StrokeWidth are meaningful. */
400 /* The caller guarantees that *op is a dictionary. */
401 int
build_gs_outline_font(i_ctx_t * i_ctx_p,os_ptr op,gs_font_base ** ppfont,font_type ftype,gs_memory_type_ptr_t pstype,const build_proc_refs * pbuild,build_font_options_t options,build_base_font_proc_t build_base_font)402 build_gs_outline_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font_base ** ppfont,
403 		      font_type ftype, gs_memory_type_ptr_t pstype,
404 		      const build_proc_refs * pbuild,
405 		      build_font_options_t options,
406 		      build_base_font_proc_t build_base_font)
407 {
408     int painttype;
409     float strokewidth;
410     gs_font_base *pfont;
411     int code = dict_int_param(op, "PaintType", 0, 3, 0, &painttype);
412 
413     if (code < 0)
414 	return code;
415     code = dict_float_param(op, "StrokeWidth", 0.0, &strokewidth);
416     if (code < 0)
417 	return code;
418     code = build_base_font(i_ctx_p, op, ppfont, ftype, pstype, pbuild,
419 			   options);
420     if (code != 0)
421 	return code;
422     pfont = *ppfont;
423     pfont->PaintType = painttype;
424     pfont->StrokeWidth = strokewidth;
425     return 0;
426 }
427 
428 /* Do the common work for building a font of any non-composite FontType. */
429 /* The caller guarantees that *op is a dictionary. */
430 int
build_gs_simple_font(i_ctx_t * i_ctx_p,os_ptr op,gs_font_base ** ppfont,font_type ftype,gs_memory_type_ptr_t pstype,const build_proc_refs * pbuild,build_font_options_t options)431 build_gs_simple_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font_base ** ppfont,
432 		     font_type ftype, gs_memory_type_ptr_t pstype,
433 		     const build_proc_refs * pbuild,
434 		     build_font_options_t options)
435 {
436     double bbox[4];
437     gs_uid uid;
438     int code;
439     gs_font_base *pfont;
440     ref *pfontinfo, *g2u = NULL, Glyph2Unicode;
441 
442     if (dict_find_string(op, "FontInfo", &pfontinfo) <= 0 ||
443 	    !r_has_type(pfontinfo, t_dictionary) ||
444 	    dict_find_string(pfontinfo, "GlyphNames2Unicode", &g2u) <= 0 ||
445 	    !r_has_type(pfontinfo, t_dictionary))
446 	g2u = NULL;
447     else
448 	/*
449 	 * Since build_gs_font may resize the dictionary and cause
450 	 * pointers to become invalid, save Glyph2Unicode
451 	 */
452 	Glyph2Unicode = *g2u;
453     code = font_bbox_param(imemory, op, bbox);
454     if (code < 0)
455 	return code;
456     code = dict_uid_param(op, &uid, 0, imemory, i_ctx_p);
457     if (code < 0)
458 	return code;
459     if ((options & bf_UniqueID_ignored) && uid_is_UniqueID(&uid))
460 	uid_set_invalid(&uid);
461     code = build_gs_font(i_ctx_p, op, (gs_font **) ppfont, ftype, pstype,
462 			 pbuild, options);
463     if (code != 0)		/* invalid or scaled font */
464 	return code;
465     pfont = *ppfont;
466     pfont->procs.init_fstack = gs_default_init_fstack;
467     pfont->procs.define_font = gs_no_define_font;
468     pfont->procs.decode_glyph = gs_font_map_glyph_to_unicode;
469     pfont->procs.make_font = zbase_make_font;
470     pfont->procs.next_char_glyph = gs_default_next_char_glyph;
471     pfont->FAPI = 0;
472     pfont->FAPI_font_data = 0;
473     init_gs_simple_font(pfont, bbox, &uid);
474     lookup_gs_simple_font_encoding(pfont);
475     if (g2u != NULL) {
476 	font_data *pdata = pfont_data(pfont);
477 
478 	ref_assign_new(&pdata->GlyphNames2Unicode, &Glyph2Unicode);
479     }
480     return 0;
481 }
482 
483 /* Initialize the FontBBox and UID of a non-composite font. */
484 void
init_gs_simple_font(gs_font_base * pfont,const double bbox[4],const gs_uid * puid)485 init_gs_simple_font(gs_font_base *pfont, const double bbox[4],
486 		    const gs_uid *puid)
487 {
488     pfont->FontBBox.p.x = bbox[0];
489     pfont->FontBBox.p.y = bbox[1];
490     pfont->FontBBox.q.x = bbox[2];
491     pfont->FontBBox.q.y = bbox[3];
492     pfont->UID = *puid;
493 }
494 
495 /* Compare the encoding of a simple font with the registered encodings. */
496 void
lookup_gs_simple_font_encoding(gs_font_base * pfont)497 lookup_gs_simple_font_encoding(gs_font_base * pfont)
498 {
499     const ref *pfe = &pfont_data(pfont)->Encoding;
500     int index = -1;
501 
502     pfont->encoding_index = index;
503     if (r_type(pfe) == t_array && r_size(pfe) <= 256) {
504 	/* Look for an encoding that's "close". */
505 	uint esize = r_size(pfe);
506 	int near_index = -1;
507 	uint best = esize / 3;	/* must match at least this many */
508 	gs_const_string fstrs[256];
509 	int i;
510 
511 	/* Get the string names of the glyphs in the font's Encoding. */
512 	for (i = 0; i < esize; ++i) {
513 	    ref fchar;
514 
515 	    if (array_get(pfont->memory, pfe, (long)i, &fchar) < 0 ||
516 		!r_has_type(&fchar, t_name)
517 		)
518 		fstrs[i].data = 0, fstrs[i].size = 0;
519 	    else {
520 		ref nsref;
521 
522 		name_string_ref(pfont->memory, &fchar, &nsref);
523 		fstrs[i].data = nsref.value.const_bytes;
524 		fstrs[i].size = r_size(&nsref);
525 	    }
526 	}
527 	/* Compare them against the known encodings. */
528 	for (index = 0; index < NUM_KNOWN_REAL_ENCODINGS; ++index) {
529 	    uint match = esize;
530 
531 	    for (i = esize; --i >= 0;) {
532 		gs_const_string rstr;
533 
534 		gs_c_glyph_name(gs_c_known_encode((gs_char)i, index), &rstr);
535 		if (rstr.size == fstrs[i].size &&
536 		    !memcmp(rstr.data, fstrs[i].data, rstr.size)
537 		    )
538 		    continue;
539 		if (--match <= best)
540 		    break;
541 	    }
542 	    if (match > best) {
543 		best = match;
544 		near_index = index;
545 		/* If we have a perfect match, stop now. */
546 		if (best == esize)
547 		    break;
548 	    }
549 	}
550 	index = near_index;
551 	if (best == esize)
552 	    pfont->encoding_index = index;
553     }
554     pfont->nearest_encoding_index = index;
555 }
556 
557 /* Get FontMatrix and FontName parameters. */
558 private int
sub_font_params(const gs_memory_t * mem,const ref * op,gs_matrix * pmat,gs_matrix * pomat,ref * pfname)559 sub_font_params(const gs_memory_t *mem, const ref *op, gs_matrix *pmat, gs_matrix *pomat, ref *pfname)
560 {
561     ref *pmatrix;
562     ref *pfontname;
563     ref *porigfont;
564 
565     if (dict_find_string(op, "FontMatrix", &pmatrix) <= 0 ||
566 	read_matrix(mem, pmatrix, pmat) < 0
567 	)
568 	return_error(e_invalidfont);
569     if (dict_find_string(op, ".OrigFont", &porigfont) <= 0)
570 	porigfont = NULL;
571     if (pomat!= NULL) {
572 	if (porigfont == NULL ||
573 	    dict_find_string(porigfont, "FontMatrix", &pmatrix) <= 0 ||
574 	    read_matrix(mem, pmatrix, pomat) < 0
575 	    )
576 	    memset(pomat, 0, sizeof(*pomat));
577     }
578     /* Use the FontInfo/OrigFontName key preferrentially (created by MS PSCRIPT driver) */
579     if ((dict_find_string((porigfont != NULL ? porigfont : op), "FontInfo", &pfontname) > 0) &&
580         (dict_find_string(pfontname, "OrigFontName", &pfontname) > 0)) {
581 	get_font_name(mem, pfname, pfontname);
582     } else if (dict_find_string((porigfont != NULL ? porigfont : op), ".Alias", &pfontname) > 0) {
583         /* If we emulate the font, we want the requested name rather than a substitute. */
584 	get_font_name(mem, pfname, pfontname);
585     } else if (dict_find_string((porigfont != NULL ? porigfont : op), "FontName", &pfontname) > 0) {
586 	get_font_name(mem, pfname, pfontname);
587     } else
588 	make_empty_string(pfname, a_readonly);
589     return 0;
590 }
591 
592 /* Do the common work for building a font of any FontType. */
593 /* The caller guarantees that *op is a dictionary. */
594 /* op[-1] must be the key under which the font is being registered */
595 /* in FontDirectory, normally a name or string. */
596 /* Return 0 for a new font, 1 for a font made by makefont or scalefont, */
597 /* or a negative error code. */
598 int
build_gs_font(i_ctx_t * i_ctx_p,os_ptr op,gs_font ** ppfont,font_type ftype,gs_memory_type_ptr_t pstype,const build_proc_refs * pbuild,build_font_options_t options)599 build_gs_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font ** ppfont, font_type ftype,
600 	      gs_memory_type_ptr_t pstype, const build_proc_refs * pbuild,
601 	      build_font_options_t options)
602 {
603     ref kname;			/* t_string */
604     ref *pftype;
605     ref *pencoding = 0;
606     bool bitmapwidths;
607     int exactsize, inbetweensize, transformedchar;
608     int wmode;
609     int code;
610     gs_font *pfont;
611     ref *pfid;
612     ref *aop = dict_access_ref(op);
613 
614     get_font_name(imemory, &kname, op - 1);
615     if (dict_find_string(op, "FontType", &pftype) <= 0 ||
616 	!r_has_type(pftype, t_integer) ||
617 	pftype->value.intval != (int)ftype
618 	)
619 	return_error(e_invalidfont);
620     if (dict_find_string(op, "Encoding", &pencoding) <= 0) {
621 	if (!(options & bf_Encoding_optional))
622 	    return_error(e_invalidfont);
623 	pencoding = 0;
624     } else {
625 	if (!r_is_array(pencoding))
626 	    return_error(e_invalidfont);
627     }
628     if ((code = dict_int_param(op, "WMode", 0, 1, 0, &wmode)) < 0 ||
629 	(code = dict_bool_param(op, "BitmapWidths", false, &bitmapwidths)) < 0 ||
630 	(code = dict_int_param(op, "ExactSize", 0, 2, fbit_use_bitmaps, &exactsize)) < 0 ||
631 	(code = dict_int_param(op, "InBetweenSize", 0, 2, fbit_use_outlines, &inbetweensize)) < 0 ||
632 	(code = dict_int_param(op, "TransformedChar", 0, 2, fbit_use_outlines, &transformedchar)) < 0
633 	)
634 	return code;
635     code = dict_find_string(op, "FID", &pfid);
636     if (code > 0) {
637 	if (!r_has_type(pfid, t_fontID))
638 	    return_error(e_invalidfont);
639 	/*
640 	 * If this font has a FID entry already, it might be a scaled font
641 	 * made by makefont or scalefont; in a Level 2 environment, it might
642 	 * be an existing font being registered under a second name, or a
643 	 * re-encoded font (which was invalid in Level 1, but dvips did it
644 	 * anyway).
645 	 */
646 	pfont = r_ptr(pfid, gs_font);
647 	if (pfont->base == pfont) {	/* original font */
648 	    if (!level2_enabled)
649 		return_error(e_invalidfont);
650 	    if (obj_eq(pfont->memory, pfont_dict(pfont), op)) {
651 		*ppfont = pfont;
652 		return 1;
653 	    }
654 	    /*
655 	     * This is a re-encoded font, or some other
656 	     * questionable situation in which the FID
657 	     * was preserved.  Pretend the FID wasn't there.
658 	     */
659 	} else {		/* This was made by makefont or scalefont. */
660 	    /* Just insert the new name. */
661 	    gs_matrix mat;
662 	    ref fname;			/* t_string */
663 
664 	    code = sub_font_params(imemory, op, &mat, NULL, &fname);
665 	    if (code < 0)
666 		return code;
667 	    code = 1;
668 	    copy_font_name(&pfont->font_name, &fname);
669 	    goto set_name;
670 	}
671     }
672     /* This is a new font. */
673     if (!r_has_attr(aop, a_write))
674 	return_error(e_invalidaccess);
675     {
676 	ref encoding;
677 
678 	/*
679 	 * Since add_FID may resize the dictionary and cause
680 	 * pencoding to become invalid, save the Encoding.
681 	 */
682 	if (pencoding) {
683 	    encoding = *pencoding;
684 	    pencoding = &encoding;
685 	}
686 	code = build_gs_sub_font(i_ctx_p, op, &pfont, ftype, pstype,
687 				 pbuild, pencoding, op);
688 	if (code < 0)
689 	    return code;
690     }
691     pfont->BitmapWidths = bitmapwidths;
692     pfont->ExactSize = (fbit_type)exactsize;
693     pfont->InBetweenSize = (fbit_type)inbetweensize;
694     pfont->TransformedChar = (fbit_type)transformedchar;
695     pfont->WMode = wmode;
696     pfont->procs.font_info = zfont_info;
697     code = 0;
698 set_name:
699     copy_font_name(&pfont->key_name, &kname);
700     *ppfont = pfont;
701     return code;
702 }
703 
704 /* Create a sub-font -- a font or an entry in the FDArray of a CIDFontType 0 */
705 /* font.  Default BitmapWidths, ExactSize, InBetweenSize, TransformedChar, */
706 /* and WMode; do not fill in key_name. */
707 /* The caller guarantees that *op is a dictionary. */
708 int
build_gs_sub_font(i_ctx_t * i_ctx_p,const ref * op,gs_font ** ppfont,font_type ftype,gs_memory_type_ptr_t pstype,const build_proc_refs * pbuild,const ref * pencoding,ref * fid_op)709 build_gs_sub_font(i_ctx_t *i_ctx_p, const ref *op, gs_font **ppfont,
710 		  font_type ftype, gs_memory_type_ptr_t pstype,
711 		  const build_proc_refs * pbuild, const ref *pencoding,
712 		  ref *fid_op)
713 {
714     gs_matrix mat, omat;
715     ref fname;			/* t_string */
716     gs_font *pfont;
717     font_data *pdata;
718     /*
719      * Make sure that we allocate the font data
720      * in the same VM as the font dictionary.
721      */
722     uint space = ialloc_space(idmemory);
723     int code = sub_font_params(imemory, op, &mat, &omat, &fname);
724 
725     if (code < 0)
726 	return code;
727     ialloc_set_space(idmemory, r_space(op));
728     pfont = gs_font_alloc(imemory, pstype, &gs_font_procs_default, NULL,
729 			  "buildfont(font)");
730     pdata = ialloc_struct(font_data, &st_font_data,
731 			  "buildfont(data)");
732     if (pfont == 0 || pdata == 0)
733 	code = gs_note_error(e_VMerror);
734     else if (fid_op)
735 	code = add_FID(i_ctx_p, fid_op, pfont, iimemory);
736     if (code < 0) {
737 	ifree_object(pdata, "buildfont(data)");
738 	ifree_object(pfont, "buildfont(font)");
739 	ialloc_set_space(idmemory, space);
740 	return code;
741     }
742     refset_null((ref *) pdata, sizeof(font_data) / sizeof(ref));
743     ref_assign_new(&pdata->dict, op);
744     ref_assign_new(&pdata->BuildChar, &pbuild->BuildChar);
745     ref_assign_new(&pdata->BuildGlyph, &pbuild->BuildGlyph);
746     if (pencoding)
747 	ref_assign_new(&pdata->Encoding, pencoding);
748     pfont->client_data = pdata;
749     pfont->FontType = ftype;
750     pfont->FontMatrix = mat;
751     pfont->orig_FontMatrix = omat;
752     pfont->BitmapWidths = false;
753     pfont->ExactSize = fbit_use_bitmaps;
754     pfont->InBetweenSize = fbit_use_outlines;
755     pfont->TransformedChar = fbit_use_outlines;
756     pfont->WMode = 0;
757     pfont->procs.encode_char = zfont_encode_char;
758     pfont->procs.glyph_name = zfont_glyph_name;
759     ialloc_set_space(idmemory, space);
760     copy_font_name(&pfont->font_name, &fname);
761     *ppfont = pfont;
762     return 0;
763 }
764 
765 /* Get the string corresponding to a font name. */
766 /* If the font name isn't a name or a string, return an empty string. */
767 void
get_font_name(const gs_memory_t * mem,ref * pfname,const ref * op)768 get_font_name(const gs_memory_t *mem, ref * pfname, const ref * op)
769 {
770     switch (r_type(op)) {
771 	case t_string:
772 	    *pfname = *op;
773 	    break;
774 	case t_name:
775 	    name_string_ref(mem, op, pfname);
776 	    break;
777 	default:
778 	    /* This is weird, but legal.... */
779 	    make_empty_string(pfname, a_readonly);
780     }
781 }
782 
783 /* Copy a font name into the gs_font structure. */
784 void
copy_font_name(gs_font_name * pfstr,const ref * pfname)785 copy_font_name(gs_font_name * pfstr, const ref * pfname)
786 {
787     uint size = r_size(pfname);
788 
789     if (size > gs_font_name_max)
790 	size = gs_font_name_max;
791     memcpy(&pfstr->chars[0], pfname->value.const_bytes, size);
792     /* Following is only for debugging printout. */
793     pfstr->chars[size] = 0;
794     pfstr->size = size;
795 }
796 
797 /* Finish building a font, by calling gs_definefont if needed. */
798 int
define_gs_font(gs_font * pfont)799 define_gs_font(gs_font * pfont)
800 {
801     return (pfont->base == pfont && pfont->dir == 0 ?
802 	    /* i.e., unregistered original font */
803 	    gs_definefont(ifont_dir, pfont) :
804 	    0);
805 }
806