1 /* Copyright (C) 2002 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gdevpdtf.c,v 1.46 2005/09/12 11:34:50 leonardo Exp $ */
18 /* Font and CMap resource implementation for pdfwrite text */
19 #include "memory_.h"
20 #include "string_.h"
21 #include "gx.h"
22 #include "gserrors.h"
23 #include "gsutil.h" /* for bytes_compare */
24 #include "gxfcache.h" /* for orig_fonts list */
25 #include "gxfcid.h"
26 #include "gxfcmap.h"
27 #include "gxfcopy.h"
28 #include "gxfont.h"
29 #include "gxfont1.h"
30 #include "gdevpsf.h"
31 #include "gdevpdfx.h"
32 #include "gdevpdtb.h"
33 #include "gdevpdtd.h"
34 #include "gdevpdtf.h"
35 #include "gdevpdtw.h"
36
37 /* GC descriptors */
38 public_st_pdf_font_resource();
39 private_st_pdf_encoding1();
40 private_st_pdf_encoding_element();
41 private_st_pdf_standard_font();
42 private_st_pdf_standard_font_element();
43 private_st_pdf_outline_fonts();
44
45 private
46 ENUM_PTRS_WITH(pdf_font_resource_enum_ptrs, pdf_font_resource_t *pdfont)
47 ENUM_PREFIX(st_pdf_resource, 12);
48 case 0: return ENUM_STRING(&pdfont->BaseFont);
49 case 1: ENUM_RETURN(pdfont->FontDescriptor);
50 case 2: ENUM_RETURN(pdfont->base_font);
51 case 3: ENUM_RETURN(pdfont->Widths);
52 case 4: ENUM_RETURN(pdfont->used);
53 case 5: ENUM_RETURN(pdfont->res_ToUnicode);
54 case 6: ENUM_RETURN(pdfont->cmap_ToUnicode);
55 case 7: switch (pdfont->FontType) {
56 case ft_composite:
57 ENUM_RETURN(pdfont->u.type0.DescendantFont);
58 case ft_CID_encrypted:
59 case ft_CID_TrueType:
60 ENUM_RETURN(pdfont->u.cidfont.Widths2);
61 default:
62 ENUM_RETURN(pdfont->u.simple.Encoding);
63 }
64 case 8: switch (pdfont->FontType) {
65 case ft_composite:
66 return (pdfont->u.type0.cmap_is_standard ? ENUM_OBJ(0) :
67 ENUM_CONST_STRING(&pdfont->u.type0.CMapName));
68 case ft_encrypted:
69 case ft_encrypted2:
70 case ft_TrueType:
71 case ft_user_defined:
72 ENUM_RETURN(pdfont->u.simple.v);
73 case ft_CID_encrypted:
74 case ft_CID_TrueType:
75 ENUM_RETURN(pdfont->u.cidfont.v);
76 default:
77 ENUM_RETURN(0);
78 }
79 case 9: switch (pdfont->FontType) {
80 case ft_user_defined:
81 ENUM_RETURN(pdfont->u.simple.s.type3.char_procs);
82 case ft_CID_encrypted:
83 case ft_CID_TrueType:
84 ENUM_RETURN(pdfont->u.cidfont.CIDToGIDMap);
85 default:
86 ENUM_RETURN(0);
87 }
88 case 10: switch (pdfont->FontType) {
89 case ft_user_defined:
90 ENUM_RETURN(pdfont->u.simple.s.type3.cached);
91 case ft_CID_encrypted:
92 case ft_CID_TrueType:
93 ENUM_RETURN(pdfont->u.cidfont.parent);
94 default:
95 ENUM_RETURN(0);
96 }
97 case 11: switch (pdfont->FontType) {
98 case ft_user_defined:
99 ENUM_RETURN(pdfont->u.simple.s.type3.used_resources);
100 case ft_CID_encrypted:
101 case ft_CID_TrueType:
102 ENUM_RETURN(pdfont->u.cidfont.used2);
103 default:
104 ENUM_RETURN(0);
105 }
106 ENUM_PTRS_END
107 private
RELOC_PTRS_WITH(pdf_font_resource_reloc_ptrs,pdf_font_resource_t * pdfont)108 RELOC_PTRS_WITH(pdf_font_resource_reloc_ptrs, pdf_font_resource_t *pdfont)
109 {
110 RELOC_PREFIX(st_pdf_resource);
111 RELOC_STRING_VAR(pdfont->BaseFont);
112 RELOC_VAR(pdfont->FontDescriptor);
113 RELOC_VAR(pdfont->base_font);
114 RELOC_VAR(pdfont->Widths);
115 RELOC_VAR(pdfont->used);
116 RELOC_VAR(pdfont->res_ToUnicode);
117 RELOC_VAR(pdfont->cmap_ToUnicode);
118 switch (pdfont->FontType) {
119 case ft_composite:
120 if (!pdfont->u.type0.cmap_is_standard)
121 RELOC_CONST_STRING_VAR(pdfont->u.type0.CMapName);
122 RELOC_VAR(pdfont->u.type0.DescendantFont);
123 break;
124 case ft_user_defined:
125 RELOC_VAR(pdfont->u.simple.Encoding);
126 RELOC_VAR(pdfont->u.simple.v);
127 RELOC_VAR(pdfont->u.simple.s.type3.char_procs);
128 RELOC_VAR(pdfont->u.simple.s.type3.cached);
129 RELOC_VAR(pdfont->u.simple.s.type3.used_resources);
130 break;
131 case ft_CID_encrypted:
132 case ft_CID_TrueType:
133 RELOC_VAR(pdfont->u.cidfont.Widths2);
134 RELOC_VAR(pdfont->u.cidfont.v);
135 RELOC_VAR(pdfont->u.cidfont.CIDToGIDMap);
136 RELOC_VAR(pdfont->u.cidfont.parent);
137 RELOC_VAR(pdfont->u.cidfont.used2);
138 break;
139 default:
140 RELOC_VAR(pdfont->u.simple.Encoding);
141 RELOC_VAR(pdfont->u.simple.v);
142 break;
143 }
144 }
145 RELOC_PTRS_END
146
147 /* ---------------- Standard fonts ---------------- */
148
149 /* ------ Private ------ */
150
151 /* Define the 14 standard built-in fonts. */
152 #define PDF_NUM_STANDARD_FONTS 14
153 typedef struct pdf_standard_font_info_s {
154 const char *fname;
155 int size;
156 gs_encoding_index_t base_encoding;
157 } pdf_standard_font_info_t;
158 private const pdf_standard_font_info_t standard_font_info[] = {
159 {"Courier", 7, ENCODING_INDEX_STANDARD},
160 {"Courier-Bold", 12, ENCODING_INDEX_STANDARD},
161 {"Courier-Oblique", 15, ENCODING_INDEX_STANDARD},
162 {"Courier-BoldOblique", 19, ENCODING_INDEX_STANDARD},
163 {"Helvetica", 9, ENCODING_INDEX_STANDARD},
164 {"Helvetica-Bold", 14, ENCODING_INDEX_STANDARD},
165 {"Helvetica-Oblique", 17, ENCODING_INDEX_STANDARD},
166 {"Helvetica-BoldOblique", 21, ENCODING_INDEX_STANDARD},
167 {"Symbol", 6, ENCODING_INDEX_SYMBOL},
168 {"Times-Roman", 11, ENCODING_INDEX_STANDARD},
169 {"Times-Bold", 10, ENCODING_INDEX_STANDARD},
170 {"Times-Italic", 12, ENCODING_INDEX_STANDARD},
171 {"Times-BoldItalic", 16, ENCODING_INDEX_STANDARD},
172 {"ZapfDingbats", 12, ENCODING_INDEX_DINGBATS},
173 {0}
174 };
175
176 /* Return the index of a standard font name, or -1 if missing. */
177 private int
pdf_find_standard_font_name(const byte * str,uint size)178 pdf_find_standard_font_name(const byte *str, uint size)
179 {
180 const pdf_standard_font_info_t *ppsf;
181
182 for (ppsf = standard_font_info; ppsf->fname; ++ppsf)
183 if (ppsf->size == size &&
184 !memcmp(ppsf->fname, (const char *)str, size)
185 )
186 return ppsf - standard_font_info;
187 return -1;
188 }
189
190 /*
191 * If there is a standard font with the same appearance (CharStrings,
192 * Private, WeightVector) as the given font, set *psame to the mask of
193 * identical properties, and return the standard-font index; otherwise,
194 * set *psame to 0 and return -1.
195 */
196 private int
find_std_appearance(const gx_device_pdf * pdev,gs_font_base * bfont,int mask,pdf_char_glyph_pair_t * pairs,int num_glyphs)197 find_std_appearance(const gx_device_pdf *pdev, gs_font_base *bfont,
198 int mask, pdf_char_glyph_pair_t *pairs, int num_glyphs)
199 {
200 bool has_uid = uid_is_UniqueID(&bfont->UID) && bfont->UID.id != 0;
201 const pdf_standard_font_t *psf = pdf_standard_fonts(pdev);
202 int i;
203
204 switch (bfont->FontType) {
205 case ft_encrypted:
206 case ft_encrypted2:
207 case ft_TrueType:
208 break;
209 default:
210 return -1;
211 }
212
213 mask |= FONT_SAME_OUTLINES;
214 for (i = 0; i < PDF_NUM_STANDARD_FONTS; ++psf, ++i) {
215 gs_font_base *cfont;
216 int code;
217
218 if (!psf->pdfont)
219 continue;
220 cfont = pdf_font_resource_font(psf->pdfont, false);
221 if (has_uid) {
222 /*
223 * Require the UIDs to match. The PostScript spec says this
224 * is the case iff the outlines are the same.
225 */
226 if (!uid_equal(&bfont->UID, &cfont->UID))
227 continue;
228 }
229 /*
230 * Require the actual outlines to match (within the given subset).
231 */
232 code = gs_copied_can_copy_glyphs((const gs_font *)cfont,
233 (const gs_font *)bfont,
234 &pairs[0].glyph, num_glyphs,
235 sizeof(pdf_char_glyph_pair_t), true);
236 if (code == gs_error_unregistered) /* Debug purpose only. */
237 return code;
238 /* Note: code < 0 means an error. Skip it here. */
239 if (code > 0)
240 return i;
241 }
242 return -1;
243 }
244
245 /*
246 * Scan a font directory for standard fonts. Return true if any new ones
247 * were found. A font is recognized as standard if it was loaded as a
248 * resource, it has a UniqueId, and it has a standard name.
249 */
250 private bool
scan_for_standard_fonts(gx_device_pdf * pdev,const gs_font_dir * dir)251 scan_for_standard_fonts(gx_device_pdf *pdev, const gs_font_dir *dir)
252 {
253 bool found = false;
254 gs_font *orig = dir->orig_fonts;
255
256 for (; orig; orig = orig->next) {
257 gs_font_base *obfont;
258
259 if (orig->FontType == ft_composite || !orig->is_resource)
260 continue;
261 obfont = (gs_font_base *)orig;
262 if (uid_is_UniqueID(&obfont->UID)) {
263 /* Is it one of the standard fonts? */
264 int i = pdf_find_standard_font_name(orig->key_name.chars,
265 orig->key_name.size);
266
267 if (i >= 0 && pdf_standard_fonts(pdev)[i].pdfont == 0) {
268 pdf_font_resource_t *pdfont;
269 int code = pdf_font_std_alloc(pdev, &pdfont, true, orig->id, obfont,
270 i);
271
272 if (code < 0)
273 continue;
274 found = true;
275 }
276 }
277 }
278 return found;
279 }
280
281 /* ---------------- Initialization ---------------- */
282
283 /*
284 * Allocate and initialize bookkeeping for outline fonts.
285 */
286 pdf_outline_fonts_t *
pdf_outline_fonts_alloc(gs_memory_t * mem)287 pdf_outline_fonts_alloc(gs_memory_t *mem)
288 {
289 pdf_outline_fonts_t *pofs =
290 gs_alloc_struct(mem, pdf_outline_fonts_t, &st_pdf_outline_fonts,
291 "pdf_outline_fonts_alloc(outline_fonts)");
292 pdf_standard_font_t *ppsf =
293 gs_alloc_struct_array(mem, PDF_NUM_STANDARD_FONTS,
294 pdf_standard_font_t,
295 &st_pdf_standard_font_element,
296 "pdf_outline_fonts_alloc(standard_fonts)");
297
298 if (pofs == 0 || ppsf == 0)
299 return 0;
300 memset(ppsf, 0, PDF_NUM_STANDARD_FONTS * sizeof(*ppsf));
301 memset(pofs, 0, sizeof(*pofs));
302 pofs->standard_fonts = ppsf;
303 return pofs;
304 }
305
306 /*
307 * Return the standard fonts array.
308 */
309 pdf_standard_font_t *
pdf_standard_fonts(const gx_device_pdf * pdev)310 pdf_standard_fonts(const gx_device_pdf *pdev)
311 {
312 return pdev->text->outline_fonts->standard_fonts;
313 }
314
315 /*
316 * Clean the standard fonts array.
317 */
318 void
pdf_clean_standard_fonts(const gx_device_pdf * pdev)319 pdf_clean_standard_fonts(const gx_device_pdf *pdev)
320 {
321 pdf_standard_font_t *ppsf = pdf_standard_fonts(pdev);
322
323 memset(ppsf, 0, PDF_NUM_STANDARD_FONTS * sizeof(*ppsf));
324 }
325
326
327 /* ---------------- Font resources ---------------- */
328
329 /* ------ Private ------ */
330
331
pdf_resize_array(gs_memory_t * mem,void ** p,int elem_size,int old_size,int new_size)332 private int pdf_resize_array(gs_memory_t *mem, void **p, int elem_size, int old_size, int new_size)
333 {
334 void *q = gs_alloc_byte_array(mem, new_size, elem_size, "pdf_resize_array");
335
336 if (q == NULL)
337 return_error(gs_error_VMerror);
338 memset((char *)q + elem_size * old_size, 0, elem_size * (new_size - old_size));
339 memcpy(q, *p, elem_size * old_size);
340 gs_free_object(mem, *p, "pdf_resize_array");
341 *p = q;
342 return 0;
343 }
344
345 /*
346 * Allocate and (minimally) initialize a font resource.
347 */
348 private int
font_resource_alloc(gx_device_pdf * pdev,pdf_font_resource_t ** ppfres,pdf_resource_type_t rtype,gs_id rid,font_type ftype,int chars_count,pdf_font_write_contents_proc_t write_contents)349 font_resource_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
350 pdf_resource_type_t rtype, gs_id rid, font_type ftype,
351 int chars_count,
352 pdf_font_write_contents_proc_t write_contents)
353 {
354 gs_memory_t *mem = pdev->pdf_memory;
355 pdf_font_resource_t *pfres;
356 double *widths = 0;
357 byte *used = 0;
358 int code;
359 bool is_CID_font = (ftype == ft_CID_encrypted || ftype == ft_CID_TrueType);
360
361 if (chars_count != 0) {
362 uint size = (chars_count + 7) / 8;
363
364 if (!is_CID_font) {
365 widths = (void *)gs_alloc_byte_array(mem, chars_count, sizeof(*widths),
366 "font_resource_alloc(Widths)");
367 } else {
368 /* Delay allocation because we don't know which WMode will be used. */
369 }
370 used = gs_alloc_bytes(mem, size, "font_resource_alloc(used)");
371 if ((!is_CID_font && widths == 0) || used == 0) {
372 code = gs_note_error(gs_error_VMerror);
373 goto fail;
374 }
375 if (!is_CID_font)
376 memset(widths, 0, chars_count * sizeof(*widths));
377 memset(used, 0, size);
378 }
379 code = pdf_alloc_resource(pdev, rtype, rid, (pdf_resource_t **)&pfres, 0L);
380 if (code < 0)
381 goto fail;
382 memset((byte *)pfres + sizeof(pdf_resource_t), 0,
383 sizeof(*pfres) - sizeof(pdf_resource_t));
384 pfres->FontType = ftype;
385 pfres->count = chars_count;
386 pfres->Widths = widths;
387 pfres->used = used;
388 pfres->write_contents = write_contents;
389 pfres->res_ToUnicode = NULL;
390 pfres->cmap_ToUnicode = NULL;
391 *ppfres = pfres;
392 return 0;
393 fail:
394 gs_free_object(mem, used, "font_resource_alloc(used)");
395 gs_free_object(mem, widths, "font_resource_alloc(Widths)");
396 return code;
397 }
398 private int
font_resource_simple_alloc(gx_device_pdf * pdev,pdf_font_resource_t ** ppfres,gs_id rid,font_type ftype,int chars_count,pdf_font_write_contents_proc_t write_contents)399 font_resource_simple_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
400 gs_id rid, font_type ftype, int chars_count,
401 pdf_font_write_contents_proc_t write_contents)
402 {
403 pdf_font_resource_t *pfres;
404 int code = font_resource_alloc(pdev, &pfres, resourceFont, rid, ftype,
405 chars_count, write_contents);
406
407 if (code < 0)
408 return code;
409 pfres->u.simple.FirstChar = 256;
410 pfres->u.simple.LastChar = -1;
411 pfres->u.simple.BaseEncoding = -1;
412 *ppfres = pfres;
413 return 0;
414 }
415 int
font_resource_encoded_alloc(gx_device_pdf * pdev,pdf_font_resource_t ** ppfres,gs_id rid,font_type ftype,pdf_font_write_contents_proc_t write_contents)416 font_resource_encoded_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
417 gs_id rid, font_type ftype,
418 pdf_font_write_contents_proc_t write_contents)
419 {
420 pdf_encoding_element_t *Encoding =
421 gs_alloc_struct_array(pdev->pdf_memory, 256, pdf_encoding_element_t,
422 &st_pdf_encoding_element,
423 "font_resource_encoded_alloc");
424 gs_point *v = (gs_point *)gs_alloc_byte_array(pdev->pdf_memory,
425 256, sizeof(gs_point), "pdf_font_simple_alloc");
426 pdf_font_resource_t *pdfont;
427 int code, i;
428
429
430 if (v == 0 || Encoding == 0) {
431 gs_free_object(pdev->pdf_memory, Encoding,
432 "font_resource_encoded_alloc");
433 gs_free_object(pdev->pdf_memory, v,
434 "font_resource_encoded_alloc");
435 return_error(gs_error_VMerror);
436 }
437 code = font_resource_simple_alloc(pdev, &pdfont, rid, ftype,
438 256, write_contents);
439 if (code < 0) {
440 gs_free_object(pdev->pdf_memory, Encoding,
441 "font_resource_encoded_alloc");
442 gs_free_object(pdev->pdf_memory, v,
443 "font_resource_encoded_alloc");
444 return_error(gs_error_VMerror);
445 }
446 if (code < 0) {
447 return code;
448 }
449 memset(v, 0, 256 * sizeof(*v));
450 memset(Encoding, 0, 256 * sizeof(*Encoding));
451 for (i = 0; i < 256; ++i)
452 Encoding[i].glyph = GS_NO_GLYPH;
453 pdfont->u.simple.Encoding = Encoding;
454 pdfont->u.simple.v = v;
455 *ppfres = pdfont;
456 return 0;
457 }
458
459 /*
460 * Record whether a Type 1 or Type 2 font is a Multiple Master instance.
461 */
462 private void
set_is_MM_instance(pdf_font_resource_t * pdfont,const gs_font_base * pfont)463 set_is_MM_instance(pdf_font_resource_t *pdfont, const gs_font_base *pfont)
464 {
465 switch (pfont->FontType) {
466 case ft_encrypted:
467 case ft_encrypted2:
468 pdfont->u.simple.s.type1.is_MM_instance =
469 ((const gs_font_type1 *)pfont)->data.WeightVector.count > 0;
470 default:
471 break;
472 }
473 }
474
475 /* ------ Generic public ------ */
476
477 /* Resize font resource arrays. */
478 int
pdf_resize_resource_arrays(gx_device_pdf * pdev,pdf_font_resource_t * pfres,int chars_count)479 pdf_resize_resource_arrays(gx_device_pdf *pdev, pdf_font_resource_t *pfres, int chars_count)
480 {
481 /* This function fixes CID fonts that provide a lesser CIDCount than
482 CIDs used in a document. Rather PS requires to print CID=0,
483 we need to provide a bigger CIDCount since we don't
484 re-encode the text. The text should look fine if the
485 viewer application substitutes the font. */
486 gs_memory_t *mem = pdev->pdf_memory;
487 int code;
488
489 if (chars_count < pfres->count)
490 return 0;
491 if (pfres->Widths != NULL) {
492 code = pdf_resize_array(mem, (void **)&pfres->Widths, sizeof(*pfres->Widths),
493 pfres->count, chars_count);
494 if (code < 0)
495 return code;
496 }
497 code = pdf_resize_array(mem, (void **)&pfres->used, sizeof(*pfres->used),
498 (pfres->count + 7) / 8, (chars_count + 7) / 8);
499 if (code < 0)
500 return code;
501 if (pfres->FontType == ft_CID_encrypted || pfres->FontType == ft_CID_TrueType) {
502 if (pfres->u.cidfont.v != NULL) {
503 code = pdf_resize_array(mem, (void **)&pfres->u.cidfont.v,
504 sizeof(*pfres->u.cidfont.v), pfres->count * 2, chars_count * 2);
505 if (code < 0)
506 return code;
507 }
508 if (pfres->u.cidfont.Widths2 != NULL) {
509 code = pdf_resize_array(mem, (void **)&pfres->u.cidfont.Widths2,
510 sizeof(*pfres->u.cidfont.Widths2), pfres->count, chars_count);
511 if (code < 0)
512 return code;
513 }
514 }
515 if (pfres->FontType == ft_CID_TrueType) {
516 if (pfres->u.cidfont.CIDToGIDMap != NULL) {
517 code = pdf_resize_array(mem, (void **)&pfres->u.cidfont.CIDToGIDMap,
518 sizeof(*pfres->u.cidfont.CIDToGIDMap), pfres->count, chars_count);
519 if (code < 0)
520 return code;
521 }
522 }
523 if (pfres->FontType == ft_CID_encrypted || pfres->FontType == ft_CID_TrueType) {
524 if (pfres->u.cidfont.used2 != NULL) {
525 code = pdf_resize_array(mem, (void **)&pfres->u.cidfont.used2,
526 sizeof(*pfres->u.cidfont.used2),
527 (pfres->count + 7) / 8, (chars_count + 7) / 8);
528 if (code < 0)
529 return code;
530 }
531 }
532 pfres->count = chars_count;
533 return 0;
534 }
535
536 /* Get the object ID of a font resource. */
537 long
pdf_font_id(const pdf_font_resource_t * pdfont)538 pdf_font_id(const pdf_font_resource_t *pdfont)
539 {
540 return pdf_resource_id((const pdf_resource_t *)pdfont);
541 }
542
543 /*
544 * Return the (copied, subset) font associated with a font resource.
545 * If this font resource doesn't have one (Type 0 or Type 3), return 0.
546 */
547 gs_font_base *
pdf_font_resource_font(const pdf_font_resource_t * pdfont,bool complete)548 pdf_font_resource_font(const pdf_font_resource_t *pdfont, bool complete)
549 {
550 if (pdfont->base_font != NULL)
551 return pdf_base_font_font(pdfont->base_font, complete);
552 if (pdfont->FontDescriptor == 0)
553 return 0;
554 return pdf_font_descriptor_font(pdfont->FontDescriptor, complete);
555 }
556
557 /*
558 * Determine the embedding status of a font. If the font is in the base
559 * 14, store its index (0..13) in *pindex and its similarity to the base
560 * font (as determined by the font's same_font procedure) in *psame.
561 */
562 private bool
font_is_symbolic(const gs_font * font)563 font_is_symbolic(const gs_font *font)
564 {
565 if (font->FontType == ft_composite)
566 return true; /* arbitrary */
567 switch (((const gs_font_base *)font)->nearest_encoding_index) {
568 case ENCODING_INDEX_STANDARD:
569 case ENCODING_INDEX_ISOLATIN1:
570 case ENCODING_INDEX_WINANSI:
571 case ENCODING_INDEX_MACROMAN:
572 return false;
573 default:
574 return true;
575 }
576 }
577 private bool
embed_list_includes(const gs_param_string_array * psa,const byte * chars,uint size)578 embed_list_includes(const gs_param_string_array *psa, const byte *chars,
579 uint size)
580 {
581 uint i;
582
583 for (i = 0; i < psa->size; ++i)
584 if (!bytes_compare(psa->data[i].data, psa->data[i].size, chars, size))
585 return true;
586 return false;
587 }
588 private bool
embed_as_standard(gx_device_pdf * pdev,gs_font * font,int index,pdf_char_glyph_pair_t * pairs,int num_glyphs)589 embed_as_standard(gx_device_pdf *pdev, gs_font *font, int index,
590 pdf_char_glyph_pair_t *pairs, int num_glyphs)
591 {
592 if (font->is_resource) {
593 return true;
594 }
595 if (find_std_appearance(pdev, (gs_font_base *)font, -1,
596 pairs, num_glyphs) == index)
597 return true;
598 if (!scan_for_standard_fonts(pdev, font->dir))
599 return false;
600 return (find_std_appearance(pdev, (gs_font_base *)font, -1,
601 pairs, num_glyphs) == index);
602 }
603 private bool
has_extension_glyphs(gs_font * pfont)604 has_extension_glyphs(gs_font *pfont)
605 {
606 psf_glyph_enum_t genum;
607 gs_glyph glyph;
608 gs_const_string str;
609 int code, j, l;
610 const int sl = strlen(gx_extendeg_glyph_name_separator);
611
612 psf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, NULL, 0, GLYPH_SPACE_NAME);
613 for (glyph = gs_no_glyph; (code = psf_enumerate_glyphs_next(&genum, &glyph)) != 1; ) {
614 code = pfont->procs.glyph_name(pfont, glyph, &str);
615 if (code < 0)
616 return code;
617 l = str.size - sl, j;
618 for (j = 0; j < l; j ++)
619 if (!memcmp(gx_extendeg_glyph_name_separator, str.data + j, sl))
620 return true;
621 }
622 psf_enumerate_glyphs_reset(&genum);
623 return false;
624 }
625
626 /*
627 * Choose a name for embedded font.
628 */
pdf_choose_font_name(gs_font * font,bool key_name)629 const gs_font_name *pdf_choose_font_name(gs_font *font, bool key_name)
630 {
631 return key_name ? (font->key_name.size != 0 ? &font->key_name : &font->font_name)
632 : (font->font_name.size != 0 ? &font->font_name : &font->key_name);
633 }
634 pdf_font_embed_t
pdf_font_embed_status(gx_device_pdf * pdev,gs_font * font,int * pindex,pdf_char_glyph_pair_t * pairs,int num_glyphs)635 pdf_font_embed_status(gx_device_pdf *pdev, gs_font *font, int *pindex,
636 pdf_char_glyph_pair_t *pairs, int num_glyphs)
637 {
638 const gs_font_name *fn = pdf_choose_font_name(font, false);
639 const byte *chars = fn->chars;
640 uint size = fn->size;
641 int index = pdf_find_standard_font_name(chars, size);
642 bool embed_as_standard_called = false;
643 bool do_embed_as_standard = false; /* Quiet compiler. */
644
645 /*
646 * The behavior of Acrobat Distiller changed between 3.0 (PDF 1.2),
647 * which will never embed the base 14 fonts, and 4.0 (PDF 1.3), which
648 * doesn't treat them any differently from any other fonts. However,
649 * if any of the base 14 fonts is not embedded, it still requires
650 * special treatment.
651 */
652 if (pindex)
653 *pindex = index;
654 if (pdev->PDFX)
655 return FONT_EMBED_YES;
656 if (pdev->CompatibilityLevel < 1.3) {
657 if (index >= 0 &&
658 (embed_as_standard_called = true,
659 do_embed_as_standard = embed_as_standard(pdev, font, index, pairs, num_glyphs))) {
660 if (pdev->ForOPDFRead && has_extension_glyphs(font))
661 return FONT_EMBED_YES;
662 return FONT_EMBED_STANDARD;
663 }
664 }
665 /* Check the Embed lists. */
666 if (!embed_list_includes(&pdev->params.NeverEmbed, chars, size) ||
667 (index >= 0 &&
668 !(embed_as_standard_called ? do_embed_as_standard :
669 (embed_as_standard_called = true,
670 (do_embed_as_standard = embed_as_standard(pdev, font, index, pairs, num_glyphs)))))
671 /* Ignore NeverEmbed for a non-standard font with a standard name */
672 ) {
673 if (pdev->params.EmbedAllFonts || font_is_symbolic(font) ||
674 embed_list_includes(&pdev->params.AlwaysEmbed, chars, size))
675 return FONT_EMBED_YES;
676 }
677 if (index >= 0 &&
678 (embed_as_standard_called ? do_embed_as_standard :
679 embed_as_standard(pdev, font, index, pairs, num_glyphs)))
680 return FONT_EMBED_STANDARD;
681 return FONT_EMBED_NO;
682 }
683
684 /*
685 * Compute the BaseFont of a font according to the algorithm described
686 * in gdevpdtf.h.
687 */
688 int
pdf_compute_BaseFont(gx_device_pdf * pdev,pdf_font_resource_t * pdfont,bool finish)689 pdf_compute_BaseFont(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, bool finish)
690 {
691 pdf_font_resource_t *pdsubf = pdfont;
692 gs_string fname;
693 uint size, extra = 0;
694 byte *data;
695
696 if (pdfont->FontType == ft_composite) {
697 int code;
698
699 pdsubf = pdfont->u.type0.DescendantFont;
700 code = pdf_compute_BaseFont(pdev, pdsubf, finish);
701 if (code < 0)
702 return code;
703 fname = pdsubf->BaseFont;
704 if (pdsubf->FontType == ft_CID_encrypted || pdsubf->FontType == ft_CID_TrueType)
705 extra = 1 + pdfont->u.type0.CMapName.size;
706 }
707 else if (pdfont->FontDescriptor == 0) {
708 /* Type 3 font, or has its BaseFont computed in some other way. */
709 return 0;
710 } else
711 fname = *pdf_font_descriptor_base_name(pdsubf->FontDescriptor);
712 size = fname.size;
713 data = gs_alloc_string(pdev->pdf_memory, size + extra,
714 "pdf_compute_BaseFont");
715 if (data == 0)
716 return_error(gs_error_VMerror);
717 memcpy(data, fname.data, size);
718 switch (pdfont->FontType) {
719 case ft_composite:
720 if (extra) {
721 data[size] = '-';
722 memcpy(data + size + 1, pdfont->u.type0.CMapName.data, extra - 1);
723 size += extra;
724 }
725 break;
726 case ft_encrypted:
727 case ft_encrypted2:
728 if (pdfont->u.simple.s.type1.is_MM_instance &&
729 !pdf_font_descriptor_embedding(pdfont->FontDescriptor)
730 ) {
731 /* Replace spaces by underscores in the base name. */
732 uint i;
733
734 for (i = 0; i < size; ++i)
735 if (data[i] == ' ')
736 data[i] = '_';
737 }
738 break;
739 case ft_TrueType:
740 case ft_CID_TrueType: {
741 /* Remove spaces from the base name. */
742 uint i, j;
743
744 for (i = j = 0; i < size; ++i)
745 if (data[i] != ' ')
746 data[j++] = data[i];
747 data = gs_resize_string(pdev->pdf_memory, data, i, j,
748 "pdf_compute_BaseFont");
749 size = j;
750 break;
751 }
752 default:
753 break;
754 }
755 pdfont->BaseFont.data = fname.data = data;
756 pdfont->BaseFont.size = fname.size = size;
757 /* Compute names for subset fonts. */
758 if (finish && pdfont->FontDescriptor != NULL &&
759 pdf_font_descriptor_is_subset(pdfont->FontDescriptor) &&
760 !pdf_has_subset_prefix(fname.data, fname.size) &&
761 pdf_font_descriptor_embedding(pdfont->FontDescriptor)
762 ) {
763 int code = pdf_add_subset_prefix(pdev, &fname, pdfont->used, pdfont->count);
764
765 if (code < 0)
766 return code;
767 pdfont->BaseFont = fname;
768 /* Don't write a UID for subset fonts. */
769 uid_set_invalid(&pdf_font_resource_font(pdfont, false)->UID);
770 }
771 if (pdfont->FontType != ft_composite && pdsubf->FontDescriptor)
772 *pdf_font_descriptor_name(pdsubf->FontDescriptor) = fname;
773 return 0;
774 }
775
776 /* ------ Type 0 ------ */
777
778 /* Allocate a Type 0 font resource. */
779 int
pdf_font_type0_alloc(gx_device_pdf * pdev,pdf_font_resource_t ** ppfres,gs_id rid,pdf_font_resource_t * DescendantFont,const gs_const_string * CMapName)780 pdf_font_type0_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
781 gs_id rid, pdf_font_resource_t *DescendantFont,
782 const gs_const_string *CMapName)
783 {
784 int code = font_resource_alloc(pdev, ppfres, resourceFont, rid,
785 ft_composite, 0, pdf_write_contents_type0);
786
787 if (code >= 0) {
788 (*ppfres)->u.type0.DescendantFont = DescendantFont;
789 (*ppfres)->u.type0.CMapName = *CMapName;
790 code = pdf_compute_BaseFont(pdev, *ppfres, false);
791 }
792 return code;
793 }
794
795 /* ------ Type 3 ------ */
796
797 /* Allocate a Type 3 font resource for sinthesyzed bitmap fonts. */
798 int
pdf_font_type3_alloc(gx_device_pdf * pdev,pdf_font_resource_t ** ppfres,pdf_font_write_contents_proc_t write_contents)799 pdf_font_type3_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
800 pdf_font_write_contents_proc_t write_contents)
801 {
802 return font_resource_simple_alloc(pdev, ppfres, gs_no_id, ft_user_defined,
803 256, write_contents);
804 }
805
806 /* ------ Standard (base 14) Type 1 or TrueType ------ */
807
808 /* Allocate a standard (base 14) font resource. */
809 int
pdf_font_std_alloc(gx_device_pdf * pdev,pdf_font_resource_t ** ppfres,bool is_original,gs_id rid,gs_font_base * pfont,int index)810 pdf_font_std_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
811 bool is_original, gs_id rid, gs_font_base *pfont, int index)
812 {
813 pdf_font_resource_t *pdfont;
814 int code = font_resource_encoded_alloc(pdev, &pdfont, rid, pfont->FontType,
815 pdf_write_contents_std);
816 const pdf_standard_font_info_t *psfi = &standard_font_info[index];
817 pdf_standard_font_t *psf = &pdf_standard_fonts(pdev)[index];
818 gs_matrix *orig_matrix = (is_original ? &pfont->FontMatrix : &psf->orig_matrix);
819
820 if (code < 0 ||
821 (code = pdf_base_font_alloc(pdev, &pdfont->base_font, pfont, orig_matrix, true, true)) < 0
822 )
823 return code;
824 pdfont->BaseFont.data = (byte *)psfi->fname; /* break const */
825 pdfont->BaseFont.size = strlen(psfi->fname);
826 set_is_MM_instance(pdfont, pfont);
827 if (is_original) {
828 psf->pdfont = pdfont;
829 psf->orig_matrix = pfont->FontMatrix;
830 }
831 *ppfres = pdfont;
832 return 0;
833 }
834
835 /* ------ Other Type 1 or TrueType ------ */
836
837 /* Allocate a Type 1 or TrueType font resource. */
838 int
pdf_font_simple_alloc(gx_device_pdf * pdev,pdf_font_resource_t ** ppfres,gs_id rid,pdf_font_descriptor_t * pfd)839 pdf_font_simple_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
840 gs_id rid, pdf_font_descriptor_t *pfd)
841 {
842 pdf_font_resource_t *pdfont;
843 int code;
844
845 code = font_resource_encoded_alloc(pdev, &pdfont, rid,
846 pdf_font_descriptor_FontType(pfd),
847 pdf_write_contents_simple);
848
849 pdfont->FontDescriptor = pfd;
850 set_is_MM_instance(pdfont, pdf_font_descriptor_font(pfd, false));
851 *ppfres = pdfont;
852 return pdf_compute_BaseFont(pdev, pdfont, false);
853 }
854
855 /* ------ CID-keyed ------ */
856
857 /* Allocate a CIDFont resource. */
858 int
pdf_font_cidfont_alloc(gx_device_pdf * pdev,pdf_font_resource_t ** ppfres,gs_id rid,pdf_font_descriptor_t * pfd)859 pdf_font_cidfont_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
860 gs_id rid, pdf_font_descriptor_t *pfd)
861 {
862 font_type FontType = pdf_font_descriptor_FontType(pfd);
863 gs_font_base *font = pdf_font_descriptor_font(pfd, false);
864 int chars_count;
865 int code;
866 pdf_font_write_contents_proc_t write_contents;
867 const gs_cid_system_info_t *pcidsi;
868 ushort *map = 0;
869 pdf_font_resource_t *pdfont;
870
871 switch (FontType) {
872 case ft_CID_encrypted:
873 chars_count = ((const gs_font_cid0 *)font)->cidata.common.CIDCount;
874 pcidsi = &((const gs_font_cid0 *)font)->cidata.common.CIDSystemInfo;
875 write_contents = pdf_write_contents_cid0;
876 break;
877 case ft_CID_TrueType:
878 chars_count = ((const gs_font_cid2 *)font)->cidata.common.CIDCount;
879 pcidsi = &((const gs_font_cid2 *)font)->cidata.common.CIDSystemInfo;
880 map = (void *)gs_alloc_byte_array(pdev->pdf_memory, chars_count,
881 sizeof(*map), "CIDToGIDMap");
882 if (map == 0)
883 return_error(gs_error_VMerror);
884 memset(map, 0, chars_count * sizeof(*map));
885 write_contents = pdf_write_contents_cid2;
886 break;
887 default:
888 return_error(gs_error_rangecheck);
889 }
890 code = font_resource_alloc(pdev, &pdfont, resourceCIDFont, rid, FontType,
891 chars_count, write_contents);
892 if (code < 0)
893 return code;
894 pdfont->FontDescriptor = pfd;
895 pdfont->u.cidfont.CIDToGIDMap = map;
896 /* fixme : Likely pdfont->u.cidfont.CIDToGIDMap duplicates
897 pdfont->FontDescriptor->base_font->copied->client_data->CIDMap.
898 Only difference is 0xFFFF designates unmapped CIDs.
899 */
900 pdfont->u.cidfont.Widths2 = NULL;
901 pdfont->u.cidfont.v = NULL;
902 pdfont->u.cidfont.parent = NULL;
903 /* Don' know whether the font will use WMode 1,
904 so reserve it now. */
905 pdfont->u.cidfont.used2 = gs_alloc_bytes(pdev->pdf_memory,
906 (chars_count + 7) / 8, "pdf_font_cidfont_alloc");
907 if (pdfont->u.cidfont.used2 == NULL)
908 return_error(gs_error_VMerror);
909 memset(pdfont->u.cidfont.used2, 0, (chars_count + 7) / 8);
910 /*
911 * Write the CIDSystemInfo now, so we don't try to access it after
912 * the font may no longer be available.
913 */
914 {
915 long cidsi_id = pdf_begin_separate(pdev);
916
917 code = pdf_write_cid_system_info(pdev, pcidsi, cidsi_id);
918 if (code < 0)
919 return code;
920 pdf_end_separate(pdev);
921 pdfont->u.cidfont.CIDSystemInfo_id = cidsi_id;
922 }
923 *ppfres = pdfont;
924 return pdf_compute_BaseFont(pdev, pdfont, false);
925 }
926
927 int
pdf_obtain_cidfont_widths_arrays(gx_device_pdf * pdev,pdf_font_resource_t * pdfont,int wmode,double ** w,double ** w0,double ** v)928 pdf_obtain_cidfont_widths_arrays(gx_device_pdf *pdev, pdf_font_resource_t *pdfont,
929 int wmode, double **w, double **w0, double **v)
930 {
931 gs_memory_t *mem = pdev->pdf_memory;
932 double *ww, *vv = 0, *ww0 = 0;
933 int chars_count = pdfont->count;
934
935 *w0 = (wmode ? pdfont->Widths : NULL);
936 *v = (wmode ? pdfont->u.cidfont.v : NULL);
937 *w = (wmode ? pdfont->u.cidfont.Widths2 : pdfont->Widths);
938 if (*w == NULL) {
939 ww = (double *)gs_alloc_byte_array(mem, chars_count, sizeof(*ww),
940 "pdf_obtain_cidfont_widths_arrays");
941 if (wmode) {
942 vv = (double *)gs_alloc_byte_array(mem, chars_count, sizeof(*vv) * 2,
943 "pdf_obtain_cidfont_widths_arrays");
944 if (pdfont->Widths == 0) {
945 ww0 = (double *)gs_alloc_byte_array(mem, chars_count, sizeof(*ww0),
946 "pdf_obtain_cidfont_widths_arrays");
947 pdfont->Widths = *w0 = ww0;
948 if (ww0 != 0)
949 memset(ww0, 0, chars_count * sizeof(*ww));
950 } else
951 *w0 = ww0 = pdfont->Widths;
952 }
953 if (ww == 0 || (wmode && vv == 0) || (wmode && ww0 == 0)) {
954 gs_free_object(mem, ww, "pdf_obtain_cidfont_widths_arrays");
955 gs_free_object(mem, vv, "pdf_obtain_cidfont_widths_arrays");
956 gs_free_object(mem, ww0, "pdf_obtain_cidfont_widths_arrays");
957 return_error(gs_error_VMerror);
958 }
959 if (wmode)
960 memset(vv, 0, chars_count * 2 * sizeof(*vv));
961 memset(ww, 0, chars_count * sizeof(*ww));
962 if (wmode) {
963 pdfont->u.cidfont.Widths2 = *w = ww;
964 pdfont->u.cidfont.v = *v = vv;
965 } else {
966 pdfont->Widths = *w = ww;
967 *v = NULL;
968 }
969 }
970 return 0;
971 }
972
973 /* ---------------- CMap resources ---------------- */
974
975 /*
976 * Allocate a CMap resource.
977 */
978 int
pdf_cmap_alloc(gx_device_pdf * pdev,const gs_cmap_t * pcmap,pdf_resource_t ** ppres,int font_index_only)979 pdf_cmap_alloc(gx_device_pdf *pdev, const gs_cmap_t *pcmap,
980 pdf_resource_t **ppres, int font_index_only)
981 {
982 return pdf_write_cmap(pdev, pcmap, ppres, font_index_only);
983 }
984