Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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 
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);
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
868
round_box_coord(floatp xy)
869
{
870
    return (int)(xy * 100 + 0.5) / 100.0;
871
}
872
private int
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
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
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
}