/src/ghostpdl/devices/vector/gdevpdtf.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-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 | | |
17 | | /* Font and CMap resource implementation for pdfwrite text */ |
18 | | #include "memory_.h" |
19 | | #include "gx.h" |
20 | | #include "gserrors.h" |
21 | | #include "gsutil.h" /* for bytes_compare */ |
22 | | #include "gxfcache.h" /* for orig_fonts list */ |
23 | | #include "gxfcid.h" |
24 | | #include "gxfcmap.h" |
25 | | #include "gxfcopy.h" |
26 | | #include "gxfont.h" |
27 | | #include "gxfont1.h" |
28 | | #include "gdevpsf.h" |
29 | | #include "gdevpdfx.h" |
30 | | #include "gdevpdtb.h" |
31 | | #include "gdevpdtd.h" |
32 | | #include "gdevpdtf.h" |
33 | | #include "gdevpdtw.h" |
34 | | #include "gdevpdti.h" |
35 | | #include "gdevpdfo.h" /* for cos_free() */ |
36 | | #include "whitelst.h" /* Checks whether protected fonta cna be embedded */ |
37 | | |
38 | | #include "gscencs.h" |
39 | | |
40 | | /* GC descriptors */ |
41 | | public_st_pdf_font_resource(); |
42 | | private_st_pdf_standard_font(); |
43 | | private_st_pdf_standard_font_element(); |
44 | | private_st_pdf_outline_fonts(); |
45 | | |
46 | | static |
47 | 574k | ENUM_PTRS_WITH(pdf_font_resource_enum_ptrs, pdf_font_resource_t *pdfont) |
48 | 143k | ENUM_PREFIX(st_pdf_resource, 12); |
49 | 35.9k | case 0: return ENUM_STRING(&pdfont->BaseFont); |
50 | 35.9k | case 1: ENUM_RETURN(pdfont->FontDescriptor); |
51 | 35.9k | case 2: ENUM_RETURN(pdfont->base_font); |
52 | 35.9k | case 3: ENUM_RETURN(pdfont->Widths); |
53 | 35.9k | case 4: ENUM_RETURN(pdfont->used); |
54 | 35.9k | case 5: ENUM_RETURN(pdfont->res_ToUnicode); |
55 | 35.9k | case 6: ENUM_RETURN(pdfont->cmap_ToUnicode); |
56 | 35.9k | case 7: switch (pdfont->FontType) { |
57 | 399 | case ft_composite: |
58 | 399 | ENUM_RETURN(pdfont->u.type0.DescendantFont); |
59 | 26 | case ft_CID_encrypted: |
60 | 398 | case ft_CID_TrueType: |
61 | 398 | ENUM_RETURN(pdfont->u.cidfont.Widths2); |
62 | 35.1k | default: |
63 | 35.1k | pdf_mark_glyph_names(pdfont, mem); |
64 | 35.1k | ENUM_RETURN(pdfont->u.simple.Encoding); |
65 | 35.9k | } |
66 | 35.9k | case 8: switch (pdfont->FontType) { |
67 | 24.6k | case ft_encrypted: |
68 | 24.8k | case ft_encrypted2: |
69 | 31.7k | case ft_TrueType: |
70 | 31.7k | case ft_PCL_user_defined: |
71 | 31.7k | case ft_MicroType: |
72 | 31.7k | case ft_GL2_stick_user_defined: |
73 | 35.1k | case ft_user_defined: |
74 | 35.1k | case ft_PDF_user_defined: |
75 | 35.1k | case ft_GL2_531: |
76 | 35.1k | ENUM_RETURN(pdfont->u.simple.v); |
77 | 26 | case ft_CID_encrypted: |
78 | 398 | case ft_CID_TrueType: |
79 | 398 | ENUM_RETURN(pdfont->u.cidfont.v); |
80 | 399 | case ft_composite: |
81 | 399 | default: |
82 | 399 | ENUM_RETURN(0); |
83 | 35.9k | } |
84 | 35.9k | case 9: switch (pdfont->FontType) { |
85 | 0 | case ft_PCL_user_defined: |
86 | 0 | case ft_MicroType: |
87 | 0 | case ft_GL2_stick_user_defined: |
88 | 3.39k | case ft_user_defined: |
89 | 3.39k | case ft_PDF_user_defined: |
90 | 3.39k | case ft_GL2_531: |
91 | 3.39k | ENUM_RETURN(pdfont->u.simple.s.type3.char_procs); |
92 | 26 | case ft_CID_encrypted: |
93 | 398 | case ft_CID_TrueType: |
94 | 398 | ENUM_RETURN(pdfont->u.cidfont.CIDToGIDMap); |
95 | 32.1k | default: |
96 | 32.1k | ENUM_RETURN(0); |
97 | 35.9k | } |
98 | 35.9k | case 10: switch (pdfont->FontType) { |
99 | 0 | case ft_PCL_user_defined: |
100 | 0 | case ft_MicroType: |
101 | 0 | case ft_GL2_stick_user_defined: |
102 | 3.39k | case ft_user_defined: |
103 | 3.39k | case ft_PDF_user_defined: |
104 | 3.39k | case ft_GL2_531: |
105 | 3.39k | ENUM_RETURN(pdfont->u.simple.s.type3.cached); |
106 | 26 | case ft_CID_encrypted: |
107 | 398 | case ft_CID_TrueType: |
108 | 398 | ENUM_RETURN(pdfont->u.cidfont.parent); |
109 | 32.1k | default: |
110 | 32.1k | ENUM_RETURN(0); |
111 | 35.9k | } |
112 | 35.9k | case 11: switch (pdfont->FontType) { |
113 | 0 | case ft_PCL_user_defined: |
114 | 0 | case ft_MicroType: |
115 | 0 | case ft_GL2_stick_user_defined: |
116 | 3.39k | case ft_user_defined: |
117 | 3.39k | case ft_PDF_user_defined: |
118 | 3.39k | case ft_GL2_531: |
119 | 3.39k | ENUM_RETURN(pdfont->u.simple.s.type3.Resources); |
120 | 26 | case ft_CID_encrypted: |
121 | 398 | case ft_CID_TrueType: |
122 | 398 | ENUM_RETURN(pdfont->u.cidfont.used2); |
123 | 32.1k | default: |
124 | 32.1k | ENUM_RETURN(0); |
125 | 35.9k | } |
126 | 574k | ENUM_PTRS_END |
127 | | static |
128 | 35.9k | RELOC_PTRS_WITH(pdf_font_resource_reloc_ptrs, pdf_font_resource_t *pdfont) |
129 | 35.9k | { |
130 | 35.9k | RELOC_PREFIX(st_pdf_resource); |
131 | 35.9k | RELOC_STRING_VAR(pdfont->BaseFont); |
132 | 35.9k | RELOC_VAR(pdfont->FontDescriptor); |
133 | 35.9k | RELOC_VAR(pdfont->base_font); |
134 | 35.9k | RELOC_VAR(pdfont->Widths); |
135 | 35.9k | RELOC_VAR(pdfont->used); |
136 | 35.9k | RELOC_VAR(pdfont->res_ToUnicode); |
137 | 35.9k | RELOC_VAR(pdfont->cmap_ToUnicode); |
138 | 35.9k | switch (pdfont->FontType) { |
139 | 399 | case ft_composite: |
140 | 399 | RELOC_VAR(pdfont->u.type0.DescendantFont); |
141 | 399 | break; |
142 | 0 | case ft_PCL_user_defined: |
143 | 0 | case ft_MicroType: |
144 | 0 | case ft_GL2_stick_user_defined: |
145 | 3.39k | case ft_user_defined: |
146 | 3.39k | case ft_PDF_user_defined: |
147 | 3.39k | case ft_GL2_531: |
148 | 3.39k | RELOC_VAR(pdfont->u.simple.Encoding); |
149 | 3.39k | RELOC_VAR(pdfont->u.simple.v); |
150 | 3.39k | RELOC_VAR(pdfont->u.simple.s.type3.char_procs); |
151 | 3.39k | RELOC_VAR(pdfont->u.simple.s.type3.cached); |
152 | 3.39k | RELOC_VAR(pdfont->u.simple.s.type3.Resources); |
153 | 3.39k | break; |
154 | 26 | case ft_CID_encrypted: |
155 | 398 | case ft_CID_TrueType: |
156 | 398 | RELOC_VAR(pdfont->u.cidfont.Widths2); |
157 | 398 | RELOC_VAR(pdfont->u.cidfont.v); |
158 | 398 | RELOC_VAR(pdfont->u.cidfont.CIDToGIDMap); |
159 | 398 | RELOC_VAR(pdfont->u.cidfont.parent); |
160 | 398 | RELOC_VAR(pdfont->u.cidfont.used2); |
161 | 398 | break; |
162 | 31.7k | default: |
163 | 31.7k | RELOC_VAR(pdfont->u.simple.Encoding); |
164 | 31.7k | RELOC_VAR(pdfont->u.simple.v); |
165 | 31.7k | break; |
166 | 35.9k | } |
167 | 35.9k | } |
168 | 35.9k | RELOC_PTRS_END |
169 | | |
170 | | /* ---------------- Standard fonts ---------------- */ |
171 | | |
172 | | /* ------ Private ------ */ |
173 | | |
174 | | /* Define the 14 standard built-in fonts. */ |
175 | 70.2k | #define PDF_NUM_STANDARD_FONTS 14 |
176 | | typedef struct pdf_standard_font_info_s { |
177 | | const char *fname; |
178 | | int size; |
179 | | gs_encoding_index_t base_encoding; |
180 | | } pdf_standard_font_info_t; |
181 | | static const pdf_standard_font_info_t standard_font_info[] = { |
182 | | {"Courier", 7, ENCODING_INDEX_STANDARD}, |
183 | | {"Courier-Bold", 12, ENCODING_INDEX_STANDARD}, |
184 | | {"Courier-Oblique", 15, ENCODING_INDEX_STANDARD}, |
185 | | {"Courier-BoldOblique", 19, ENCODING_INDEX_STANDARD}, |
186 | | {"Helvetica", 9, ENCODING_INDEX_STANDARD}, |
187 | | {"Helvetica-Bold", 14, ENCODING_INDEX_STANDARD}, |
188 | | {"Helvetica-Oblique", 17, ENCODING_INDEX_STANDARD}, |
189 | | {"Helvetica-BoldOblique", 21, ENCODING_INDEX_STANDARD}, |
190 | | {"Symbol", 6, ENCODING_INDEX_SYMBOL}, |
191 | | {"Times-Roman", 11, ENCODING_INDEX_STANDARD}, |
192 | | {"Times-Bold", 10, ENCODING_INDEX_STANDARD}, |
193 | | {"Times-Italic", 12, ENCODING_INDEX_STANDARD}, |
194 | | {"Times-BoldItalic", 16, ENCODING_INDEX_STANDARD}, |
195 | | {"ZapfDingbats", 12, ENCODING_INDEX_DINGBATS}, |
196 | | {0} |
197 | | }; |
198 | | |
199 | | /* Return the index of a standard font name, or -1 if missing. */ |
200 | | static int |
201 | | pdf_find_standard_font_name(const byte *str, uint size) |
202 | 48.1k | { |
203 | 48.1k | const pdf_standard_font_info_t *ppsf; |
204 | | |
205 | 698k | for (ppsf = standard_font_info; ppsf->fname; ++ppsf) |
206 | 653k | if (ppsf->size == size && |
207 | 653k | !memcmp(ppsf->fname, (const char *)str, size) |
208 | 653k | ) |
209 | 3.43k | return ppsf - standard_font_info; |
210 | 44.6k | return -1; |
211 | 48.1k | } |
212 | | |
213 | | /* |
214 | | * If there is a standard font with the same appearance (CharStrings, |
215 | | * Private, WeightVector) as the given font, set *psame to the mask of |
216 | | * identical properties, and return the standard-font index; otherwise, |
217 | | * set *psame to 0 and return -1. |
218 | | */ |
219 | | static int |
220 | | find_std_appearance(const gx_device_pdf *pdev, gs_font_base *bfont, |
221 | | int mask, pdf_char_glyph_pair_t *pairs, int num_glyphs) |
222 | 146 | { |
223 | 146 | bool has_uid = uid_is_UniqueID(&bfont->UID) && bfont->UID.id != 0; |
224 | 146 | const pdf_standard_font_t *psf = pdf_standard_fonts(pdev); |
225 | 146 | int i; |
226 | | |
227 | 146 | switch (bfont->FontType) { |
228 | 145 | case ft_encrypted: |
229 | 145 | case ft_encrypted2: |
230 | 145 | case ft_TrueType: |
231 | 145 | break; |
232 | 1 | default: |
233 | 1 | return -1; |
234 | 146 | } |
235 | | |
236 | 2.17k | for (i = 0; i < PDF_NUM_STANDARD_FONTS; ++psf, ++i) { |
237 | 2.03k | gs_font_base *cfont; |
238 | 2.03k | int code; |
239 | | |
240 | 2.03k | if (!psf->pdfont) |
241 | 1.99k | continue; |
242 | 38 | cfont = pdf_font_resource_font(psf->pdfont, false); |
243 | 38 | if (has_uid) { |
244 | | /* |
245 | | * Require the UIDs to match. The PostScript spec says this |
246 | | * is the case iff the outlines are the same. |
247 | | */ |
248 | 0 | if (!uid_equal(&bfont->UID, &cfont->UID)) |
249 | 0 | continue; |
250 | 0 | } |
251 | | /* |
252 | | * Require the actual outlines to match (within the given subset). |
253 | | */ |
254 | 38 | code = gs_copied_can_copy_glyphs((const gs_font *)cfont, |
255 | 38 | (const gs_font *)bfont, |
256 | 38 | &pairs[0].glyph, num_glyphs, |
257 | 38 | sizeof(pdf_char_glyph_pair_t), true); |
258 | 38 | if (code == gs_error_unregistered) /* Debug purpose only. */ |
259 | 0 | return code; |
260 | | /* Note: code < 0 means an error. Skip it here. */ |
261 | 38 | if (code > 0) |
262 | 0 | return i; |
263 | 38 | } |
264 | 145 | return -1; |
265 | 145 | } |
266 | | |
267 | | /* |
268 | | * Scan a font directory for standard fonts. Return true if any new ones |
269 | | * were found. A font is recognized as standard if it was loaded as a |
270 | | * resource, it has a UniqueId, and it has a standard name. |
271 | | */ |
272 | | static bool |
273 | | scan_for_standard_fonts(gx_device_pdf *pdev, const gs_font_dir *dir) |
274 | 146 | { |
275 | 146 | bool found = false; |
276 | 146 | gs_font *orig = dir->orig_fonts; |
277 | | |
278 | 574 | for (; orig; orig = orig->next) { |
279 | 428 | gs_font_base *obfont; |
280 | | |
281 | 428 | if (orig->FontType == ft_composite || !orig->is_resource) |
282 | 228 | continue; |
283 | 200 | obfont = (gs_font_base *)orig; |
284 | 200 | if (uid_is_UniqueID(&obfont->UID)) { |
285 | | /* Is it one of the standard fonts? */ |
286 | 0 | int i = pdf_find_standard_font_name(orig->key_name.chars, |
287 | 0 | orig->key_name.size); |
288 | |
|
289 | 0 | if (i >= 0 && pdf_standard_fonts(pdev)[i].pdfont == 0) { |
290 | 0 | pdf_font_resource_t *pdfont; |
291 | 0 | int code = pdf_font_std_alloc(pdev, &pdfont, true, orig->id, obfont, |
292 | 0 | i); |
293 | |
|
294 | 0 | if (code < 0) |
295 | 0 | continue; |
296 | 0 | found = true; |
297 | 0 | } |
298 | 0 | } |
299 | 200 | } |
300 | 146 | return found; |
301 | 146 | } |
302 | | |
303 | | /* ---------------- Initialization ---------------- */ |
304 | | |
305 | | /* |
306 | | * Allocate and initialize bookkeeping for outline fonts. |
307 | | */ |
308 | | pdf_outline_fonts_t * |
309 | | pdf_outline_fonts_alloc(gs_memory_t *mem) |
310 | 34.0k | { |
311 | 34.0k | pdf_outline_fonts_t *pofs = |
312 | 34.0k | gs_alloc_struct(mem, pdf_outline_fonts_t, &st_pdf_outline_fonts, |
313 | 34.0k | "pdf_outline_fonts_alloc(outline_fonts)"); |
314 | 34.0k | pdf_standard_font_t *ppsf = |
315 | 34.0k | gs_alloc_struct_array(mem, PDF_NUM_STANDARD_FONTS, |
316 | 34.0k | pdf_standard_font_t, |
317 | 34.0k | &st_pdf_standard_font_element, |
318 | 34.0k | "pdf_outline_fonts_alloc(standard_fonts)"); |
319 | | |
320 | 34.0k | if (pofs == 0 || ppsf == 0) |
321 | 0 | return 0; |
322 | 34.0k | memset(ppsf, 0, PDF_NUM_STANDARD_FONTS * sizeof(*ppsf)); |
323 | 34.0k | memset(pofs, 0, sizeof(*pofs)); |
324 | 34.0k | pofs->standard_fonts = ppsf; |
325 | 34.0k | return pofs; |
326 | 34.0k | } |
327 | | |
328 | | /* |
329 | | * Return the standard fonts array. |
330 | | */ |
331 | | pdf_standard_font_t * |
332 | | pdf_standard_fonts(const gx_device_pdf *pdev) |
333 | 37.4k | { |
334 | 37.4k | if (pdev->text != NULL && pdev->text->outline_fonts != NULL) |
335 | 37.4k | return pdev->text->outline_fonts->standard_fonts; |
336 | 0 | return NULL; |
337 | 37.4k | } |
338 | | |
339 | | /* |
340 | | * Clean the standard fonts array. |
341 | | */ |
342 | | void |
343 | | pdf_clean_standard_fonts(const gx_device_pdf *pdev) |
344 | 34.0k | { |
345 | 34.0k | pdf_standard_font_t *ppsf = pdf_standard_fonts(pdev); |
346 | | |
347 | 34.0k | if (ppsf != NULL) |
348 | 34.0k | memset(ppsf, 0, PDF_NUM_STANDARD_FONTS * sizeof(*ppsf)); |
349 | 34.0k | } |
350 | | |
351 | | /* ---------------- Font resources ---------------- */ |
352 | | |
353 | | /* ------ Private ------ */ |
354 | | |
355 | | static int |
356 | | pdf_resize_array(gs_memory_t *mem, void **p, int elem_size, uint old_size, uint new_size) |
357 | 778 | { |
358 | 778 | void *q = gs_alloc_byte_array(mem, new_size, elem_size, "pdf_resize_array"); |
359 | | |
360 | 778 | if (q == NULL) |
361 | 0 | return_error(gs_error_VMerror); |
362 | 778 | memset((char *)q + elem_size * old_size, 0, elem_size * (new_size - old_size)); |
363 | 778 | memcpy(q, *p, elem_size * old_size); |
364 | 778 | gs_free_object(mem, *p, "pdf_resize_array"); |
365 | 778 | *p = q; |
366 | 778 | return 0; |
367 | 778 | } |
368 | | |
369 | | /* |
370 | | * Allocate and (minimally) initialize a font resource. |
371 | | */ |
372 | | static int |
373 | | font_resource_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, |
374 | | pdf_resource_type_t rtype, gs_id rid, font_type ftype, |
375 | | int chars_count, |
376 | | pdf_font_write_contents_proc_t write_contents) |
377 | 32.9k | { |
378 | 32.9k | gs_memory_t *mem = pdev->pdf_memory; |
379 | 32.9k | pdf_font_resource_t *pfres; |
380 | 32.9k | double *widths = 0; |
381 | 32.9k | byte *used = 0; |
382 | 32.9k | int code; |
383 | 32.9k | bool is_CID_font = (ftype == ft_CID_encrypted || ftype == ft_CID_TrueType); |
384 | | |
385 | 32.9k | if (chars_count != 0) { |
386 | 32.5k | uint size = (chars_count + 7) / 8; |
387 | | |
388 | 32.5k | if (!is_CID_font) { |
389 | 32.2k | widths = (void *)gs_alloc_byte_array(mem, chars_count, sizeof(*widths), |
390 | 32.2k | "font_resource_alloc(Widths)"); |
391 | 32.2k | } else { |
392 | | /* Delay allocation because we don't know which WMode will be used. */ |
393 | 324 | } |
394 | 32.5k | used = gs_alloc_bytes(mem, size, "font_resource_alloc(used)"); |
395 | 32.5k | if ((!is_CID_font && widths == 0) || used == 0) { |
396 | 0 | code = gs_note_error(gs_error_VMerror); |
397 | 0 | goto fail; |
398 | 0 | } |
399 | 32.5k | if (!is_CID_font) |
400 | 32.2k | memset(widths, 0, chars_count * sizeof(*widths)); |
401 | 32.5k | memset(used, 0, size); |
402 | 32.5k | } |
403 | 32.9k | code = pdf_alloc_resource(pdev, rtype, rid, (pdf_resource_t **)&pfres, -1L); |
404 | 32.9k | if (code < 0) |
405 | 0 | goto fail; |
406 | 32.9k | pfres->FontType = ftype; |
407 | 32.9k | pfres->count = chars_count; |
408 | 32.9k | pfres->Widths = widths; |
409 | 32.9k | pfres->used = used; |
410 | 32.9k | pfres->write_contents = write_contents; |
411 | 32.9k | pfres->res_ToUnicode = NULL; |
412 | 32.9k | pfres->cmap_ToUnicode = NULL; |
413 | 32.9k | pfres->mark_glyph = 0; |
414 | 32.9k | pfres->mark_glyph_data = 0; |
415 | 32.9k | pfres->u.simple.standard_glyph_code_for_notdef = gs_c_name_glyph((const byte *)".notdef", 7) - gs_c_min_std_encoding_glyph; |
416 | 32.9k | *ppfres = pfres; |
417 | 32.9k | return 0; |
418 | 0 | fail: |
419 | 0 | gs_free_object(mem, used, "font_resource_alloc(used)"); |
420 | 0 | gs_free_object(mem, widths, "font_resource_alloc(Widths)"); |
421 | 0 | return code; |
422 | 32.9k | } |
423 | | |
424 | | int font_resource_free(gx_device_pdf *pdev, pdf_font_resource_t *pdfont) |
425 | 32.9k | { |
426 | 32.9k | if(pdfont->BaseFont.size |
427 | 32.9k | && (pdfont->base_font == NULL || !pdfont->base_font->is_standard)) { |
428 | | |
429 | 26.2k | gs_free_string(pdev->pdf_memory, pdfont->BaseFont.data, pdfont->BaseFont.size, "Free BaseFont string"); |
430 | 26.2k | pdfont->BaseFont.data = (byte *)0L; |
431 | 26.2k | pdfont->BaseFont.size = 0; |
432 | 26.2k | } |
433 | 32.9k | if(pdfont->Widths) { |
434 | 32.5k | gs_free_object(pdev->pdf_memory, pdfont->Widths, "Free Widths array"); |
435 | 32.5k | pdfont->Widths = 0; |
436 | 32.5k | } |
437 | 32.9k | if(pdfont->used) { |
438 | 32.5k | gs_free_object(pdev->pdf_memory, pdfont->used, "Free used array"); |
439 | 32.5k | pdfont->used = 0; |
440 | 32.5k | } |
441 | 32.9k | if(pdfont->res_ToUnicode) { |
442 | | /* ToUnicode resources are tracked amd released separately */ |
443 | 2.62k | pdfont->res_ToUnicode = 0; |
444 | 2.62k | } |
445 | 32.9k | if(pdfont->cmap_ToUnicode) { |
446 | 2.91k | gs_cmap_ToUnicode_free(pdev->pdf_memory, pdfont->cmap_ToUnicode); |
447 | 2.91k | pdfont->cmap_ToUnicode = 0; |
448 | 2.91k | } |
449 | 32.9k | switch(pdfont->FontType) { |
450 | 325 | case ft_composite: |
451 | 325 | if (pdfont->u.type0.CMapName_data != NULL) { |
452 | 325 | gs_free_object(pdev->memory->non_gc_memory, (byte *)pdfont->u.type0.CMapName_data, "font_resource_free(CMapName)"); |
453 | 325 | pdfont->u.type0.CMapName_data = NULL; |
454 | 325 | pdfont->u.type0.CMapName_size = 0; |
455 | 325 | } |
456 | 325 | break; |
457 | 0 | case ft_PCL_user_defined: |
458 | 0 | case ft_MicroType: |
459 | 0 | case ft_GL2_stick_user_defined: |
460 | 3.37k | case ft_user_defined: |
461 | 3.37k | case ft_PDF_user_defined: |
462 | 3.37k | case ft_GL2_531: |
463 | 3.37k | if(pdfont->u.simple.Encoding) { |
464 | 991 | int ix; |
465 | 254k | for (ix = 0; ix <= 255;ix++) |
466 | 253k | gs_free_object(pdev->pdf_memory->non_gc_memory, pdfont->u.simple.Encoding[ix].data, "Free copied glyph name string"); |
467 | 991 | gs_free_object(pdev->pdf_memory, pdfont->u.simple.Encoding, "Free simple Encoding"); |
468 | 991 | pdfont->u.simple.Encoding = 0; |
469 | 991 | } |
470 | 3.37k | if(pdfont->u.simple.v) { |
471 | 991 | gs_free_object(pdev->pdf_memory, pdfont->u.simple.v, "Free simple v"); |
472 | 991 | pdfont->u.simple.v = 0; |
473 | 991 | } |
474 | 3.37k | if (pdfont->u.simple.s.type3.char_procs) { |
475 | 3.34k | pdf_free_charproc_ownership(pdev, (pdf_resource_t *)pdfont->u.simple.s.type3.char_procs); |
476 | 3.34k | pdfont->u.simple.s.type3.char_procs = 0; |
477 | 3.34k | } |
478 | 3.37k | if (pdfont->u.simple.s.type3.cached) { |
479 | 991 | gs_free_object(pdev->pdf_memory, pdfont->u.simple.s.type3.cached, "Free type 3 cached array"); |
480 | 991 | pdfont->u.simple.s.type3.cached = NULL; |
481 | 991 | } |
482 | 3.37k | if (pdfont->u.simple.s.type3.Resources != NULL) { |
483 | 991 | cos_free((cos_object_t *)pdfont->u.simple.s.type3.Resources, "Free type 3 Resources dictionary"); |
484 | 991 | pdfont->u.simple.s.type3.Resources = NULL; |
485 | 991 | } |
486 | 3.37k | break; |
487 | 26 | case ft_CID_encrypted: |
488 | 324 | case ft_CID_TrueType: |
489 | 324 | if(pdfont->u.cidfont.Widths2) { |
490 | 10 | gs_free_object(pdev->pdf_memory, pdfont->u.cidfont.Widths2, "Free CIDFont Widths2 array"); |
491 | 10 | pdfont->u.cidfont.Widths2 = NULL; |
492 | 10 | } |
493 | 324 | if(pdfont->u.cidfont.v) { |
494 | 10 | gs_free_object(pdev->pdf_memory, pdfont->u.cidfont.v, "Free CIDFont v array"); |
495 | 10 | pdfont->u.cidfont.v = NULL; |
496 | 10 | } |
497 | 324 | if(pdfont->u.cidfont.used2) { |
498 | 324 | gs_free_object(pdev->pdf_memory, pdfont->u.cidfont.used2, "Free CIDFont used2"); |
499 | 324 | pdfont->u.cidfont.used2 = 0; |
500 | 324 | } |
501 | 324 | if(pdfont->u.cidfont.CIDToGIDMap) { |
502 | 298 | gs_free_object(pdev->pdf_memory, pdfont->u.cidfont.CIDToGIDMap, "Free CIDToGID map"); |
503 | 298 | pdfont->u.cidfont.CIDToGIDMap = 0; |
504 | 298 | } |
505 | 324 | break; |
506 | 28.8k | default: |
507 | 28.8k | if(pdfont->u.simple.Encoding) { |
508 | 28.8k | int ix; |
509 | 7.42M | for (ix = 0; ix <= 255;ix++) |
510 | 7.39M | gs_free_object(pdev->pdf_memory->non_gc_memory, pdfont->u.simple.Encoding[ix].data, "Free copied glyph name string"); |
511 | 28.8k | gs_free_object(pdev->pdf_memory, pdfont->u.simple.Encoding, "Free simple Encoding"); |
512 | 28.8k | pdfont->u.simple.Encoding = 0; |
513 | 28.8k | } |
514 | 28.8k | if(pdfont->u.simple.v) { |
515 | 28.8k | gs_free_object(pdev->pdf_memory, pdfont->u.simple.v, "Free simple v"); |
516 | 28.8k | pdfont->u.simple.v = 0; |
517 | 28.8k | } |
518 | 28.8k | break; |
519 | 32.9k | } |
520 | 32.9k | if (pdfont->object) { |
521 | 32.9k | gs_free_object(pdev->pdf_memory, pdfont->object, "Free font resource object"); |
522 | 32.9k | pdfont->object = 0; |
523 | 32.9k | } |
524 | | /* We free FontDescriptor resources separately */ |
525 | 32.9k | if(pdfont->FontDescriptor) |
526 | 25.9k | pdfont->FontDescriptor = NULL; |
527 | 6.98k | else { |
528 | 6.98k | if (pdfont->base_font) { |
529 | | /* Normally we free the 'base font' when we free the Font Descriptor, |
530 | | * but if we have no font descriptor (we are not embedding the font), |
531 | | * we won't free the copies of the font, or any other associated memory, |
532 | | * so do it now. |
533 | | */ |
534 | 3.29k | pdf_base_font_t *pbfont = pdfont->base_font; |
535 | 3.29k | gs_font *copied = (gs_font *)pbfont->copied, *complete = (gs_font *)pbfont->complete; |
536 | | |
537 | 3.29k | if (copied) |
538 | 3.29k | gs_free_copied_font(copied); |
539 | 3.29k | if (complete && copied != complete) { |
540 | 0 | gs_free_copied_font(complete); |
541 | 0 | pbfont->complete = 0; |
542 | 0 | } |
543 | 3.29k | pbfont->copied = 0; |
544 | 3.29k | if (pbfont && pbfont->font_name.size) { |
545 | 3.29k | gs_free_string(pdev->pdf_memory, pbfont->font_name.data, pbfont->font_name.size, "Free BaseFont FontName string"); |
546 | 3.29k | pbfont->font_name.data = (byte *)0L; |
547 | 3.29k | pbfont->font_name.size = 0; |
548 | 3.29k | } |
549 | 3.29k | if (pbfont) { |
550 | 3.29k | gs_free_object(pdev->pdf_memory, pbfont, "Free base font from FontDescriptor)"); |
551 | 3.29k | pdfont->base_font = 0; |
552 | 3.29k | } |
553 | 3.29k | } |
554 | 6.98k | } |
555 | 32.9k | return 0; |
556 | 32.9k | } |
557 | | |
558 | | int |
559 | | pdf_assign_font_object_id(gx_device_pdf *pdev, pdf_font_resource_t *pdfont) |
560 | 1.91M | { |
561 | 1.91M | if (pdf_resource_id((pdf_resource_t *)pdfont) == -1) { |
562 | 27.7k | int code; |
563 | | |
564 | 27.7k | pdf_reserve_object_id(pdev, (pdf_resource_t *)pdfont, 0); |
565 | 27.7k | code = pdf_mark_font_descriptor_used(pdev, pdfont->FontDescriptor); |
566 | 27.7k | if (code < 0) |
567 | 0 | return code; |
568 | 27.7k | if (pdfont->FontType == 0) { |
569 | 320 | pdf_font_resource_t *pdfont1 = pdfont->u.type0.DescendantFont; |
570 | | |
571 | 320 | if (pdf_font_id(pdfont1) == -1) { |
572 | 319 | pdf_reserve_object_id(pdev, (pdf_resource_t *)pdfont1, 0); |
573 | 319 | code = pdf_mark_font_descriptor_used(pdev, pdfont1->FontDescriptor); |
574 | 319 | if (code < 0) |
575 | 0 | return code; |
576 | 319 | } |
577 | 320 | } |
578 | 27.7k | } |
579 | 1.91M | return 0; |
580 | 1.91M | } |
581 | | |
582 | | static int |
583 | | font_resource_simple_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, |
584 | | gs_id rid, font_type ftype, int chars_count, |
585 | | pdf_font_write_contents_proc_t write_contents) |
586 | 32.2k | { |
587 | 32.2k | pdf_font_resource_t *pfres; |
588 | 32.2k | int code = font_resource_alloc(pdev, &pfres, resourceFont, rid, ftype, |
589 | 32.2k | chars_count, write_contents); |
590 | | |
591 | 32.2k | if (code < 0) |
592 | 0 | return code; |
593 | 32.2k | pfres->u.simple.FirstChar = 256; |
594 | 32.2k | pfres->u.simple.LastChar = -1; |
595 | 32.2k | pfres->u.simple.BaseEncoding = -1; |
596 | 32.2k | pfres->u.simple.preferred_encoding_index = -1; |
597 | 32.2k | pfres->u.simple.last_reserved_char = -1; |
598 | 32.2k | *ppfres = pfres; |
599 | 32.2k | return 0; |
600 | 32.2k | } |
601 | | int |
602 | | font_resource_encoded_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, |
603 | | gs_id rid, font_type ftype, |
604 | | pdf_font_write_contents_proc_t write_contents) |
605 | 29.8k | { |
606 | 29.8k | pdf_encoding_element_t *Encoding = (pdf_encoding_element_t *)gs_alloc_bytes(pdev->pdf_memory, 256 * sizeof(pdf_encoding_element_t), "font_resource_encoded_alloc"); |
607 | 29.8k | gs_point *v = (gs_point *)gs_alloc_byte_array(pdev->pdf_memory, |
608 | 29.8k | 256, sizeof(gs_point), "pdf_font_simple_alloc"); |
609 | 29.8k | pdf_font_resource_t *pdfont; |
610 | 29.8k | int code, i; |
611 | | |
612 | 29.8k | if (v == 0 || Encoding == 0) { |
613 | 0 | gs_free_object(pdev->pdf_memory, Encoding, |
614 | 0 | "font_resource_encoded_alloc"); |
615 | 0 | gs_free_object(pdev->pdf_memory, v, |
616 | 0 | "font_resource_encoded_alloc"); |
617 | 0 | return_error(gs_error_VMerror); |
618 | 0 | } |
619 | 29.8k | code = font_resource_simple_alloc(pdev, &pdfont, rid, ftype, |
620 | 29.8k | 256, write_contents); |
621 | 29.8k | if (code < 0) { |
622 | 0 | gs_free_object(pdev->pdf_memory, Encoding, |
623 | 0 | "font_resource_encoded_alloc"); |
624 | 0 | gs_free_object(pdev->pdf_memory, v, |
625 | 0 | "font_resource_encoded_alloc"); |
626 | 0 | return_error(gs_error_VMerror); |
627 | 0 | } |
628 | 29.8k | memset(v, 0, 256 * sizeof(*v)); |
629 | 29.8k | memset(Encoding, 0, 256 * sizeof(*Encoding)); |
630 | 7.67M | for (i = 0; i < 256; ++i) |
631 | 7.64M | Encoding[i].glyph = GS_NO_GLYPH; |
632 | 29.8k | pdfont->u.simple.Encoding = Encoding; |
633 | 29.8k | pdfont->u.simple.v = v; |
634 | 29.8k | *ppfres = pdfont; |
635 | 29.8k | return 0; |
636 | 29.8k | } |
637 | | |
638 | | /* |
639 | | * Record whether a Type 1 or Type 2 font is a Multiple Master instance. |
640 | | */ |
641 | | static void |
642 | | set_is_MM_instance(pdf_font_resource_t *pdfont, const gs_font_base *pfont) |
643 | 28.8k | { |
644 | 28.8k | switch (pfont->FontType) { |
645 | 23.3k | case ft_encrypted: |
646 | 23.5k | case ft_encrypted2: |
647 | 23.5k | pdfont->u.simple.s.type1.is_MM_instance = |
648 | 23.5k | ((const gs_font_type1 *)pfont)->data.WeightVector.count > 0; |
649 | 28.8k | default: |
650 | 28.8k | break; |
651 | 28.8k | } |
652 | 28.8k | } |
653 | | |
654 | | /* ------ Generic public ------ */ |
655 | | |
656 | | /* Resize font resource arrays. */ |
657 | | int |
658 | | pdf_resize_resource_arrays(gx_device_pdf *pdev, pdf_font_resource_t *pfres, uint chars_count) |
659 | 87.1k | { |
660 | | /* This function fixes CID fonts that provide a lesser CIDCount than |
661 | | CIDs used in a document. Rather PS requires to print CID=0, |
662 | | we need to provide a bigger CIDCount since we don't |
663 | | re-encode the text. The text should look fine if the |
664 | | viewer application substitutes the font. */ |
665 | 87.1k | gs_memory_t *mem = pdev->pdf_memory; |
666 | 87.1k | int code; |
667 | | |
668 | | /* Ensure the 'round up' code below doesn't overflow an unsigned int when adding 7 */ |
669 | 87.1k | if (pfres->count >= max_uint - 7 || chars_count > max_uint - 7) |
670 | 0 | return_error(gs_error_rangecheck); |
671 | | |
672 | 87.1k | if (chars_count < pfres->count) |
673 | 86.9k | return 0; |
674 | 165 | if (pfres->Widths != NULL) { |
675 | 142 | code = pdf_resize_array(mem, (void **)&pfres->Widths, sizeof(*pfres->Widths), |
676 | 142 | pfres->count, chars_count); |
677 | 142 | if (code < 0) |
678 | 0 | return code; |
679 | 142 | } |
680 | 165 | code = pdf_resize_array(mem, (void **)&pfres->used, sizeof(*pfres->used), |
681 | 165 | (pfres->count + 7) / 8, (chars_count + 7) / 8); |
682 | 165 | if (code < 0) |
683 | 0 | return code; |
684 | 165 | if (pfres->FontType == ft_CID_encrypted || pfres->FontType == ft_CID_TrueType) { |
685 | 165 | if (pfres->u.cidfont.v != NULL) { |
686 | 94 | code = pdf_resize_array(mem, (void **)&pfres->u.cidfont.v, |
687 | 94 | sizeof(*pfres->u.cidfont.v), pfres->count * 2, chars_count * 2); |
688 | 94 | if (code < 0) |
689 | 0 | return code; |
690 | 94 | } |
691 | 165 | if (pfres->u.cidfont.Widths2 != NULL) { |
692 | 94 | code = pdf_resize_array(mem, (void **)&pfres->u.cidfont.Widths2, |
693 | 94 | sizeof(*pfres->u.cidfont.Widths2), pfres->count, chars_count); |
694 | 94 | if (code < 0) |
695 | 0 | return code; |
696 | 94 | } |
697 | 165 | } |
698 | 165 | if (pfres->FontType == ft_CID_TrueType) { |
699 | 118 | if (pfres->u.cidfont.CIDToGIDMap != NULL) { |
700 | 118 | code = pdf_resize_array(mem, (void **)&pfres->u.cidfont.CIDToGIDMap, |
701 | 118 | sizeof(*pfres->u.cidfont.CIDToGIDMap), pfres->count, chars_count); |
702 | 118 | if (code < 0) |
703 | 0 | return code; |
704 | 118 | pfres->u.cidfont.CIDToGIDMapLength = chars_count; |
705 | 118 | } |
706 | 118 | } |
707 | 165 | if (pfres->FontType == ft_CID_encrypted || pfres->FontType == ft_CID_TrueType) { |
708 | 165 | if (pfres->u.cidfont.used2 != NULL) { |
709 | 165 | code = pdf_resize_array(mem, (void **)&pfres->u.cidfont.used2, |
710 | 165 | sizeof(*pfres->u.cidfont.used2), |
711 | 165 | (pfres->count + 7) / 8, (chars_count + 7) / 8); |
712 | 165 | if (code < 0) |
713 | 0 | return code; |
714 | 165 | } |
715 | 165 | } |
716 | 165 | pfres->count = chars_count; |
717 | 165 | return 0; |
718 | 165 | } |
719 | | |
720 | | /* Get the object ID of a font resource. */ |
721 | | int64_t |
722 | | pdf_font_id(const pdf_font_resource_t *pdfont) |
723 | 28.6k | { |
724 | 28.6k | return pdf_resource_id((const pdf_resource_t *)pdfont); |
725 | 28.6k | } |
726 | | |
727 | | /* |
728 | | * Return the (copied, subset) font associated with a font resource. |
729 | | * If this font resource doesn't have one (Type 0 or Type 3), return 0. |
730 | | */ |
731 | | gs_font_base * |
732 | | pdf_font_resource_font(const pdf_font_resource_t *pdfont, bool complete) |
733 | 49.8M | { |
734 | 49.8M | if (pdfont->base_font != NULL) |
735 | 6.63M | return pdf_base_font_font(pdfont->base_font, complete); |
736 | 43.1M | if (pdfont->FontDescriptor == 0) |
737 | 1.88M | return 0; |
738 | 41.3M | return pdf_font_descriptor_font(pdfont->FontDescriptor, complete); |
739 | 43.1M | } |
740 | | |
741 | | /* |
742 | | * Determine the embedding status of a font. If the font is in the base |
743 | | * 14, store its index (0..13) in *pindex and its similarity to the base |
744 | | * font (as determined by the font's same_font procedure) in *psame. |
745 | | */ |
746 | | static bool |
747 | | font_is_symbolic(const gs_font *font) |
748 | 0 | { |
749 | 0 | if (font->FontType == ft_composite || font->FontType == ft_CID_encrypted || |
750 | 0 | font->FontType == ft_CID_user_defined || font->FontType == ft_CID_TrueType || |
751 | 0 | font->FontType == ft_CID_bitmap) |
752 | 0 | return false; /* arbitrary */ |
753 | 0 | switch (((const gs_font_base *)font)->nearest_encoding_index) { |
754 | 0 | case ENCODING_INDEX_STANDARD: |
755 | 0 | case ENCODING_INDEX_ISOLATIN1: |
756 | 0 | case ENCODING_INDEX_WINANSI: |
757 | 0 | case ENCODING_INDEX_MACROMAN: |
758 | 0 | return false; |
759 | 0 | default: |
760 | 0 | return true; |
761 | 0 | } |
762 | 0 | } |
763 | | static bool |
764 | | embed_list_includes(const gs_param_string_array *psa, const byte *chars, |
765 | | uint size) |
766 | 47.9k | { |
767 | 47.9k | uint i; |
768 | | |
769 | 184k | for (i = 0; i < psa->size; ++i) |
770 | 136k | if (!bytes_compare(psa->data[i].data, psa->data[i].size, chars, size)) |
771 | 503 | return true; |
772 | 47.4k | return false; |
773 | 47.9k | } |
774 | | static bool |
775 | | embed_as_standard(gx_device_pdf *pdev, gs_font *font, int index, |
776 | | pdf_char_glyph_pair_t *pairs, int num_glyphs) |
777 | 3.43k | { |
778 | 3.43k | if (font->is_resource) { |
779 | 3.29k | return true; |
780 | 3.29k | } |
781 | 146 | if (find_std_appearance(pdev, (gs_font_base *)font, -1, |
782 | 146 | pairs, num_glyphs) == index) |
783 | 0 | return true; |
784 | 146 | if (!scan_for_standard_fonts(pdev, font->dir)) |
785 | 146 | return false; |
786 | 0 | return (find_std_appearance(pdev, (gs_font_base *)font, -1, |
787 | 0 | pairs, num_glyphs) == index); |
788 | 146 | } |
789 | | static bool |
790 | | has_extension_glyphs(gs_font *pfont) |
791 | 2.82k | { |
792 | 2.82k | psf_glyph_enum_t genum; |
793 | 2.82k | gs_glyph glyph; |
794 | 2.82k | gs_const_string str; |
795 | 2.82k | int code, j = 0, l; |
796 | 2.82k | const int sl = strlen(gx_extendeg_glyph_name_separator); |
797 | | |
798 | 2.82k | psf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, NULL, 0, GLYPH_SPACE_NAME); |
799 | 2.20M | for (glyph = GS_NO_GLYPH; (psf_enumerate_glyphs_next(&genum, &glyph)) != 1; ) { |
800 | 2.20M | code = pfont->procs.glyph_name(pfont, glyph, &str); |
801 | 2.20M | if (code < 0) |
802 | 0 | return code; |
803 | 2.20M | l = str.size - sl; |
804 | 10.0M | for (j = 0; j < l; j ++) |
805 | 7.85M | if (!memcmp(gx_extendeg_glyph_name_separator, str.data + j, sl)) |
806 | 0 | return true; |
807 | 2.20M | } |
808 | 2.82k | psf_enumerate_glyphs_reset(&genum); |
809 | 2.82k | return false; |
810 | 2.82k | } |
811 | | |
812 | | pdf_font_embed_t |
813 | | pdf_font_embed_status(gx_device_pdf *pdev, gs_font *font, int *pindex, |
814 | | pdf_char_glyph_pair_t *pairs, int num_glyphs, font_type *orig_type) |
815 | 48.1k | { |
816 | 48.1k | const gs_font_name *fn = &font->font_name; |
817 | 48.1k | const byte *chars = fn->chars; |
818 | 48.1k | uint size = fn->size; |
819 | 48.1k | int index = pdf_find_standard_font_name(chars, size); |
820 | 48.1k | bool embed_as_standard_called = false; |
821 | 48.1k | bool do_embed_as_standard = false; /* Quiet compiler. */ |
822 | 48.1k | int code; |
823 | 48.1k | gs_font_info_t info; |
824 | | |
825 | 48.1k | memset(&info, 0x00, sizeof(gs_font_info_t)); |
826 | 48.1k | code = font->procs.font_info(font, NULL, FONT_INFO_EMBEDDING_RIGHTS | FONT_INFO_EMBEDDED, &info); |
827 | 48.1k | if (code == 0 && (info.members & FONT_INFO_EMBEDDING_RIGHTS)) { |
828 | 19.6k | if (((info.EmbeddingRights == 0x0002) || (info.EmbeddingRights & 0x0200)) |
829 | 19.6k | && !IsInWhiteList ((const char *)chars, size)) { |
830 | | /* See the OpenType specification, "The 'OS/2' and Windows Metrics Table" for details |
831 | | of the fstype parameter. This is a bitfield, currently we forbid embedding of fonts |
832 | | with these bits set: |
833 | | bit 1 0x0002 Fonts that have only this bit set must not be modified, embedded or |
834 | | exchanged in any manner. |
835 | | bit 9 0x0200 Bitmap embedding only. |
836 | | |
837 | | Note for Restricted License embedding (bit 1), this must be the only level of embedding |
838 | | selected (see the OpenType spec). |
839 | | */ |
840 | 136 | char name[gs_font_name_max + 1]; |
841 | 136 | int len; |
842 | | |
843 | 136 | len = min(gs_font_name_max, font->font_name.size); |
844 | 136 | memcpy(name, font->font_name.chars, len); |
845 | 136 | name[len] = 0; |
846 | 136 | emprintf1(pdev->pdf_memory, |
847 | 136 | "\nWarning: Font %s cannot be embedded because of licensing restrictions\n", |
848 | 136 | name); |
849 | 136 | return FONT_EMBED_NO; |
850 | 136 | } |
851 | 19.6k | } |
852 | | /* |
853 | | * The behavior of Acrobat Distiller changed between 3.0 (PDF 1.2), |
854 | | * which will never embed the base 14 fonts, and 4.0 (PDF 1.3), which |
855 | | * doesn't treat them any differently from any other fonts. However, |
856 | | * if any of the base 14 fonts is not embedded, it still requires |
857 | | * special treatment. |
858 | | */ |
859 | 47.9k | if (pindex) |
860 | 47.9k | *pindex = index; |
861 | 47.9k | if (pdev->PDFX != 0 || pdev->PDFA != 0) |
862 | 0 | return FONT_EMBED_YES; |
863 | 47.9k | if (pdev->CompatibilityLevel < 1.3) { |
864 | 37.9k | if (index >= 0 && |
865 | 37.9k | (embed_as_standard_called = true, |
866 | 2.93k | do_embed_as_standard = embed_as_standard(pdev, font, index, pairs, num_glyphs))) { |
867 | 2.82k | if (pdev->ForOPDFRead && has_extension_glyphs(font)) |
868 | 0 | return FONT_EMBED_YES; |
869 | | |
870 | 2.82k | if (pdev->ForOPDFRead && embed_list_includes(&pdev->params.AlwaysEmbed, chars, size)) |
871 | 0 | return FONT_EMBED_YES; |
872 | | |
873 | 2.82k | return FONT_EMBED_STANDARD; |
874 | 2.82k | } |
875 | 37.9k | } |
876 | | /* Check the Embed lists. */ |
877 | 45.1k | if (!embed_list_includes(&pdev->params.NeverEmbed, chars, size) || |
878 | 45.1k | (index >= 0 && |
879 | 503 | !(embed_as_standard_called ? do_embed_as_standard : |
880 | 503 | (embed_as_standard_called = true, |
881 | 503 | (do_embed_as_standard = embed_as_standard(pdev, font, index, pairs, num_glyphs))))) |
882 | | /* Ignore NeverEmbed for a non-standard font with a standard name */ |
883 | 45.1k | ) |
884 | 44.7k | { |
885 | | /* We always mebed fonts that were embedded in the input, so if we embed substitutes as well then we are embedding everything |
886 | | * which isn't explicitly *not* embedded, via the NeverEmbed test above |
887 | | */ |
888 | 44.7k | if (pdev->EmbedSubstituteFonts) |
889 | 44.7k | return FONT_EMBED_YES; |
890 | | /* We aren't embedding subsitutes, check the AlwaysEmbed list, which overrides that */ |
891 | 0 | if (embed_list_includes(&pdev->params.AlwaysEmbed, chars, size)) |
892 | 0 | return FONT_EMBED_YES; |
893 | 0 | if (pdev->params.EmbedAllFonts) { |
894 | 0 | if (!(info.members & FONT_INFO_EMBEDDED) || info.FontEmbedded) |
895 | 0 | return FONT_EMBED_YES; |
896 | 0 | } else { |
897 | | /* Always embed symbolic fonts (we have to ) */ |
898 | 0 | if (font_is_symbolic(font)) |
899 | 0 | return FONT_EMBED_YES; |
900 | 0 | } |
901 | 0 | } |
902 | 464 | if (index >= 0 && |
903 | 464 | (embed_as_standard_called ? do_embed_as_standard : |
904 | 464 | embed_as_standard(pdev, font, index, pairs, num_glyphs))) |
905 | 464 | return FONT_EMBED_STANDARD; |
906 | | |
907 | 0 | if (info.members & FONT_INFO_EMBEDDED) |
908 | 0 | *orig_type = info.orig_FontType; |
909 | 0 | return FONT_EMBED_NO; |
910 | 464 | } |
911 | | |
912 | | /* |
913 | | * Compute the BaseFont of a font according to the algorithm described |
914 | | * in gdevpdtf.h. |
915 | | */ |
916 | | int |
917 | | pdf_compute_BaseFont(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, bool finish) |
918 | 54.9k | { |
919 | 54.9k | pdf_font_resource_t *pdsubf = pdfont; |
920 | 54.9k | gs_string fname; |
921 | 54.9k | uint size; |
922 | 54.9k | byte *data; |
923 | | |
924 | 54.9k | if (pdfont->FontType == ft_composite) { |
925 | 645 | int code; |
926 | | |
927 | 645 | pdsubf = pdfont->u.type0.DescendantFont; |
928 | 645 | code = pdf_compute_BaseFont(pdev, pdsubf, finish); |
929 | 645 | if (code < 0) |
930 | 0 | return code; |
931 | 645 | fname = pdsubf->BaseFont; |
932 | 645 | } |
933 | 54.2k | else if (pdfont->FontDescriptor == 0) { |
934 | | /* Type 3 font, or has its BaseFont computed in some other way. */ |
935 | 6.51k | return 0; |
936 | 6.51k | } else |
937 | 47.7k | fname = *pdf_font_descriptor_base_name(pdsubf->FontDescriptor); |
938 | 48.3k | size = fname.size; |
939 | 48.3k | data = gs_alloc_string(pdev->pdf_memory, size, |
940 | 48.3k | "pdf_compute_BaseFont"); |
941 | 48.3k | if (data == 0) |
942 | 0 | return_error(gs_error_VMerror); |
943 | 48.3k | memcpy(data, fname.data, size); |
944 | 48.3k | switch (pdfont->FontType) { |
945 | 645 | case ft_composite: |
946 | | /* Previously we copied the name of the original CMap onto the font name |
947 | | * but this doesn't make any sense. |
948 | | */ |
949 | 645 | break; |
950 | 38.3k | case ft_encrypted: |
951 | 38.7k | case ft_encrypted2: |
952 | 38.7k | if (pdfont->u.simple.s.type1.is_MM_instance && |
953 | 38.7k | !pdf_font_descriptor_embedding(pdfont->FontDescriptor) |
954 | 38.7k | ) { |
955 | | /* Replace spaces by underscores in the base name. */ |
956 | 0 | uint i; |
957 | |
|
958 | 0 | for (i = 0; i < size; ++i) |
959 | 0 | if (data[i] == ' ') |
960 | 0 | data[i] = '_'; |
961 | 0 | } |
962 | 38.7k | break; |
963 | 7.72k | case ft_TrueType: |
964 | 8.91k | case ft_CID_TrueType: { |
965 | | /* Remove spaces from the base name. */ |
966 | 8.91k | uint i, j; |
967 | | |
968 | 95.0k | for (i = j = 0; i < size; ++i) |
969 | 86.1k | if (data[i] != ' ') |
970 | 85.7k | data[j++] = data[i]; |
971 | 8.91k | data = gs_resize_string(pdev->pdf_memory, data, i, j, |
972 | 8.91k | "pdf_compute_BaseFont"); |
973 | 8.91k | size = j; |
974 | 8.91k | break; |
975 | 7.72k | } |
976 | 96 | default: |
977 | 96 | break; |
978 | 48.3k | } |
979 | 48.3k | if (pdfont->BaseFont.size) |
980 | 22.1k | gs_free_string(pdev->pdf_memory, pdfont->BaseFont.data, pdfont->BaseFont.size, "Replacing BaseFont string"); |
981 | 48.3k | pdfont->BaseFont.data = fname.data = data; |
982 | 48.3k | pdfont->BaseFont.size = fname.size = size; |
983 | | /* Compute names for subset fonts. */ |
984 | 48.3k | if (finish && pdfont->FontDescriptor != NULL && |
985 | 48.3k | pdf_font_descriptor_is_subset(pdfont->FontDescriptor) && |
986 | 48.3k | !pdf_has_subset_prefix(fname.data, fname.size) && |
987 | 48.3k | pdf_font_descriptor_embedding(pdfont->FontDescriptor) |
988 | 48.3k | ) { |
989 | 21.5k | int code; |
990 | 21.5k | gs_font_base *pbfont = pdf_font_resource_font(pdfont, false); |
991 | | |
992 | 21.5k | if (pdfont->FontDescriptor) |
993 | 21.5k | code = pdf_add_subset_prefix(pdev, &fname, pdfont->used, pdfont->count, pdf_fontfile_hash(pdfont->FontDescriptor)); |
994 | 0 | else |
995 | 0 | code = pdf_add_subset_prefix(pdev, &fname, pdfont->used, pdfont->count, 0); |
996 | | |
997 | 21.5k | if (code < 0) |
998 | 0 | return code; |
999 | 21.5k | pdfont->BaseFont = fname; |
1000 | | |
1001 | | /* Don't write a UID for subset fonts. */ |
1002 | 21.5k | if (uid_is_XUID(&pbfont->UID)) { |
1003 | 5.02k | uid_free(&pbfont->UID, pbfont->memory, "gs_font_finalize"); |
1004 | 5.02k | } |
1005 | 21.5k | uid_set_invalid(&pbfont->UID); |
1006 | 21.5k | } |
1007 | 48.3k | if (pdfont->FontType != ft_composite && pdsubf->FontDescriptor) |
1008 | 47.7k | *pdf_font_descriptor_name(pdsubf->FontDescriptor) = fname; |
1009 | 48.3k | return 0; |
1010 | 48.3k | } |
1011 | | |
1012 | | /* ------ Type 0 ------ */ |
1013 | | |
1014 | | /* Allocate a Type 0 font resource. */ |
1015 | | int |
1016 | | pdf_font_type0_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, |
1017 | | gs_id rid, pdf_font_resource_t *DescendantFont, |
1018 | | const gs_const_string *CMapName) |
1019 | 325 | { |
1020 | 325 | int code = font_resource_alloc(pdev, ppfres, resourceFont, rid, |
1021 | 325 | ft_composite, 0, pdf_write_contents_type0); |
1022 | | |
1023 | 325 | if (code >= 0) { |
1024 | 325 | byte *chars = NULL; |
1025 | | |
1026 | 325 | (*ppfres)->u.type0.DescendantFont = DescendantFont; |
1027 | | |
1028 | 325 | chars = gs_alloc_bytes(pdev->pdf_memory->non_gc_memory, CMapName->size, "pdf_font_resource_t(CMapName)"); |
1029 | 325 | if (chars == 0) |
1030 | 0 | return_error(gs_error_VMerror); |
1031 | 325 | memcpy(chars, CMapName->data, CMapName->size); |
1032 | 325 | (*ppfres)->u.type0.CMapName_data = chars; |
1033 | 325 | (*ppfres)->u.type0.CMapName_size = CMapName->size; |
1034 | | |
1035 | 325 | (*ppfres)->u.type0.font_index = 0; |
1036 | 325 | code = pdf_compute_BaseFont(pdev, *ppfres, false); |
1037 | 325 | } |
1038 | 325 | return code; |
1039 | 325 | } |
1040 | | |
1041 | | /* ------ Type 3 ------ */ |
1042 | | |
1043 | | /* Allocate a Type 3 font resource for sinthesyzed bitmap fonts. */ |
1044 | | int |
1045 | | pdf_font_type3_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, |
1046 | | pdf_font_write_contents_proc_t write_contents) |
1047 | 2.38k | { |
1048 | 2.38k | return font_resource_simple_alloc(pdev, ppfres, gs_no_id, ft_user_defined, |
1049 | 2.38k | 256, write_contents); |
1050 | 2.38k | } |
1051 | | |
1052 | | /* ------ Standard (base 14) Type 1 or TrueType ------ */ |
1053 | | |
1054 | | /* Allocate a standard (base 14) font resource. */ |
1055 | | int |
1056 | | pdf_font_std_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, |
1057 | | bool is_original, gs_id rid, gs_font_base *pfont, int index) |
1058 | 3.29k | { |
1059 | 3.29k | pdf_font_resource_t *pdfont; |
1060 | 3.29k | int code = font_resource_encoded_alloc(pdev, &pdfont, rid, pfont->FontType, |
1061 | 3.29k | pdf_write_contents_std); |
1062 | 3.29k | const pdf_standard_font_info_t *psfi = &standard_font_info[index]; |
1063 | 3.29k | pdf_standard_font_t *psf = &pdf_standard_fonts(pdev)[index]; |
1064 | 3.29k | gs_matrix *orig_matrix = (is_original ? &pfont->FontMatrix : &psf->orig_matrix); |
1065 | | |
1066 | 3.29k | if (code < 0 || |
1067 | 3.29k | (code = pdf_base_font_alloc(pdev, &pdfont->base_font, pfont, orig_matrix, true)) < 0 |
1068 | 3.29k | ) |
1069 | 0 | return code; |
1070 | 3.29k | pdfont->BaseFont.data = (byte *)psfi->fname; /* break const */ |
1071 | 3.29k | pdfont->BaseFont.size = strlen(psfi->fname); |
1072 | 3.29k | pdfont->mark_glyph = pfont->dir->ccache.mark_glyph; |
1073 | 3.29k | set_is_MM_instance(pdfont, pfont); |
1074 | 3.29k | if (is_original) { |
1075 | 3.27k | psf->pdfont = pdfont; |
1076 | 3.27k | psf->orig_matrix = pfont->FontMatrix; |
1077 | 3.27k | } |
1078 | 3.29k | *ppfres = pdfont; |
1079 | 3.29k | return 0; |
1080 | 3.29k | } |
1081 | | |
1082 | | /* ------ Other Type 1 or TrueType ------ */ |
1083 | | |
1084 | | /* Allocate a Type 1 or TrueType font resource. */ |
1085 | | int |
1086 | | pdf_font_simple_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, |
1087 | | gs_id rid, pdf_font_descriptor_t *pfd) |
1088 | 25.5k | { |
1089 | 25.5k | pdf_font_resource_t *pdfont; |
1090 | 25.5k | int code; |
1091 | | |
1092 | 25.5k | code = font_resource_encoded_alloc(pdev, &pdfont, rid, |
1093 | 25.5k | pdf_font_descriptor_FontType(pfd), |
1094 | 25.5k | pdf_write_contents_simple); |
1095 | | |
1096 | 25.5k | if (code < 0) |
1097 | 0 | return(gs_note_error(code)); |
1098 | 25.5k | pdfont->FontDescriptor = pfd; |
1099 | 25.5k | set_is_MM_instance(pdfont, pdf_font_descriptor_font(pfd, false)); |
1100 | 25.5k | *ppfres = pdfont; |
1101 | 25.5k | return pdf_compute_BaseFont(pdev, pdfont, false); |
1102 | 25.5k | } |
1103 | | |
1104 | | /* ------ CID-keyed ------ */ |
1105 | | |
1106 | | /* Allocate a CIDFont resource. */ |
1107 | | int |
1108 | | pdf_font_cidfont_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, |
1109 | | gs_id rid, pdf_font_descriptor_t *pfd) |
1110 | 324 | { |
1111 | 324 | font_type FontType = pdf_font_descriptor_FontType(pfd); |
1112 | 324 | gs_font_base *font = pdf_font_descriptor_font(pfd, false); |
1113 | 324 | int chars_count; |
1114 | 324 | int code; |
1115 | 324 | pdf_font_write_contents_proc_t write_contents; |
1116 | 324 | const gs_cid_system_info_t *pcidsi; |
1117 | 324 | ushort *map = 0; |
1118 | 324 | pdf_font_resource_t *pdfont; |
1119 | | |
1120 | 324 | switch (FontType) { |
1121 | 26 | case ft_CID_encrypted: |
1122 | 26 | chars_count = ((const gs_font_cid0 *)font)->cidata.common.CIDCount; |
1123 | 26 | pcidsi = &((const gs_font_cid0 *)font)->cidata.common.CIDSystemInfo; |
1124 | 26 | write_contents = pdf_write_contents_cid0; |
1125 | 26 | break; |
1126 | 298 | case ft_CID_TrueType: |
1127 | 298 | chars_count = ((const gs_font_cid2 *)font)->cidata.common.CIDCount; |
1128 | 298 | pcidsi = &((const gs_font_cid2 *)font)->cidata.common.CIDSystemInfo; |
1129 | 298 | map = (void *)gs_alloc_byte_array(pdev->pdf_memory, chars_count, |
1130 | 298 | sizeof(*map), "CIDToGIDMap"); |
1131 | 298 | if (map == 0) |
1132 | 0 | return_error(gs_error_VMerror); |
1133 | 298 | memset(map, 0, chars_count * sizeof(*map)); |
1134 | 298 | write_contents = pdf_write_contents_cid2; |
1135 | 298 | break; |
1136 | 0 | default: |
1137 | 0 | return_error(gs_error_rangecheck); |
1138 | 324 | } |
1139 | 324 | code = font_resource_alloc(pdev, &pdfont, resourceCIDFont, rid, FontType, |
1140 | 324 | chars_count, write_contents); |
1141 | 324 | if (code < 0) |
1142 | 0 | return code; |
1143 | 324 | pdfont->FontDescriptor = pfd; |
1144 | 324 | pdfont->u.cidfont.CIDToGIDMap = map; |
1145 | 324 | pdfont->u.cidfont.CIDToGIDMapLength = chars_count; |
1146 | | /* fixme : Likely pdfont->u.cidfont.CIDToGIDMap duplicates |
1147 | | pdfont->FontDescriptor->base_font->copied->client_data->CIDMap. |
1148 | | Only difference is 0xFFFF designates unmapped CIDs. |
1149 | | */ |
1150 | 324 | pdfont->u.cidfont.Widths2 = NULL; |
1151 | 324 | pdfont->u.cidfont.v = NULL; |
1152 | 324 | pdfont->u.cidfont.parent = NULL; |
1153 | | /* Don' know whether the font will use WMode 1, |
1154 | | so reserve it now. */ |
1155 | 324 | pdfont->u.cidfont.used2 = gs_alloc_bytes(pdev->pdf_memory, |
1156 | 324 | (chars_count + 7) / 8, "pdf_font_cidfont_alloc"); |
1157 | 324 | if (pdfont->u.cidfont.used2 == NULL) |
1158 | 0 | return_error(gs_error_VMerror); |
1159 | 324 | memset(pdfont->u.cidfont.used2, 0, (chars_count + 7) / 8); |
1160 | | /* |
1161 | | * Write the CIDSystemInfo now, so we don't try to access it after |
1162 | | * the font may no longer be available. |
1163 | | */ |
1164 | 324 | code = pdf_write_cid_systemInfo_separate(pdev, pcidsi, &pdfont->u.cidfont.CIDSystemInfo_id); |
1165 | 324 | if (code < 0) |
1166 | 0 | return code; |
1167 | 324 | *ppfres = pdfont; |
1168 | 324 | return pdf_compute_BaseFont(pdev, pdfont, false); |
1169 | 324 | } |
1170 | | |
1171 | | int |
1172 | | pdf_obtain_cidfont_widths_arrays(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, |
1173 | | int wmode, double **w, double **w0, double **v) |
1174 | 87.1k | { |
1175 | 87.1k | gs_memory_t *mem = pdev->pdf_memory; |
1176 | 87.1k | double *ww, *vv = 0, *ww0 = 0; |
1177 | 87.1k | int chars_count = pdfont->count; |
1178 | | |
1179 | 87.1k | *w0 = (wmode ? pdfont->Widths : NULL); |
1180 | 87.1k | *v = (wmode ? pdfont->u.cidfont.v : NULL); |
1181 | 87.1k | *w = (wmode ? pdfont->u.cidfont.Widths2 : pdfont->Widths); |
1182 | 87.1k | if (*w == NULL) { |
1183 | 324 | ww = (double *)gs_alloc_byte_array(mem, chars_count, sizeof(*ww), |
1184 | 324 | "pdf_obtain_cidfont_widths_arrays"); |
1185 | 324 | if (wmode) { |
1186 | 10 | vv = (double *)gs_alloc_byte_array(mem, chars_count, sizeof(*vv) * 2, |
1187 | 10 | "pdf_obtain_cidfont_widths_arrays"); |
1188 | 10 | if (pdfont->Widths == 0) { |
1189 | 10 | ww0 = (double *)gs_alloc_byte_array(mem, chars_count, sizeof(*ww0), |
1190 | 10 | "pdf_obtain_cidfont_widths_arrays"); |
1191 | 10 | pdfont->Widths = *w0 = ww0; |
1192 | 10 | if (ww0 != 0) |
1193 | 10 | memset(ww0, 0, chars_count * sizeof(*ww)); |
1194 | 10 | } else |
1195 | 0 | *w0 = ww0 = pdfont->Widths; |
1196 | 10 | } |
1197 | 324 | if (ww == 0 || (wmode && vv == 0) || (wmode && ww0 == 0)) { |
1198 | 0 | gs_free_object(mem, ww, "pdf_obtain_cidfont_widths_arrays"); |
1199 | 0 | gs_free_object(mem, vv, "pdf_obtain_cidfont_widths_arrays"); |
1200 | 0 | gs_free_object(mem, ww0, "pdf_obtain_cidfont_widths_arrays"); |
1201 | 0 | return_error(gs_error_VMerror); |
1202 | 0 | } |
1203 | 324 | if (wmode) |
1204 | 10 | memset(vv, 0, chars_count * 2 * sizeof(*vv)); |
1205 | 324 | memset(ww, 0, chars_count * sizeof(*ww)); |
1206 | 324 | if (wmode) { |
1207 | 10 | pdfont->u.cidfont.Widths2 = *w = ww; |
1208 | 10 | pdfont->u.cidfont.v = *v = vv; |
1209 | 314 | } else { |
1210 | 314 | pdfont->Widths = *w = ww; |
1211 | 314 | *v = NULL; |
1212 | 314 | } |
1213 | 324 | } |
1214 | 87.1k | return 0; |
1215 | 87.1k | } |
1216 | | |
1217 | | /* |
1218 | | * Convert True Type fonts into CID fonts for PDF/A. |
1219 | | */ |
1220 | | int |
1221 | | pdf_convert_truetype_font(gx_device_pdf *pdev, pdf_resource_t *pres) |
1222 | 32.5k | { |
1223 | 32.5k | if (pdev->PDFA == 0) |
1224 | 32.5k | return 0; |
1225 | 0 | else { |
1226 | 0 | pdf_font_resource_t *pdfont = (pdf_font_resource_t *)pres; |
1227 | |
|
1228 | 0 | if (pdfont->FontType != ft_TrueType) |
1229 | 0 | return 0; |
1230 | 0 | else if (pdf_resource_id(pres) == -1) |
1231 | 0 | return 0; /* An unused font. */ |
1232 | 0 | else { |
1233 | 0 | int code = pdf_different_encoding_index(pdfont, 0); |
1234 | |
|
1235 | 0 | if (code < 0) |
1236 | 0 | return code; |
1237 | 0 | if (code == 256 && pdfont->u.simple.BaseEncoding != ENCODING_INDEX_UNKNOWN) |
1238 | 0 | return 0; |
1239 | 0 | { /* The encoding have a difference - do convert. */ |
1240 | 0 | pdf_font_resource_t *pdfont0; |
1241 | 0 | gs_const_string CMapName = {(const byte *)"OneByteIdentityH", 16}; |
1242 | |
|
1243 | 0 | code = pdf_convert_truetype_font_descriptor(pdev, pdfont); |
1244 | 0 | if (code < 0) |
1245 | 0 | return code; |
1246 | 0 | code = pdf_font_type0_alloc(pdev, &pdfont0, pres->rid + 1, pdfont, &CMapName); |
1247 | 0 | if (code < 0) |
1248 | 0 | return code; |
1249 | | /* Pass the font object ID to the type 0 font resource. */ |
1250 | 0 | pdf_reserve_object_id(pdev, (pdf_resource_t *)pdfont0, pdf_resource_id(pres)); |
1251 | 0 | pdf_reserve_object_id(pdev, (pdf_resource_t *)pdfont, gs_no_id); |
1252 | | /* Set Encoding_name because we won't call attach_cmap_resource for it : */ |
1253 | 0 | code = pdf_write_OneByteIdentityH(pdev); |
1254 | 0 | if (code < 0) |
1255 | 0 | return 0; |
1256 | 0 | pdfont->u.cidfont.CIDSystemInfo_id = pdev->IdentityCIDSystemInfo_id; |
1257 | 0 | gs_snprintf(pdfont0->u.type0.Encoding_name, sizeof(pdfont0->u.type0.Encoding_name), |
1258 | 0 | "%"PRId64" 0 R", pdf_resource_id(pdev->OneByteIdentityH)); |
1259 | | /* Move ToUnicode : */ |
1260 | 0 | pdfont0->res_ToUnicode = pdfont->res_ToUnicode; pdfont->res_ToUnicode = 0; |
1261 | 0 | pdfont0->cmap_ToUnicode = pdfont->cmap_ToUnicode; pdfont->cmap_ToUnicode = 0; |
1262 | | /* Change the font type to CID font : */ |
1263 | 0 | pdfont->FontType = ft_CID_TrueType; |
1264 | 0 | pdfont->write_contents = pdf_write_contents_cid2; |
1265 | 0 | return 0; |
1266 | 0 | } |
1267 | 0 | } |
1268 | 0 | } |
1269 | 32.5k | } |
1270 | | |
1271 | | /* ---------------- CMap resources ---------------- */ |
1272 | | |
1273 | | /* |
1274 | | * Allocate a CMap resource. |
1275 | | */ |
1276 | | int |
1277 | | pdf_cmap_alloc(gx_device_pdf *pdev, const gs_cmap_t *pcmap, |
1278 | | pdf_resource_t **ppres, int font_index_only) |
1279 | 2.65k | { |
1280 | 2.65k | return pdf_write_cmap(pdev, pcmap, ppres, font_index_only); |
1281 | 2.65k | } |