xref: /plan9/sys/src/cmd/gs/src/gdevpdtf.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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