xref: /plan9/sys/src/cmd/gs/src/gdevpdf.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1996, 2000 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: gdevpdf.c,v 1.124 2005/09/12 11:34:50 leonardo Exp $ */
18 /* PDF-writing driver */
19 #include "fcntl_.h"
20 #include "memory_.h"
21 #include "string_.h"
22 #include "time_.h"
23 #include "unistd_.h"
24 #include "gx.h"
25 #include "gp.h"			/* for gp_get_realtime */
26 #include "gserrors.h"
27 #include "gxdevice.h"
28 #include "gdevpdfx.h"
29 #include "gdevpdfg.h"		/* only for pdf_reset_graphics */
30 #include "gdevpdfo.h"
31 #include "gdevpdt.h"
32 #include "smd5.h"
33 #include "sarc4.h"
34 
35 /* Define the default language level and PDF compatibility level. */
36 /* Acrobat 4 (PDF 1.3) is the default. */
37 #define PSDF_VERSION_INITIAL psdf_version_ll3
38 #define PDF_COMPATIBILITY_LEVEL_INITIAL 1.4
39 
40 /* Define the size of internal stream buffers. */
41 /* (This is not a limitation, it only affects performance.) */
42 #define sbuf_size 512
43 
44 /* GC descriptors */
45 private_st_pdf_page();
46 gs_private_st_element(st_pdf_page_element, pdf_page_t, "pdf_page_t[]",
47 		      pdf_page_elt_enum_ptrs, pdf_page_elt_reloc_ptrs,
48 		      st_pdf_page);
49 private_st_device_pdfwrite();
50 private_st_pdf_substream_save();
51 private_st_pdf_substream_save_element();
52 
53 /* GC procedures */
54 private
ENUM_PTRS_WITH(device_pdfwrite_enum_ptrs,gx_device_pdf * pdev)55 ENUM_PTRS_WITH(device_pdfwrite_enum_ptrs, gx_device_pdf *pdev)
56 {
57     index -= gx_device_pdf_num_ptrs + gx_device_pdf_num_param_strings;
58     if (index < NUM_RESOURCE_TYPES * NUM_RESOURCE_CHAINS)
59 	ENUM_RETURN(pdev->resources[index / NUM_RESOURCE_CHAINS].chains[index % NUM_RESOURCE_CHAINS]);
60     index -= NUM_RESOURCE_TYPES * NUM_RESOURCE_CHAINS;
61     if (index <= pdev->outline_depth)
62 	ENUM_RETURN(pdev->outline_levels[index].first.action);
63     index -= pdev->outline_depth + 1;
64     if (index <= pdev->outline_depth)
65 	ENUM_RETURN(pdev->outline_levels[index].last.action);
66     index -= pdev->outline_depth + 1;
67     ENUM_PREFIX(st_device_psdf, 0);
68 }
69 #define e1(i,elt) ENUM_PTR(i, gx_device_pdf, elt);
70 gx_device_pdf_do_ptrs(e1)
71 #undef e1
72 #define e1(i,elt) ENUM_PARAM_STRING_PTR(i + gx_device_pdf_num_ptrs, gx_device_pdf, elt);
gx_device_pdf_do_param_strings(e1)73 gx_device_pdf_do_param_strings(e1)
74 #undef e1
75 #define e1(i,elt) ENUM_STRING_PTR(i + gx_device_pdf_num_ptrs + gx_device_pdf_num_param_strings,\
76 				 gx_device_pdf, elt);
77 gx_device_pdf_do_const_strings(e1)
78 #undef e1
79 ENUM_PTRS_END
80 private RELOC_PTRS_WITH(device_pdfwrite_reloc_ptrs, gx_device_pdf *pdev)
81 {
82     RELOC_PREFIX(st_device_psdf);
83 #define r1(i,elt) RELOC_PTR(gx_device_pdf,elt);
84     gx_device_pdf_do_ptrs(r1)
85 #undef r1
86 #define r1(i,elt) RELOC_PARAM_STRING_PTR(gx_device_pdf,elt);
87 	gx_device_pdf_do_param_strings(r1)
88 #undef r1
89 #define r1(i,elt) RELOC_CONST_STRING_PTR(gx_device_pdf,elt);
90 	gx_device_pdf_do_const_strings(r1)
91 #undef r1
92     {
93 	int i, j;
94 
95 	for (i = 0; i < NUM_RESOURCE_TYPES; ++i)
96 	    for (j = 0; j < NUM_RESOURCE_CHAINS; ++j)
97 		RELOC_PTR(gx_device_pdf, resources[i].chains[j]);
98 	for (i = 0; i <= pdev->outline_depth; ++i) {
99 	    RELOC_PTR(gx_device_pdf, outline_levels[i].first.action);
100 	    RELOC_PTR(gx_device_pdf, outline_levels[i].last.action);
101 	}
102     }
103 }
104 RELOC_PTRS_END
105 /* Even though device_pdfwrite_finalize is the same as gx_device_finalize, */
106 /* we need to implement it separately because st_composite_final */
107 /* declares all 3 procedures as private. */
108 private void
device_pdfwrite_finalize(void * vpdev)109 device_pdfwrite_finalize(void *vpdev)
110 {
111     gx_device_finalize(vpdev);
112 }
113 
114 /* Driver procedures */
115 private dev_proc_open_device(pdf_open);
116 private dev_proc_output_page(pdf_output_page);
117 private dev_proc_close_device(pdf_close);
118 /* Driver procedures defined in other files are declared in gdevpdfx.h. */
119 
120 #ifndef X_DPI
121 #  define X_DPI 720
122 #endif
123 #ifndef Y_DPI
124 #  define Y_DPI 720
125 #endif
126 
127 /* ---------------- Device prototype ---------------- */
128 
129 #define PDF_DEVICE_NAME "pdfwrite"
130 #define PDF_DEVICE_IDENT gs_pdfwrite_device
131 #define PDF_DEVICE_MaxInlineImageSize 4000
132 #define PDF_FOR_OPDFREAD 0
133 
134 #include "gdevpdfb.h"
135 
136 #undef PDF_DEVICE_NAME
137 #undef PDF_DEVICE_IDENT
138 #undef PDF_DEVICE_MaxInlineImageSize
139 #undef PDF_FOR_OPDFREAD
140 
141 #define PDF_DEVICE_NAME "ps2write"
142 #define PDF_DEVICE_IDENT gs_ps2write_device
143 #define PDF_DEVICE_MaxInlineImageSize max_long
144 #define PDF_FOR_OPDFREAD 1
145 
146 #include "gdevpdfb.h"
147 
148 #undef PDF_DEVICE_NAME
149 #undef PDF_DEVICE_IDENT
150 #undef PDF_DEVICE_MaxInlineImageSize
151 #undef PDF_FOR_OPDFREAD
152 /* ---------------- Device open/close ---------------- */
153 
154 /* Close and remove temporary files. */
155 private int
pdf_close_temp_file(gx_device_pdf * pdev,pdf_temp_file_t * ptf,int code)156 pdf_close_temp_file(gx_device_pdf *pdev, pdf_temp_file_t *ptf, int code)
157 {
158     int err = 0;
159     FILE *file = ptf->file;
160 
161     /*
162      * ptf->strm == 0 or ptf->file == 0 is only possible if this procedure
163      * is called to clean up during initialization failure, but ptf->strm
164      * might not be open if it was finalized before the device was closed.
165      */
166     if (ptf->strm) {
167 	if (s_is_valid(ptf->strm)) {
168 	    sflush(ptf->strm);
169 	    /* Prevent freeing the stream from closing the file. */
170 	    ptf->strm->file = 0;
171 	} else
172 	    ptf->file = file = 0;	/* file was closed by finalization */
173 	gs_free_object(pdev->pdf_memory, ptf->strm_buf,
174 		       "pdf_close_temp_file(strm_buf)");
175 	ptf->strm_buf = 0;
176 	gs_free_object(pdev->pdf_memory, ptf->strm,
177 		       "pdf_close_temp_file(strm)");
178 	ptf->strm = 0;
179     }
180     if (file) {
181 	err = ferror(file) | fclose(file);
182 	unlink(ptf->file_name);
183 	ptf->file = 0;
184     }
185     ptf->save_strm = 0;
186     return
187 	(code < 0 ? code : err != 0 ? gs_note_error(gs_error_ioerror) : code);
188 }
189 private int
pdf_close_files(gx_device_pdf * pdev,int code)190 pdf_close_files(gx_device_pdf * pdev, int code)
191 {
192     code = pdf_close_temp_file(pdev, &pdev->pictures, code);
193     code = pdf_close_temp_file(pdev, &pdev->streams, code);
194     code = pdf_close_temp_file(pdev, &pdev->asides, code);
195     return pdf_close_temp_file(pdev, &pdev->xref, code);
196 }
197 
198 /* Reset the state of the current page. */
199 private void
pdf_reset_page(gx_device_pdf * pdev)200 pdf_reset_page(gx_device_pdf * pdev)
201 {
202     pdev->page_dsc_info = gs_pdfwrite_device.page_dsc_info;
203     pdev->contents_id = 0;
204     pdf_reset_graphics(pdev);
205     pdev->procsets = NoMarks;
206     memset(pdev->cs_Patterns, 0, sizeof(pdev->cs_Patterns));	/* simplest to create for each page */
207     pdf_reset_text_page(pdev->text);
208     pdf_remember_clip_path(pdev, 0);
209     pdev->clip_path_id = pdev->no_clip_path_id;
210 }
211 
212 /* Open a temporary file, with or without a stream. */
213 private int
pdf_open_temp_file(gx_device_pdf * pdev,pdf_temp_file_t * ptf)214 pdf_open_temp_file(gx_device_pdf *pdev, pdf_temp_file_t *ptf)
215 {
216     char fmode[4];
217 
218     strcpy(fmode, "w+");
219     strcat(fmode, gp_fmode_binary_suffix);
220     ptf->file =
221 	gp_open_scratch_file(gp_scratch_file_name_prefix,
222 			     ptf->file_name, fmode);
223     if (ptf->file == 0)
224 	return_error(gs_error_invalidfileaccess);
225     return 0;
226 }
227 private int
pdf_open_temp_stream(gx_device_pdf * pdev,pdf_temp_file_t * ptf)228 pdf_open_temp_stream(gx_device_pdf *pdev, pdf_temp_file_t *ptf)
229 {
230     int code = pdf_open_temp_file(pdev, ptf);
231 
232     if (code < 0)
233 	return code;
234     ptf->strm = s_alloc(pdev->pdf_memory, "pdf_open_temp_stream(strm)");
235     if (ptf->strm == 0)
236 	return_error(gs_error_VMerror);
237     ptf->strm_buf = gs_alloc_bytes(pdev->pdf_memory, sbuf_size,
238 				   "pdf_open_temp_stream(strm_buf)");
239     if (ptf->strm_buf == 0) {
240 	gs_free_object(pdev->pdf_memory, ptf->strm,
241 		       "pdf_open_temp_stream(strm)");
242 	ptf->strm = 0;
243 	return_error(gs_error_VMerror);
244     }
245     swrite_file(ptf->strm, ptf->file, ptf->strm_buf, sbuf_size);
246     return 0;
247 }
248 
249 /* Initialize the IDs allocated at startup. */
250 void
pdf_initialize_ids(gx_device_pdf * pdev)251 pdf_initialize_ids(gx_device_pdf * pdev)
252 {
253     gs_param_string nstr;
254 
255     pdev->next_id = pdev->FirstObjectNumber;
256 
257     /* Initialize the Catalog. */
258 
259     param_string_from_string(nstr, "{Catalog}");
260     pdf_create_named_dict(pdev, &nstr, &pdev->Catalog, 0L);
261 
262     /* Initialize the Info dictionary. */
263 
264     param_string_from_string(nstr, "{DocInfo}");
265     pdf_create_named_dict(pdev, &nstr, &pdev->Info, 0L);
266     {
267 	char buf[PDF_MAX_PRODUCER];
268 
269 	pdf_store_default_Producer(buf);
270 	cos_dict_put_c_key_string(pdev->Info, "/Producer", (byte *)buf,
271 				  strlen(buf));
272     }
273     /*
274      * Acrobat Distiller sets CreationDate and ModDate to the current
275      * date and time, rather than (for example) %%CreationDate from the
276      * PostScript file.  We think this is wrong, but we do the same.
277      */
278     {
279 	struct tm tms;
280 	time_t t;
281 	char buf[1+2+4+2+2+2+2+2+2+1+1]; /* (D:yyyymmddhhmmss)\0 */
282 
283 	time(&t);
284 	tms = *localtime(&t);
285 	sprintf(buf,
286 		"(D:%04d%02d%02d%02d%02d%02d)",
287 		tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday,
288 		tms.tm_hour, tms.tm_min, tms.tm_sec);
289 	cos_dict_put_c_key_string(pdev->Info, "/CreationDate", (byte *)buf,
290 				  strlen(buf));
291 	cos_dict_put_c_key_string(pdev->Info, "/ModDate", (byte *)buf,
292 				  strlen(buf));
293     }
294 
295     /* Allocate the root of the pages tree. */
296 
297     pdf_create_named_dict(pdev, NULL, &pdev->Pages, 0L);
298 }
299 
300 private int
pdf_compute_fileID(gx_device_pdf * pdev)301 pdf_compute_fileID(gx_device_pdf * pdev)
302 {
303     /* We compute a file identifier when beginning a document
304        to allow its usage with PDF encryption. Due to that,
305        in contradiction to the Adobe recommendation, our
306        ID doesn't depend on the document size.
307     */
308     gs_memory_t *mem = pdev->pdf_memory;
309     stream *strm = pdev->strm;
310     uint ignore;
311     int code;
312     stream *s = s_MD5E_make_stream(mem, pdev->fileID, sizeof(pdev->fileID));
313     long secs_ns[2];
314     uint KeyLength = pdev->KeyLength;
315 
316     if (s == NULL)
317 	return_error(gs_error_VMerror);
318     pdev->KeyLength = 0; /* Disable encryption. Not so important though. */
319     gp_get_usertime(secs_ns);
320     sputs(s, (byte *)secs_ns, sizeof(secs_ns), &ignore);
321     sputs(s, (const byte *)pdev->fname, strlen(pdev->fname), &ignore);
322     pdev->strm = s;
323     code = cos_dict_elements_write(pdev->Info, pdev);
324     pdev->strm = strm;
325     pdev->KeyLength = KeyLength;
326     if (code < 0)
327 	return code;
328     sclose(s);
329     gs_free_object(mem, s, "pdf_compute_fileID");
330 #if 0
331     memcpy(pdev->fileID, "xxxxxxxxxxxxxxxx", sizeof(pdev->fileID)); /* Debug */
332 #endif
333     return 0;
334 }
335 
336 private const byte pad[32] = { 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41,
337 			       0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
338 			       0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80,
339 			       0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A};
340 
341 private inline void
copy_padded(byte buf[32],gs_param_string * str)342 copy_padded(byte buf[32], gs_param_string *str)
343 {
344     memcpy(buf, str->data, min(str->size, 32));
345     if (32 > str->size)
346 	memcpy(buf + str->size, pad, 32 - str->size);
347 }
348 
349 private void
Adobe_magic_loop_50(byte digest[16],int key_length)350 Adobe_magic_loop_50(byte digest[16], int key_length)
351 {
352     md5_state_t md5;
353     int i;
354 
355     for (i = 0; i < 50; i++) {
356 	md5_init(&md5);
357 	md5_append(&md5, digest, key_length);
358 	md5_finish(&md5, digest);
359     }
360 }
361 
362 private void
Adobe_magic_loop_19(byte * data,int data_size,const byte * key,int key_size)363 Adobe_magic_loop_19(byte *data, int data_size, const byte *key, int key_size)
364 {
365     stream_arcfour_state sarc4;
366     byte key_buf[16];
367     int i, j;
368 
369     for (i = 1; i <= 19; i++) {
370 	for (j = 0; j < key_size; j++)
371 	    key_buf[j] = key[j] ^ (byte)i;
372 	s_arcfour_set_key(&sarc4, key_buf, key_size);
373 	s_arcfour_process_buffer(&sarc4, data, data_size);
374     }
375 }
376 
377 private int
pdf_compute_encryption_data(gx_device_pdf * pdev)378 pdf_compute_encryption_data(gx_device_pdf * pdev)
379 {
380     md5_state_t md5;
381     byte digest[16], buf[32], t;
382     stream_arcfour_state sarc4;
383 
384     if (pdev->PDFX && pdev->KeyLength != 0) {
385 	eprintf("Encryption is not allowed in a PDF/X doucment.\n");
386 	return_error(gs_error_rangecheck);
387     }
388     if (pdev->KeyLength == 0)
389 	pdev->KeyLength = 40;
390     if (pdev->EncryptionV == 0 && pdev->KeyLength == 40)
391 	pdev->EncryptionV = 1;
392     if (pdev->EncryptionV == 0 && pdev->KeyLength > 40)
393 	pdev->EncryptionV = 2;
394     if (pdev->EncryptionV > 1 && pdev->CompatibilityLevel < 1.4) {
395 	eprintf("PDF 1.3 only supports 40 bits keys.\n");
396 	return_error(gs_error_rangecheck);
397     }
398     if (pdev->EncryptionR == 0)
399 	pdev->EncryptionR = 2;
400     if (pdev->EncryptionR < 2 || pdev->EncryptionR > 3) {
401 	eprintf("Encryption revisions 2 and 3 are only supported.\n");
402 	return_error(gs_error_rangecheck);
403     }
404     if (pdev->EncryptionR > 2 && pdev->CompatibilityLevel < 1.4) {
405 	eprintf("PDF 1.3 only supports the encryption revision 2.\n");
406 	return_error(gs_error_rangecheck);
407     }
408     if (pdev->KeyLength > 128) {
409 	eprintf("The maximal length of PDF encryption key is 128 bits.\n");
410 	return_error(gs_error_rangecheck);
411     }
412     if (pdev->KeyLength % 8) {
413 	eprintf("PDF encryption key length must be a multiple of 8.\n");
414 	return_error(gs_error_rangecheck);
415     }
416     if (pdev->EncryptionR == 2 &&
417 	((pdev->Permissions & (0xFFFFFFC3)) != 0xFFFFFFC0)) {
418 	eprintf("Some of Permissions are not allowed with R=2.\n");
419 	return_error(gs_error_rangecheck);
420     }
421     if (pdev->EncryptionV == 2 && pdev->EncryptionR == 2 && pdev->KeyLength > 40) {
422 	eprintf("Encryption version 2 revision 2 with KeyLength > 40 appears incompatible to some viewers. With long keys use revision 3.\n");
423 	return_error(gs_error_rangecheck);
424     }
425     /* Compute O : */
426     md5_init(&md5);
427     copy_padded(buf, &pdev->OwnerPassword);
428     md5_append(&md5, buf, sizeof(buf));
429     md5_finish(&md5, digest);
430     if (pdev->EncryptionR == 3)
431 	Adobe_magic_loop_50(digest, pdev->KeyLength / 8);
432     copy_padded(buf, &pdev->UserPassword);
433     s_arcfour_set_key(&sarc4, digest, pdev->KeyLength / 8);
434     s_arcfour_process_buffer(&sarc4, buf, sizeof(buf));
435     if (pdev->EncryptionR == 3)
436 	Adobe_magic_loop_19(buf, sizeof(buf), digest, pdev->KeyLength / 8);
437     memcpy(pdev->EncryptionO, buf, sizeof(pdev->EncryptionO));
438     /* Compute Key : */
439     md5_init(&md5);
440     copy_padded(buf, &pdev->UserPassword);
441     md5_append(&md5, buf, sizeof(buf));
442     md5_append(&md5, pdev->EncryptionO, sizeof(pdev->EncryptionO));
443     t = (byte)(pdev->Permissions >>  0);  md5_append(&md5, &t, 1);
444     t = (byte)(pdev->Permissions >>  8);  md5_append(&md5, &t, 1);
445     t = (byte)(pdev->Permissions >> 16);  md5_append(&md5, &t, 1);
446     t = (byte)(pdev->Permissions >> 24);  md5_append(&md5, &t, 1);
447     md5_append(&md5, pdev->fileID, sizeof(pdev->fileID));
448     if (pdev->EncryptionR == 3)
449 	if (!pdev->EncryptMetadata) {
450 	    const byte v[4] = {0xFF, 0xFF, 0xFF, 0xFF};
451 
452 	    md5_append(&md5, v, 4);
453 	}
454     md5_finish(&md5, digest);
455     if (pdev->EncryptionR == 3)
456 	Adobe_magic_loop_50(digest, pdev->KeyLength / 8);
457     memcpy(pdev->EncryptionKey, digest, pdev->KeyLength / 8);
458     /* Compute U : */
459     if (pdev->EncryptionR == 3) {
460 	md5_init(&md5);
461 	md5_append(&md5, pad, sizeof(pad));
462 	md5_append(&md5, pdev->fileID, sizeof(pdev->fileID));
463 	md5_finish(&md5, digest);
464 	s_arcfour_set_key(&sarc4, pdev->EncryptionKey, pdev->KeyLength / 8);
465 	s_arcfour_process_buffer(&sarc4, digest, sizeof(digest));
466 	Adobe_magic_loop_19(digest, sizeof(digest), pdev->EncryptionKey, pdev->KeyLength / 8);
467 	memcpy(pdev->EncryptionU, digest, sizeof(digest));
468 	memcpy(pdev->EncryptionU + sizeof(digest), pad,
469 		sizeof(pdev->EncryptionU) - sizeof(digest));
470     } else {
471 	memcpy(pdev->EncryptionU, pad, sizeof(pdev->EncryptionU));
472 	s_arcfour_set_key(&sarc4, pdev->EncryptionKey, pdev->KeyLength / 8);
473 	s_arcfour_process_buffer(&sarc4, pdev->EncryptionU, sizeof(pdev->EncryptionU));
474     }
475     return 0;
476 }
477 
478 #ifdef __DECC
479 /* The ansi alias rules are violated in this next routine.  Tell the compiler
480    to ignore this.
481  */
482 #pragma optimize save
483 #pragma optimize ansi_alias=off
484 #endif
485 /*
486  * Update the color mapping procedures after setting ProcessColorModel.
487  *
488  * The 'index' value indicates the ProcessColorModel.
489  *	0 = DeviceGray
490  *	1 = DeviceRGB
491  *	2 = DeviceCMYK
492  *	3 = DeviceN (treat like CMYK except for color model name)
493  */
494 void
pdf_set_process_color_model(gx_device_pdf * pdev,int index)495 pdf_set_process_color_model(gx_device_pdf * pdev, int index)
496 {
497 
498     const static gx_device_color_info pcm_color_info[] = {
499 	dci_values(1, 8, 255, 0, 256, 0),		/* Gray */
500 	dci_values(3, 24, 255, 255, 256, 256),		/* RGB */
501 	dci_values(4, 32, 255, 255, 256, 256),		/* CMYK */
502 	dci_values(4, 32, 255, 255, 256, 256)	/* Treat DeviceN like CMYK */
503     };
504 
505     pdev->pcm_color_info_index = index;
506     pdev->color_info = pcm_color_info[index];
507     /* Set the separable and linear shift, masks, bits. */
508     set_linear_color_bits_mask_shift((gx_device *)pdev);
509     pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
510     /*
511      * The conversion from PS to PDF should be transparent as possible.
512      * Particularly it should not change representation of colors.
513      * Perhaps due to historical reasons the source color information
514      * sometimes isn't accessible from device methods, and
515      * therefore they perform a mapping of colors to
516      * an output color model. Here we handle some color models,
517      * which were selected almost due to antique reasons.
518      */
519     switch (index) {
520 	case 0:		/* DeviceGray */
521 	    set_dev_proc(pdev, map_rgb_color, gx_default_gray_map_rgb_color);
522 	    set_dev_proc(pdev, map_color_rgb, gx_default_gray_map_color_rgb);
523 	    set_dev_proc(pdev, map_cmyk_color, NULL);
524 	    set_dev_proc(pdev, get_color_mapping_procs,
525 			gx_default_DevGray_get_color_mapping_procs);
526 	    set_dev_proc(pdev, get_color_comp_index,
527 			gx_default_DevGray_get_color_comp_index);
528 	    set_dev_proc(pdev, encode_color, gx_default_gray_encode);
529 	    set_dev_proc(pdev, decode_color, gx_default_decode_color);
530 	    break;
531 	case 1:		/* DeviceRGB */
532 	    set_dev_proc(pdev, map_rgb_color, gx_default_rgb_map_rgb_color);
533 	    set_dev_proc(pdev, map_color_rgb, gx_default_rgb_map_color_rgb);
534 	    set_dev_proc(pdev, map_cmyk_color, NULL);
535 	    set_dev_proc(pdev, get_color_mapping_procs,
536 			gx_default_DevRGB_get_color_mapping_procs);
537 	    set_dev_proc(pdev, get_color_comp_index,
538 			gx_default_DevRGB_get_color_comp_index);
539 	    set_dev_proc(pdev, encode_color, gx_default_rgb_map_rgb_color);
540 	    set_dev_proc(pdev, decode_color, gx_default_rgb_map_color_rgb);
541 	    break;
542 	case 3:		/* DeviceN - treat like DeviceCMYK except for cm_name */
543 	    pdev->color_info.cm_name = "DeviceN";
544 	case 2:		/* DeviceCMYK */
545 	    set_dev_proc(pdev, map_rgb_color, NULL);
546 	    set_dev_proc(pdev, map_color_rgb, cmyk_8bit_map_color_rgb);
547 	   /* possible problems with aliassing on next statement */
548 	    set_dev_proc(pdev, map_cmyk_color, cmyk_8bit_map_cmyk_color);
549 	    set_dev_proc(pdev, get_color_mapping_procs,
550 			gx_default_DevCMYK_get_color_mapping_procs);
551 	    set_dev_proc(pdev, get_color_comp_index,
552 			gx_default_DevCMYK_get_color_comp_index);
553 	    set_dev_proc(pdev, encode_color, cmyk_8bit_map_cmyk_color);
554 	    set_dev_proc(pdev, decode_color, cmyk_8bit_map_color_rgb);
555 	    break;
556 	default:	/* can't happen - see the call from gdev_pdf_put_params. */
557 	    DO_NOTHING;
558     }
559 }
560 #ifdef __DECC
561 #pragma optimize restore
562 #endif
563 
564 /*
565  * Reset the text state parameters to initial values.
566  */
567 void
pdf_reset_text(gx_device_pdf * pdev)568 pdf_reset_text(gx_device_pdf * pdev)
569 {
570     pdf_reset_text_state(pdev->text);
571 }
572 
573 /* Open the device. */
574 private int
pdf_open(gx_device * dev)575 pdf_open(gx_device * dev)
576 {
577     gx_device_pdf *const pdev = (gx_device_pdf *) dev;
578     gs_memory_t *mem = pdev->pdf_memory = gs_memory_stable(pdev->memory);
579     int code;
580 
581     if ((code = pdf_open_temp_file(pdev, &pdev->xref)) < 0 ||
582 	(code = pdf_open_temp_stream(pdev, &pdev->asides)) < 0 ||
583 	(code = pdf_open_temp_stream(pdev, &pdev->streams)) < 0 ||
584 	(code = pdf_open_temp_stream(pdev, &pdev->pictures)) < 0
585 	)
586 	goto fail;
587     code = gdev_vector_open_file((gx_device_vector *) pdev, sbuf_size);
588     if (code < 0)
589 	goto fail;
590     gdev_vector_init((gx_device_vector *) pdev);
591     pdev->vec_procs = &pdf_vector_procs;
592     pdev->fill_options = pdev->stroke_options = gx_path_type_optimize;
593     /* Set in_page so the vector routines won't try to call */
594     /* any vector implementation procedures. */
595     pdev->in_page = true;
596     /*
597      * pdf_initialize_ids allocates some (global) named objects, so we must
598      * initialize the named objects dictionary now.
599      */
600     pdev->local_named_objects =
601 	pdev->global_named_objects =
602 	cos_dict_alloc(pdev, "pdf_open(global_named_objects)");
603     /* Initialize internal structures that don't have IDs. */
604     pdev->NI_stack = cos_array_alloc(pdev, "pdf_open(NI stack)");
605     pdev->Namespace_stack = cos_array_alloc(pdev, "pdf_open(Namespace stack)");
606     pdf_initialize_ids(pdev);
607     code = pdf_compute_fileID(pdev);
608     if (code < 0)
609 	goto fail;
610     if (pdev->OwnerPassword.size > 0) {
611 	code = pdf_compute_encryption_data(pdev);
612 	if (code < 0)
613 	    goto fail;
614     } else if(pdev->UserPassword.size > 0) {
615 	eprintf("User password is specified. Need an Owner password or both.\n");
616 	return_error(gs_error_rangecheck);
617     } else if (pdev->KeyLength) {
618 	eprintf("Can't accept encryption options without a password.\n");
619 	return_error(gs_error_rangecheck);
620     }
621     /* Now create a new dictionary for the local named objects. */
622     pdev->local_named_objects =
623 	cos_dict_alloc(pdev, "pdf_open(local_named_objects)");
624     pdev->outlines_id = 0;
625     pdev->next_page = 0;
626     pdev->text = pdf_text_data_alloc(mem);
627     pdev->sbstack_size = count_of(pdev->vgstack); /* Overestimated a few. */
628     pdev->sbstack = gs_alloc_struct_array(mem, pdev->sbstack_size, pdf_substream_save,
629 				 &st_pdf_substream_save_element, "pdf_open");
630     pdev->pages =
631 	gs_alloc_struct_array(mem, initial_num_pages, pdf_page_t,
632 			      &st_pdf_page_element, "pdf_open(pages)");
633     if (pdev->text == 0 || pdev->pages == 0 || pdev->sbstack == 0) {
634 	code = gs_error_VMerror;
635 	goto fail;
636     }
637     memset(pdev->sbstack, 0, pdev->sbstack_size * sizeof(pdf_substream_save));
638     memset(pdev->pages, 0, initial_num_pages * sizeof(pdf_page_t));
639     pdev->num_pages = initial_num_pages;
640     {
641 	int i, j;
642 
643 	for (i = 0; i < NUM_RESOURCE_TYPES; ++i)
644 	    for (j = 0; j < NUM_RESOURCE_CHAINS; ++j)
645 		pdev->resources[i].chains[j] = 0;
646     }
647     pdev->outline_levels[0].first.id = 0;
648     pdev->outline_levels[0].left = max_int;
649     pdev->outline_levels[0].first.action = 0;
650     pdev->outline_levels[0].last.action = 0;
651     pdev->outline_depth = 0;
652     pdev->closed_outline_depth = 0;
653     pdev->outlines_open = 0;
654     pdev->articles = 0;
655     pdev->Dests = 0;
656     /* {global,local}_named_objects was initialized above */
657     pdev->PageLabels = 0;
658     pdev->PageLabels_current_page = 0;
659     pdev->PageLabels_current_label = 0;
660     pdev->pte = NULL;
661     pdf_reset_page(pdev);
662     return 0;
663   fail:
664     return pdf_close_files(pdev, code);
665 }
666 
667 /* Detect I/O errors. */
668 private int
pdf_ferror(gx_device_pdf * pdev)669 pdf_ferror(gx_device_pdf *pdev)
670 {
671     fflush(pdev->file);
672     fflush(pdev->xref.file);
673     sflush(pdev->strm);
674     sflush(pdev->asides.strm);
675     sflush(pdev->streams.strm);
676     sflush(pdev->pictures.strm);
677     return ferror(pdev->file) || ferror(pdev->xref.file) ||
678 	ferror(pdev->asides.file) || ferror(pdev->streams.file) ||
679 	ferror(pdev->pictures.file);
680 }
681 
682 /* Compute the dominant text orientation of a page. */
683 private int
pdf_dominant_rotation(const pdf_text_rotation_t * ptr)684 pdf_dominant_rotation(const pdf_text_rotation_t *ptr)
685 {
686     int i, imax = -1;
687     long max_count = 0;
688     static const int angles[] = { pdf_text_rotation_angle_values };
689 
690     for (i = 0; i < countof(ptr->counts); ++i) {
691 	long count = ptr->counts[i];
692 
693 	if (count > max_count)
694 	    imax = i, max_count = count;
695     }
696     return (imax < 0 ? imax : angles[imax]);
697 }
698 
699 /* Print a Rotate command, if requested and possible. */
700 private void
pdf_print_orientation(gx_device_pdf * pdev,pdf_page_t * page)701 pdf_print_orientation(gx_device_pdf * pdev, pdf_page_t *page)
702 {
703     stream *s = pdev->strm;
704     int dsc_orientation = -1;
705     const pdf_page_dsc_info_t *ppdi;
706 
707     if (pdev->params.AutoRotatePages == arp_None)
708 	return; /* Not requested. */
709 
710     ppdi = (page != NULL ? &page->dsc_info : &pdev->doc_dsc_info);
711 
712     /* Determine DSC orientation : */
713     if (ppdi->viewing_orientation >= 0)
714 	dsc_orientation = ppdi->viewing_orientation;
715     else if (ppdi->orientation >= 0)
716 	dsc_orientation = ppdi->orientation;
717     if ((page == NULL && pdev->params.AutoRotatePages == arp_All) || /* document */
718         (page != NULL && page->text_rotation.Rotate >= 0) || /* page */
719 	dsc_orientation >= 0 /* have DSC */) {
720         const pdf_text_rotation_t *ptr =
721 	    (page != NULL ? &page->text_rotation : &pdev->text_rotation);
722 	int angle = -1;
723 
724 #define  Bug687800
725 #ifndef Bug687800 	/* Bug 687800 together with Bug687489.ps . */
726 	const gs_point *pbox = &(page != NULL ? page : &pdev->pages[0])->MediaBox;
727 
728 	if (dsc_orientation >= 0 && pbox->x > pbox->y) {
729 	    /* The page is in landscape format. Adjust the rotation accordingly. */
730 	    dsc_orientation ^= 1;
731 	}
732 #endif
733 
734 	/* Combine DSC rotation with text rotation : */
735 	if (dsc_orientation == 0) {
736 	    if (ptr->Rotate == 0 || ptr->Rotate == 180)
737 		angle = ptr->Rotate;
738 	} else if (dsc_orientation == 1) {
739 	    if (ptr->Rotate == 90 || ptr->Rotate == 270)
740 		angle = ptr->Rotate;
741 	    else
742 		angle = 90;
743 	}
744 
745 	/* If not combinable, prefer text rotation : */
746 	if (angle < 0) {
747 	    if (ptr->Rotate >= 0)
748 		angle = ptr->Rotate;
749 #ifdef Bug687800
750 	    else
751 		angle = dsc_orientation * 90;
752 #endif
753 	}
754 
755 	/* If got some, write it out : */
756 	if (angle >= 0)
757 	    pprintd1(s, "/Rotate %d", angle);
758     }
759 }
760 
761 
762 /* Close the current page. */
763 private int
pdf_close_page(gx_device_pdf * pdev)764 pdf_close_page(gx_device_pdf * pdev)
765 {
766     int page_num = ++(pdev->next_page);
767     pdf_page_t *page;
768     int code;
769 
770     /*
771      * If the very first page is blank, we need to open the document
772      * before doing anything else.
773      */
774 
775     code = pdf_open_document(pdev);
776     if (code < 0)
777 	return code;
778     if (pdev->ForOPDFRead && pdev->context == PDF_IN_NONE) {
779 	/* Must create a context stream for empty pages. */
780 	code = pdf_open_contents(pdev, PDF_IN_STREAM);
781 	if (code < 0)
782 	    return code;
783     }
784     pdf_close_contents(pdev, true);
785 
786     /*
787      * We can't write the page object or the annotations array yet, because
788      * later pdfmarks might add elements to them.  Write the other objects
789      * that the page references, and record what we'll need later.
790      *
791      * Start by making sure the pages array element exists.
792      */
793 
794     pdf_page_id(pdev, page_num);
795     page = &pdev->pages[page_num - 1];
796     page->MediaBox.x = pdev->MediaSize[0];
797     page->MediaBox.y = pdev->MediaSize[1];
798     page->contents_id = pdev->contents_id;
799     page->NumCopies_set = pdev->NumCopies_set;
800     page->NumCopies = pdev->NumCopies;
801     /* pdf_store_page_resources sets procsets, resource_ids[]. */
802     code = pdf_store_page_resources(pdev, page);
803     if (code < 0)
804 	return code;
805 
806     /* Write the Functions. */
807 
808     pdf_write_resource_objects(pdev, resourceFunction);
809 
810     /* Save viewer's memory with cleaning resources. */
811 
812     if (pdev->MaxViewerMemorySize < 10000000) {
813 	/* fixme: the condition above and the cleaning algorithm
814 	   may be improved with counting stored resource size
815 	   and creating multiple streams per page. */
816 
817 	if (pdev->ForOPDFRead) {
818 	    pdf_resource_t *pres = pdf_find_resource_by_resource_id(pdev, resourcePage, pdev->contents_id);
819 
820 	    if (pres != NULL) {
821 		code = cos_dict_put_c_strings((cos_dict_t *)pres->object, "/.CleanResources", "/All");
822 		if (code < 0)
823 		    return code;
824 	    }
825 	}
826 	code = pdf_close_text_document(pdev);
827 	if (code < 0)
828 	    return code;
829 	code = pdf_write_and_free_all_resource_objects(pdev);
830 	if (code < 0)
831 	    return code;
832     }
833 
834     /* Close use of text on the page. */
835 
836     pdf_close_text_page(pdev);
837 
838     /* Accumulate text rotation. */
839 
840     page->text_rotation.Rotate =
841 	(pdev->params.AutoRotatePages == arp_PageByPage ?
842 	 pdf_dominant_rotation(&page->text_rotation) : -1);
843     {
844 	int i;
845 
846 	for (i = 0; i < countof(page->text_rotation.counts); ++i)
847 	    pdev->text_rotation.counts[i] += page->text_rotation.counts[i];
848     }
849 
850     /* Record information from DSC comments. */
851 
852     page->dsc_info = pdev->page_dsc_info;
853     if (page->dsc_info.orientation < 0)
854 	page->dsc_info.orientation = pdev->doc_dsc_info.orientation;
855     if (page->dsc_info.bounding_box.p.x >= page->dsc_info.bounding_box.q.x ||
856 	page->dsc_info.bounding_box.p.y >= page->dsc_info.bounding_box.q.y
857 	)
858 	page->dsc_info.bounding_box = pdev->doc_dsc_info.bounding_box;
859 
860     /* Finish up. */
861 
862     pdf_reset_page(pdev);
863     return (pdf_ferror(pdev) ? gs_note_error(gs_error_ioerror) : 0);
864 }
865 
866 /* Write the page object. */
867 private double
round_box_coord(floatp xy)868 round_box_coord(floatp xy)
869 {
870     return (int)(xy * 100 + 0.5) / 100.0;
871 }
872 private int
pdf_write_page(gx_device_pdf * pdev,int page_num)873 pdf_write_page(gx_device_pdf *pdev, int page_num)
874 {
875     long page_id = pdf_page_id(pdev, page_num);
876     pdf_page_t *page = &pdev->pages[page_num - 1];
877     stream *s;
878 
879     pdf_open_obj(pdev, page_id);
880     s = pdev->strm;
881     pprintg2(s, "<</Type/Page/MediaBox [0 0 %g %g]\n",
882 	     round_box_coord(page->MediaBox.x),
883 	     round_box_coord(page->MediaBox.y));
884     if (pdev->PDFX) {
885 	pprintg2(s, "/TrimBox [0 0 %g %g]\n",
886 		round_box_coord(page->MediaBox.x),
887 		round_box_coord(page->MediaBox.y));
888     }
889     pdf_print_orientation(pdev, page);
890     pprintld1(s, "/Parent %ld 0 R\n", pdev->Pages->id);
891     if (pdev->ForOPDFRead) {
892 	if (page->NumCopies_set)
893 	    pprintld1(s, "/NumCopies %ld\n", page->NumCopies);
894     }
895     if (page->group_id > 0) {
896 	pprintld1(s, "/Group %ld 0 R\n", page->group_id);
897     }
898     stream_puts(s, "/Resources<</ProcSet[/PDF");
899     if (page->procsets & ImageB)
900 	stream_puts(s, " /ImageB");
901     if (page->procsets & ImageC)
902 	stream_puts(s, " /ImageC");
903     if (page->procsets & ImageI)
904 	stream_puts(s, " /ImageI");
905     if (page->procsets & Text)
906 	stream_puts(s, " /Text");
907     stream_puts(s, "]\n");
908     {
909 	int i;
910 
911 	for (i = 0; i < countof(page->resource_ids); ++i)
912 	    if (page->resource_ids[i] && pdf_resource_type_names[i]) {
913 		stream_puts(s, pdf_resource_type_names[i]);
914 		pprintld1(s, " %ld 0 R\n", page->resource_ids[i]);
915 	    }
916     }
917     stream_puts(s, ">>\n");
918 
919     /* Write the annotations array if any. */
920 
921     if (page->Annots) {
922 	stream_puts(s, "/Annots");
923 	COS_WRITE(page->Annots, pdev);
924 	COS_FREE(page->Annots, "pdf_write_page(Annots)");
925 	page->Annots = 0;
926     }
927     /*
928      * The PDF documentation allows, and this code formerly emitted,
929      * a Contents entry whose value was an empty array.  Acrobat Reader
930      * 3 and 4 accept this, but Acrobat Reader 5.0 rejects it.
931      * Fortunately, the Contents entry is optional.
932      */
933     if (page->contents_id != 0)
934 	pprintld1(s, "/Contents %ld 0 R\n", page->contents_id);
935 
936     /* Write any elements stored by pdfmarks. */
937 
938     cos_dict_elements_write(page->Page, pdev);
939 
940     stream_puts(s, ">>\n");
941     pdf_end_obj(pdev);
942     return 0;
943 }
944 
945 /* Wrap up ("output") a page. */
946 private int
pdf_output_page(gx_device * dev,int num_copies,int flush)947 pdf_output_page(gx_device * dev, int num_copies, int flush)
948 {
949     gx_device_pdf *const pdev = (gx_device_pdf *) dev;
950     int code = pdf_close_page(pdev);
951 
952     return (code < 0 ? code :
953 	    pdf_ferror(pdev) ? gs_note_error(gs_error_ioerror) :
954 	    gx_finish_output_page(dev, num_copies, flush));
955 }
956 
957 /* Close the device. */
958 private int
pdf_close(gx_device * dev)959 pdf_close(gx_device * dev)
960 {
961     gx_device_pdf *const pdev = (gx_device_pdf *) dev;
962     gs_memory_t *mem = pdev->pdf_memory;
963     stream *s;
964     FILE *tfile = pdev->xref.file;
965     long xref;
966     long resource_pos;
967     long Catalog_id = pdev->Catalog->id, Info_id = pdev->Info->id,
968 	Pages_id = pdev->Pages->id, Encrypt_id = 0;
969     long Threads_id = 0;
970     bool partial_page = (pdev->contents_id != 0 && pdev->next_page != 0);
971     int code = 0, code1;
972 
973     /*
974      * If this is an EPS file, or if the file didn't end with a showpage for
975      * some other reason, or if the file has produced no marks at all, we
976      * need to tidy up a little so as not to produce illegal PDF.  However,
977      * if there is at least one complete page, we discard any leftover
978      * marks.
979      */
980     if (pdev->next_page == 0) {
981 	code = pdf_open_page(pdev, PDF_IN_STREAM);
982 
983 	if (code < 0)
984 	    return code;
985     }
986     if (pdev->contents_id != 0)
987 	pdf_close_page(pdev);
988 
989     /* Write the page objects. */
990 
991     {
992 	int i;
993 
994 	for (i = 1; i <= pdev->next_page; ++i)
995 	    pdf_write_page(pdev, i);
996     }
997 
998     if (pdev->PrintStatistics)
999 	pdf_print_resource_statistics(pdev);
1000 
1001     /* Write the font resources and related resources. */
1002     code1 = pdf_write_resource_objects(pdev, resourceXObject);
1003     if (code >= 0)
1004 	code = code1;
1005     code1 = pdf_free_resource_objects(pdev, resourceXObject);
1006     if (code >= 0)
1007 	code = code1;
1008     code1 = pdf_write_resource_objects(pdev, resourceGroup);
1009     if (code >= 0)
1010 	code = code1;
1011     code1 = pdf_free_resource_objects(pdev, resourceGroup);
1012     if (code >= 0)
1013 	code = code1;
1014     code1 = pdf_write_resource_objects(pdev, resourceSoftMaskDict);
1015     if (code >= 0)
1016 	code = code1;
1017     code1 = pdf_free_resource_objects(pdev, resourceSoftMaskDict);
1018     if (code >= 0)
1019 	code = code1;
1020     code1 = pdf_close_text_document(pdev);
1021     if (code >= 0)
1022 	code = code1;
1023     code1 = pdf_write_resource_objects(pdev, resourceCMap);
1024     if (code >= 0)
1025 	code = code1;
1026     code1 = pdf_free_resource_objects(pdev, resourceCMap);
1027     if (code >= 0)
1028 	code = code1;
1029     if (pdev->ResourcesBeforeUsage)
1030 	pdf_reverse_resource_chain(pdev, resourcePage);
1031     code1 = pdf_write_resource_objects(pdev, resourcePage);
1032     if (code >= 0)
1033 	code = code1;
1034     code1 = pdf_free_resource_objects(pdev, resourcePage);
1035     if (code >= 0)
1036 	code = code1;
1037 
1038     code1 = pdf_free_resource_objects(pdev, resourceOther);
1039     if (code >= 0)
1040 	code = code1;
1041 
1042 
1043     /* Create the Pages tree. */
1044 
1045     pdf_open_obj(pdev, Pages_id);
1046     s = pdev->strm;
1047     stream_puts(s, "<< /Type /Pages /Kids [\n");
1048     /* Omit the last page if it was incomplete. */
1049     if (partial_page)
1050 	--(pdev->next_page);
1051     {
1052 	int i;
1053 
1054 	for (i = 0; i < pdev->next_page; ++i)
1055 	    pprintld1(s, "%ld 0 R\n", pdev->pages[i].Page->id);
1056     }
1057     pprintd1(s, "] /Count %d\n", pdev->next_page);
1058     pdev->text_rotation.Rotate = pdf_dominant_rotation(&pdev->text_rotation);
1059     pdf_print_orientation(pdev, NULL);
1060     cos_dict_elements_write(pdev->Pages, pdev);
1061     stream_puts(s, ">>\n");
1062     pdf_end_obj(pdev);
1063 
1064     /* Close outlines and articles. */
1065 
1066     if (pdev->outlines_id != 0) {
1067 	/* depth > 0 is only possible for an incomplete outline tree. */
1068 	while (pdev->outline_depth > 0)
1069 	    pdfmark_close_outline(pdev);
1070 	pdfmark_close_outline(pdev);
1071 	pdf_open_obj(pdev, pdev->outlines_id);
1072 	pprintd1(s, "<< /Count %d", pdev->outlines_open);
1073 	pprintld2(s, " /First %ld 0 R /Last %ld 0 R >>\n",
1074 		  pdev->outline_levels[0].first.id,
1075 		  pdev->outline_levels[0].last.id);
1076 	pdf_end_obj(pdev);
1077     }
1078     if (pdev->articles != 0) {
1079 	pdf_article_t *part;
1080 
1081 	/* Write the remaining information for each article. */
1082 	for (part = pdev->articles; part != 0; part = part->next)
1083 	    pdfmark_write_article(pdev, part);
1084     }
1085 
1086     /* Write named destinations.  (We can't free them yet.) */
1087 
1088     if (pdev->Dests)
1089 	COS_WRITE_OBJECT(pdev->Dests, pdev);
1090 
1091     /* Write the PageLabel array */
1092     pdfmark_end_pagelabels(pdev);
1093     if (pdev->PageLabels) {
1094 	COS_WRITE_OBJECT(pdev->PageLabels, pdev);
1095     }
1096 
1097     /* Write the Catalog. */
1098 
1099     /*
1100      * The PDF specification requires Threads to be an indirect object.
1101      * Write the threads now, if any.
1102      */
1103     if (pdev->articles != 0) {
1104 	pdf_article_t *part;
1105 
1106 	Threads_id = pdf_begin_obj(pdev);
1107 	s = pdev->strm;
1108 	stream_puts(s, "[ ");
1109 	while ((part = pdev->articles) != 0) {
1110 	    pdev->articles = part->next;
1111 	    pprintld1(s, "%ld 0 R\n", part->contents->id);
1112 	    COS_FREE(part->contents, "pdf_close(article contents)");
1113 	    gs_free_object(mem, part, "pdf_close(article)");
1114 	}
1115 	stream_puts(s, "]\n");
1116 	pdf_end_obj(pdev);
1117     }
1118     pdf_open_obj(pdev, Catalog_id);
1119     s = pdev->strm;
1120     stream_puts(s, "<<");
1121     pprintld1(s, "/Type /Catalog /Pages %ld 0 R\n", Pages_id);
1122     if (pdev->outlines_id != 0)
1123 	pprintld1(s, "/Outlines %ld 0 R\n", pdev->outlines_id);
1124     if (Threads_id)
1125 	pprintld1(s, "/Threads %ld 0 R\n", Threads_id);
1126     if (pdev->Dests)
1127 	pprintld1(s, "/Dests %ld 0 R\n", pdev->Dests->id);
1128     if (pdev->PageLabels)
1129 	pprintld1(s, "/PageLabels << /Nums  %ld 0 R >>\n",
1130                   pdev->PageLabels->id);
1131     cos_dict_elements_write(pdev->Catalog, pdev);
1132     stream_puts(s, ">>\n");
1133     pdf_end_obj(pdev);
1134     if (pdev->Dests) {
1135 	COS_FREE(pdev->Dests, "pdf_close(Dests)");
1136 	pdev->Dests = 0;
1137     }
1138     if (pdev->PageLabels) {
1139 	COS_FREE(pdev->PageLabels, "pdf_close(PageLabels)");
1140 	pdev->PageLabels = 0;
1141         pdev->PageLabels_current_label = 0;
1142     }
1143 
1144     /* Prevent writing special named objects twice. */
1145 
1146     pdev->Catalog->id = 0;
1147     /*pdev->Info->id = 0;*/	/* Info should get written */
1148     pdev->Pages->id = 0;
1149     {
1150 	int i;
1151 
1152 	for (i = 0; i < pdev->num_pages; ++i)
1153 	    if (pdev->pages[i].Page)
1154 		pdev->pages[i].Page->id = 0;
1155     }
1156 
1157     /*
1158      * Write the definitions of the named objects.
1159      * Note that this includes Form XObjects created by BP/EP, named PS
1160      * XObjects, and images named by NI.
1161      */
1162 
1163     do {
1164 	cos_dict_objects_write(pdev->local_named_objects, pdev);
1165     } while (pdf_pop_namespace(pdev) >= 0);
1166     cos_dict_objects_write(pdev->global_named_objects, pdev);
1167 
1168     /* Copy the resources into the main file. */
1169 
1170     s = pdev->strm;
1171     resource_pos = stell(s);
1172     sflush(pdev->asides.strm);
1173     {
1174 	FILE *rfile = pdev->asides.file;
1175 	long res_end = ftell(rfile);
1176 
1177 	fseek(rfile, 0L, SEEK_SET);
1178 	pdf_copy_data(s, rfile, res_end, NULL);
1179     }
1180 
1181     /* Write Encrypt. */
1182     if (pdev->OwnerPassword.size > 0) {
1183 	Encrypt_id = pdf_obj_ref(pdev);
1184 
1185 	pdf_open_obj(pdev, Encrypt_id);
1186 	s = pdev->strm;
1187 	stream_puts(s, "<<");
1188 	stream_puts(s, "/Filter /Standard ");
1189 	pprintld1(s, "/V %ld ", pdev->EncryptionV);
1190 	pprintld1(s, "/Length %ld ", pdev->KeyLength);
1191 	pprintld1(s, "/R %ld ", pdev->EncryptionR);
1192 	pprintld1(s, "/P %ld ", pdev->Permissions);
1193 	stream_puts(s, "/O ");
1194 	pdf_put_string(pdev, pdev->EncryptionO, sizeof(pdev->EncryptionO));
1195 	stream_puts(s, "\n/U ");
1196 	pdf_put_string(pdev, pdev->EncryptionU, sizeof(pdev->EncryptionU));
1197 	stream_puts(s, ">>\n");
1198 	pdf_end_obj(pdev);
1199 	s = pdev->strm;
1200     }
1201 
1202     /* Write the cross-reference section. */
1203 
1204     xref = pdf_stell(pdev);
1205     if (pdev->FirstObjectNumber == 1)
1206 	pprintld1(s, "xref\n0 %ld\n0000000000 65535 f \n",
1207 		  pdev->next_id);
1208     else
1209 	pprintld2(s, "xref\n0 1\n0000000000 65535 f \n%ld %ld\n",
1210 		  pdev->FirstObjectNumber,
1211 		  pdev->next_id - pdev->FirstObjectNumber);
1212     fseek(tfile, 0L, SEEK_SET);
1213     {
1214 	long i;
1215 
1216 	for (i = pdev->FirstObjectNumber; i < pdev->next_id; ++i) {
1217 	    ulong pos;
1218 	    char str[21];
1219 
1220 	    fread(&pos, sizeof(pos), 1, tfile);
1221 	    if (pos & ASIDES_BASE_POSITION)
1222 		pos += resource_pos - ASIDES_BASE_POSITION;
1223 	    sprintf(str, "%010ld 00000 n \n", pos);
1224 	    stream_puts(s, str);
1225 	}
1226     }
1227 
1228     /* Write the trailer. */
1229 
1230     stream_puts(s, "trailer\n");
1231     pprintld3(s, "<< /Size %ld /Root %ld 0 R /Info %ld 0 R\n",
1232 	      pdev->next_id, Catalog_id, Info_id);
1233     stream_puts(s, "/ID [");
1234     psdf_write_string(pdev->strm, pdev->fileID, sizeof(pdev->fileID), 0);
1235     psdf_write_string(pdev->strm, pdev->fileID, sizeof(pdev->fileID), 0);
1236     stream_puts(s, "]\n");
1237     if (pdev->OwnerPassword.size > 0) {
1238 	pprintld1(s, "/Encrypt %ld 0 R ", Encrypt_id);
1239     }
1240     stream_puts(s, ">>\n");
1241     pprintld1(s, "startxref\n%ld\n%%%%EOF\n", xref);
1242 
1243     /* Release the resource records. */
1244 
1245     {
1246 	pdf_resource_t *pres;
1247 	pdf_resource_t *prev;
1248 
1249 	for (prev = pdev->last_resource; (pres = prev) != 0;) {
1250 	    prev = pres->prev;
1251 	    gs_free_object(mem, pres, "pdf_resource_t");
1252 	}
1253 	pdev->last_resource = 0;
1254     }
1255 
1256     /* Free named objects. */
1257 
1258     cos_dict_objects_delete(pdev->local_named_objects);
1259     COS_FREE(pdev->local_named_objects, "pdf_close(local_named_objects)");
1260     pdev->local_named_objects = 0;
1261     cos_dict_objects_delete(pdev->global_named_objects);
1262     COS_FREE(pdev->global_named_objects, "pdf_close(global_named_objects)");
1263     pdev->global_named_objects = 0;
1264 
1265     /* Wrap up. */
1266 
1267     gs_free_object(mem, pdev->pages, "pages");
1268     pdev->pages = 0;
1269     pdev->num_pages = 0;
1270 
1271     if (pdev->ForOPDFRead && pdev->OPDFReadProcsetPath.size) {
1272         /* pdf_open_dcument could set up filters for entire document.
1273            Removing them now. */
1274 	int status;
1275 
1276 	stream_putc(s, 0x04);
1277 	while (s->strm) {
1278 	    s = s->strm;
1279 	}
1280 	status = s_close_filters(&pdev->strm, s);
1281 	if (status < 0 && code == 0)
1282 	    code = gs_error_ioerror;
1283     }
1284     code1 = gdev_vector_close_file((gx_device_vector *) pdev);
1285     if (code >= 0)
1286 	code = code1;
1287     if (pdev->max_referred_page >= pdev->next_page + 1) {
1288         /* Note : pdev->max_referred_page counts from 1,
1289 	   and pdev->next_page counts from 0. */
1290 	eprintf2("ERROR: A pdfmark destination page %d points beyond the last page %d.\n",
1291 		pdev->max_referred_page, pdev->next_page);
1292 #if 0 /* Temporary disabled due to Bug 687686. */
1293 	if (code >= 0)
1294 	    code = gs_note_error(gs_error_rangecheck);
1295 #endif
1296     }
1297     return pdf_close_files(pdev, code);
1298 }
1299