/src/ghostpdl/pdf/pdf_font0.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2019-2025 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 | | /* Include this first so that we don't get a macro redefnition of 'offsetof' */ |
17 | | #include "pdf_int.h" |
18 | | |
19 | | /* code for type 0 (CID) font handling */ |
20 | | #include "gxfont.h" |
21 | | #include "gxfont0.h" |
22 | | |
23 | | #include "pdf_int.h" |
24 | | #include "pdf_font.h" |
25 | | #include "pdf_font0.h" |
26 | | #include "pdf_font1C.h" |
27 | | #include "pdf_font_types.h" |
28 | | #include "pdf_stack.h" |
29 | | #include "pdf_array.h" |
30 | | #include "pdf_dict.h" |
31 | | #include "pdf_file.h" |
32 | | #include "pdf_cmap.h" |
33 | | #include "pdf_deref.h" |
34 | | |
35 | | #include "gsutil.h" /* For gs_next_ids() */ |
36 | | |
37 | | static int |
38 | | pdfi_font0_glyph_name(gs_font *pfont, gs_glyph index, gs_const_string *pstr) |
39 | 0 | { |
40 | 0 | int code; |
41 | 0 | pdf_font_type0 *pt0font = (pdf_font_type0 *)pfont->client_data; |
42 | 0 | char gnm[64]; |
43 | 0 | pdf_context *ctx = pt0font->ctx; |
44 | 0 | uint gindex = 0; |
45 | |
|
46 | 0 | gs_snprintf(gnm, 64, "%lu", (long)index); |
47 | 0 | code = (*ctx->get_glyph_index)((gs_font *)pfont, (byte *)gnm, strlen(gnm), &gindex); |
48 | 0 | if (code < 0) |
49 | 0 | return code; |
50 | 0 | code = (*ctx->get_glyph_name)(pfont, (gs_glyph)gindex, (gs_const_string *)pstr); |
51 | |
|
52 | 0 | return code; |
53 | 0 | } |
54 | | |
55 | | static int |
56 | | pdfi_font0_map_glyph_to_unicode(gs_font *font, gs_glyph glyph, int ch, ushort *u, unsigned int length) |
57 | 1.05M | { |
58 | 1.05M | gs_glyph cc = glyph < GS_MIN_CID_GLYPH ? glyph : glyph - GS_MIN_CID_GLYPH; |
59 | 1.05M | pdf_font_type0 *pt0font = (pdf_font_type0 *)font->client_data; |
60 | 1.05M | int code = gs_error_undefined, i; |
61 | 1.05M | uchar *unicode_return = (uchar *)u; |
62 | 1.05M | pdf_cidfont_type2 *decfont = NULL; |
63 | 1.05M | pdfi_cid_subst_nwp_table_t *substnwp = pt0font->substnwp; |
64 | | |
65 | 1.05M | code = pdfi_array_get(pt0font->ctx, pt0font->DescendantFonts, 0, (pdf_obj **)&decfont); |
66 | 1.05M | if (code < 0 || pdfi_type_of(decfont) != PDF_FONT) { |
67 | 0 | pdfi_countdown(decfont); |
68 | 0 | return gs_error_undefined; |
69 | 0 | } |
70 | | |
71 | 1.05M | code = gs_error_undefined; |
72 | 1.05M | while (1) { /* Loop to make retrying with a substitute CID easier */ |
73 | | /* Favour the ToUnicode if one exists */ |
74 | 1.05M | code = pdfi_tounicode_char_to_unicode(pt0font->ctx, (pdf_cmap *)pt0font->ToUnicode, glyph, ch, u, length); |
75 | | |
76 | 1.05M | if (code == gs_error_undefined && pt0font->decoding) { |
77 | 11.1k | const int *n; |
78 | | |
79 | 11.1k | if (cc / 256 < pt0font->decoding->nranges) { |
80 | 11.1k | n = (const int *)pt0font->decoding->ranges[cc / 256][cc % 256]; |
81 | 11.4k | for (i = 0; i < pt0font->decoding->val_sizes; i++) { |
82 | 11.4k | unsigned int cmapcc; |
83 | 11.4k | if (n[i] == -1) |
84 | 2.70k | break; |
85 | 8.78k | cc = n[i]; |
86 | 8.78k | cmapcc = (unsigned int)cc; |
87 | 8.78k | if (decfont->pdfi_font_type == e_pdf_cidfont_type2) |
88 | 8.78k | code = pdfi_fapi_check_cmap_for_GID((gs_font *)decfont->pfont, (unsigned int)cc, &cmapcc); |
89 | 0 | else |
90 | 0 | code = 0; |
91 | 8.78k | if (code >= 0 && cmapcc != 0){ |
92 | 8.45k | code = 0; |
93 | 8.45k | break; |
94 | 8.45k | } |
95 | 8.78k | } |
96 | | /* If it's a TTF derived CIDFont, we prefer a code point supported by the cmap table |
97 | | but if not, use the first available one |
98 | | */ |
99 | 11.1k | if (code < 0 && n[0] != -1) { |
100 | 0 | cc = n[0]; |
101 | 0 | code = 0; |
102 | 0 | } |
103 | 11.1k | } |
104 | 11.1k | if (code >= 0) { |
105 | 8.45k | if (cc > 65535) { |
106 | 0 | code = 4; |
107 | 0 | if (unicode_return != NULL && length >= code) { |
108 | 0 | unicode_return[0] = (cc & 0xFF000000)>> 24; |
109 | 0 | unicode_return[1] = (cc & 0x00FF0000) >> 16; |
110 | 0 | unicode_return[2] = (cc & 0x0000FF00) >> 8; |
111 | 0 | unicode_return[3] = (cc & 0x000000FF); |
112 | 0 | } |
113 | 0 | } |
114 | 8.45k | else { |
115 | 8.45k | code = 2; |
116 | 8.45k | if (unicode_return != NULL && length >= code) { |
117 | 8.45k | unicode_return[0] = (cc & 0x0000FF00) >> 8; |
118 | 8.45k | unicode_return[1] = (cc & 0x000000FF); |
119 | 8.45k | } |
120 | 8.45k | } |
121 | 8.45k | } |
122 | 11.1k | } |
123 | | /* If we get here, and still don't have a usable code point, check for a |
124 | | pre-defined CID substitution, and if there's one, jump back to the start |
125 | | and try again. |
126 | | */ |
127 | 1.05M | if (code == gs_error_undefined && substnwp) { |
128 | 4.87k | for (i = 0; substnwp->subst[i].s_type != 0; i++ ) { |
129 | 4.68k | if (cc >= substnwp->subst[i].s_scid && cc <= substnwp->subst[i].e_scid) { |
130 | 0 | cc = substnwp->subst[i].s_dcid + (cc - substnwp->subst[i].s_scid); |
131 | 0 | substnwp = NULL; |
132 | 0 | break; |
133 | 0 | } |
134 | 4.68k | if (cc >= substnwp->subst[i].s_dcid |
135 | 4.68k | && cc <= substnwp->subst[i].s_dcid + (substnwp->subst[i].e_scid - substnwp->subst[i].s_scid)) { |
136 | 2.50k | cc = substnwp->subst[i].s_scid + (cc - substnwp->subst[i].s_dcid); |
137 | 2.50k | substnwp = NULL; |
138 | 2.50k | break; |
139 | 2.50k | } |
140 | 4.68k | } |
141 | 2.70k | if (substnwp == NULL) |
142 | 2.50k | continue; |
143 | 2.70k | } |
144 | 1.05M | break; |
145 | 1.05M | } |
146 | 1.05M | pdfi_countdown(decfont); |
147 | 1.05M | return (code < 0 ? 0 : code); |
148 | 1.05M | } |
149 | | |
150 | | int pdfi_read_type0_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, pdf_dict *page_dict, pdf_font **ppdffont) |
151 | 41.4k | { |
152 | 41.4k | int code, nlen; |
153 | 41.4k | pdf_obj *cmap = NULL; |
154 | 41.4k | pdf_cmap *pcmap = NULL; |
155 | 41.4k | pdf_array *arr = NULL; |
156 | 41.4k | pdf_dict *decfontdict = NULL; /* there can only be one */ |
157 | 41.4k | pdf_name *n = NULL; |
158 | 41.4k | pdf_obj *basefont = NULL; |
159 | 41.4k | pdf_obj *tounicode = NULL; |
160 | 41.4k | pdf_dict *dfontdesc = NULL; |
161 | 41.4k | pdf_dict *fontdesc = NULL; |
162 | 41.4k | pdf_stream *ffile = NULL; |
163 | 41.4k | pdf_font *descpfont = NULL; |
164 | 41.4k | pdf_font_type0 *pdft0 = NULL; |
165 | 41.4k | gs_font_type0 *pfont0 = NULL; |
166 | 41.4k | pdfi_cid_decoding_t *dec = NULL; |
167 | 41.4k | pdfi_cid_subst_nwp_table_t *substnwp = NULL; |
168 | | |
169 | | /* We're supposed to have a FontDescriptor, it can be missing, and we have to carry on */ |
170 | 41.4k | (void)pdfi_dict_get(ctx, font_dict, "FontDescriptor", (pdf_obj **)&fontdesc); |
171 | | |
172 | 41.4k | if (fontdesc != NULL) { |
173 | 63 | pdf_obj *Name = NULL; |
174 | | |
175 | 63 | code = pdfi_dict_get_type(ctx, (pdf_dict *) fontdesc, "FontName", PDF_NAME, (pdf_obj**)&Name); |
176 | 63 | if (code < 0) |
177 | 0 | pdfi_set_warning(ctx, 0, NULL, W_PDF_FDESC_BAD_FONTNAME, "pdfi_load_font", ""); |
178 | 63 | pdfi_countdown(Name); |
179 | 63 | } |
180 | | |
181 | 41.4k | code = pdfi_dict_get(ctx, font_dict, "Encoding", &cmap); |
182 | 41.4k | if (code < 0) goto error; |
183 | | |
184 | 41.2k | if (pdfi_type_of(cmap) == PDF_CMAP) { |
185 | 0 | pcmap = (pdf_cmap *)cmap; |
186 | 0 | cmap = NULL; |
187 | 0 | } |
188 | 41.2k | else { |
189 | 41.2k | code = pdfi_read_cmap(ctx, cmap, &pcmap); |
190 | 41.2k | pdfi_countdown(cmap); |
191 | 41.2k | cmap = NULL; |
192 | 41.2k | if (code < 0) goto error; |
193 | 41.2k | } |
194 | | |
195 | 40.8k | code = pdfi_dict_get(ctx, font_dict, "DescendantFonts", (pdf_obj **)&arr); |
196 | 40.8k | if (code < 0) goto error; |
197 | | |
198 | 38.2k | if (pdfi_type_of(arr) != PDF_ARRAY || arr->size != 1) { |
199 | 138 | code = gs_note_error(gs_error_invalidfont); |
200 | 138 | goto error; |
201 | 138 | } |
202 | 38.1k | code = pdfi_array_get(ctx, arr, 0, (pdf_obj **)&decfontdict); |
203 | 38.1k | pdfi_countdown(arr); |
204 | 38.1k | arr = NULL; |
205 | 38.1k | if (code < 0) goto error; |
206 | 26.7k | switch (pdfi_type_of(decfontdict)) { |
207 | 1.85k | case PDF_FONT: |
208 | 1.85k | descpfont = (pdf_font *)decfontdict; |
209 | 1.85k | decfontdict = descpfont->PDF_font; |
210 | 1.85k | pdfi_countup(decfontdict); |
211 | 1.85k | break; |
212 | 23.7k | case PDF_DICT: |
213 | 23.7k | code = pdfi_dict_get(ctx, (pdf_dict *)decfontdict, "Type", (pdf_obj **)&n); |
214 | 23.7k | if (code < 0) goto error; |
215 | 23.5k | if (pdfi_type_of(n) != PDF_NAME || n->length != 4 || memcmp(n->data, "Font", 4) != 0) { |
216 | 259 | pdfi_countdown(n); |
217 | 259 | code = gs_note_error(gs_error_invalidfont); |
218 | 259 | goto error; |
219 | 259 | } |
220 | 23.2k | pdfi_countdown(n); |
221 | 23.2k | break; |
222 | 1.15k | default: |
223 | 1.15k | code = gs_note_error(gs_error_invalidfont); |
224 | 1.15k | goto error; |
225 | 26.7k | } |
226 | | #if 0 |
227 | | code = pdfi_dict_get(ctx, (pdf_dict *)decfontdict, "Subtype", (pdf_obj **)&n); |
228 | | if (code < 0) |
229 | | goto error; |
230 | | |
231 | | if (pdfi_type_of(n) != PDF_NAME || n->length != 12 || memcmp(n->data, "CIDFontType", 11) != 0) { |
232 | | pdfi_countdown(n); |
233 | | code = gs_note_error(gs_error_invalidfont); |
234 | | goto error; |
235 | | } |
236 | | /* cidftype is ignored for now, but we may need to know it when |
237 | | subsitutions are allowed |
238 | | */ |
239 | | cidftype = n->data[11] - 48; |
240 | | |
241 | | pdfi_countdown(n); |
242 | | #endif |
243 | | |
244 | 25.1k | code = pdfi_dict_get(ctx, font_dict, "BaseFont", (pdf_obj **)&basefont); |
245 | 25.1k | if (code < 0) { |
246 | 184 | basefont = NULL; |
247 | 184 | } |
248 | | |
249 | 25.1k | if (ctx->args.ignoretounicode != true) { |
250 | 25.1k | code = pdfi_dict_get(ctx, font_dict, "ToUnicode", (pdf_obj **)&tounicode); |
251 | 25.1k | if (code >= 0 && pdfi_type_of(tounicode) == PDF_STREAM) { |
252 | 16.3k | pdf_cmap *tu = NULL; |
253 | 16.3k | code = pdfi_read_cmap(ctx, tounicode, &tu); |
254 | 16.3k | pdfi_countdown(tounicode); |
255 | 16.3k | tounicode = (pdf_obj *)tu; |
256 | 16.3k | } |
257 | 25.1k | if (code < 0 || (tounicode != NULL && pdfi_type_of(tounicode) != PDF_CMAP)) { |
258 | 9.02k | pdfi_countdown(tounicode); |
259 | 9.02k | tounicode = NULL; |
260 | 9.02k | code = 0; |
261 | 9.02k | } |
262 | 25.1k | } |
263 | 0 | else { |
264 | 0 | tounicode = NULL; |
265 | 0 | } |
266 | | |
267 | 25.1k | if (descpfont == NULL) { |
268 | 23.2k | gs_font *pf; |
269 | | |
270 | 23.2k | code = pdfi_load_font(ctx, stream_dict, page_dict, decfontdict, &pf, true); |
271 | 23.2k | if (code < 0) |
272 | 7.56k | goto error; |
273 | 15.7k | descpfont = (pdf_font *)pf->client_data; |
274 | 15.7k | } |
275 | | |
276 | 17.5k | if (descpfont->pdfi_font_type < e_pdf_cidfont_type0 || descpfont->pdfi_font_type > e_pdf_cidfont_type4) { |
277 | 276 | code = gs_note_error(gs_error_invalidfont); |
278 | 276 | goto error; |
279 | 276 | } |
280 | | |
281 | 17.3k | if (descpfont != NULL && ((pdf_cidfont_t *)descpfont)->substitute) { |
282 | 7.83k | pdf_obj *csi = NULL; |
283 | 7.83k | pdf_string *reg = NULL, *ord = NULL; |
284 | 7.83k | char *r = NULL, *o = NULL; |
285 | 7.83k | int rlen = 0, olen = 0; |
286 | | |
287 | 7.83k | code = pdfi_dict_get(ctx, decfontdict, "CIDSystemInfo", (pdf_obj **)&csi); |
288 | 7.83k | if (code >= 0) { |
289 | 6.58k | (void)pdfi_dict_get(ctx, (pdf_dict *)csi, "Registry", (pdf_obj **)®); |
290 | 6.58k | (void)pdfi_dict_get(ctx, (pdf_dict *)csi, "Ordering", (pdf_obj **)&ord); |
291 | 6.58k | if (reg != NULL && pdfi_type_of(reg) == PDF_STRING |
292 | 6.58k | && ord != NULL && pdfi_type_of(ord) == PDF_STRING) { |
293 | 6.49k | r = (char *)reg->data; |
294 | 6.49k | rlen = reg->length; |
295 | 6.49k | o = (char *)ord->data; |
296 | 6.49k | olen = ord->length; |
297 | 6.49k | } |
298 | 6.58k | pdfi_countdown(csi); |
299 | 6.58k | pdfi_countdown(reg); |
300 | 6.58k | pdfi_countdown(ord); |
301 | 6.58k | } |
302 | 7.83k | if (r == NULL || o == NULL) { |
303 | 1.34k | r = (char *)pcmap->csi_reg.data; |
304 | 1.34k | rlen = pcmap->csi_reg.size; |
305 | 1.34k | o = (char *)pcmap->csi_ord.data; |
306 | 1.34k | olen = pcmap->csi_ord.size; |
307 | 1.34k | } |
308 | 7.83k | if (rlen > 0 && olen > 0) |
309 | 7.83k | pdfi_cidfont_cid_subst_tables(r, rlen, o, olen, &dec, &substnwp); |
310 | | |
311 | 7.83k | ((pdf_cidfont_t *)descpfont)->decoding = dec; |
312 | 7.83k | ((pdf_cidfont_t *)descpfont)->substnwp = substnwp; |
313 | 7.83k | } |
314 | | /* reference is now owned by the descendent font created above */ |
315 | 17.3k | pdfi_countdown(decfontdict); |
316 | 17.3k | decfontdict = NULL; |
317 | 17.3k | if (code < 0) { |
318 | 1.25k | code = gs_note_error(gs_error_invalidfont); |
319 | 1.25k | goto error; |
320 | 1.25k | } |
321 | | /* If we're got this far, we have a CMap and a descendant font, let's make the Type 0 */ |
322 | 16.0k | pdft0 = (pdf_font_type0 *)gs_alloc_bytes(ctx->memory, sizeof(pdf_font_type0), "pdfi (type0 pdf_font)"); |
323 | 16.0k | if (pdft0 == NULL) { |
324 | 0 | code = gs_note_error(gs_error_VMerror); |
325 | 0 | goto error; |
326 | 0 | } |
327 | | |
328 | | /* This is the only font type these entries not relevant for */ |
329 | 16.0k | pdft0->copyright = pdft0->notice = pdft0->fullname = pdft0->familyname = NULL; |
330 | | |
331 | 16.0k | code = pdfi_array_alloc(ctx, 1, &arr); |
332 | 16.0k | if (code < 0) { |
333 | 0 | gs_free_object(ctx->memory, pdft0, "pdfi_read_type0_font(pdft0)"); |
334 | 0 | goto error; |
335 | 0 | } |
336 | 16.0k | arr->refcnt = 1; |
337 | 16.0k | code = pdfi_array_put(ctx, arr, 0, (pdf_obj *)descpfont); |
338 | 16.0k | if (code < 0) { |
339 | 0 | gs_free_object(ctx->memory, pdft0, "pdfi_read_type0_font(pdft0)"); |
340 | 0 | goto error; |
341 | 0 | } |
342 | | |
343 | 16.0k | pdft0->type = PDF_FONT; |
344 | 16.0k | pdft0->pdfi_font_type = e_pdf_font_type0; |
345 | 16.0k | pdft0->ctx = ctx; |
346 | | #if REFCNT_DEBUG |
347 | | pdft0->UID = ctx->UID++; |
348 | | outprintf(ctx->memory, "Allocated object of type %c with UID %"PRIi64"\n", pdft0->type, pdft0->UID); |
349 | | #endif |
350 | 16.0k | pdft0->refcnt = 1; |
351 | 16.0k | pdft0->filename = NULL; |
352 | 16.0k | pdft0->object_num = font_dict->object_num; |
353 | 16.0k | pdft0->generation_num = font_dict->generation_num; |
354 | 16.0k | pdft0->indirect_num = font_dict->indirect_num; |
355 | 16.0k | pdft0->indirect_gen = font_dict->indirect_gen; |
356 | 16.0k | pdft0->Encoding = (pdf_obj *)pcmap; |
357 | 16.0k | pdft0->ToUnicode = tounicode; |
358 | 16.0k | tounicode = NULL; |
359 | 16.0k | pdft0->DescendantFonts = arr; |
360 | 16.0k | pdft0->PDF_font = font_dict; |
361 | 16.0k | pdfi_countup(font_dict); |
362 | 16.0k | pdft0->FontDescriptor = fontdesc; |
363 | 16.0k | fontdesc = NULL; |
364 | 16.0k | pdft0->BaseFont = basefont; |
365 | 16.0k | pdft0->decoding = dec; |
366 | 16.0k | pdft0->substnwp = substnwp; |
367 | | |
368 | | /* Ownership transferred to pdft0, if we jump to error |
369 | | * these will now be freed by counting down pdft0. |
370 | | */ |
371 | 16.0k | tounicode = NULL; |
372 | 16.0k | arr = NULL; |
373 | 16.0k | basefont = NULL; |
374 | | |
375 | 16.0k | pdft0->pfont = NULL; /* In case we error out */ |
376 | | |
377 | 16.0k | pfont0 = (gs_font_type0 *)gs_alloc_struct(ctx->memory, gs_font, &st_gs_font_type0, "pdfi gs type 0 font"); |
378 | 16.0k | if (pfont0 == NULL) { |
379 | 0 | gs_free_object(ctx->memory, pdft0, "pdfi_read_type0_font(pdft0)"); |
380 | 0 | code = gs_note_error(gs_error_VMerror); |
381 | 0 | goto error; |
382 | 0 | } |
383 | 16.0k | gs_make_identity(&pfont0->orig_FontMatrix); |
384 | 16.0k | gs_make_identity(&pfont0->FontMatrix); |
385 | 16.0k | pfont0->next = pfont0->prev = 0; |
386 | 16.0k | pfont0->memory = ctx->memory; |
387 | 16.0k | pfont0->dir = ctx->font_dir; |
388 | 16.0k | pfont0->is_resource = false; |
389 | 16.0k | gs_notify_init(&pfont0->notify_list, ctx->memory); |
390 | 16.0k | pfont0->id = gs_next_ids(ctx->memory, 1); |
391 | 16.0k | pfont0->base = (gs_font *) pfont0; |
392 | 16.0k | pfont0->client_data = pdft0; |
393 | 16.0k | pfont0->WMode = pcmap->wmode; |
394 | 16.0k | pfont0->FontType = ft_composite; |
395 | 16.0k | pfont0->PaintType = 0; |
396 | 16.0k | pfont0->StrokeWidth = 0; |
397 | 16.0k | pfont0->is_cached = 0; |
398 | 16.0k | if (pdft0->BaseFont != NULL) { |
399 | 16.0k | pdf_name *nobj = (pdf_name *)pdft0->BaseFont; |
400 | 16.0k | nlen = nobj->length > gs_font_name_max ? gs_font_name_max : nobj->length; |
401 | | |
402 | 16.0k | memcpy(pfont0->key_name.chars, nobj->data, nlen); |
403 | 16.0k | pfont0->key_name.size = nlen; |
404 | 16.0k | memcpy(pfont0->font_name.chars, nobj->data, nlen); |
405 | 16.0k | pfont0->font_name.size = nlen; |
406 | 16.0k | } |
407 | 31 | else { |
408 | 31 | nlen = descpfont->pfont->key_name.size > gs_font_name_max ? gs_font_name_max : descpfont->pfont->key_name.size; |
409 | | |
410 | 31 | memcpy(pfont0->key_name.chars, descpfont->pfont->key_name.chars, nlen); |
411 | 31 | pfont0->key_name.size = nlen; |
412 | 31 | memcpy(pfont0->font_name.chars, descpfont->pfont->font_name.chars, nlen); |
413 | 31 | pfont0->font_name.size = nlen; |
414 | 31 | } |
415 | | |
416 | 16.0k | if (pcmap->name.size > 0) { |
417 | 16.0k | if (pfont0->key_name.size + pcmap->name.size + 1 < gs_font_name_max) { |
418 | 15.4k | memcpy(pfont0->key_name.chars + pfont0->key_name.size, "-", 1); |
419 | 15.4k | memcpy(pfont0->key_name.chars + pfont0->key_name.size + 1, pcmap->name.data, pcmap->name.size); |
420 | 15.4k | pfont0->key_name.size += pcmap->name.size + 1; |
421 | 15.4k | } |
422 | 16.0k | if (pfont0->font_name.size + pcmap->name.size + 1 < gs_font_name_max) { |
423 | 15.4k | memcpy(pfont0->font_name.chars + pfont0->font_name.size, "-", 1); |
424 | 15.4k | memcpy(pfont0->font_name.chars + pfont0->font_name.size + 1, pcmap->name.data, pcmap->name.size); |
425 | 15.4k | pfont0->font_name.size += pcmap->name.size + 1; |
426 | 15.4k | } |
427 | 16.0k | } |
428 | 16.0k | pfont0->procs.define_font = gs_no_define_font; |
429 | 16.0k | pfont0->procs.make_font = gs_no_make_font; |
430 | 16.0k | pfont0->procs.font_info = gs_default_font_info; |
431 | 16.0k | pfont0->procs.same_font = gs_default_same_font; |
432 | 16.0k | pfont0->procs.encode_char = pdfi_encode_char; |
433 | 16.0k | pfont0->procs.decode_glyph = pdfi_font0_map_glyph_to_unicode; |
434 | 16.0k | pfont0->procs.enumerate_glyph = gs_no_enumerate_glyph; |
435 | 16.0k | pfont0->procs.glyph_info = gs_default_glyph_info; |
436 | 16.0k | pfont0->procs.glyph_outline = gs_no_glyph_outline; |
437 | 16.0k | pfont0->procs.glyph_name = pdfi_font0_glyph_name; |
438 | 16.0k | pfont0->procs.init_fstack = gs_type0_init_fstack; |
439 | 16.0k | pfont0->procs.next_char_glyph = gs_type0_next_char_glyph; |
440 | 16.0k | pfont0->procs.build_char = gs_no_build_char; |
441 | | |
442 | 16.0k | pfont0->data.FMapType = fmap_CMap; |
443 | 16.0k | pfont0->data.EscChar = 0xff; |
444 | 16.0k | pfont0->data.ShiftIn = 0x0f; |
445 | 16.0k | pfont0->data.SubsVector.data = NULL; |
446 | 16.0k | pfont0->data.SubsVector.size = 0; |
447 | 16.0k | pfont0->data.subs_size = pfont0->data.subs_width = 0; |
448 | | |
449 | 16.0k | pfont0->data.Encoding = (uint *)gs_alloc_bytes(ctx->memory, sizeof(uint), "pdfi_read_type0_font Encoding"); |
450 | 16.0k | if (pfont0->data.Encoding == NULL) { |
451 | 0 | gs_free_object(ctx->memory, pfont0, "pdfi_read_type0_font(pfont0)"); |
452 | 0 | code = gs_note_error(gs_error_VMerror); |
453 | 0 | goto error; |
454 | 0 | } |
455 | 16.0k | *pfont0->data.Encoding = 0; |
456 | | |
457 | 16.0k | pfont0->data.encoding_size = 1; |
458 | 16.0k | pfont0->data.FDepVector = (gs_font **)gs_alloc_bytes(ctx->memory, sizeof(gs_font *), "pdfi_read_type0_font FDepVector"); |
459 | 16.0k | if (pfont0->data.FDepVector == NULL) { |
460 | | /* We transferred ownership of pcmap to pfont0 above, but we didn't null the pointer |
461 | | * so we could keep using it. We must NULL it out before returning an error to prevent |
462 | | * reference counting problems. |
463 | | */ |
464 | 0 | pcmap = NULL; |
465 | 0 | gs_free_object(ctx->memory, pfont0, "pdfi_read_type0_font(pfont0)"); |
466 | 0 | code = gs_note_error(gs_error_VMerror); |
467 | 0 | goto error; |
468 | 0 | } |
469 | 16.0k | *pfont0->data.FDepVector = (gs_font *)descpfont->pfont; |
470 | 16.0k | pdfi_countdown(descpfont); |
471 | 16.0k | descpfont = NULL; |
472 | 16.0k | pfont0->data.fdep_size = 1; |
473 | 16.0k | pfont0->data.CMap = (gs_cmap_t *)pcmap->gscmap; |
474 | | |
475 | | /* NULL he pointer to prevent any reference counting problems, ownership was |
476 | | * transferred to pfont0, but we maintained the pointer for easy access until this |
477 | | * point. |
478 | | */ |
479 | 16.0k | pcmap = NULL; |
480 | | |
481 | 16.0k | pdft0->pfont = (gs_font_base *)pfont0; |
482 | | |
483 | 16.0k | code = gs_definefont(ctx->font_dir, (gs_font *)pdft0->pfont); |
484 | 16.0k | if (code < 0) { |
485 | 0 | gs_free_object(ctx->memory, pfont0, "pdfi_read_type0_font(pfont0)"); |
486 | 0 | code = gs_note_error(gs_error_VMerror); |
487 | 0 | goto error; |
488 | 0 | } |
489 | | |
490 | | /* object_num can be zero if the dictionary was defined inline */ |
491 | 16.0k | if (pdft0->object_num != 0) { |
492 | 16.0k | (void)replace_cache_entry(ctx, (pdf_obj *)pdft0); |
493 | 16.0k | } |
494 | | |
495 | 16.0k | *ppdffont = (pdf_font *)pdft0; |
496 | 16.0k | return 0; |
497 | | |
498 | 25.4k | error: |
499 | 25.4k | (void)pdfi_set_error_var(ctx, code, NULL, E_PDF_BADSTREAM, "pdfi_read_type0_font", "Error reading embedded Type0 font object %u\n", font_dict->object_num); |
500 | | |
501 | 25.4k | pdfi_countdown(arr); |
502 | 25.4k | pdfi_countdown(pcmap); |
503 | 25.4k | pdfi_countdown(tounicode); |
504 | 25.4k | pdfi_countdown(basefont); |
505 | 25.4k | pdfi_countdown(decfontdict); |
506 | 25.4k | pdfi_countdown(dfontdesc); |
507 | 25.4k | pdfi_countdown(fontdesc); |
508 | 25.4k | pdfi_countdown(ffile); |
509 | 25.4k | pdfi_countdown(descpfont); |
510 | 25.4k | pdfi_countdown(pdft0); |
511 | | |
512 | 25.4k | return code; |
513 | 16.0k | } |
514 | | |
515 | | int |
516 | | pdfi_free_font_type0(pdf_obj *font) |
517 | 16.0k | { |
518 | 16.0k | pdf_font_type0 *pdft0 = (pdf_font_type0 *)font; |
519 | 16.0k | gs_font_type0 *pfont0 = (gs_font_type0 *)pdft0->pfont; |
520 | 16.0k | pdfi_countdown(pdft0->PDF_font); |
521 | 16.0k | pdfi_countdown(pdft0->BaseFont); |
522 | 16.0k | pdfi_countdown(pdft0->FontDescriptor); |
523 | 16.0k | pdfi_countdown(pdft0->Encoding); |
524 | 16.0k | pdfi_countdown(pdft0->DescendantFonts); |
525 | 16.0k | pdfi_countdown(pdft0->ToUnicode); |
526 | 16.0k | pdfi_countdown(pdft0->filename); |
527 | 16.0k | pdfi_countdown(pdft0->copyright); |
528 | 16.0k | pdfi_countdown(pdft0->notice); |
529 | 16.0k | pdfi_countdown(pdft0->fullname); |
530 | 16.0k | pdfi_countdown(pdft0->familyname); |
531 | | |
532 | 16.0k | gs_free_object(OBJ_MEMORY(pdft0), pfont0->data.Encoding, "pdfi_free_font_type0(data.Encoding)"); |
533 | | /* We shouldn't need to free the fonts in the FDepVector, that should happen |
534 | | with DescendantFonts above. |
535 | | */ |
536 | 16.0k | gs_free_object(OBJ_MEMORY(pdft0), pfont0->data.FDepVector, "pdfi_free_font_type0(data.FDepVector)"); |
537 | 16.0k | gs_free_object(OBJ_MEMORY(pdft0), pfont0, "pdfi_free_font_type0(pfont0)"); |
538 | 16.0k | gs_free_object(OBJ_MEMORY(pdft0), pdft0, "pdfi_free_font_type0(pdft0)"); |
539 | | |
540 | 16.0k | return 0; |
541 | 16.0k | } |