/src/ghostpdl/devices/vector/gdevpdtb.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2024 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 | | /* BaseFont implementation for pdfwrite */ |
18 | | #include "memory_.h" |
19 | | #include "ctype_.h" |
20 | | #include "gx.h" |
21 | | #include "gserrors.h" |
22 | | #include "gsutil.h" /* for bytes_compare */ |
23 | | #include "gxfcid.h" |
24 | | #include "gxfcopy.h" |
25 | | #include "gxfont.h" /* for gxfont42.h */ |
26 | | #include "gxfont42.h" |
27 | | #include "gdevpsf.h" |
28 | | #include "gdevpdfx.h" |
29 | | #include "gdevpdfo.h" |
30 | | #include "gdevpdtb.h" |
31 | | #include "gdevpdtf.h" |
32 | | #include "gdevpdtd.h" |
33 | | #include "smd5.h" |
34 | | #include "gxfcache.h" /* for gs_purge_font_from_char_caches_completely */ |
35 | | /* |
36 | | * Adobe's Distiller Parameters documentation for Acrobat Distiller 5 |
37 | | * says that all fonts other than Type 1 are always subsetted; the |
38 | | * documentation for Distiller 4 says that fonts other than Type 1 and |
39 | | * TrueType are subsetted. We do the latter, except that we always |
40 | | * subset large TrueType fonts. |
41 | | */ |
42 | 23.2k | #define MAX_NO_SUBSET_GLYPHS 4096 /* arbitrary */ |
43 | | |
44 | | /* ---------------- Private ---------------- */ |
45 | | |
46 | | private_st_pdf_base_font(); |
47 | | gs_private_st_basic(st_pdf_base_font, pdf_base_font_t, "pdf_base_font_t",\ |
48 | | pdf_base_font_ptrs, pdf_base_font_data); |
49 | | |
50 | | typedef struct pdf_base14_font_info_s { |
51 | | const char *urwname; |
52 | | const char *stdname; |
53 | | } pdf_base14_font_info_t; |
54 | | |
55 | | static const pdf_base14_font_info_t base14_font_info[] = { |
56 | | /* Standard mapping of URW fonts */ |
57 | | {"NimbusMonL-Regu", "Courier" }, |
58 | | {"NimbusMonL-Bold", "Courier-Bold" }, |
59 | | {"NimbusMonL-ReguObli", "Courier-Oblique" }, |
60 | | {"NimbusMonL-BoldObli", "Courier-BoldOblique" }, |
61 | | {"NimbusSanL-Regu", "Helvetica" }, |
62 | | {"NimbusSanL-Bold", "Helvetica-Bold" }, |
63 | | {"NimbusSanL-ReguItal", "Helvetica-Oblique" }, |
64 | | {"NimbusSanL-BoldItal", "Helvetica-BoldOblique"}, |
65 | | {"StandardSymL", "Symbol" }, |
66 | | {"NimbusRomNo9L-Regu", "Times-Roman" }, |
67 | | {"NimbusRomNo9L-Medi", "Times-Bold" }, |
68 | | {"NimbusRomNo9L-ReguItal","Times-Italic" }, |
69 | | {"NimbusRomNo9L-MediItal","Times-BoldItalic" }, |
70 | | {"Dingbats", "ZapfDingbats" }, |
71 | | /* A few other mappings of URW fonts */ |
72 | | {"NimbusMono-Reg", "Courier" }, |
73 | | {"NimbusMono-Bol", "Courier-Bold" }, |
74 | | {"NimbusMono-Ita", "Courier-Oblique" }, |
75 | | {"NimbusMono-BolIta", "Courier-BoldOblique" }, |
76 | | {"NimbusSan-Reg", "Helvetica" }, |
77 | | {"NimbusSan-Bol", "Helvetica-Bold" }, |
78 | | {"NimbusSan-Ita", "Helvetica-Oblique" }, |
79 | | {"NimbusSan-BolIta", "Helvetica-BoldOblique"}, |
80 | | {"A030-Reg", "Helvetica" }, |
81 | | {"A030-Bol", "Helvetica-Bold" }, |
82 | | {"A030-Ita", "Helvetica-Oblique" }, |
83 | | {"A030-BolIta", "Helvetica-BoldOblique"}, |
84 | | {"NimbusSanNo2-Reg", "Helvetica" }, |
85 | | {"NimbusSanNo2-Bol", "Helvetica-Bold" }, |
86 | | {"NimbusSanNo2-Ita", "Helvetica-Oblique" }, |
87 | | {"NimbusSanNo2-BolIta", "Helvetica-BoldOblique"}, |
88 | | {"NimbusRomanNo4-Lig", "Times-Roman" }, |
89 | | {"NimbusRomanNo4-Bol", "Times-Bold" }, |
90 | | {"NimbusRomanNo4-LigIta", "Times-Italic" }, |
91 | | {"NimbusRomanNo4-BolIta", "Times-BoldItalic" }, |
92 | | {"NimbusRomanNo9-Reg", "Times-Roman" }, |
93 | | {"NimbusRomanNo9-Med", "Times-Bold" }, |
94 | | {"NimbusRomanNo9-Ita", "Times-Italic" }, |
95 | | {"NimbusRomanNo9-MedIta", "Times-BoldItalic" }, |
96 | | {"NimbusRom-Reg", "Times-Roman" }, |
97 | | {"NimbusRom-Med", "Times-Bold" }, |
98 | | {"NimbusRom-Ita", "Times-Italic" }, |
99 | | {"NimbusRom-MedIta", "Times-BoldItalic" }, |
100 | | {"NimbusRomNo9-Reg", "Times-Roman" }, |
101 | | {"NimbusRomNo9-Bol", "Times-Bold" }, |
102 | | {"NimbusRomNo9-Ita", "Times-Italic" }, |
103 | | {"NimbusRomNo9-MedIta", "Times-BoldItalic" }, |
104 | | {0} |
105 | | }; |
106 | | |
107 | | /* Given a pointer to a font name, return a pointer to an |
108 | | * equivalent base 14 font name, of NULL if there is no |
109 | | * equivalent. |
110 | | */ |
111 | | const char *pdf_find_base14_name(const byte *str, uint size) |
112 | 26 | { |
113 | 26 | const pdf_base14_font_info_t *ppsf; |
114 | | |
115 | 1.22k | for (ppsf = base14_font_info; ppsf->urwname; ++ppsf) { |
116 | 1.19k | if (strlen(ppsf->urwname) == size) { |
117 | 12 | if (!memcmp(ppsf->urwname, (const char *)str, size)) |
118 | 0 | return ppsf->stdname; |
119 | 12 | } |
120 | 1.19k | } |
121 | 26 | return NULL; |
122 | 26 | } |
123 | | |
124 | | |
125 | | /* |
126 | | * Determine whether a font is a subset font by examining the name. |
127 | | */ |
128 | | bool |
129 | | pdf_has_subset_prefix(const byte *str, uint size) |
130 | 8.43M | { |
131 | 8.43M | int i; |
132 | | |
133 | 8.43M | if (size < SUBSET_PREFIX_SIZE || str[SUBSET_PREFIX_SIZE - 1] != '+') |
134 | 5.28M | return false; |
135 | 22.0M | for (i = 0; i < SUBSET_PREFIX_SIZE - 1; ++i) |
136 | 18.9M | if ((uint)(str[i] - 'A') >= 26) |
137 | 279 | return false; |
138 | 3.15M | return true; |
139 | 3.15M | } |
140 | | |
141 | | static inline ulong |
142 | | hash(ulong v, int index, ushort w) |
143 | 1.89M | { |
144 | 1.89M | return v * 3141592653u + w; |
145 | 1.89M | } |
146 | | |
147 | | /* |
148 | | * Add the XXXXXX+ prefix for a subset font. |
149 | | */ |
150 | | int |
151 | | pdf_add_subset_prefix(const gx_device_pdf *pdev, gs_string *pstr, byte *used, int count, char *md5_hash) |
152 | 21.5k | { |
153 | 21.5k | uint size = pstr->size; |
154 | 21.5k | byte *data = gs_resize_string(pdev->pdf_memory, pstr->data, size, |
155 | 21.5k | size + SUBSET_PREFIX_SIZE, |
156 | 21.5k | "pdf_add_subset_prefix"); |
157 | 21.5k | int len = (count + 7) / 8; |
158 | 21.5k | int len0 = len & ~(sizeof(ushort) - 1); |
159 | 21.5k | ulong v = 0; |
160 | 21.5k | int i; |
161 | | |
162 | 21.5k | if (data == 0) |
163 | 0 | return_error(gs_error_VMerror); |
164 | | |
165 | 21.5k | if (md5_hash) { |
166 | 107k | for (i = 0; i < 8; i += sizeof(ushort)) { |
167 | 85.8k | v = hash(v, i, (*(md5_hash + i) | *(md5_hash + i + 1) << 8)); |
168 | 85.8k | } |
169 | 21.4k | } |
170 | | |
171 | | /* Hash the 'used' array. */ |
172 | 1.83M | for (i = 0; i < len0; i += sizeof(ushort)) |
173 | 1.81M | v = hash(v, i, *(ushort *)(used + i)); |
174 | 22.0k | for (; i < len; i++) |
175 | 547 | v = hash(v, i, used[i]); |
176 | | |
177 | 21.5k | memmove(data + SUBSET_PREFIX_SIZE, data, size); |
178 | 150k | for (i = 0; i < SUBSET_PREFIX_SIZE - 1; ++i, v /= 26) |
179 | 129k | data[i] = 'A' + (v % 26); |
180 | 21.5k | data[SUBSET_PREFIX_SIZE - 1] = '+'; |
181 | 21.5k | pstr->data = data; |
182 | 21.5k | pstr->size = size + SUBSET_PREFIX_SIZE; |
183 | 21.5k | return 0; |
184 | 21.5k | } |
185 | | |
186 | | /* Finish writing FontFile* data. */ |
187 | | static int |
188 | | pdf_end_fontfile(gx_device_pdf *pdev, pdf_data_writer_t *pdw) |
189 | 21.1k | { |
190 | | /* We would like to call pdf_end_data, |
191 | | but we don't want to write the object to the output file now. */ |
192 | 21.1k | return pdf_close_aside(pdw->pdev); |
193 | 21.1k | } |
194 | | |
195 | | static int copied_font_notify(void *proc_data, void *event_data) |
196 | 29.2k | { |
197 | 29.2k | return gs_purge_font_from_char_caches_completely((gs_font *)proc_data); |
198 | 29.2k | } |
199 | | |
200 | | /* ---------------- Public ---------------- */ |
201 | | /* |
202 | | * Allocate and initialize a base font structure, making the required |
203 | | * stable copy/ies of the gs_font. Note that this removes any XXXXXX+ |
204 | | * font name prefix from the copy. If is_standard is true, the copy is |
205 | | * a complete one, and adding glyphs or Encoding entries is not allowed. |
206 | | */ |
207 | | int |
208 | | pdf_base_font_alloc(gx_device_pdf *pdev, pdf_base_font_t **ppbfont, |
209 | | gs_font_base *font, const gs_matrix *orig_matrix, |
210 | | bool is_standard) |
211 | 47.1k | { |
212 | 47.1k | gs_memory_t *mem = pdev->pdf_memory; |
213 | 47.1k | gs_font *copied; |
214 | 47.1k | gs_font *complete; |
215 | 47.1k | pdf_base_font_t *pbfont = |
216 | 47.1k | gs_alloc_struct(mem, pdf_base_font_t, |
217 | 47.1k | &st_pdf_base_font, "pdf_base_font_alloc"); |
218 | 47.1k | const gs_font_name *pfname = &font->font_name; |
219 | 47.1k | gs_const_string font_name; |
220 | 47.1k | char fnbuf[2*sizeof(long) + 3]; /* .F########\0 */ |
221 | 47.1k | int code, reserve_glyphs = -1; |
222 | | |
223 | 47.1k | if (pbfont == 0) |
224 | 0 | return_error(gs_error_VMerror); |
225 | 47.1k | memset(pbfont, 0, sizeof(*pbfont)); |
226 | 47.1k | switch (font->FontType) { |
227 | 23.3k | case ft_encrypted: |
228 | 23.5k | case ft_encrypted2: |
229 | 23.5k | { |
230 | 23.5k | int index, count; |
231 | 23.5k | gs_glyph glyph; |
232 | | |
233 | 23.5k | for (index = 0, count = 0; |
234 | 18.2M | (font->procs.enumerate_glyph((gs_font *)font, &index, |
235 | 18.2M | GLYPH_SPACE_NAME, &glyph), |
236 | 18.2M | index != 0); |
237 | 23.5k | ) |
238 | 18.2M | ++count; |
239 | 23.5k | pbfont->num_glyphs = count; |
240 | 23.5k | pbfont->do_subset = (is_standard ? DO_SUBSET_NO : DO_SUBSET_UNKNOWN); |
241 | 23.5k | } |
242 | | /* If we find an excessively large type 1 font we won't be able to emit |
243 | | * a complete copy. Instead we will emit multiple subsets. Detect that here |
244 | | * and only reserve enough space in the font copy for the maximum subset |
245 | | * glyphs, 257. |
246 | | * This also prevents us making a 'complete' copy of the font below. NB the |
247 | | * value 2048 is merely a guess, intended to prevent copying very large fonts. |
248 | | */ |
249 | 23.5k | if(pbfont->num_glyphs > 2048 && !is_standard) { |
250 | 0 | reserve_glyphs = 257; |
251 | 0 | if(pbfont->do_subset != DO_SUBSET_NO){ |
252 | 0 | char buf[gs_font_name_max + 1]; |
253 | 0 | int l = min(font->font_name.size, sizeof(buf) - 1); |
254 | |
|
255 | 0 | memcpy(buf, font->font_name.chars, l); |
256 | 0 | buf[l] = 0; |
257 | 0 | emprintf1(pdev->memory, |
258 | 0 | "Can't embed the complete font %s as it is too large, embedding a subset.\n", |
259 | 0 | buf); |
260 | 0 | } |
261 | 0 | } |
262 | 23.5k | break; |
263 | 23.2k | case ft_TrueType: |
264 | 23.2k | pbfont->num_glyphs = ((gs_font_type42 *)font)->data.trueNumGlyphs; |
265 | 23.2k | pbfont->do_subset = |
266 | 23.2k | (pbfont->num_glyphs <= MAX_NO_SUBSET_GLYPHS ? |
267 | 20.7k | DO_SUBSET_UNKNOWN : DO_SUBSET_YES); |
268 | 23.2k | break; |
269 | 26 | case ft_CID_encrypted: |
270 | 26 | pbfont->num_glyphs = ((gs_font_cid0 *)font)->cidata.common.CIDCount; |
271 | 26 | goto cid; |
272 | 331 | case ft_CID_TrueType: |
273 | 331 | pbfont->num_glyphs = ((gs_font_cid2 *)font)->cidata.common.CIDCount; |
274 | 357 | cid: |
275 | 357 | pbfont->do_subset = DO_SUBSET_YES; |
276 | 357 | pbfont->CIDSet = |
277 | 357 | gs_alloc_bytes(mem, (pbfont->num_glyphs + 7) / 8, |
278 | 357 | "pdf_base_font_alloc(CIDSet)"); |
279 | 357 | if (pbfont->CIDSet == 0) { |
280 | 0 | code = gs_note_error(gs_error_VMerror); |
281 | 0 | goto fail; |
282 | 0 | } |
283 | 357 | pbfont->CIDSetLength = (pbfont->num_glyphs + 7) / 8; |
284 | 357 | memset(pbfont->CIDSet, 0, (pbfont->num_glyphs + 7) / 8); |
285 | 357 | break; |
286 | 0 | default: |
287 | 0 | code = gs_note_error(gs_error_rangecheck); |
288 | 0 | goto fail; |
289 | 47.1k | } |
290 | | |
291 | 47.1k | code = gs_copy_font((gs_font *)font, orig_matrix, mem, &copied, reserve_glyphs); |
292 | 47.1k | if (code < 0) |
293 | 17.9k | goto fail; |
294 | 29.2k | gs_notify_register(&copied->notify_list, copied_font_notify, copied); |
295 | 29.2k | { |
296 | | /* |
297 | | * Adobe Technical Note # 5012 "The Type 42 Font Format Specification" says : |
298 | | * |
299 | | * There is a known bug in the TrueType rasterizer included in versions of the |
300 | | * PostScript interpreter previous to version 2013. The problem is that the |
301 | | * translation components of the FontMatrix, as used as an argument to the |
302 | | * definefont or makefont operators, are ignored. Translation of user space is |
303 | | * not affected by this bug. |
304 | | * |
305 | | * Besides that, we found that Adobe Acrobat Reader 4 and 5 ignore |
306 | | * FontMatrix.ty . |
307 | | */ |
308 | 29.2k | copied->FontMatrix.tx = copied->FontMatrix.ty = 0; |
309 | 29.2k | } |
310 | | |
311 | 29.2k | if (pbfont->do_subset != DO_SUBSET_YES && reserve_glyphs == -1) { |
312 | | /* The only possibly non-subsetted fonts are Type 1/2 and Type 42. */ |
313 | 28.7k | if (is_standard) |
314 | 3.29k | complete = copied; |
315 | 25.4k | else { |
316 | 25.4k | code = gs_copy_font((gs_font *)font, &font->FontMatrix, mem, &complete, -1); |
317 | 25.4k | if (code < 0) { |
318 | 0 | gs_free_copied_font(copied); |
319 | 0 | goto fail; |
320 | 0 | } |
321 | 25.4k | } |
322 | 28.7k | code = gs_copy_font_complete((gs_font *)font, complete); |
323 | 28.7k | if (code < 0 && pbfont->do_subset == DO_SUBSET_NO) { |
324 | 0 | char buf[gs_font_name_max + 1]; |
325 | 0 | int l = min(copied->font_name.size, sizeof(buf) - 1); |
326 | |
|
327 | 0 | memcpy(buf, copied->font_name.chars, l); |
328 | 0 | buf[l] = 0; |
329 | 0 | emprintf1(pdev->memory, |
330 | 0 | "Can't embed the complete font %s due to font error.\n", |
331 | 0 | buf); |
332 | 0 | gs_free_copied_font(copied); |
333 | 0 | copied = NULL; |
334 | 0 | goto fail; |
335 | 0 | } |
336 | 28.7k | if (code < 0) { |
337 | | /* A font error happened, but it may be caused by a glyph, |
338 | | which is not used in the document. Continue with subsetting the font. |
339 | | If the failed glyph will be used in the document, |
340 | | another error will hgappen when the glyph is used. |
341 | | */ |
342 | 3.86k | gs_free_copied_font(complete); |
343 | 3.86k | complete = copied; |
344 | 3.86k | } |
345 | 28.7k | } else |
346 | 483 | complete = copied; |
347 | 29.2k | pbfont->copied = (gs_font_base *)copied; |
348 | 29.2k | pbfont->complete = (gs_font_base *)complete; |
349 | | |
350 | | /* replace the font cache of the copied fonts with our own font cache |
351 | | * this is required for PCL, see 'pdf_free_pdf_font_cache' in gdevpdf.c |
352 | | * for further details. |
353 | | */ |
354 | 29.2k | pdev->pdf_font_dir->global_glyph_code = font->dir->global_glyph_code; |
355 | | |
356 | 29.2k | pbfont->copied->dir = pbfont->complete->dir = pdev->pdf_font_dir; |
357 | | |
358 | 29.2k | if (pbfont->copied->FontType == ft_CID_encrypted) { |
359 | 26 | gs_font_cid0 *copied0 = (gs_font_cid0 *)pbfont->copied; |
360 | 26 | int i; |
361 | 74 | for (i = 0; i < copied0->cidata.FDArray_size; ++i) { |
362 | 48 | ((gs_font *)copied0->cidata.FDArray[i])->dir = pdev->pdf_font_dir; |
363 | 48 | } |
364 | 26 | } |
365 | | |
366 | 29.2k | pbfont->is_standard = is_standard; |
367 | 29.2k | if (pfname->size > 0) { |
368 | 28.0k | font_name.data = pfname->chars; |
369 | 28.0k | font_name.size = pfname->size; |
370 | 39.4k | while (pdf_has_subset_prefix(font_name.data, font_name.size)) { |
371 | | /* Strip off an existing subset prefix. */ |
372 | 11.3k | font_name.data += SUBSET_PREFIX_SIZE; |
373 | 11.3k | font_name.size -= SUBSET_PREFIX_SIZE; |
374 | 11.3k | } |
375 | 28.0k | } else { |
376 | 1.11k | gs_snprintf(fnbuf, sizeof(fnbuf), "Anonymous"); |
377 | 1.11k | font_name.data = (byte *)fnbuf; |
378 | 1.11k | font_name.size = strlen(fnbuf); |
379 | 1.11k | } |
380 | 29.2k | pbfont->font_name.data = |
381 | 29.2k | gs_alloc_string(mem, font_name.size, "pdf_base_font_alloc(font_name)"); |
382 | 29.2k | if (pbfont->font_name.data == 0) |
383 | 0 | goto fail; |
384 | 29.2k | memcpy(pbfont->font_name.data, font_name.data, font_name.size); |
385 | 29.2k | pbfont->font_name.size = font_name.size; |
386 | 29.2k | *ppbfont = pbfont; |
387 | 29.2k | return 0; |
388 | 17.9k | fail: |
389 | 17.9k | pdf_base_font_free(pdev, pbfont); |
390 | 17.9k | return code; |
391 | 29.2k | } |
392 | | |
393 | | /* |
394 | | * Return a reference to the name of a base font. This name is guaranteed |
395 | | * not to have a XXXXXX+ prefix. The client may change the name at will, |
396 | | * but must not add a XXXXXX+ prefix. |
397 | | */ |
398 | | gs_string * |
399 | | pdf_base_font_name(pdf_base_font_t *pbfont) |
400 | 47.7k | { |
401 | 47.7k | return &pbfont->font_name; |
402 | 47.7k | } |
403 | | |
404 | | /* |
405 | | * Return the (copied, subset) font associated with a base font. |
406 | | * This procedure probably shouldn't exist.... |
407 | | */ |
408 | | gs_font_base * |
409 | | pdf_base_font_font(const pdf_base_font_t *pbfont, bool complete) |
410 | 47.9M | { |
411 | 47.9M | return (complete ? pbfont->complete : pbfont->copied); |
412 | 47.9M | } |
413 | | |
414 | | /* |
415 | | * Check for subset font. |
416 | | */ |
417 | | bool |
418 | | pdf_base_font_is_subset(const pdf_base_font_t *pbfont) |
419 | 21.5k | { |
420 | 21.5k | return pbfont->do_subset == DO_SUBSET_YES; |
421 | 21.5k | } |
422 | | |
423 | | /* |
424 | | * Drop the copied complete font associated with a base font. |
425 | | */ |
426 | | void |
427 | | pdf_base_font_drop_complete(pdf_base_font_t *pbfont) |
428 | 788 | { |
429 | | /* gs_font is a subset of gs_font_base and we only want to |
430 | | * free the members which are common to both, so this cast is |
431 | | * (at the time of writing) safe. |
432 | | */ |
433 | 788 | if (pbfont->complete != pbfont->copied) |
434 | 788 | gs_free_copied_font((gs_font *)pbfont->complete); |
435 | 788 | pbfont->complete = NULL; |
436 | 788 | } |
437 | | |
438 | | /* |
439 | | * Copy a glyph (presumably one that was just used) into a saved base |
440 | | * font. Note that it is the client's responsibility to determine that |
441 | | * the source font is compatible with the target font. (Normally they |
442 | | * will be the same.) |
443 | | */ |
444 | | int |
445 | | pdf_base_font_copy_glyph(pdf_base_font_t *pbfont, gs_glyph glyph, |
446 | | gs_font_base *font) |
447 | 718k | { |
448 | 718k | int code; |
449 | | |
450 | | /* If we're a TrueType CIDFont, check teh GSUB table for replacement glyphs. |
451 | | * Bug #691574 |
452 | | */ |
453 | 718k | if (font->FontType == ft_CID_TrueType) { |
454 | 86.6k | code = |
455 | 86.6k | gs_copy_glyph_options((gs_font *)font, glyph, |
456 | 86.6k | (gs_font *)pbfont->copied, |
457 | 86.6k | (pbfont->is_standard ? COPY_GLYPH_NO_NEW : COPY_GLYPH_USE_GSUB)); |
458 | 632k | } else { |
459 | 632k | code = |
460 | 632k | gs_copy_glyph_options((gs_font *)font, glyph, |
461 | 632k | (gs_font *)pbfont->copied, |
462 | 632k | (pbfont->is_standard ? COPY_GLYPH_NO_NEW : 0)); |
463 | 632k | } |
464 | 718k | if (code < 0) |
465 | 18.5k | return code; |
466 | 700k | if (pbfont->CIDSet != 0 && |
467 | 700k | (uint)(glyph - GS_MIN_CID_GLYPH) < pbfont->num_glyphs |
468 | 700k | ) { |
469 | 85.6k | uint cid = glyph - GS_MIN_CID_GLYPH; |
470 | | |
471 | 85.6k | pbfont->CIDSet[cid >> 3] |= 0x80 >> (cid & 7); |
472 | 85.6k | } |
473 | 700k | return 0; |
474 | 718k | } |
475 | | |
476 | | /* |
477 | | * Determine whether a font should be subsetted. |
478 | | */ |
479 | | bool |
480 | | pdf_do_subset_font(gx_device_pdf *pdev, pdf_base_font_t *pbfont, gs_id rid) |
481 | 68.2k | { |
482 | 68.2k | gs_font_base *copied = pbfont->copied; |
483 | | |
484 | | /* |
485 | | * If the decision has not been made already, determine whether or not |
486 | | * to subset the font. |
487 | | */ |
488 | 68.2k | if (pbfont->do_subset == DO_SUBSET_UNKNOWN) { |
489 | 25.4k | int max_pct = pdev->params.MaxSubsetPct; |
490 | 25.4k | bool do_subset = pdev->params.SubsetFonts && max_pct > 0; |
491 | | |
492 | 25.4k | if (do_subset && max_pct < 100) { |
493 | | /* We want to subset iff used <= total * MaxSubsetPct / 100. */ |
494 | 0 | do_subset = false; |
495 | 0 | if (max_pct > 0) { |
496 | 0 | int max_subset_used = pbfont->num_glyphs * max_pct / 100; |
497 | 0 | int used, index; |
498 | 0 | gs_glyph ignore_glyph; |
499 | |
|
500 | 0 | do_subset = true; |
501 | 0 | for (index = 0, used = 0; |
502 | 0 | (copied->procs.enumerate_glyph((gs_font *)copied, |
503 | 0 | &index, GLYPH_SPACE_INDEX, |
504 | 0 | &ignore_glyph), index != 0); |
505 | 0 | ) |
506 | 0 | if (++used > max_subset_used) { |
507 | 0 | do_subset = false; |
508 | 0 | break; |
509 | 0 | } |
510 | 0 | } |
511 | 0 | } |
512 | 25.4k | pbfont->do_subset = (do_subset ? DO_SUBSET_YES : DO_SUBSET_NO); |
513 | 25.4k | } |
514 | 68.2k | return (pbfont->do_subset == DO_SUBSET_YES); |
515 | 68.2k | } |
516 | | |
517 | | /* |
518 | | * Write the FontFile entry for an embedded font, /FontFile<n> # # R. |
519 | | */ |
520 | | int |
521 | | pdf_write_FontFile_entry(gx_device_pdf *pdev, pdf_base_font_t *pbfont) |
522 | 21.1k | { |
523 | 21.1k | stream *s = pdev->strm; |
524 | 21.1k | const char *FontFile_key; |
525 | | |
526 | 21.1k | switch (pbfont->copied->FontType) { |
527 | 2.39k | case ft_TrueType: |
528 | 2.69k | case ft_CID_TrueType: |
529 | 2.69k | FontFile_key = "/FontFile2"; |
530 | 2.69k | break; |
531 | 18.4k | default: /* Type 1/2, CIDFontType 0 */ |
532 | 18.4k | if (!pdev->HaveCFF) |
533 | 13.1k | FontFile_key = "/FontFile"; |
534 | 5.30k | else |
535 | 5.30k | FontFile_key = "/FontFile3"; |
536 | 21.1k | } |
537 | 21.1k | stream_puts(s, FontFile_key); |
538 | 21.1k | pprinti64d1(s, " %"PRId64" 0 R", pbfont->FontFile->id); |
539 | 21.1k | return 0; |
540 | 21.1k | } |
541 | | |
542 | | /* |
543 | | * Adjust font name for Acrobat Reader 3. |
544 | | */ |
545 | | static int |
546 | | pdf_adjust_font_name(gx_device_pdf *pdev, int64_t id, pdf_base_font_t *pbfont) |
547 | 0 | { |
548 | | /* |
549 | | * In contradiction with previous version of pdfwrite, |
550 | | * this always adds a suffix. We don't check the original name |
551 | | * for uniquity bacause the layered architecture |
552 | | * (see gdevpdtx.h) doesn't provide an easy access for |
553 | | * related information. |
554 | | */ |
555 | 0 | int i; |
556 | 0 | byte *chars = (byte *)pbfont->font_name.data; /* break 'const' */ |
557 | 0 | byte *data; |
558 | 0 | uint size = pbfont->font_name.size; |
559 | 0 | char suffix[sizeof(int64_t) * 2 + 2]; |
560 | 0 | uint suffix_size; |
561 | |
|
562 | 0 | #define SUFFIX_CHAR '~' |
563 | | /* |
564 | | * If the name looks as though it has one of our unique suffixes, |
565 | | * remove the suffix. |
566 | | */ |
567 | 0 | for (i = size; |
568 | 0 | i > 0 && isxdigit(chars[i - 1]); |
569 | 0 | --i) |
570 | 0 | DO_NOTHING; |
571 | 0 | if (i < size && i > 0 && chars[i - 1] == SUFFIX_CHAR) { |
572 | 0 | do { |
573 | 0 | --i; |
574 | 0 | } while (i > 0 && chars[i - 1] == SUFFIX_CHAR); |
575 | 0 | size = i + 1; |
576 | 0 | } |
577 | | /* Create a unique name. */ |
578 | 0 | gs_snprintf(suffix, sizeof(suffix), "%c%lx", SUFFIX_CHAR, id); |
579 | 0 | suffix_size = strlen(suffix); |
580 | 0 | data = gs_resize_string(pdev->pdf_memory, chars, size, |
581 | 0 | size + suffix_size, |
582 | 0 | "pdf_adjust_font_name"); |
583 | 0 | if (data == 0) |
584 | 0 | return_error(gs_error_VMerror); |
585 | 0 | memcpy(data + size, (const byte *)suffix, suffix_size); |
586 | 0 | pbfont->font_name.data = data; |
587 | 0 | pbfont->font_name.size = size + suffix_size; |
588 | 0 | #undef SUFFIX_CHAR |
589 | 0 | return 0; |
590 | 0 | } |
591 | | |
592 | | /* |
593 | | * Write an embedded font. |
594 | | */ |
595 | | int |
596 | | pdf_write_embedded_font(gx_device_pdf *pdev, pdf_base_font_t *pbfont, font_type FontType, |
597 | | gs_int_rect *FontBBox, gs_id rid, cos_dict_t **ppcd) |
598 | 21.1k | { |
599 | 21.1k | bool do_subset = pdf_do_subset_font(pdev, pbfont, rid); |
600 | 21.1k | gs_font_base *out_font = |
601 | 21.1k | (do_subset || pbfont->complete == NULL ? pbfont->copied : pbfont->complete); |
602 | 21.1k | gs_const_string fnstr; |
603 | 21.1k | pdf_data_writer_t writer; |
604 | 21.1k | byte digest[6] = {0,0,0,0,0,0}; |
605 | 21.1k | int code = 0; |
606 | 21.1k | int options=0; |
607 | | |
608 | 21.1k | if (pbfont->written) |
609 | 0 | return 0; /* already written */ |
610 | 21.1k | code = copied_order_font((gs_font *)out_font); |
611 | 21.1k | if (code < 0) |
612 | 0 | return code; |
613 | | /* Since we now always ASCIIHex encode the eexec encrypted portion of a |
614 | | * Type 1 font, such a font cannot contain any binary data, if its not being |
615 | | * compressed then there is no reason to ASCII encode it (which will happen |
616 | | * we set DATA_STREAM_BINARY and the device does not permit binary output) |
617 | | * NB if HaveCFF is true then we convert type 1 to CFF which is a binary |
618 | | * format, so we still need to set DATA_STREAM_BINARY. |
619 | | */ |
620 | 21.1k | if (pdev->CompressFonts) |
621 | 21.1k | options = DATA_STREAM_BINARY | DATA_STREAM_COMPRESS; |
622 | 0 | else |
623 | 0 | if (FontType != ft_encrypted || pdev->HaveCFF) |
624 | 0 | options = DATA_STREAM_BINARY; |
625 | | /* Don't set DATA_STREAM_ENCRYPT since we write to a temporary file. |
626 | | * See comment in pdf_begin_encrypt. |
627 | | */ |
628 | 21.1k | code = pdf_begin_data_stream(pdev, &writer, options, 0); |
629 | 21.1k | if (code < 0) |
630 | 0 | return code; |
631 | 21.1k | if (pdev->PDFA != 0) { |
632 | 0 | stream *s = s_MD5C_make_stream(pdev->pdf_memory, writer.binary.strm); |
633 | |
|
634 | 0 | if (s == NULL) |
635 | 0 | return_error(gs_error_VMerror); |
636 | 0 | writer.binary.strm = s; |
637 | 0 | } |
638 | 21.1k | if (pdev->CompatibilityLevel == 1.2 && |
639 | 21.1k | !do_subset && !pbfont->is_standard ) { |
640 | | /* |
641 | | * Due to a bug in Acrobat Reader 3, we need to generate |
642 | | * unique font names, except base 14 fonts being not embedded. |
643 | | * To recognize base 14 fonts here we used the knowledge |
644 | | * that pbfont->is_standard is true for base 14 fonts only. |
645 | | * Note that subsetted fonts already have an unique name |
646 | | * due to subset prefix. |
647 | | */ |
648 | 0 | int code = pdf_adjust_font_name(pdev, writer.pres->object->id, pbfont); |
649 | 0 | if (code < 0) |
650 | 0 | return code; |
651 | 0 | } |
652 | 21.1k | fnstr.data = pbfont->font_name.data; |
653 | 21.1k | fnstr.size = pbfont->font_name.size; |
654 | | /* Now write the font (or subset). */ |
655 | 21.1k | switch (FontType) { |
656 | | |
657 | 0 | case ft_composite: |
658 | | /* Nothing to embed -- the descendant fonts do it all. */ |
659 | 0 | code = 0; |
660 | 0 | break; |
661 | | |
662 | 188 | case ft_encrypted2: |
663 | 188 | if (!pdev->HaveCFF) { |
664 | | /* Must convert to Type 1 charstrings. */ |
665 | 0 | return_error(gs_error_unregistered); /* Not implemented yet. */ |
666 | 0 | } |
667 | 18.4k | case ft_encrypted: |
668 | 18.4k | if (pdev->HavePDFWidths) { |
669 | 5.31k | code = copied_drop_extension_glyphs((gs_font *)out_font); |
670 | 5.31k | if (code < 0) |
671 | 0 | return code; |
672 | 5.31k | } |
673 | 18.4k | if (!pdev->HaveCFF) { |
674 | | /* Write the type 1 font with no converting to CFF. */ |
675 | 13.1k | int lengths[3]; |
676 | | |
677 | 13.1k | if (pbfont->do_subset != DO_SUBSET_NO) |
678 | 13.1k | code = psf_write_type1_font(writer.binary.strm, |
679 | 13.1k | (gs_font_type1 *)out_font, |
680 | 13.1k | WRITE_TYPE1_WITH_LENIV | WRITE_TYPE1_EEXEC | |
681 | 13.1k | WRITE_TYPE1_EEXEC_PAD | WRITE_TYPE1_ASCIIHEX, |
682 | 13.1k | NULL, 0, &fnstr, lengths); |
683 | 0 | else |
684 | 0 | code = psf_write_type1_font(writer.binary.strm, |
685 | 0 | (gs_font_type1 *)out_font, |
686 | 0 | WRITE_TYPE1_WITH_LENIV | WRITE_TYPE1_EEXEC | |
687 | 0 | WRITE_TYPE1_EEXEC_PAD | WRITE_TYPE1_ASCIIHEX | WRITE_TYPE1_XUID, |
688 | 0 | NULL, 0, &fnstr, lengths); |
689 | 13.1k | if (lengths[0] > 0) { |
690 | 13.1k | if (code < 0) |
691 | 0 | goto finish; |
692 | 13.1k | code = cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object, |
693 | 13.1k | "/Length1", lengths[0]); |
694 | 13.1k | } |
695 | 13.1k | if (lengths[1] > 0) { |
696 | 13.1k | if (code < 0) |
697 | 0 | goto finish; |
698 | 13.1k | code = cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object, |
699 | 13.1k | "/Length2", lengths[1]); |
700 | 13.1k | if (code < 0) |
701 | 0 | return code; |
702 | 13.1k | code = cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object, |
703 | 13.1k | "/Length3", lengths[2]); |
704 | 13.1k | } |
705 | 13.1k | } else { |
706 | | /* |
707 | | * Since we only support PDF 1.2 and later, always write Type 1 |
708 | | * fonts as Type1C (Type 2). Acrobat Reader apparently doesn't |
709 | | * accept CFF fonts with Type 1 CharStrings, so we need to convert |
710 | | * them. Also remove lenIV, so Type 2 fonts will compress better. |
711 | | */ |
712 | 5.33k | #define TYPE2_OPTIONS (WRITE_TYPE2_NO_LENIV | WRITE_TYPE2_CHARSTRINGS) |
713 | 5.31k | code = cos_dict_put_string_copy((cos_dict_t *)writer.pres->object, "/Subtype", "/Type1C"); |
714 | 5.31k | if (code < 0) |
715 | 0 | return code; |
716 | 5.31k | code = psf_write_type2_font(writer.binary.strm, |
717 | 5.31k | (gs_font_type1 *)out_font, |
718 | 5.31k | TYPE2_OPTIONS | |
719 | 5.31k | (pdev->CompatibilityLevel < 1.3 ? WRITE_TYPE2_AR3 : 0) | |
720 | 5.31k | (pbfont->do_subset == DO_SUBSET_NO ? WRITE_TYPE2_XUID : 0), |
721 | 5.31k | NULL, 0, &fnstr, FontBBox); |
722 | 5.31k | } |
723 | 18.4k | goto finish; |
724 | | |
725 | 18.4k | case ft_TrueType: { |
726 | 2.39k | gs_font_type42 *const pfont = (gs_font_type42 *)out_font; |
727 | 2.39k | #define TRUETYPE_OPTIONS (WRITE_TRUETYPE_NAME | WRITE_TRUETYPE_HVMTX) |
728 | | /* Acrobat Reader 3 doesn't handle cmap format 6 correctly. */ |
729 | 2.39k | const int options = TRUETYPE_OPTIONS | |
730 | 2.39k | (pdev->PDFA != 0 ? WRITE_TRUETYPE_UNICODE_CMAP : 0) | |
731 | 2.39k | (pdev->CompatibilityLevel <= 1.2 ? |
732 | 1.97k | WRITE_TRUETYPE_NO_TRIMMED_TABLE : 0) | |
733 | | /* Generate a cmap only for incrementally downloaded fonts |
734 | | and for subsetted fonts. */ |
735 | 2.39k | (pfont->data.numGlyphs != pfont->data.trueNumGlyphs || |
736 | 2.39k | pbfont->do_subset == DO_SUBSET_YES ? |
737 | 2.39k | WRITE_TRUETYPE_CMAP : 0); |
738 | 2.39k | stream poss; |
739 | | |
740 | 2.39k | if (pdev->HavePDFWidths) { |
741 | 420 | code = copied_drop_extension_glyphs((gs_font *)out_font); |
742 | 420 | if (code < 0) |
743 | 0 | return code; |
744 | 420 | } |
745 | 2.39k | s_init(&poss, pdev->memory); |
746 | 2.39k | swrite_position_only(&poss); |
747 | 2.39k | code = psf_write_truetype_font(&poss, pfont, options, NULL, 0, &fnstr); |
748 | 2.39k | if (code < 0) |
749 | 0 | goto finish; |
750 | 2.39k | code = cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object, "/Length1", stell(&poss)); |
751 | 2.39k | if (code < 0) |
752 | 0 | goto finish; |
753 | 2.39k | code = psf_write_truetype_font(writer.binary.strm, pfont, |
754 | 2.39k | options, NULL, 0, &fnstr); |
755 | 2.39k | goto finish; |
756 | 2.39k | } |
757 | | |
758 | 21 | case ft_CID_encrypted: |
759 | 21 | code = cos_dict_put_string_copy((cos_dict_t *)writer.pres->object, "/Subtype", "/CIDFontType0C"); |
760 | 21 | if (code < 0) |
761 | 0 | return code; |
762 | 21 | code = psf_write_cid0_font(writer.binary.strm, |
763 | 21 | (gs_font_cid0 *)out_font, TYPE2_OPTIONS, |
764 | 21 | NULL, 0, &fnstr); |
765 | 21 | goto finish; |
766 | | |
767 | 298 | case ft_CID_TrueType: |
768 | | /* CIDFontType 2 fonts don't use cmap, name, OS/2, or post. */ |
769 | 298 | #define CID2_OPTIONS WRITE_TRUETYPE_HVMTX |
770 | 298 | code = psf_write_cid2_font(writer.binary.strm, |
771 | 298 | (gs_font_cid2 *)out_font, |
772 | 298 | CID2_OPTIONS, NULL, 0, &fnstr); |
773 | 21.1k | finish: |
774 | 21.1k | if (pdev->PDFA != 0) { |
775 | 0 | sflush(writer.binary.strm); |
776 | 0 | s_MD5C_get_digest(writer.binary.strm, digest, sizeof(digest)); |
777 | 0 | } |
778 | 21.1k | *ppcd = (cos_dict_t *)writer.pres->object; |
779 | 21.1k | if (code < 0) { |
780 | 30 | pdf_end_fontfile(pdev, &writer); |
781 | 30 | pdf_obj_mark_unused(pdev, writer.pres->object->id); |
782 | 30 | return code; |
783 | 30 | } |
784 | 21.1k | code = pdf_end_fontfile(pdev, &writer); |
785 | 21.1k | break; |
786 | | |
787 | 0 | default: |
788 | 0 | code = gs_note_error(gs_error_rangecheck); |
789 | 21.1k | } |
790 | | |
791 | 21.1k | pbfont->written = true; |
792 | 21.1k | return code; |
793 | 21.1k | } |
794 | | |
795 | | /* |
796 | | * Write the CharSet for a subsetted font, as a PDF string. |
797 | | */ |
798 | | int |
799 | | pdf_write_CharSet(gx_device_pdf *pdev, pdf_base_font_t *pbfont) |
800 | 18.4k | { |
801 | 18.4k | stream *s = pdev->strm; |
802 | 18.4k | gs_font_base *font = pbfont->copied; |
803 | 18.4k | int index; |
804 | 18.4k | gs_glyph glyph; |
805 | | |
806 | 18.4k | stream_puts(s, "("); |
807 | 18.4k | for (index = 0; |
808 | 374k | (font->procs.enumerate_glyph((gs_font *)font, &index, |
809 | 374k | GLYPH_SPACE_NAME, &glyph), |
810 | 374k | index != 0); |
811 | 356k | ) { |
812 | 356k | gs_const_string gstr; |
813 | 356k | int code = font->procs.glyph_name((gs_font *)font, glyph, &gstr); |
814 | | |
815 | | /* Don't include .notdef. */ |
816 | 356k | if (code >= 0 && |
817 | 356k | bytes_compare(gstr.data, gstr.size, (const byte *)".notdef", 7) |
818 | 356k | ) |
819 | 337k | pdf_put_name(pdev, gstr.data, gstr.size); |
820 | 356k | } |
821 | 18.4k | stream_puts(s, ")"); |
822 | 18.4k | return 0; |
823 | 18.4k | } |
824 | | |
825 | | /* |
826 | | * Write the CIDSet object for a subsetted CIDFont. |
827 | | */ |
828 | | int |
829 | | pdf_write_CIDSet(gx_device_pdf *pdev, pdf_base_font_t *pbfont, |
830 | | int64_t *pcidset_id) |
831 | 319 | { |
832 | 319 | pdf_data_writer_t writer; |
833 | 319 | int code; |
834 | | |
835 | 319 | code = pdf_begin_data_stream(pdev, &writer, |
836 | 319 | DATA_STREAM_BINARY | |
837 | 319 | (pdev->CompressFonts ? DATA_STREAM_COMPRESS : 0), |
838 | 319 | gs_no_id); |
839 | 319 | if (code < 0) |
840 | 0 | return code; |
841 | 319 | stream_write(writer.binary.strm, pbfont->CIDSet, |
842 | 319 | pbfont->CIDSetLength); |
843 | 319 | code = pdf_end_data(&writer); |
844 | 319 | if (code < 0) |
845 | 0 | return code; |
846 | 319 | *pcidset_id = pdf_resource_id(writer.pres); |
847 | 319 | return 0; |
848 | 319 | } |
849 | | /* |
850 | | * Check whether a base font is standard. |
851 | | */ |
852 | | bool |
853 | | pdf_is_standard_font(pdf_base_font_t *bfont) |
854 | 0 | { return bfont->is_standard; |
855 | 0 | } |
856 | | |
857 | | void |
858 | | pdf_set_FontFile_object(pdf_base_font_t *bfont, cos_dict_t *pcd) |
859 | 21.1k | { |
860 | 21.1k | bfont->FontFile = pcd; |
861 | 21.1k | } |
862 | | const cos_dict_t * |
863 | | pdf_get_FontFile_object(pdf_base_font_t *bfont) |
864 | 21.1k | { |
865 | 21.1k | return bfont->FontFile; |
866 | 21.1k | } |