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