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