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