/src/ghostpdl/psi/zfcid0.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 | | /* CIDFontType 0 operators */ |
18 | | #include "memory_.h" |
19 | | #include "ghost.h" |
20 | | #include "oper.h" |
21 | | #include "gsmatrix.h" |
22 | | #include "gsccode.h" |
23 | | #include "gsstruct.h" |
24 | | #include "gxfcid.h" |
25 | | #include "gxfont1.h" |
26 | | #include "gxalloc.h" /* for gs_ref_memory_t */ |
27 | | #include "stream.h" /* for files.h */ |
28 | | #include "bfont.h" |
29 | | #include "files.h" |
30 | | #include "ichar.h" |
31 | | #include "ichar1.h" |
32 | | #include "icid.h" |
33 | | #include "idict.h" |
34 | | #include "idparam.h" |
35 | | #include "ifcid.h" |
36 | | #include "ifont1.h" |
37 | | #include "ifont2.h" |
38 | | #include "ifont42.h" |
39 | | #include "store.h" |
40 | | #include "imain.h" |
41 | | #include "iapi.h" |
42 | | #include "iminst.h" |
43 | | |
44 | | /* Type 1 font procedures (defined in zchar1.c) */ |
45 | | font_proc_glyph_outline(zcharstring_glyph_outline); |
46 | | |
47 | | /* ---------------- CIDFontType 0 (FontType 9) ---------------- */ |
48 | | |
49 | | /* ------ Accessing ------ */ |
50 | | |
51 | | /* Parse a multi-byte integer from a string. */ |
52 | | static int |
53 | | get_index(gs_glyph_data_t *pgd, int count, ulong *pval) |
54 | 0 | { |
55 | 0 | int i; |
56 | |
|
57 | 0 | if (pgd->bits.size < count) |
58 | 0 | return_error(gs_error_rangecheck); |
59 | 0 | *pval = 0; |
60 | 0 | for (i = 0; i < count; ++i) |
61 | 0 | *pval = (*pval << 8) + pgd->bits.data[i]; |
62 | 0 | pgd->bits.data += count; |
63 | 0 | pgd->bits.size -= count; |
64 | 0 | return 0; |
65 | 0 | } |
66 | | |
67 | | /* Get bytes from GlyphData or DataSource. */ |
68 | | static int |
69 | | cid0_read_bytes(gs_font_cid0 *pfont, ulong base, uint count, byte *buf, |
70 | | gs_glyph_data_t *pgd) |
71 | 0 | { |
72 | 0 | const font_data *pfdata = pfont_data(pfont); |
73 | 0 | byte *data = buf; |
74 | 0 | gs_font *gdfont = 0; /* pfont if newly allocated, 0 if not */ |
75 | 0 | int code = 0; |
76 | | |
77 | | /* Check for overflow. */ |
78 | 0 | if (base != (long)base || base > base + count) |
79 | 0 | return_error(gs_error_rangecheck); |
80 | 0 | if (r_has_type(&pfdata->u.cid0.DataSource, t_null)) { |
81 | | /* Get the bytes from GlyphData (a string or array of strings). */ |
82 | 0 | const ref *pgdata = &pfdata->u.cid0.GlyphData; |
83 | |
|
84 | 0 | if (r_has_type(pgdata, t_string)) { /* single string */ |
85 | 0 | uint size = r_size(pgdata); |
86 | |
|
87 | 0 | if (base >= size || count > size - base) |
88 | 0 | return_error(gs_error_rangecheck); |
89 | 0 | data = pgdata->value.bytes + base; |
90 | 0 | } else { /* array of strings */ |
91 | | /* |
92 | | * The algorithm is similar to the one in |
93 | | * string_array_access_proc in zfont42.c, but it also has to |
94 | | * deal with the case where the requested string crosses array |
95 | | * elements. |
96 | | */ |
97 | 0 | ulong skip = base; |
98 | 0 | uint copied = 0; |
99 | 0 | uint index = 0; |
100 | 0 | ref rstr; |
101 | 0 | uint size; |
102 | |
|
103 | 0 | for (;; skip -= size, ++index) { |
104 | 0 | int code = array_get(pfont->memory, pgdata, index, &rstr); |
105 | |
|
106 | 0 | if (code < 0) |
107 | 0 | return code; |
108 | 0 | if (!r_has_type(&rstr, t_string)) |
109 | 0 | return_error(gs_error_typecheck); |
110 | 0 | size = r_size(&rstr); |
111 | 0 | if (skip < size) |
112 | 0 | break; |
113 | 0 | } |
114 | 0 | size -= skip; |
115 | 0 | if (count <= size) { |
116 | 0 | data = rstr.value.bytes + skip; |
117 | 0 | } else { /* multiple strings needed */ |
118 | 0 | if (data == 0) { /* no buffer provided */ |
119 | 0 | data = gs_alloc_string(pfont->memory, count, |
120 | 0 | "cid0_read_bytes"); |
121 | 0 | if (data == 0) |
122 | 0 | return_error(gs_error_VMerror); |
123 | 0 | gdfont = (gs_font *)pfont; /* newly allocated */ |
124 | 0 | } |
125 | 0 | memcpy(data, rstr.value.bytes + skip, size); |
126 | 0 | copied = size; |
127 | 0 | while (copied < count) { |
128 | 0 | int code = array_get(pfont->memory, pgdata, ++index, &rstr); |
129 | |
|
130 | 0 | if (code < 0) |
131 | 0 | goto err; |
132 | 0 | if (!r_has_type(&rstr, t_string)) { |
133 | 0 | code = gs_note_error(gs_error_typecheck); |
134 | 0 | goto err; |
135 | 0 | } |
136 | 0 | size = r_size(&rstr); |
137 | 0 | if (size > count - copied) |
138 | 0 | size = count - copied; |
139 | 0 | memcpy(data + copied, rstr.value.bytes, size); |
140 | 0 | copied += size; |
141 | 0 | } |
142 | 0 | } |
143 | 0 | } |
144 | 0 | } else { |
145 | | /* Get the bytes from DataSource (a stream). */ |
146 | 0 | stream *s; |
147 | 0 | uint nread; |
148 | 0 | i_ctx_t *i_ctx_p = get_minst_from_memory(pfont->memory)->i_ctx_p; |
149 | |
|
150 | 0 | check_read_known_file(i_ctx_p, s, &pfdata->u.cid0.DataSource, return_error); |
151 | 0 | if (sseek(s, base) < 0) |
152 | 0 | return_error(gs_error_ioerror); |
153 | 0 | if (data == 0) { /* no buffer provided */ |
154 | 0 | data = gs_alloc_string(pfont->memory, count, "cid0_read_bytes"); |
155 | 0 | if (data == 0) |
156 | 0 | return_error(gs_error_VMerror); |
157 | 0 | gdfont = (gs_font *)pfont; /* newly allocated */ |
158 | 0 | } |
159 | 0 | if (sgets(s, data, count, &nread) < 0 || nread != count) { |
160 | 0 | code = gs_note_error(gs_error_ioerror); |
161 | 0 | goto err; |
162 | 0 | } |
163 | 0 | } |
164 | 0 | gs_glyph_data_from_string(pgd, data, count, gdfont); |
165 | 0 | return code; |
166 | 0 | err: |
167 | 0 | if (data != buf) |
168 | 0 | gs_free_string(pfont->memory, data, count, "cid0_read_bytes"); |
169 | 0 | return code; |
170 | 0 | } |
171 | | |
172 | | /* Get the CharString data for a CIDFontType 0 font. */ |
173 | | /* This is the glyph_data procedure in the font itself. */ |
174 | | /* Note that pgd may be NULL. */ |
175 | | static int |
176 | | z9_glyph_data(gs_font_base *pbfont, gs_glyph glyph, gs_glyph_data_t *pgd, |
177 | | int *pfidx) |
178 | 0 | { |
179 | 0 | gs_font_cid0 *pfont = (gs_font_cid0 *)pbfont; |
180 | 0 | const font_data *pfdata = pfont_data(pfont); |
181 | 0 | long glyph_index = (long)(glyph - GS_MIN_CID_GLYPH); |
182 | 0 | gs_glyph_data_t gdata; |
183 | 0 | ulong fidx; |
184 | 0 | int code; |
185 | |
|
186 | 0 | gdata.memory = pfont->memory; |
187 | 0 | if (!r_has_type(&pfdata->u.cid0.GlyphDirectory, t_null)) { |
188 | 0 | code = font_gdir_get_outline(pfont->memory, |
189 | 0 | &pfdata->u.cid0.GlyphDirectory, |
190 | 0 | glyph_index, &gdata); |
191 | 0 | if (code < 0) |
192 | 0 | return code; |
193 | | /* Get the definition from GlyphDirectory. */ |
194 | 0 | if (!gdata.bits.data) |
195 | 0 | return_error(gs_error_rangecheck); |
196 | 0 | code = get_index(&gdata, pfont->cidata.FDBytes, &fidx); |
197 | 0 | if (code < 0) |
198 | 0 | return code; |
199 | 0 | if (fidx >= pfont->cidata.FDArray_size) |
200 | 0 | return_error(gs_error_rangecheck); |
201 | 0 | if (pgd) |
202 | 0 | *pgd = gdata; |
203 | 0 | *pfidx = (int)fidx; |
204 | 0 | return code; |
205 | 0 | } |
206 | | /* Get the definition from the binary data (GlyphData or DataSource). */ |
207 | 0 | if (glyph_index < 0 || glyph_index >= pfont->cidata.common.CIDCount) { |
208 | 0 | *pfidx = 0; |
209 | 0 | if (pgd) |
210 | 0 | gs_glyph_data_from_null(pgd); |
211 | 0 | return_error(gs_error_rangecheck); |
212 | 0 | } |
213 | 0 | { |
214 | 0 | byte fd_gd[(MAX_FDBytes + MAX_GDBytes) * 2]; |
215 | 0 | uint num_bytes = pfont->cidata.FDBytes + pfont->cidata.common.GDBytes; |
216 | 0 | ulong base = pfont->cidata.CIDMapOffset + glyph_index * num_bytes; |
217 | 0 | ulong gidx, fidx_next, gidx_next; |
218 | 0 | int rcode = cid0_read_bytes(pfont, base, (ulong)(num_bytes * 2), fd_gd, |
219 | 0 | &gdata); |
220 | 0 | gs_glyph_data_t orig_data; |
221 | |
|
222 | 0 | if (rcode < 0) |
223 | 0 | return rcode; |
224 | 0 | orig_data = gdata; |
225 | 0 | if ((code = get_index(&gdata, pfont->cidata.FDBytes, &fidx)) < 0 || |
226 | 0 | (code = get_index(&gdata, pfont->cidata.common.GDBytes, &gidx)) < 0 || |
227 | 0 | (code = get_index(&gdata, pfont->cidata.FDBytes, &fidx_next)) < 0 || |
228 | 0 | (code = get_index(&gdata, pfont->cidata.common.GDBytes, &gidx_next)) < 0 |
229 | 0 | ) |
230 | 0 | DO_NOTHING; |
231 | 0 | gs_glyph_data_free(&orig_data, "z9_glyph_data"); |
232 | 0 | if (code < 0) |
233 | 0 | return code; |
234 | | /* |
235 | | * Some CID fonts (from Adobe!) have invalid font indexes for |
236 | | * missing glyphs. Handle this now. |
237 | | */ |
238 | 0 | if (gidx_next <= gidx) { /* missing glyph */ |
239 | 0 | *pfidx = 0; |
240 | 0 | if (pgd) |
241 | 0 | gs_glyph_data_from_null(pgd); |
242 | 0 | return_error(gs_error_undefined); |
243 | 0 | } |
244 | 0 | if (fidx >= pfont->cidata.FDArray_size) |
245 | 0 | return_error(gs_error_rangecheck); |
246 | 0 | *pfidx = (int)fidx; |
247 | 0 | if (pgd == 0) |
248 | 0 | return 0; |
249 | 0 | return cid0_read_bytes(pfont, gidx, gidx_next - gidx, NULL, pgd); |
250 | 0 | } |
251 | 0 | } |
252 | | |
253 | | /* Get the outline of a CIDFontType 0 glyph. */ |
254 | | static int |
255 | | z9_glyph_outline(gs_font *font, int WMode, gs_glyph glyph, const gs_matrix *pmat, |
256 | | gx_path *ppath, double sbw[4]) |
257 | 0 | { |
258 | 0 | gs_font_cid0 *const pfcid = (gs_font_cid0 *)font; |
259 | 0 | ref gref; |
260 | 0 | gs_glyph_data_t gdata; |
261 | 0 | int code, fidx, ocode; |
262 | |
|
263 | 0 | gdata.memory = font->memory; |
264 | 0 | code = pfcid->cidata.glyph_data((gs_font_base *)pfcid, glyph, &gdata, |
265 | 0 | &fidx); |
266 | 0 | if (code < 0) |
267 | 0 | return code; |
268 | 0 | glyph_ref(font->memory, glyph, &gref); |
269 | 0 | ocode = zcharstring_outline(pfcid->cidata.FDArray[fidx], WMode, &gref, &gdata, |
270 | 0 | pmat, ppath, sbw); |
271 | 0 | gs_glyph_data_free(&gdata, "z9_glyph_outline"); |
272 | 0 | return ocode; |
273 | 0 | } |
274 | | |
275 | | static int |
276 | | z9_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat, |
277 | | int members, gs_glyph_info_t *info) |
278 | 0 | { /* fixme : same as z11_glyph_info. */ |
279 | 0 | int wmode = (members & GLYPH_INFO_WIDTH0 ? 0 : 1); |
280 | |
|
281 | 0 | return z1_glyph_info_generic(font, glyph, pmat, members, info, |
282 | 0 | &gs_default_glyph_info, wmode); |
283 | 0 | } |
284 | | |
285 | | /* |
286 | | * The "fonts" in the FDArray don't have access to their outlines -- the |
287 | | * outlines are always provided externally. Replace the accessor procedures |
288 | | * with ones that will give an error if called. |
289 | | */ |
290 | | static int |
291 | | z9_FDArray_glyph_data(gs_font_type1 * pfont, gs_glyph glyph, |
292 | | gs_glyph_data_t *pgd) |
293 | 0 | { |
294 | 0 | return_error(gs_error_invalidfont); |
295 | 0 | } |
296 | | static int |
297 | | z9_FDArray_seac_data(gs_font_type1 *pfont, int ccode, gs_glyph *pglyph, |
298 | | gs_const_string *gstr, gs_glyph_data_t *pgd) |
299 | 0 | { |
300 | 0 | return_error(gs_error_invalidfont); |
301 | 0 | } |
302 | | |
303 | | /* ------ Defining ------ */ |
304 | | |
305 | | /* Get one element of a FDArray. */ |
306 | | static int |
307 | | fd_array_element(i_ctx_t *i_ctx_p, gs_font_type1 **ppfont, ref *prfd) |
308 | 1 | { |
309 | 1 | charstring_font_refs_t refs; |
310 | 1 | gs_type1_data data1; |
311 | 1 | build_proc_refs build; |
312 | 1 | gs_font_base *pbfont; |
313 | 1 | gs_font_type1 *pfont; |
314 | | /* |
315 | | * Standard CIDFontType 0 fonts have Type 1 fonts in the FDArray, but |
316 | | * CFF CIDFontType 0 fonts have Type 2 fonts there. |
317 | | */ |
318 | 1 | int fonttype = 1; /* default */ |
319 | 1 | int code = charstring_font_get_refs(prfd, &refs); |
320 | | |
321 | 1 | if (code < 0 || |
322 | 1 | (code = dict_int_param(prfd, "FontType", 1, 2, 1, &fonttype)) < 0 |
323 | 1 | ) |
324 | 0 | return code; |
325 | | /* |
326 | | * We don't handle the alternate Subr representation (SubrCount, |
327 | | * SDBytes, SubrMapOffset) here: currently that is handled in |
328 | | * PostScript code (lib/gs_cidfn.ps). |
329 | | */ |
330 | 1 | switch (fonttype) { |
331 | 1 | case 1: |
332 | 1 | data1.interpret = gs_type1_interpret; |
333 | 1 | data1.subroutineNumberBias = 0; |
334 | 1 | data1.lenIV = DEFAULT_LENIV_1; |
335 | 1 | code = charstring_font_params(imemory, prfd, &refs, &data1); |
336 | 1 | if (code < 0) |
337 | 0 | return code; |
338 | 1 | code = build_proc_name_refs(imemory, &build, |
339 | 1 | "%Type1BuildChar", "%Type1BuildGlyph"); |
340 | 1 | break; |
341 | 0 | case 2: |
342 | 0 | code = type2_font_params(prfd, &refs, &data1); |
343 | 0 | if (code < 0) |
344 | 0 | return code; |
345 | 0 | code = charstring_font_params(imemory, prfd, &refs, &data1); |
346 | 0 | if (code < 0) |
347 | 0 | return code; |
348 | 0 | code = build_proc_name_refs(imemory, &build, |
349 | 0 | "%Type2BuildChar", "%Type2BuildGlyph"); |
350 | 0 | break; |
351 | 0 | default: /* can't happen */ |
352 | 0 | return_error(gs_error_Fatal); |
353 | 1 | } |
354 | 1 | if (code < 0) |
355 | 0 | return code; |
356 | 1 | code = build_gs_FDArray_font(i_ctx_p, prfd, &pbfont, fonttype, |
357 | 1 | &st_gs_font_type1, &build); |
358 | 1 | if (code < 0) |
359 | 0 | return code; |
360 | 1 | pfont = (gs_font_type1 *)pbfont; |
361 | 1 | pbfont->FAPI = NULL; |
362 | 1 | pbfont->FAPI_font_data = NULL; |
363 | 1 | charstring_font_init(pfont, &refs, &data1); |
364 | 1 | pfont->data.procs.glyph_data = z9_FDArray_glyph_data; |
365 | 1 | pfont->data.procs.seac_data = z9_FDArray_seac_data; |
366 | 1 | *ppfont = pfont; |
367 | 1 | return 0; |
368 | 1 | } |
369 | | |
370 | | static int |
371 | | notify_remove_font_type9(void *proc_data, void *event_data) |
372 | 1 | { /* Likely type 9 font descendents are never released explicitly. |
373 | | So releaseing a type 9 font we must reset pointers in descendents. |
374 | | */ |
375 | | /* gs_font_finalize passes event_data == NULL, so check it here. */ |
376 | 1 | if (event_data == NULL) { |
377 | 1 | gs_font_cid0 *pfcid = proc_data; |
378 | 1 | int i; |
379 | | |
380 | 2 | for (i = 0; i < pfcid->cidata.FDArray_size; ++i) { |
381 | 1 | if (pfcid->cidata.FDArray[i]->data.parent == (gs_font_base *)pfcid) |
382 | 1 | pfcid->cidata.FDArray[i]->data.parent = NULL; |
383 | 1 | } |
384 | 1 | } |
385 | 1 | return 0; |
386 | 1 | } |
387 | | |
388 | | /* <string|name> <font_dict> .buildfont9 <string|name> <font> */ |
389 | | static int |
390 | | zbuildfont9(i_ctx_t *i_ctx_p) |
391 | 10 | { |
392 | 10 | os_ptr op = osp; |
393 | 10 | build_proc_refs build; |
394 | 10 | int code = build_proc_name_refs(imemory, &build, NULL, "%Type9BuildGlyph"); |
395 | 10 | gs_font_cid_data common; |
396 | 10 | ref GlyphDirectory, GlyphData, DataSource; |
397 | 10 | ref *prfda, cfnstr; |
398 | 10 | ref *pCIDFontName, CIDFontName; |
399 | 10 | gs_font_type1 **FDArray; |
400 | 10 | uint FDArray_size; |
401 | 10 | int FDBytes; |
402 | 10 | uint CIDMapOffset; |
403 | 10 | gs_font_base *pfont; |
404 | 10 | gs_font_cid0 *pfcid; |
405 | 10 | uint i; |
406 | | |
407 | 10 | check_op(2); |
408 | | /* |
409 | | * If the CIDFont's data have been loaded into VM, GlyphData will be |
410 | | * a string or an array of strings; if they are loaded incrementally |
411 | | * from a file, GlyphData will be an integer, and DataSource will be |
412 | | * a (reusable) stream. |
413 | | */ |
414 | 1 | if (code < 0) |
415 | 0 | return code; |
416 | 1 | code = cid_font_data_param(op, &common, &GlyphDirectory); |
417 | 1 | if (code < 0) |
418 | 0 | return code; |
419 | 1 | code = dict_find_string(op, "FDArray", &prfda); |
420 | 1 | if (code < 0) |
421 | 0 | return code; |
422 | 1 | if (code == 0) |
423 | 0 | return_error(gs_error_undefined); |
424 | 1 | code = dict_find_string(op, "CIDFontName", &pCIDFontName); |
425 | 1 | if (code < 0) |
426 | 0 | return code; |
427 | 1 | if (code == 0) |
428 | 0 | return_error(gs_error_undefined); |
429 | 1 | code = dict_int_param(op, "FDBytes", 0, MAX_FDBytes, -1, &FDBytes); |
430 | 1 | if (code < 0) |
431 | 0 | return code; |
432 | | |
433 | | /* |
434 | | * Since build_gs_simple_font may resize the dictionary and cause |
435 | | * pointers to become invalid, save CIDFontName |
436 | | */ |
437 | 1 | CIDFontName = *pCIDFontName; |
438 | 1 | if (r_has_type(&GlyphDirectory, t_null)) { |
439 | | /* Standard CIDFont, require GlyphData and CIDMapOffset. */ |
440 | 1 | ref *pGlyphData; |
441 | | |
442 | 1 | code = dict_find_string(op, "GlyphData", &pGlyphData); |
443 | 1 | if (code < 0) |
444 | 0 | return code; |
445 | 1 | if (code == 0) |
446 | 0 | return_error(gs_error_undefined); |
447 | 1 | code = dict_uint_param(op, "CIDMapOffset", 0, max_uint - 1, max_uint, &CIDMapOffset); |
448 | 1 | if (code < 0) |
449 | 0 | return code; |
450 | 1 | GlyphData = *pGlyphData; |
451 | 1 | if (r_has_type(&GlyphData, t_integer)) { |
452 | 0 | ref *pds; |
453 | 0 | stream *ignore_s; |
454 | |
|
455 | 0 | code = dict_find_string(op, "DataSource", &pds); |
456 | 0 | if (code < 0) |
457 | 0 | return code; |
458 | 0 | if (code == 0) |
459 | 0 | return_error(gs_error_undefined); |
460 | 0 | check_read_file(i_ctx_p, ignore_s, pds); |
461 | 0 | DataSource = *pds; |
462 | 1 | } else { |
463 | 1 | if (!r_has_type(&GlyphData, t_string) && !r_is_array(&GlyphData)) |
464 | 0 | return_error(gs_error_typecheck); |
465 | 1 | make_null(&DataSource); |
466 | 1 | } |
467 | 1 | } else { |
468 | 0 | make_null(&GlyphData); |
469 | 0 | make_null(&DataSource); |
470 | 0 | CIDMapOffset = 0; |
471 | 0 | } |
472 | 1 | if (!r_is_array(prfda)) |
473 | 0 | return_error(gs_error_invalidfont); |
474 | 1 | FDArray_size = r_size(prfda); |
475 | 1 | if (FDArray_size == 0) |
476 | 0 | return_error(gs_error_invalidfont); |
477 | 1 | FDArray = ialloc_struct_array(FDArray_size, gs_font_type1 *, |
478 | 1 | &st_gs_font_type1_ptr_element, |
479 | 1 | "buildfont9(FDarray)"); |
480 | 1 | if (FDArray == 0) |
481 | 0 | return_error(gs_error_VMerror); |
482 | 1 | memset(FDArray, 0, sizeof(gs_font_type1 *) * FDArray_size); |
483 | 2 | for (i = 0; i < FDArray_size; ++i) { |
484 | 1 | ref rfd; |
485 | | |
486 | 1 | array_get(imemory, prfda, (long)i, &rfd); |
487 | 1 | code = fd_array_element(i_ctx_p, &FDArray[i], &rfd); |
488 | 1 | if (code < 0) |
489 | 0 | goto fail; |
490 | 1 | } |
491 | 1 | code = build_gs_outline_font(i_ctx_p, op, &pfont, ft_CID_encrypted, |
492 | 1 | &st_gs_font_cid0, &build, |
493 | 1 | bf_Encoding_optional | bf_UniqueID_ignored, |
494 | 1 | build_gs_simple_font); |
495 | 1 | if (code < 0) |
496 | 0 | goto fail; |
497 | 1 | if (code == 1) { |
498 | | /* The font already has a FID, don't need to build it again. |
499 | | Release FDArray and return normally. |
500 | | fixme: FDArray fonts are thrown for garbager. |
501 | | We're not safe to build them after |
502 | | build_gs_simple_font(..., &pfont, ...), |
503 | | because a failure in building them would throw |
504 | | an underbuilt font with unclear consequences. |
505 | | */ |
506 | 0 | ifree_object(FDArray, "buildfont9(FDarray)"); |
507 | 0 | return 0; |
508 | 0 | } |
509 | 1 | pfont->procs.enumerate_glyph = gs_font_cid0_enumerate_glyph; |
510 | 1 | pfont->procs.glyph_outline = z9_glyph_outline; |
511 | 1 | pfont->procs.glyph_info = z9_glyph_info; |
512 | 1 | pfcid = (gs_font_cid0 *)pfont; |
513 | 1 | pfcid->cidata.common = common; |
514 | 1 | pfcid->cidata.CIDMapOffset = CIDMapOffset; |
515 | 1 | pfcid->cidata.FDArray = FDArray; |
516 | 1 | pfcid->cidata.FDArray_size = FDArray_size; |
517 | 1 | pfcid->cidata.FDBytes = FDBytes; |
518 | 1 | pfcid->cidata.glyph_data = z9_glyph_data; |
519 | 1 | pfcid->cidata.proc_data = 0; /* for GC */ |
520 | 1 | if (pfcid->font_name.size == 0) { |
521 | 1 | get_font_name(imemory, &cfnstr, &CIDFontName); |
522 | 1 | copy_font_name(&pfcid->font_name, &cfnstr); |
523 | 1 | } |
524 | 1 | ref_assign(&pfont_data(pfont)->u.cid0.GlyphDirectory, &GlyphDirectory); |
525 | 1 | ref_assign(&pfont_data(pfont)->u.cid0.GlyphData, &GlyphData); |
526 | 1 | ref_assign(&pfont_data(pfont)->u.cid0.DataSource, &DataSource); |
527 | 1 | code = define_gs_font(i_ctx_p, (gs_font *)pfont); |
528 | 1 | if (code >= 0) |
529 | 1 | code = gs_notify_register(&pfont->notify_list, notify_remove_font_type9, pfont); |
530 | 1 | if (code >= 0) { |
531 | 2 | for (i = 0; i < FDArray_size; ++i) { |
532 | 1 | FDArray[i]->dir = pfont->dir; |
533 | 1 | FDArray[i]->data.parent = pfont; |
534 | 1 | } |
535 | 1 | return code; |
536 | 1 | } |
537 | 0 | fail: |
538 | 0 | ifree_object(FDArray, "buildfont9(FDarray)"); |
539 | 0 | return code; |
540 | 1 | } |
541 | | |
542 | | /* <cid9font> <cid> .type9mapcid <charstring> <font_index> */ |
543 | | int |
544 | | ztype9mapcid(i_ctx_t *i_ctx_p) |
545 | 0 | { |
546 | 0 | os_ptr op = osp; |
547 | 0 | gs_font *pfont; |
548 | 0 | gs_font_cid0 *pfcid; |
549 | 0 | int code; |
550 | 0 | gs_glyph_data_t gdata; |
551 | 0 | int fidx; |
552 | |
|
553 | 0 | check_op(2); |
554 | 0 | code = font_param(op - 1, &pfont); |
555 | 0 | if (code < 0) |
556 | 0 | return code; |
557 | 0 | if (pfont->FontType != ft_CID_encrypted) |
558 | 0 | return_error(gs_error_invalidfont); |
559 | 0 | check_type(*op, t_integer); |
560 | 0 | pfcid = (gs_font_cid0 *)pfont; |
561 | 0 | gdata.memory = pfont->memory; |
562 | 0 | code = pfcid->cidata.glyph_data((gs_font_base *)pfcid, |
563 | 0 | (gs_glyph)(GS_MIN_CID_GLYPH + op->value.intval), |
564 | 0 | &gdata, &fidx); |
565 | | |
566 | | /* return code; original error-sensitive & fragile code */ |
567 | 0 | if (code < 0) { /* failed to load glyph data, put CID 0 */ |
568 | 0 | ps_int default_fallback_CID = 0 ; |
569 | |
|
570 | 0 | if_debug2m('J', imemory, "[J]ztype9cidmap() use CID %" PRIpsint " instead of glyph-missing CID %" PRIpsint "\n", default_fallback_CID, op->value.intval); |
571 | |
|
572 | 0 | op->value.intval = default_fallback_CID; |
573 | | |
574 | | /* reload glyph for default_fallback_CID */ |
575 | |
|
576 | 0 | code = pfcid->cidata.glyph_data((gs_font_base *)pfcid, |
577 | 0 | (gs_glyph)(GS_MIN_CID_GLYPH + default_fallback_CID), |
578 | 0 | &gdata, &fidx); |
579 | |
|
580 | 0 | if (code < 0) { |
581 | 0 | if_debug1m('J', imemory, "[J]ztype9cidmap() could not load default glyph (CID %" PRIpsint ")\n", op->value.intval); |
582 | 0 | return_error(gs_error_invalidfont); |
583 | 0 | } |
584 | |
|
585 | 0 | } |
586 | | |
587 | | /****** FOLLOWING IS NOT GENERAL W.R.T. ALLOCATION OF GLYPH DATA ******/ |
588 | 0 | make_const_string(op - 1, |
589 | 0 | a_readonly | imemory_space((gs_ref_memory_t *)pfont->memory), |
590 | 0 | gdata.bits.size, |
591 | 0 | gdata.bits.data); |
592 | 0 | make_int(op, fidx); |
593 | 0 | return code; |
594 | 0 | } |
595 | | |
596 | | /* ------ Initialization procedure ------ */ |
597 | | |
598 | | const op_def zfcid0_op_defs[] = |
599 | | { |
600 | | {"2.buildfont9", zbuildfont9}, |
601 | | {"2.type9mapcid", ztype9mapcid}, |
602 | | op_def_end(0) |
603 | | }; |