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