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