/src/ghostpdl/psi/zfont42.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 | | /* Type 42 font creation operator */ |
18 | | #include "memory_.h" |
19 | | #include "ghost.h" |
20 | | #include "oper.h" |
21 | | #include "gsccode.h" |
22 | | #include "gsmatrix.h" |
23 | | #include "gxfont.h" |
24 | | #include "gxfont42.h" |
25 | | #include "bfont.h" |
26 | | #include "icharout.h" |
27 | | #include "idict.h" |
28 | | #include "idparam.h" |
29 | | #include "ifont42.h" |
30 | | #include "ichar1.h" |
31 | | #include "iname.h" |
32 | | #include "store.h" |
33 | | #include "ipacked.h" |
34 | | |
35 | | /* Forward references */ |
36 | | static int z42_string_proc(gs_font_type42 *, ulong, uint, const byte **); |
37 | | static uint z42_get_glyph_index(gs_font_type42 *, gs_glyph); |
38 | | static int z42_gdir_get_outline(gs_font_type42 *, uint, gs_glyph_data_t *); |
39 | | static font_proc_enumerate_glyph(z42_enumerate_glyph); |
40 | | static font_proc_enumerate_glyph(z42_gdir_enumerate_glyph); |
41 | | static font_proc_encode_char(z42_encode_char); |
42 | | static font_proc_glyph_info(z42_glyph_info); |
43 | | static font_proc_glyph_outline(z42_glyph_outline); |
44 | | static font_proc_font_info(z42_font_info); |
45 | | |
46 | | /* <string|name> <font_dict> .buildfont11/42 <string|name> <font> */ |
47 | | /* Build a type 11 (TrueType CID-keyed) or 42 (TrueType) font. */ |
48 | | int |
49 | | build_gs_TrueType_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font_type42 **ppfont, |
50 | | font_type ftype, gs_memory_type_ptr_t pstype, |
51 | | const char *bcstr, const char *bgstr, |
52 | | build_font_options_t options) |
53 | 38 | { |
54 | 38 | build_proc_refs build; |
55 | 38 | ref sfnts, GlyphDirectory; |
56 | 38 | gs_font_type42 *pfont; |
57 | 38 | font_data *pdata; |
58 | 38 | int code; |
59 | | |
60 | 38 | check_op(2); |
61 | 26 | code = build_proc_name_refs(imemory, &build, bcstr, bgstr); |
62 | 26 | if (code < 0) |
63 | 0 | return code; |
64 | 26 | check_type(*op, t_dictionary); |
65 | | /* |
66 | | * Since build_gs_primitive_font may resize the dictionary and cause |
67 | | * pointers to become invalid, we save sfnts and GlyphDirectory. |
68 | | */ |
69 | 26 | if ((code = font_string_array_param(imemory, op, "sfnts", &sfnts)) < 0 || |
70 | 26 | (code = font_GlyphDirectory_param(op, &GlyphDirectory)) < 0 |
71 | 26 | ) |
72 | 0 | return code; |
73 | 26 | code = build_gs_primitive_font(i_ctx_p, op, (gs_font_base **)ppfont, |
74 | 26 | ftype, pstype, &build, options); |
75 | 26 | if (code != 0) |
76 | 0 | return code; |
77 | 26 | pfont = *ppfont; |
78 | 26 | pdata = pfont_data(pfont); |
79 | 26 | ref_assign(&pdata->u.type42.sfnts, &sfnts); |
80 | 26 | pdata->u.type42.mru_sfnts_index = 0; |
81 | 26 | pdata->u.type42.mru_sfnts_pos = 0; |
82 | 26 | make_null_new(&pdata->u.type42.CIDMap); |
83 | 26 | ref_assign(&pdata->u.type42.GlyphDirectory, &GlyphDirectory); |
84 | 26 | pfont->data.string_proc = z42_string_proc; |
85 | 26 | pfont->data.proc_data = (char *)pdata; |
86 | 26 | pfont->is_resource = (options & bf_has_font_file ? true : false); |
87 | 26 | code = gs_type42_font_init(pfont, 0); |
88 | 26 | if (code < 0) |
89 | 0 | return code; |
90 | 26 | pfont->procs.font_info = z42_font_info; |
91 | | /* |
92 | | * If the font has a GlyphDictionary, this replaces loca and glyf for |
93 | | * accessing character outlines. In this case, we use alternate |
94 | | * get_outline and enumerate_glyph procedures. |
95 | | */ |
96 | 26 | if (!r_has_type(&GlyphDirectory, t_null)) { |
97 | 0 | pfont->data.get_outline = z42_gdir_get_outline; |
98 | 0 | pfont->procs.enumerate_glyph = z42_gdir_enumerate_glyph; |
99 | 0 | } else |
100 | 26 | pfont->procs.enumerate_glyph = z42_enumerate_glyph; |
101 | | /* |
102 | | * The procedures that access glyph information must accept either |
103 | | * glyph names or glyph indexes. |
104 | | */ |
105 | 26 | pfont->data.get_glyph_index = z42_get_glyph_index; |
106 | 26 | pfont->data.substitute_glyph_index_vertical = gs_type42_substitute_glyph_index_vertical; |
107 | 26 | pfont->procs.encode_char = z42_encode_char; |
108 | 26 | pfont->procs.glyph_info = z42_glyph_info; |
109 | 26 | pfont->procs.glyph_outline = z42_glyph_outline; |
110 | 26 | return 0; |
111 | 26 | } |
112 | | static int |
113 | | zbuildfont42(i_ctx_t *i_ctx_p) |
114 | 38 | { |
115 | 38 | os_ptr op = osp; |
116 | 38 | gs_font_type42 *pfont; |
117 | 38 | int code = build_gs_TrueType_font(i_ctx_p, op, &pfont, ft_TrueType, |
118 | 38 | &st_gs_font_type42, "%Type42BuildChar", |
119 | 38 | "%Type42BuildGlyph", bf_options_none); |
120 | | |
121 | 38 | if (code < 0) |
122 | 12 | return code; |
123 | 26 | return define_gs_font(i_ctx_p, (gs_font *)pfont); |
124 | 38 | } |
125 | | |
126 | | /* |
127 | | * Check a parameter for being an array of strings. Return the parameter |
128 | | * value even if it is of the wrong type. |
129 | | */ |
130 | | int |
131 | | font_string_array_param(const gs_memory_t *mem, os_ptr op, const char *kstr, ref *psa) |
132 | 26 | { |
133 | 26 | ref *pvsa; |
134 | 26 | ref rstr0; |
135 | 26 | int code; |
136 | | |
137 | 26 | if (dict_find_string(op, kstr, &pvsa) <= 0) |
138 | 0 | return_error(gs_error_invalidfont); |
139 | 26 | *psa = *pvsa; |
140 | 26 | if (!r_has_type(pvsa, t_array)) |
141 | 0 | return_error(gs_error_typecheck); |
142 | | /* |
143 | | * We only check the first element of the array now, as a sanity test; |
144 | | * elements are checked as needed by string_array_access_proc. |
145 | | */ |
146 | 26 | if ((code = array_get(mem, pvsa, 0L, &rstr0)) < 0) |
147 | 0 | return code; |
148 | 26 | if (!r_has_type(&rstr0, t_string)) |
149 | 0 | return_error(gs_error_typecheck); |
150 | 26 | return 0; |
151 | 26 | } |
152 | | |
153 | | /* |
154 | | * Get a GlyphDirectory if present. Return 0 if present, 1 if absent, |
155 | | * or an error code. |
156 | | */ |
157 | | int |
158 | | font_GlyphDirectory_param(os_ptr op, ref *pGlyphDirectory) |
159 | 26 | { |
160 | 26 | ref *pgdir; |
161 | | |
162 | 26 | if (dict_find_string(op, "GlyphDirectory", &pgdir) <= 0) |
163 | 26 | make_null(pGlyphDirectory); |
164 | 0 | else if (!r_has_type(pgdir, t_dictionary) && !r_is_array(pgdir)) |
165 | 0 | return_error(gs_error_typecheck); |
166 | 0 | else |
167 | 0 | *pGlyphDirectory = *pgdir; |
168 | 26 | return 0; |
169 | 26 | } |
170 | | |
171 | | /* |
172 | | * Access a given byte offset and length in an array of strings. |
173 | | * This is used for sfnts and for CIDMap. The int argument is 2 for sfnts |
174 | | * (because of the strange behavior of odd-length strings), 1 for CIDMap. |
175 | | * Return code : 0 - success, <0 - error, |
176 | | * >0 - number of accessible bytes (client must cycle). |
177 | | */ |
178 | | int |
179 | | string_array_access_proc(const gs_memory_t *mem, |
180 | | const ref *psa, int modulus, ulong offset, uint length, |
181 | | uint *mru_index, ulong *mru_pos, |
182 | | const byte **pdata) |
183 | 338 | { |
184 | 338 | ulong left; |
185 | 338 | uint index; |
186 | 338 | bool backwards; |
187 | | |
188 | 338 | if (length == 0) |
189 | 0 | return 0; |
190 | 338 | if (mru_index && mru_pos && offset >= (*mru_pos >> 1)) { |
191 | | /* offset in or after mru string */ |
192 | | /* OR offset in 2nd half of the fragment before the mru string */ |
193 | 338 | backwards = (*mru_pos > offset); |
194 | 338 | if (backwards) { |
195 | 0 | index = *mru_index - 1; /* 1st string to examine */ |
196 | 0 | left = *mru_pos - offset; /* how many bytes to seek backwards */ |
197 | 338 | } else { |
198 | 338 | index = *mru_index; /* 1st string to examine */ |
199 | 338 | left = offset - *mru_pos; /* how many bytes to seek forward */ |
200 | 338 | } |
201 | 338 | } else { |
202 | | /* no mru */ |
203 | | /* OR offset in 1st half of the fragment before the mru string */ |
204 | 0 | backwards = false; |
205 | 0 | index = 0; |
206 | 0 | left = offset; |
207 | 0 | } |
208 | 494 | for (;;) { |
209 | 494 | ref rstr; |
210 | 494 | int code = array_get(mem, psa, index, &rstr); |
211 | 494 | uint size; |
212 | | |
213 | 494 | if (code < 0) |
214 | 0 | return code; |
215 | 494 | if (!r_has_type(&rstr, t_string)) |
216 | 0 | return_error(gs_error_typecheck); |
217 | | /* |
218 | | * NOTE: According to the Adobe documentation, each sfnts |
219 | | * string should have even length. If the length is odd, |
220 | | * the additional byte is padding and should be ignored. |
221 | | */ |
222 | 494 | size = r_size(&rstr) & -modulus; |
223 | 494 | if (backwards) { |
224 | 0 | if (left <= size) { |
225 | 0 | left = size - left; |
226 | 0 | backwards = false; |
227 | | /* "index" does not change */ |
228 | 0 | } else { |
229 | 0 | left -= size; |
230 | 0 | --index; |
231 | 0 | continue; |
232 | 0 | } |
233 | 0 | } |
234 | 494 | if (left < size) { |
235 | 338 | *pdata = rstr.value.const_bytes + left; |
236 | 338 | if (mru_index) |
237 | 338 | *mru_index = index; |
238 | 338 | if (mru_pos) |
239 | 338 | *mru_pos = offset - left; |
240 | 338 | if (left + length > size) |
241 | 0 | return size - left; |
242 | 338 | return 0; |
243 | 338 | } |
244 | 156 | left -= size; |
245 | 156 | ++index; |
246 | 156 | } |
247 | 338 | } |
248 | | |
249 | | /* ------ Initialization procedure ------ */ |
250 | | |
251 | | const op_def zfont42_op_defs[] = |
252 | | { |
253 | | {"2.buildfont42", zbuildfont42}, |
254 | | op_def_end(0) |
255 | | }; |
256 | | |
257 | | /* Reduce a glyph name to a glyph index if needed. */ |
258 | | static gs_glyph |
259 | | glyph_to_index(const gs_font *font, gs_glyph glyph) |
260 | 0 | { |
261 | 0 | ref gref; |
262 | 0 | ref *pcstr; |
263 | |
|
264 | 0 | if (glyph >= GS_MIN_GLYPH_INDEX) |
265 | 0 | return glyph; |
266 | 0 | name_index_ref(font->memory, glyph, &gref); |
267 | 0 | if (dict_find(&pfont_data(font)->CharStrings, &gref, &pcstr) > 0 && |
268 | 0 | r_has_type(pcstr, t_integer) |
269 | 0 | ) { |
270 | 0 | gs_glyph index_glyph = pcstr->value.intval + GS_MIN_GLYPH_INDEX; |
271 | | |
272 | | /* We don't need to check the upper limit of the value, since the |
273 | | * upper limit is the maximum value of the data type |
274 | | */ |
275 | 0 | if (index_glyph >= GS_MIN_GLYPH_INDEX) |
276 | 0 | return index_glyph; |
277 | 0 | } |
278 | 0 | return GS_MIN_GLYPH_INDEX; /* glyph 0 is notdef */ |
279 | 0 | } |
280 | | static uint |
281 | | z42_get_glyph_index(gs_font_type42 *pfont, gs_glyph glyph) |
282 | 0 | { |
283 | 0 | gs_glyph gid = glyph_to_index((gs_font *)pfont, glyph); |
284 | |
|
285 | 0 | return gid - GS_MIN_GLYPH_INDEX; |
286 | 0 | } |
287 | | |
288 | | /* |
289 | | * Get a glyph outline from GlyphDirectory. Return an empty string if |
290 | | * the glyph is missing or out of range. |
291 | | */ |
292 | | int |
293 | | font_gdir_get_outline(const gs_memory_t *mem, |
294 | | const ref *pgdir, |
295 | | long glyph_index, |
296 | | gs_glyph_data_t *pgd) |
297 | 0 | { |
298 | 0 | ref iglyph; |
299 | 0 | ref gdef; |
300 | 0 | ref *pgdef; |
301 | 0 | int code; |
302 | |
|
303 | 0 | if (r_has_type(pgdir, t_dictionary)) { |
304 | 0 | make_int(&iglyph, glyph_index); |
305 | 0 | code = dict_find(pgdir, &iglyph, &pgdef) - 1; /* 0 => not found */ |
306 | 0 | } else { |
307 | 0 | code = array_get(mem, pgdir, glyph_index, &gdef); |
308 | 0 | pgdef = &gdef; |
309 | 0 | } |
310 | 0 | if (code < 0) { |
311 | 0 | gs_glyph_data_from_null(pgd); |
312 | 0 | } else if (!r_has_type(pgdef, t_string)) { |
313 | 0 | return_error(gs_error_typecheck); |
314 | 0 | } else { |
315 | 0 | gs_glyph_data_from_string(pgd, pgdef->value.const_bytes, r_size(pgdef), |
316 | 0 | NULL); |
317 | 0 | } |
318 | 0 | return 0; |
319 | 0 | } |
320 | | static int |
321 | | z42_gdir_get_outline(gs_font_type42 * pfont, uint glyph_index, |
322 | | gs_glyph_data_t *pgd) |
323 | 0 | { |
324 | 0 | const font_data *pfdata = pfont_data(pfont); |
325 | 0 | const ref *pgdir = &pfdata->u.type42.GlyphDirectory; |
326 | |
|
327 | 0 | return font_gdir_get_outline(pfont->memory, pgdir, (long)glyph_index, pgd); |
328 | 0 | } |
329 | | |
330 | | /* Enumerate glyphs from CharStrings or loca / glyf. */ |
331 | | static int |
332 | | z42_enumerate_glyph(gs_font *font, int *pindex, gs_glyph_space_t glyph_space, |
333 | | gs_glyph *pglyph) |
334 | 0 | { |
335 | 0 | if (glyph_space == GLYPH_SPACE_INDEX) |
336 | 0 | return gs_type42_enumerate_glyph(font, pindex, glyph_space, pglyph); |
337 | 0 | else { |
338 | 0 | const ref *pcsdict = &pfont_data(font)->CharStrings; |
339 | |
|
340 | 0 | return zchar_enumerate_glyph(font->memory, pcsdict, pindex, pglyph); |
341 | 0 | } |
342 | 0 | } |
343 | | |
344 | | /* Enumerate glyphs (keys) from GlyphDirectory instead of loca / glyf. */ |
345 | | static int |
346 | | z42_gdir_enumerate_glyph(gs_font *font, int *pindex, |
347 | | gs_glyph_space_t glyph_space, gs_glyph *pglyph) |
348 | 0 | { |
349 | 0 | const ref *pgdict; |
350 | 0 | int code; |
351 | |
|
352 | 0 | if (glyph_space == GLYPH_SPACE_INDEX) { |
353 | 0 | pgdict = &pfont_data(font)->u.type42.GlyphDirectory; |
354 | 0 | if (!r_has_type(pgdict, t_dictionary)) { |
355 | 0 | const ref_packed *packed = pgdict->value.packed; |
356 | 0 | ref gdef; |
357 | 0 | uint i; |
358 | | |
359 | | /* Advance to *pindex */ |
360 | 0 | for (i = 0; i < (uint)*pindex; i++) |
361 | 0 | packed = packed_next(packed); |
362 | | |
363 | | /* Scan forward for non-null */ |
364 | 0 | for (; (uint)*pindex < r_size(pgdict); (*pindex)++) { |
365 | 0 | packed_get(font->memory, packed, &gdef); |
366 | 0 | packed = packed_next(packed); |
367 | 0 | if (!r_has_type(&gdef, t_null)) { |
368 | 0 | *pglyph = GS_MIN_GLYPH_INDEX + (*pindex)++; |
369 | 0 | return 0; |
370 | 0 | } |
371 | 0 | } |
372 | 0 | *pindex = 0; |
373 | 0 | return 0; |
374 | 0 | } |
375 | 0 | } else |
376 | 0 | pgdict = &pfont_data(font)->CharStrings; |
377 | | /* A trick : use zchar_enumerate_glyph to enumerate GIDs : */ |
378 | 0 | code = zchar_enumerate_glyph(font->memory, pgdict, pindex, pglyph); |
379 | 0 | if (*pindex != 0 && *pglyph >= GS_MIN_CID_GLYPH) |
380 | 0 | *pglyph = *pglyph - GS_MIN_CID_GLYPH + GS_MIN_GLYPH_INDEX; |
381 | 0 | return code; |
382 | 0 | } |
383 | | |
384 | | /* |
385 | | * Define font procedures that accept either a character name or a glyph |
386 | | * index as the glyph. |
387 | | */ |
388 | | static gs_glyph |
389 | | z42_encode_char(gs_font *font, gs_char chr, gs_glyph_space_t glyph_space) |
390 | 0 | { |
391 | 0 | gs_glyph glyph = zfont_encode_char(font, chr, glyph_space); |
392 | |
|
393 | 0 | return (glyph_space == GLYPH_SPACE_INDEX && glyph != GS_NO_GLYPH ? |
394 | 0 | glyph_to_index(font, glyph) : glyph); |
395 | 0 | } |
396 | | static int |
397 | | z42_glyph_outline(gs_font *font, int WMode, gs_glyph glyph, const gs_matrix *pmat, |
398 | | gx_path *ppath, double sbw[4]) |
399 | 0 | { |
400 | 0 | return gs_type42_glyph_outline(font, WMode, glyph_to_index(font, glyph), |
401 | 0 | pmat, ppath, sbw); |
402 | 0 | } |
403 | | static int |
404 | | z42_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat, |
405 | | int members, gs_glyph_info_t *info) |
406 | 0 | { /* fixme : same as z1_glyph_info. */ |
407 | 0 | int wmode = font->WMode; |
408 | |
|
409 | 0 | return z1_glyph_info_generic(font, glyph, pmat, members, info, gs_type42_glyph_info, wmode); |
410 | 0 | } |
411 | | |
412 | | /* Procedure for accessing the sfnts array. |
413 | | * Return code : 0 - success, <0 - error, |
414 | | * >0 - number of accessible bytes (client must cycle). |
415 | | */ |
416 | | static int |
417 | | z42_string_proc(gs_font_type42 * pfont, ulong offset, uint length, |
418 | | const byte ** pdata) |
419 | 338 | { |
420 | 338 | return string_array_access_proc(pfont->memory, &pfont_data(pfont)->u.type42.sfnts, 2, |
421 | 338 | offset, length, &pfont_data(pfont)->u.type42.mru_sfnts_index, |
422 | 338 | &pfont_data(pfont)->u.type42.mru_sfnts_pos, pdata); |
423 | 338 | } |
424 | | |
425 | | static int |
426 | | z42_font_info(gs_font *font, const gs_point *pscale, int members, |
427 | | gs_font_info_t *info) |
428 | 0 | { |
429 | 0 | int code = zfont_info(font, pscale, members, info); |
430 | |
|
431 | 0 | if (code < 0) |
432 | 0 | return code; |
433 | 0 | return gs_truetype_font_info(font, pscale, members, info); |
434 | 0 | } |