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