xref: /plan9/sys/src/cmd/gs/src/gdevpdtw.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: gdevpdtw.c,v 1.44 2005/06/06 15:32:22 igor Exp $ */
18 /* Font resource writing for pdfwrite text */
19 #include "memory_.h"
20 #include "gx.h"
21 #include "gserrors.h"
22 #include "gxfcmap.h"
23 #include "gxfont.h"
24 #include "gscencs.h"
25 #include "gdevpsf.h"
26 #include "gdevpdfx.h"
27 #include "gdevpdfo.h"		/* for object->written */
28 #include "gdevpdtd.h"		/* for writing FontDescriptor */
29 #include "gdevpdtf.h"
30 #include "gdevpdti.h"		/* for writing bitmap fonts Encoding */
31 #include "gdevpdtw.h"
32 #include "gdevpdtv.h"
33 #include "sarc4.h"
34 
35 private const char *const encoding_names[] = {
36     KNOWN_REAL_ENCODING_NAMES
37 };
38 
39 /* ================ Font resource writing ================ */
40 
41 /* ---------------- Private ---------------- */
42 
43 /* Write the Widths for a font. */
44 private int
pdf_write_Widths(gx_device_pdf * pdev,int first,int last,const double * widths)45 pdf_write_Widths(gx_device_pdf *pdev, int first, int last, const double *widths)
46 {
47     stream *s = pdev->strm;
48     int i;
49 
50     if (first > last)
51 	first = last = 0;
52     pprintd2(s, "/FirstChar %d/LastChar %d/Widths[", first, last);
53     for (i = first; i <= last; ++i)
54     	pprintg1(s, (i & 15 ? " %g" : "\n%g"), psdf_round(widths[i], 100, 10));
55     stream_puts(s, "]\n");
56     return 0;
57 }
58 
59 /* Check strings equality. */
60 private bool
strings_equal(const gs_const_string * str0,const gs_const_string * str1)61 strings_equal(const gs_const_string *str0, const gs_const_string *str1)
62 {
63     return str0->size == str1->size &&
64 	   !memcmp(str0->data, str1->data, str0->size);
65 }
66 
67 /* Check if an encoding element differs from a standard one. */
68 private int
pdf_different_encoding_element(const pdf_font_resource_t * pdfont,int ch,int encoding_index)69 pdf_different_encoding_element(const pdf_font_resource_t *pdfont, int ch, int encoding_index)
70 {
71     if (pdfont->u.simple.Encoding[ch].is_difference)
72 	return 1;
73     else if (encoding_index != ENCODING_INDEX_UNKNOWN) {
74 	gs_glyph glyph0 = gs_c_known_encode(ch, encoding_index);
75 	gs_glyph glyph1 = pdfont->u.simple.Encoding[ch].glyph;
76 	gs_const_string str;
77 	int code = gs_c_glyph_name(glyph0, &str);
78 
79 	if (code < 0)
80 	    return code; /* Must not happen */
81 	if (glyph1 != GS_NO_GLYPH)
82 	    if (!strings_equal(&str, &pdfont->u.simple.Encoding[ch].str))
83 		return 1;
84     }
85     return 0;
86 }
87 
88 /* Find an index of a different encoding element. */
89 int
pdf_different_encoding_index(const pdf_font_resource_t * pdfont,int ch0)90 pdf_different_encoding_index(const pdf_font_resource_t *pdfont, int ch0)
91 {
92     gs_encoding_index_t base_encoding = pdfont->u.simple.BaseEncoding;
93     int ch, code;
94 
95     for (ch = ch0; ch < 256; ++ch) {
96 	code = pdf_different_encoding_element(pdfont, ch, base_encoding);
97 	if (code < 0)
98 	    return code; /* Must not happen */
99 	if (code)
100 	    break;
101     }
102     return ch;
103 }
104 
105 /* Check for unknown encode (simple fonts only). */
106 private bool
pdf_simple_font_needs_ToUnicode(const pdf_font_resource_t * pdfont)107 pdf_simple_font_needs_ToUnicode(const pdf_font_resource_t *pdfont)
108 {
109     int ch;
110     unsigned char mask = (pdfont->FontType == ft_encrypted || pdfont->FontType == ft_encrypted2
111 		? GS_C_PDF_GOOD_GLYPH_MASK : GS_C_PDF_GOOD_NON_SYMBOL_MASK);
112 
113     if (pdfont->u.simple.Encoding == NULL)
114 	return true; /* Bitmap Type 3 fonts have no pdfont->u.simple.Encoding . */
115     for (ch = 0; ch < 256; ++ch) {
116 	pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch];
117 	gs_glyph glyph = pet->glyph;
118 
119 	if (glyph == GS_NO_GLYPH)
120 	    continue;
121 	if (glyph < gs_c_min_std_encoding_glyph || glyph >= GS_MIN_CID_GLYPH) {
122 	    if (pet->str.size == 0)
123 		return true;
124 	    glyph = gs_c_name_glyph(pet->str.data, pet->str.size);
125 	    if (glyph == GS_NO_GLYPH)
126 		return true;
127 	}
128         glyph -= gs_c_min_std_encoding_glyph;
129         if( glyph > GS_C_PDF_MAX_GOOD_GLYPH ||
130            !(gs_c_pdf_glyph_type[glyph >> 2] & (mask << (( glyph & 3 )<<1) )))
131           return true;
132     }
133     return false;
134 }
135 
136 /* Write Encoding differencrs. */
137 int
pdf_write_encoding(gx_device_pdf * pdev,const pdf_font_resource_t * pdfont,long id,int ch)138 pdf_write_encoding(gx_device_pdf *pdev, const pdf_font_resource_t *pdfont, long id, int ch)
139 {
140     /* Note : this truncates extended glyph names to original names. */
141     stream *s;
142     gs_encoding_index_t base_encoding = pdfont->u.simple.BaseEncoding;
143     const int sl = strlen(gx_extendeg_glyph_name_separator);
144     int prev = 256, code;
145 
146     pdf_open_separate(pdev, id);
147     s = pdev->strm;
148     stream_puts(s, "<</Type/Encoding");
149     if (base_encoding < 0 && pdev->ForOPDFRead)
150 	base_encoding = ENCODING_INDEX_STANDARD;
151     if (base_encoding > 0)
152 	pprints1(s, "/BaseEncoding/%s", encoding_names[base_encoding]);
153     stream_puts(s, "/Differences[");
154     for (; ch < 256; ++ch) {
155 	code = pdf_different_encoding_element(pdfont, ch, base_encoding);
156 	if (code < 0)
157 	    return code; /* Must not happen */
158 	if (code == 0 && pdfont->FontType == ft_user_defined) {
159 	    /* PDF 1.4 spec Appendix H Note 42 says that
160 	     * Acrobat 4 can't properly handle Base Encoding.
161 	     * Enforce writing differences against that.
162 	     */
163 	    if (pdfont->used[ch >> 3] & 0x80 >> (ch & 7))
164 		if (pdfont->u.simple.Encoding[ch].str.size)
165 		    code = 1;
166 	}
167 	if (code) {
168 	    const byte *d = pdfont->u.simple.Encoding[ch].str.data;
169 	    int i, l = pdfont->u.simple.Encoding[ch].str.size;
170 
171     	    if (pdev->HavePDFWidths) {
172 		for (i = 0; i + sl < l; i++)
173 		    if (!memcmp(d + i, gx_extendeg_glyph_name_separator, sl)) {
174 			l = i;
175 			break;
176 		    }
177 	    }
178 	    if (ch != prev + 1)
179 		pprintd1(s, "\n%d", ch);
180 	    pdf_put_name(pdev, d, l);
181 	    prev = ch;
182 	}
183     }
184     stream_puts(s, "]>>\n");
185     pdf_end_separate(pdev);
186     return 0;
187 }
188 
189 /* Write Encoding reference. */
190 int
pdf_write_encoding_ref(gx_device_pdf * pdev,const pdf_font_resource_t * pdfont,long id)191 pdf_write_encoding_ref(gx_device_pdf *pdev,
192 	  const pdf_font_resource_t *pdfont, long id)
193 {
194     stream *s = pdev->strm;
195 
196     if (id != 0)
197 	pprintld1(s, "/Encoding %ld 0 R", id);
198     else if (pdfont->u.simple.BaseEncoding > 0) {
199 	gs_encoding_index_t base_encoding = pdfont->u.simple.BaseEncoding;
200 	pprints1(s, "/Encoding/%s", encoding_names[base_encoding]);
201     }
202     return 0;
203 }
204 
205 /* Write the Subtype and Encoding for a simple font. */
206 private int
pdf_write_simple_contents(gx_device_pdf * pdev,const pdf_font_resource_t * pdfont)207 pdf_write_simple_contents(gx_device_pdf *pdev,
208 			  const pdf_font_resource_t *pdfont)
209 {
210     stream *s = pdev->strm;
211     long diff_id = 0;
212     int ch = (pdfont->u.simple.Encoding ? 0 : 256);
213     int code = 0;
214 
215     ch = pdf_different_encoding_index(pdfont, ch);
216     if (ch < 256)
217 	diff_id = pdf_obj_ref(pdev);
218     code = pdf_write_encoding_ref(pdev, pdfont, diff_id);
219     if (code < 0)
220 	return code;
221     pprints1(s, "/Subtype/%s>>\n",
222 	     (pdfont->FontType == ft_TrueType ? "TrueType" :
223 	      pdfont->u.simple.s.type1.is_MM_instance ? "MMType1" : "Type1"));
224     pdf_end_separate(pdev);
225     if (diff_id) {
226 	code = pdf_write_encoding(pdev, pdfont, diff_id, ch);
227 	if (code < 0)
228 	    return code;
229     }
230     return 0;
231 }
232 
233 /*
234  * Write the W[2] entries for a CIDFont.  *pdfont is known to be a
235  * CIDFont (type 0 or 2).
236  */
237 private bool
pdf_compute_CIDFont_default_widths(const pdf_font_resource_t * pdfont,int wmode,int * pdw,int * pdv)238 pdf_compute_CIDFont_default_widths(const pdf_font_resource_t *pdfont, int wmode, int *pdw, int *pdv)
239 {
240     psf_glyph_enum_t genum;
241     gs_glyph glyph;
242     ushort counts[1500]; /* Some CID fonts use vertical widths 1026 .*/
243     int dw_count = 0, i, dwi = 0, neg_count = 0, pos_count = 0;
244     double *w = (wmode ? pdfont->u.cidfont.Widths2 : pdfont->Widths);
245 
246     /* We don't wont to scan for both negative and positive widths,
247      * to save the C stack space.
248      * Doubtly they both are used in same font.
249      * So just count positive and negative widths separately
250      * and use the corresponding sign.
251      * fixme : implement 2 hystograms.
252      */
253     psf_enumerate_bits_begin(&genum, NULL,
254 			     wmode ? pdfont->u.cidfont.used2 : pdfont->used,
255 			     pdfont->count, GLYPH_SPACE_INDEX);
256     memset(counts, 0, sizeof(counts));
257     while (!psf_enumerate_glyphs_next(&genum, &glyph)) {
258         int i = glyph - GS_MIN_CID_GLYPH;
259 
260 	if ( i < pdfont->count) { /* safety */
261 	    int width = (int)(w[i] + 0.5);
262 
263 	    counts[min(any_abs(width), countof(counts) - 1)]++;
264 	    if (width > 0)
265 		pos_count++;
266 	    else if (width < 0)
267 		neg_count++;
268 	}
269     }
270     for (i = 1; i < countof(counts); ++i)
271 	if (counts[i] > dw_count)
272 	    dwi = i, dw_count = counts[i];
273     *pdw = (neg_count > pos_count ? -dwi : dwi);
274     *pdv = 0;
275     if (wmode) {
276 	psf_enumerate_glyphs_reset(&genum);
277 	while (!psf_enumerate_glyphs_next(&genum, &glyph)) {
278 	    int i = glyph - GS_MIN_CID_GLYPH;
279 
280 	    if ( i < pdfont->count) { /* safety */
281 		int width = (int)(w[i] + 0.5);
282 
283 		if (min(any_abs(width), countof(counts) - 1) == any_abs(dwi)) {
284 		    *pdv = (int)(pdfont->u.cidfont.v[i * 2 + 1] + 0.5);
285 		    break;
286 		}
287 	    }
288 	}
289     }
290     return (dw_count + counts[0] > 0);
291 }
292 
293 /*
294  * Write the [D]W[2] entries for a CIDFont.  *pdfont is known to be a
295  * CIDFont (type 0 or 2).
296  */
297 private int
pdf_write_CIDFont_widths(gx_device_pdf * pdev,const pdf_font_resource_t * pdfont,int wmode)298 pdf_write_CIDFont_widths(gx_device_pdf *pdev,
299 			 const pdf_font_resource_t *pdfont, int wmode)
300 {
301     /*
302      * The values of the CIDFont width keys are as follows:
303      *   DW = w (default 0)
304      *   W = [{c [w ...] | cfirst clast w}*]
305      *   DW2 = [vy w1y] (default [880 -1000])
306      *   W2 = [{c [w1y vx vy ...] | cfirst clast w1y vx vy}*]
307      */
308     stream *s = pdev->strm;
309     psf_glyph_enum_t genum;
310     gs_glyph glyph;
311     int dw = 0, dv = 0, prev = -2;
312     const char *Widths_key = (wmode ? "/W2" : "/W");
313     double *w = (wmode ? pdfont->u.cidfont.Widths2 : pdfont->Widths);
314 
315     /* Compute and write default width : */
316     if (pdf_compute_CIDFont_default_widths(pdfont, wmode, &dw, &dv)) {
317 	if (wmode) {
318 	    pprintd2(s, "/DW2 [%d %d]\n", dv, dw);
319 	} else
320 	    pprintd1(s, "/DW %d\n", dw);
321     }
322 
323     /*
324      * Now write all widths different from the default one.  Currently we make no
325      * attempt to optimize this: we write every width individually.
326      */
327     psf_enumerate_bits_begin(&genum, NULL,
328 			     wmode ? pdfont->u.cidfont.used2 : pdfont->used,
329 			     pdfont->count, GLYPH_SPACE_INDEX);
330     {
331 	while (!psf_enumerate_glyphs_next(&genum, &glyph)) {
332 	    int cid = glyph - GS_MIN_CID_GLYPH;
333 	    int width = (int)(w[cid] + 0.5);
334 
335 #if 0 /* Must write zero widths - see test file of the bug Bug 687681.
336 	 We don't enumerate unused glyphs here due to pdfont->used. */
337 	    if (width == 0)
338 		continue; /* Don't write for unused glyphs. */
339 #else
340 	    {	/* Check whether copied font really have this glyph.
341 	           debugged with 401-01.ps, which uses undefined CIDs. */
342 		gs_font_base *pfont = pdf_font_resource_font(pdfont, false);
343 		gs_glyph_info_t info;
344 
345 		if (pdfont != NULL) {
346 		    if (pfont->procs.glyph_info((gs_font *)pfont, glyph, NULL, 0, &info) < 0)
347 			continue;
348 		}
349 	    }
350 #endif
351 	    if (cid == prev + 1) {
352 		if (wmode) {
353 		    int vx = (int)(pdfont->u.cidfont.v[cid * 2 + 0] + 0.5);
354 		    int vy = (int)(pdfont->u.cidfont.v[cid * 2 + 1] + 0.5);
355 
356 		    pprintd3(s, "\n%d %d %d", width, vx, vy);
357 		} else
358 		    pprintd1(s, "\n%d", width);
359 	    } else if (width == dw &&
360 		    (!wmode || (int)(pdfont->u.cidfont.v[cid * 2 + 0] + 0.5) ==
361 				(int)(pdfont->Widths[cid] / 2 + 0.5)) &&
362 		    (!wmode || (int)(pdfont->u.cidfont.v[cid * 2 + 1] + 0.5) == dv))
363 		continue;
364 	    else {
365 		if (prev >= 0)
366 		    stream_puts(s, "]\n");
367 		else {
368 		    stream_puts(s, Widths_key);
369 		    stream_puts(s, "[");
370 		}
371 		if (wmode) {
372 		    int vx = (int)(pdfont->u.cidfont.v[cid * 2 + 0] + 0.5);
373 		    int vy = (int)(pdfont->u.cidfont.v[cid * 2 + 1] + 0.5);
374 
375 		    pprintd4(s, "%d[%d %d %d", cid, width, vx, vy);
376 		} else
377 		    pprintd2(s, "%d[%d", cid, width);
378 	    }
379 	    prev = cid;
380 	}
381 	if (prev >= 0)
382 	    stream_puts(s, "]]\n");
383     }
384 
385     return 0;
386 }
387 
388 /* ---------------- Specific FontTypes ---------------- */
389 
390 /* Write the contents of a Type 0 font resource. */
391 int
pdf_write_contents_type0(gx_device_pdf * pdev,pdf_font_resource_t * pdfont)392 pdf_write_contents_type0(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
393 {
394     stream *s = pdev->strm;
395 
396     /*
397      * The Encoding name might be missing if an error occurred when
398      * creating the font resource.
399      */
400     if (pdfont->u.type0.Encoding_name[0])
401 	pprints1(s, "/Encoding %s", pdfont->u.type0.Encoding_name);
402     pprintld1(s, "/DescendantFonts[%ld 0 R]",
403 	      pdf_font_id(pdfont->u.type0.DescendantFont));
404     stream_puts(s, "/Subtype/Type0>>\n");
405     pdf_end_separate(pdev);
406     return 0;
407 }
408 
409 /*
410  * Finish writing the contents of a Type 3 font resource (FontBBox, Widths,
411  * Subtype).
412  */
413 int
pdf_finish_write_contents_type3(gx_device_pdf * pdev,pdf_font_resource_t * pdfont)414 pdf_finish_write_contents_type3(gx_device_pdf *pdev,
415 				pdf_font_resource_t *pdfont)
416 {
417     stream *s = pdev->strm;
418 
419     pdf_write_font_bbox(pdev, &pdfont->u.simple.s.type3.FontBBox);
420     pdf_write_Widths(pdev, pdfont->u.simple.FirstChar,
421 		    pdfont->u.simple.LastChar, pdfont->Widths);
422     stream_puts(s, "/Subtype/Type3>>\n");
423     pdf_end_separate(pdev);
424     return 0;
425 }
426 
427 /* Write the contents of a standard (base 14) font resource. */
428 int
pdf_write_contents_std(gx_device_pdf * pdev,pdf_font_resource_t * pdfont)429 pdf_write_contents_std(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
430 {
431     return pdf_write_simple_contents(pdev, pdfont);
432 }
433 
434 /* Write the contents of a simple (Type 1 or Type 42) font resource. */
435 int
pdf_write_contents_simple(gx_device_pdf * pdev,pdf_font_resource_t * pdfont)436 pdf_write_contents_simple(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
437 {
438     pdf_write_Widths(pdev, pdfont->u.simple.FirstChar,
439 		     pdfont->u.simple.LastChar, pdfont->Widths);
440     return pdf_write_simple_contents(pdev, pdfont);
441 }
442 
443 /* Write the contents of a CIDFont resource. */
444 private int
write_contents_cid_common(gx_device_pdf * pdev,pdf_font_resource_t * pdfont,int subtype)445 write_contents_cid_common(gx_device_pdf *pdev, pdf_font_resource_t *pdfont,
446 			  int subtype)
447 {
448     /* Write [D]W[2], CIDSystemInfo, and Subtype, and close the object. */
449     stream *s = pdev->strm;
450     int code;
451 
452     if (pdfont->Widths != 0) {
453 	code = pdf_write_CIDFont_widths(pdev, pdfont, 0);
454 	if (code < 0)
455 	    return code;
456     } else {
457 	/* With a vertical font, the viewer uses /DW
458 	   to determine glyph width to compute its v-vector. */
459 	stream_puts(s, "/DW 0\n");
460     }
461     if (pdfont->u.cidfont.Widths2 != 0) {
462 	code = pdf_write_CIDFont_widths(pdev, pdfont, 1);
463 	if (code < 0)
464 	    return code;
465     }
466     if (pdfont->u.cidfont.CIDSystemInfo_id)
467 	pprintld1(s, "/CIDSystemInfo %ld 0 R",
468 		  pdfont->u.cidfont.CIDSystemInfo_id);
469     pprintd1(s, "/Subtype/CIDFontType%d>>\n", subtype);
470     pdf_end_separate(pdev);
471     return 0;
472 }
473 int
pdf_write_contents_cid0(gx_device_pdf * pdev,pdf_font_resource_t * pdfont)474 pdf_write_contents_cid0(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
475 {
476     return write_contents_cid_common(pdev, pdfont, 0);
477 }
478 int
pdf_write_contents_cid2(gx_device_pdf * pdev,pdf_font_resource_t * pdfont)479 pdf_write_contents_cid2(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
480 {
481     int count = pdfont->count;
482     long map_id = 0;
483     psf_glyph_enum_t genum;
484     gs_glyph glyph;
485     int code;
486 
487     /* Check for the identity CIDMap. */
488     psf_enumerate_bits_begin(&genum, NULL, pdfont->used, count,
489 			     GLYPH_SPACE_INDEX);
490     while (!psf_enumerate_glyphs_next(&genum, &glyph)) {
491 	int cid = glyph - GS_MIN_CID_GLYPH;
492 	int gid = pdfont->u.cidfont.CIDToGIDMap[cid];
493 
494 	if (gid != cid) {	/* non-identity map */
495 	    map_id = pdf_obj_ref(pdev);
496 	    pprintld1(pdev->strm, "/CIDToGIDMap %ld 0 R\n", map_id);
497 	    break;
498 	}
499     }
500 
501     code = write_contents_cid_common(pdev, pdfont, 2);
502     if (code < 0)
503 	return code;
504 
505     if (map_id) {
506 	pdf_data_writer_t writer;
507 	int i;
508 
509 	pdf_begin_data_stream(pdev, &writer,
510 	    DATA_STREAM_BINARY | DATA_STREAM_COMPRESS,
511 		    /* Don't set DATA_STREAM_ENCRYPT since we write to a temporary file.
512 		       See comment in pdf_begin_encrypt. */
513 		    map_id);
514 	for (i = 0; i < count; ++i) {
515 	    uint gid = pdfont->u.cidfont.CIDToGIDMap[i];
516 
517 	    stream_putc(writer.binary.strm, (byte)(gid >> 8));
518 	    stream_putc(writer.binary.strm, (byte)(gid));
519 	}
520 	code = pdf_end_data(&writer);
521     }
522     return code;
523 }
524 
525 /* ---------------- External entries ---------------- */
526 
527 /* Write a font resource. */
528 private int
pdf_write_font_resource(gx_device_pdf * pdev,pdf_font_resource_t * pdfont)529 pdf_write_font_resource(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
530 {
531     stream *s;
532 
533     if (pdfont->cmap_ToUnicode != NULL && pdfont->res_ToUnicode == NULL)
534 	if (((pdfont->FontType == ft_composite) &&
535 		!gs_cmap_is_identity(pdfont->cmap_ToUnicode, -1)) ||
536 	    ((pdfont->FontType == ft_encrypted || pdfont->FontType == ft_encrypted2 ||
537 		pdfont->FontType == ft_TrueType || pdfont->FontType == ft_user_defined) &&
538 		pdf_simple_font_needs_ToUnicode(pdfont))
539 	   ) {
540 	    pdf_resource_t *prcmap;
541 	    int code = pdf_cmap_alloc(pdev, pdfont->cmap_ToUnicode, &prcmap, -1);
542 
543 	    if (code < 0)
544 		return code;
545 	    pdfont->res_ToUnicode = prcmap;
546 	}
547     pdf_open_separate(pdev, pdf_font_id(pdfont));
548     s = pdev->strm;
549     stream_puts(s, "<<");
550     if (pdfont->BaseFont.size > 0) {
551 	stream_puts(s, "/BaseFont");
552 	pdf_put_name(pdev, pdfont->BaseFont.data, pdfont->BaseFont.size);
553     }
554     if (pdfont->FontDescriptor)
555 	pprintld1(s, "/FontDescriptor %ld 0 R",
556 		  pdf_font_descriptor_id(pdfont->FontDescriptor));
557     if (pdfont->res_ToUnicode)
558 	pprintld1(s, "/ToUnicode %ld 0 R",
559 		  pdf_resource_id((const pdf_resource_t *)pdfont->res_ToUnicode));
560     if (pdev->CompatibilityLevel > 1.0)
561 	stream_puts(s, "/Type/Font\n");
562     else
563 	pprintld1(s, "/Type/Font/Name/R%ld\n", pdf_font_id(pdfont));
564     if (pdev->ForOPDFRead && pdfont->global)
565 	stream_puts(s, "/.Global true\n");
566     return pdfont->write_contents(pdev, pdfont);
567 }
568 
569 /*
570  * Close the text-related parts of a document, including writing out font
571  * and related resources.
572  */
573 private int
write_font_resources(gx_device_pdf * pdev,pdf_resource_list_t * prlist)574 write_font_resources(gx_device_pdf *pdev, pdf_resource_list_t *prlist)
575 {
576     int j;
577     pdf_resource_t *pres;
578 
579     for (j = 0; j < NUM_RESOURCE_CHAINS; ++j)
580 	for (pres = prlist->chains[j]; pres != 0; pres = pres->next) {
581 	    pdf_font_resource_t *const pdfont = (pdf_font_resource_t *)pres;
582 	    int code = pdf_compute_BaseFont(pdev, pdfont, true);
583 
584 	    if (code < 0)
585 		return code;
586 	    code = pdf_write_font_resource(pdev, pdfont);
587 	    if (code < 0)
588 		return code;
589 	    pdfont->object->written = true;
590 	}
591     return 0;
592 }
593 int
pdf_finish_font_descriptors(gx_device_pdf * pdev,int (* finish_proc)(gx_device_pdf *,pdf_font_descriptor_t *))594 pdf_finish_font_descriptors(gx_device_pdf *pdev,
595 			int (*finish_proc)(gx_device_pdf *,
596 					   pdf_font_descriptor_t *))
597 {
598     int j;
599     pdf_resource_t *pres;
600 
601     for (j = 0; j < NUM_RESOURCE_CHAINS; ++j)
602 	for (pres = pdev->resources[resourceFontDescriptor].chains[j];
603 	     pres != 0; pres = pres->next
604 	     ) {
605 	    int code = finish_proc(pdev, (pdf_font_descriptor_t *)pres);
606 
607 	    if (code < 0)
608 		return code;
609 	}
610     return 0;
611 }
612 int
pdf_close_text_document(gx_device_pdf * pdev)613 pdf_close_text_document(gx_device_pdf *pdev)
614 {
615     int code;
616 
617     /*
618      * Finish the descriptors and write any embedded fonts, but don't
619      * write the descriptors yet; then write the fonts; finally write
620      * the descriptors.
621      */
622 
623     pdf_clean_standard_fonts(pdev);
624     if ((code = pdf_free_font_cache(pdev)) < 0 ||
625 	(code = pdf_write_resource_objects(pdev, resourceCharProc)) < 0 ||
626  	(code = pdf_finish_font_descriptors(pdev, pdf_finish_FontDescriptor)) < 0 ||
627   	(code = write_font_resources(pdev, &pdev->resources[resourceCIDFont])) < 0 ||
628 	(code = write_font_resources(pdev, &pdev->resources[resourceFont])) < 0 ||
629 	(code = pdf_finish_font_descriptors(pdev, pdf_write_FontDescriptor)) < 0
630 	)
631 	return code;
632 
633     /* If required, write the Encoding for Type 3 bitmap fonts. */
634 
635     return pdf_write_bitmap_fonts_Encoding(pdev);
636 }
637 
638 /* ================ CMap resource writing ================ */
639 
640 /*
641  * Write the CIDSystemInfo for a CIDFont or a CMap.
642  */
643 private int
pdf_write_cid_system_info_to_stream(gx_device_pdf * pdev,stream * s,const gs_cid_system_info_t * pcidsi,gs_id object_id)644 pdf_write_cid_system_info_to_stream(gx_device_pdf *pdev, stream *s,
645 			  const gs_cid_system_info_t *pcidsi, gs_id object_id)
646 {
647     byte Registry[32], Ordering[32];
648 
649     if (pcidsi->Registry.size > sizeof(Registry))
650 	return_error(gs_error_limitcheck);
651     if (pcidsi->Ordering.size > sizeof(Ordering))
652 	return_error(gs_error_limitcheck);
653     memcpy(Registry, pcidsi->Registry.data, pcidsi->Registry.size);
654     memcpy(Ordering, pcidsi->Ordering.data, pcidsi->Ordering.size);
655     if (pdev->KeyLength && object_id != 0) {
656 	stream_arcfour_state sarc4;
657 	int code;
658 
659 	code = pdf_encrypt_init(pdev, object_id, &sarc4);
660 	if (code < 0)
661 	    return code;
662 	s_arcfour_process_buffer(&sarc4, Registry, pcidsi->Registry.size);
663 	code = pdf_encrypt_init(pdev, object_id, &sarc4);
664 	if (code < 0)
665 	    return code;
666 	s_arcfour_process_buffer(&sarc4, Ordering, pcidsi->Ordering.size);
667     }
668     stream_puts(s, "<<\n/Registry");
669     s_write_ps_string(s, Registry, pcidsi->Registry.size, PRINT_HEX_NOT_OK);
670     stream_puts(s, "\n/Ordering");
671     s_write_ps_string(s, Ordering, pcidsi->Ordering.size, PRINT_HEX_NOT_OK);
672     pprintd1(s, "\n/Supplement %d\n>>\n", pcidsi->Supplement);
673     return 0;
674 }
675 
676 int
pdf_write_cid_system_info(gx_device_pdf * pdev,const gs_cid_system_info_t * pcidsi,gs_id object_id)677 pdf_write_cid_system_info(gx_device_pdf *pdev,
678 			  const gs_cid_system_info_t *pcidsi, gs_id object_id)
679 {
680     return pdf_write_cid_system_info_to_stream(pdev, pdev->strm, pcidsi, object_id);
681 }
682 
683 
684 /*
685  * Write a CMap resource.  We pass the CMap object as well as the resource,
686  * because we write CMaps when they are created.
687  */
688 int
pdf_write_cmap(gx_device_pdf * pdev,const gs_cmap_t * pcmap,pdf_resource_t ** ppres,int font_index_only)689 pdf_write_cmap(gx_device_pdf *pdev, const gs_cmap_t *pcmap,
690 	       pdf_resource_t **ppres /*CMap*/, int font_index_only)
691 {
692     int code;
693     pdf_data_writer_t writer;
694 
695     code = pdf_begin_data_stream(pdev, &writer,
696 				 DATA_STREAM_NOT_BINARY |
697 			    /* Don't set DATA_STREAM_ENCRYPT since we write to a temporary file.
698 			       See comment in pdf_begin_encrypt. */
699 				 (pdev->CompressFonts ?
700 				  DATA_STREAM_COMPRESS : 0), gs_no_id);
701     if (code < 0)
702 	return code;
703     *ppres = writer.pres;
704     writer.pres->where_used = 0; /* CMap isn't a PDF resource. */
705     if (!pcmap->ToUnicode) {
706 	byte buf[200];
707 	cos_dict_t *pcd = (cos_dict_t *)writer.pres->object;
708 	stream s;
709 
710 	code = cos_dict_put_c_key_int(pcd, "/WMode", pcmap->WMode);
711 	if (code < 0)
712 	    return code;
713 	buf[0] = '/';
714 	memcpy(buf + 1, pcmap->CMapName.data, pcmap->CMapName.size);
715 	code = cos_dict_put_c_key_string(pcd, "/CMapName",
716 			buf, pcmap->CMapName.size + 1);
717 	if (code < 0)
718 	    return code;
719 	s_init(&s, pdev->memory);
720 	swrite_string(&s, buf, sizeof(buf));
721 	code = pdf_write_cid_system_info_to_stream(pdev, &s, pcmap->CIDSystemInfo, 0);
722 	if (code < 0)
723 	    return code;
724 	code = cos_dict_put_c_key_string(pcd, "/CIDSystemInfo",
725 			buf, stell(&s));
726 	if (code < 0)
727 	    return code;
728 	code = cos_dict_put_string_copy(pcd, "/Type", "/CMap");
729 	if (code < 0)
730 	    return code;
731     }
732     code = psf_write_cmap(pdev->memory, writer.binary.strm, pcmap,
733 			  pdf_put_name_chars_proc(pdev), NULL, font_index_only);
734     if (code < 0)
735 	return code;
736     code = pdf_end_data(&writer);
737     if (code < 0)
738 	return code;
739     return code;
740 }
741