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