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