1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gdevpdfu.c 8611 2008-03-27 08:37:58Z ken $ */
15
/* Output utilities for PDF-writing driver */
17
#include "jpeglib_.h" /* for sdct.h */
42
#include "sjbig2_luratech.h"
45
#include "sjpx_luratech.h"
48
/* Define the size of internal stream buffers. */
49
/* (This is not a limitation, it only affects performance.) */
52
/* Optionally substitute other filters for FlateEncode for debugging. */
54
# define compression_filter_name "FlateDecode"
55
# define compression_filter_template s_zlibE_template
56
# define compression_filter_state stream_zlib_state
58
# define compression_filter_name "LZWDecode"
59
# define compression_filter_template s_LZWE_template
60
# define compression_filter_state stream_LZW_state
63
/* Import procedures for writing filter parameters. */
64
extern stream_state_proc_get_params(s_DCTE_get_params, stream_DCT_state);
65
extern stream_state_proc_get_params(s_CF_get_params, stream_CF_state);
68
BEGIN if ((code = (expr)) < 0) return code; END
71
extern_st(st_pdf_color_space);
72
extern_st(st_pdf_font_resource);
73
extern_st(st_pdf_char_proc);
74
extern_st(st_pdf_font_descriptor);
75
public_st_pdf_resource();
76
private_st_pdf_x_object();
77
private_st_pdf_pattern();
79
/* ---------------- Utilities ---------------- */
82
* Strip whitespace and comments from a line of PostScript code as possible.
83
* Return a pointer to any string that remains, or NULL if none.
84
* Note that this may store into the string.
86
/* This function copied from geninit.c . */
88
doit(char *line, bool intact)
97
while (*str == ' ' || *str == '\t') /* strip leading whitespace */
99
if (*str == 0) /* all whitespace */
101
if (!strncmp(str, "%END", 4)) /* keep these for .skipeof */
103
if (str[0] == '%') /* comment line */
106
* Copy the string over itself removing:
107
* - All comments not within string literals;
108
* - Whitespace adjacent to '[' ']' '{' '}';
109
* - Whitespace before '/' '(' '<';
110
* - Whitespace after ')' '>'.
112
for (to = from = str; (*to = *from) != 0; ++from, ++to) {
120
if (to > str && !in_string && strchr(" \t>[]{})", to[-1]))
130
if (to > str && !in_string && strchr(" \t", to[-1]))
139
if (from[1] == '\\' || from[1] == '(' || from[1] == ')')
147
/* Strip trailing whitespace. */
148
while (to > str && (to[-1] == ' ' || to[-1] == '\t'))
156
copy_ps_file_stripping(stream *s, const char *fname, bool HaveTrueTypes)
159
char buf[1024], *p, *q = buf;
160
int n, l = 0, m = sizeof(buf) - 1, outl = 0;
161
bool skipping = false;
163
f = gp_fopen(fname, "rb");
165
return_error(gs_error_undefinedfilename);
166
n = fread(buf, 1, m, f);
169
if (*q == '\r' || *q == '\n') {
182
m = sizeof(buf) - 1 - l;
184
eprintf1("The procset %s contains a too long line.", fname);
185
return_error(gs_error_ioerror);
187
n = fread(buf + l, 1, m, f);
206
if (!HaveTrueTypes && !strcmp("%%beg TrueType", q))
215
stream_write(s, q, l + 1);
217
if (!HaveTrueTypes && !strcmp("%%end TrueType", q))
221
} while (n == m || q < buf + n);
223
stream_write(s, "\r", 1);
229
copy_procsets(stream *s, const gs_param_string *path, bool HaveTrueTypes)
231
char fname[gp_file_name_sizeof];
232
const byte *p = path->data, *e = path->data + path->size;
234
const char *tt_encs[] = {"gs_agl.ps", "gs_mgl_e.ps"};
238
const byte *c = memchr(p, gp_file_name_list_separator, e - p);
239
int k = 0; /* Initializing against a compiler warning only. */
245
if (l > sizeof(fname) - 1)
246
return_error(gs_error_limitcheck);
249
if (!HaveTrueTypes) {
250
for (k = count_of(tt_encs) - 1; k >= 0; k--) {
251
int L = strlen(tt_encs[k]);
253
if (!strcmp(fname + strlen(fname) - L, tt_encs[k]))
257
if (HaveTrueTypes || k < 0) {
258
code = copy_ps_file_stripping(s, fname, HaveTrueTypes);
269
return_error(gs_error_undefinedfilename);
274
encode(stream **s, const stream_template *t, gs_memory_t *mem)
276
stream_state *st = s_alloc_state(mem, t->stype, "pdf_open_document.encode");
279
return_error(gs_error_VMerror);
282
if (s_add_filter(s, t, st, mem) == 0) {
283
gs_free_object(mem, st, "pdf_open_document.encode");
284
return_error(gs_error_VMerror);
289
/* ------ Document ------ */
291
/* Open the document if necessary. */
293
pdf_open_document(gx_device_pdf * pdev)
295
if (!is_in_page(pdev) && pdf_stell(pdev) == 0) {
296
stream *s = pdev->strm;
297
int level = (int)(pdev->CompatibilityLevel * 10 + 0.5);
299
pdev->binary_ok = !pdev->params.ASCII85EncodePages;
300
if (pdev->ForOPDFRead && pdev->OPDFReadProcsetPath.size) {
303
stream_write(s, (byte *)"%!PS-Adobe-2.0\r", 15);
304
if (pdev->params.CompressPages || pdev->CompressEntireFile) {
305
/* When CompressEntireFile is true and ASCII85EncodePages is false,
306
the ASCII85Encode filter is applied, rather one may expect the opposite.
307
Keeping it so due to no demand for this mode.
308
A right implementation should compute the length of the compressed procset,
309
write out an invocation of SubFileDecode filter, and write the length to
310
there assuming the output file is positionable. */
311
stream_write(s, (byte *)"currentfile /ASCII85Decode filter /LZWDecode filter cvx exec\r", 61);
312
code = encode(&s, &s_A85E_template, pdev->pdf_memory);
315
code = encode(&s, &s_LZWE_template, pdev->pdf_memory);
319
code = copy_procsets(s, &pdev->OPDFReadProcsetPath, pdev->HaveTrueTypes);
322
if (!pdev->CompressEntireFile) {
323
status = s_close_filters(&s, pdev->strm);
325
return_error(gs_error_ioerror);
328
pdev->OPDFRead_procset_length = stell(s);
330
pprintd2(s, "%%PDF-%d.%d\n", level / 10, level % 10);
332
stream_puts(s, "%\307\354\217\242\n");
335
* Determine the compression method. Currently this does nothing.
336
* It also isn't clear whether the compression method can now be
337
* changed in the course of the document.
339
* Flate compression is available starting in PDF 1.2. Since we no
340
* longer support any older PDF versions, we ignore UseFlateCompression
341
* and always use Flate compression.
343
if (!pdev->params.CompressPages)
344
pdev->compression = pdf_compress_none;
346
pdev->compression = pdf_compress_Flate;
350
/* ------ Objects ------ */
352
/* Allocate an object ID. */
354
pdf_next_id(gx_device_pdf * pdev)
356
return (pdev->next_id)++;
360
* Return the current position in the output. Note that this may be in the
361
* main output file, the asides file, or the pictures file. If the current
362
* file is the pictures file, positions returned by pdf_stell must only be
363
* used locally (for computing lengths or patching), since there is no way
364
* to map them later to the eventual position in the output file.
367
pdf_stell(gx_device_pdf * pdev)
369
stream *s = pdev->strm;
372
if (s == pdev->asides.strm)
373
pos += ASIDES_BASE_POSITION;
377
/* Allocate an ID for a future object. */
379
pdf_obj_ref(gx_device_pdf * pdev)
381
long id = pdf_next_id(pdev);
382
long pos = pdf_stell(pdev);
384
fwrite(&pos, sizeof(pos), 1, pdev->xref.file);
388
/* Begin an object, optionally allocating an ID. */
390
pdf_open_obj(gx_device_pdf * pdev, long id)
392
stream *s = pdev->strm;
395
id = pdf_obj_ref(pdev);
397
long pos = pdf_stell(pdev);
398
FILE *tfile = pdev->xref.file;
399
long tpos = ftell(tfile);
401
fseek(tfile, (id - pdev->FirstObjectNumber) * sizeof(pos),
403
fwrite(&pos, sizeof(pos), 1, tfile);
404
fseek(tfile, tpos, SEEK_SET);
406
pprintld1(s, "%ld 0 obj\n", id);
410
pdf_begin_obj(gx_device_pdf * pdev)
412
return pdf_open_obj(pdev, 0L);
417
pdf_end_obj(gx_device_pdf * pdev)
419
stream_puts(pdev->strm, "endobj\n");
423
/* ------ Page contents ------ */
425
/* Handle transitions between contexts. */
427
none_to_stream(gx_device_pdf *), stream_to_text(gx_device_pdf *),
428
string_to_text(gx_device_pdf *), text_to_stream(gx_device_pdf *),
429
stream_to_none(gx_device_pdf *);
430
typedef int (*context_proc) (gx_device_pdf *);
431
static const context_proc context_procs[4][4] =
433
{0, none_to_stream, none_to_stream, none_to_stream},
434
{stream_to_none, 0, stream_to_text, stream_to_text},
435
{text_to_stream, text_to_stream, 0, 0},
436
{string_to_text, string_to_text, string_to_text, 0}
439
/* Compute an object encryption key. */
441
pdf_object_key(const gx_device_pdf * pdev, gs_id object_id, byte key[16])
444
gs_md5_byte_t zero[2] = {0, 0}, t;
445
int KeySize = pdev->KeyLength / 8;
448
gs_md5_append(&md5, pdev->EncryptionKey, KeySize);
449
t = (byte)(object_id >> 0); gs_md5_append(&md5, &t, 1);
450
t = (byte)(object_id >> 8); gs_md5_append(&md5, &t, 1);
451
t = (byte)(object_id >> 16); gs_md5_append(&md5, &t, 1);
452
gs_md5_append(&md5, zero, 2);
453
gs_md5_finish(&md5, key);
454
return min(KeySize + 5, 16);
457
/* Initialize encryption. */
459
pdf_encrypt_init(const gx_device_pdf * pdev, gs_id object_id, stream_arcfour_state *psarc4)
463
return s_arcfour_set_key(psarc4, key, pdf_object_key(pdev, object_id, key));
467
/* Add the encryption filter. */
469
pdf_begin_encrypt(gx_device_pdf * pdev, stream **s, gs_id object_id)
471
gs_memory_t *mem = pdev->v_memory;
472
stream_arcfour_state *ss;
473
gs_md5_byte_t key[16];
476
if (!pdev->KeyLength)
478
keylength = pdf_object_key(pdev, object_id, key);
479
ss = gs_alloc_struct(mem, stream_arcfour_state,
480
s_arcfour_template.stype, "psdf_encrypt");
482
return_error(gs_error_VMerror);
483
code = s_arcfour_set_key(ss, key, keylength);
486
if (s_add_filter(s, &s_arcfour_template, (stream_state *)ss, mem) == 0)
487
return_error(gs_error_VMerror);
490
We don't encrypt streams written into temporary files,
491
because they can be used for comparizon
492
(for example, for merging equal images).
493
Instead that the encryption is applied in pdf_copy_data,
494
when the stream is copied to the output file.
498
/* Remove the encryption filter. */
500
pdf_end_encrypt(gx_device_pdf * pdev)
502
if (pdev->KeyLength) {
503
stream *s = pdev->strm;
504
stream *fs = s->strm;
507
gs_free_object(pdev->pdf_memory, s->cbuf, "encrypt buffer");
508
gs_free_object(pdev->pdf_memory, s, "encrypt stream");
513
/* Enter stream context. */
515
none_to_stream(gx_device_pdf * pdev)
520
if (pdev->contents_id != 0)
521
return_error(gs_error_Fatal); /* only 1 contents per page */
522
pdev->compression_at_page_start = pdev->compression;
523
if (pdev->ResourcesBeforeUsage) {
524
pdf_resource_t *pres;
526
code = pdf_enter_substream(pdev, resourcePage, gs_no_id, &pres,
527
true, pdev->params.CompressPages);
530
pdev->contents_id = pres->object->id;
531
pdev->contents_length_id = gs_no_id; /* inapplicable */
532
pdev->contents_pos = -1; /* inapplicable */
535
pdev->contents_id = pdf_begin_obj(pdev);
536
pdev->contents_length_id = pdf_obj_ref(pdev);
538
pprintld1(s, "<</Length %ld 0 R", pdev->contents_length_id);
539
if (pdev->compression == pdf_compress_Flate) {
541
pprints1(s, "/Filter /%s", compression_filter_name);
543
pprints1(s, "/Filter [/ASCII85Decode /%s]", compression_filter_name);
545
stream_puts(s, ">>\nstream\n");
546
pdev->contents_pos = pdf_stell(pdev);
547
code = pdf_begin_encrypt(pdev, &s, pdev->contents_id);
551
if (pdev->compression == pdf_compress_Flate) { /* Set up the Flate filter. */
552
const stream_template *template;
555
compression_filter_state *st;
557
if (!pdev->binary_ok) { /* Set up the A85 filter */
558
const stream_template *template = &s_A85E_template;
559
stream *as = s_alloc(pdev->pdf_memory, "PDF contents stream");
560
byte *buf = gs_alloc_bytes(pdev->pdf_memory, sbuf_size,
561
"PDF contents buffer");
562
stream_A85E_state *ast = gs_alloc_struct(pdev->pdf_memory, stream_A85E_state,
563
template->stype, "PDF contents state");
564
if (as == 0 || ast == 0 || buf == 0)
565
return_error(gs_error_VMerror);
566
s_std_init(as, buf, sbuf_size, &s_filter_write_procs,
568
ast->memory = pdev->pdf_memory;
569
ast->template = template;
570
as->state = (stream_state *) ast;
571
as->procs.process = template->process;
573
(*template->init) ((stream_state *) ast);
576
template = &compression_filter_template;
577
es = s_alloc(pdev->pdf_memory, "PDF compression stream");
578
buf = gs_alloc_bytes(pdev->pdf_memory, sbuf_size,
579
"PDF compression buffer");
580
st = gs_alloc_struct(pdev->pdf_memory, compression_filter_state,
581
template->stype, "PDF compression state");
582
if (es == 0 || st == 0 || buf == 0)
583
return_error(gs_error_VMerror);
584
s_std_init(es, buf, sbuf_size, &s_filter_write_procs,
586
st->memory = pdev->pdf_memory;
587
st->template = template;
588
es->state = (stream_state *) st;
589
es->procs.process = template->process;
591
(*template->set_defaults) ((stream_state *) st);
592
(*template->init) ((stream_state *) st);
597
* Scale the coordinate system. Use an extra level of q/Q for the
598
* sake of poorly designed PDF tools that assume that the contents
599
* stream restores the CTM.
601
pprintg2(s, "q %g 0 0 %g 0 0 cm\n",
602
72.0 / pdev->HWResolution[0], 72.0 / pdev->HWResolution[1]);
603
if (pdev->CompatibilityLevel >= 1.3) {
604
/* Set the default rendering intent. */
605
if (pdev->params.DefaultRenderingIntent != ri_Default) {
606
static const char *const ri_names[] = { psdf_ri_names };
608
pprints1(s, "/%s ri\n",
609
ri_names[(int)pdev->params.DefaultRenderingIntent]);
612
pdev->AR4_save_bug = false;
613
return PDF_IN_STREAM;
615
/* Enter text context from stream context. */
617
stream_to_text(gx_device_pdf * pdev)
622
* Bizarrely enough, Acrobat Reader cares how the final font size is
623
* obtained -- the CTM (cm), text matrix (Tm), and font size (Tf)
624
* are *not* all equivalent. In particular, it seems to use the
625
* product of the text matrix and font size to decide how to
626
* anti-alias characters. Therefore, we have to temporarily patch
627
* the CTM so that the scale factors are unity. What a nuisance!
629
code = pdf_save_viewer_state(pdev, pdev->strm);
632
pprintg2(pdev->strm, "%g 0 0 %g 0 0 cm BT\n",
633
pdev->HWResolution[0] / 72.0, pdev->HWResolution[1] / 72.0);
634
pdev->procsets |= Text;
635
code = pdf_from_stream_to_text(pdev);
636
return (code < 0 ? code : PDF_IN_TEXT);
638
/* Exit string context to text context. */
640
string_to_text(gx_device_pdf * pdev)
642
int code = pdf_from_string_to_text(pdev);
644
return (code < 0 ? code : PDF_IN_TEXT);
646
/* Exit text context to stream context. */
648
text_to_stream(gx_device_pdf * pdev)
652
stream_puts(pdev->strm, "ET\n");
653
code = pdf_restore_viewer_state(pdev, pdev->strm);
656
pdf_reset_text(pdev); /* because of Q */
657
return PDF_IN_STREAM;
659
/* Exit stream context. */
661
stream_to_none(gx_device_pdf * pdev)
663
stream *s = pdev->strm;
666
if (pdev->ResourcesBeforeUsage) {
667
int code = pdf_exit_substream(pdev);
672
if (pdev->vgstack_depth)
673
pdf_restore_viewer_state(pdev, s);
674
if (pdev->compression_at_page_start == pdf_compress_Flate) { /* Terminate the filters. */
675
stream *fs = s->strm;
677
if (!pdev->binary_ok) {
678
sclose(s); /* Terminate the ASCII85 filter. */
679
gs_free_object(pdev->pdf_memory, s->cbuf, "A85E contents buffer");
680
gs_free_object(pdev->pdf_memory, s, "A85E contents stream");
684
sclose(s); /* Next terminate the compression filter */
685
gs_free_object(pdev->pdf_memory, s->cbuf, "zlib buffer");
686
gs_free_object(pdev->pdf_memory, s, "zlib stream");
689
pdf_end_encrypt(pdev);
691
length = pdf_stell(pdev) - pdev->contents_pos;
693
stream_puts(s, "\n");
694
stream_puts(s, "endstream\n");
696
pdf_open_obj(pdev, pdev->contents_length_id);
697
pprintld1(s, "%ld\n", length);
703
/* Begin a page contents part. */
705
pdf_open_contents(gx_device_pdf * pdev, pdf_context_t context)
707
int (*proc) (gx_device_pdf *);
709
while ((proc = context_procs[pdev->context][context]) != 0) {
710
int code = (*proc) (pdev);
714
pdev->context = (pdf_context_t) code;
716
pdev->context = context;
720
/* Close the current contents part if we are in one. */
722
pdf_close_contents(gx_device_pdf * pdev, bool last)
724
if (pdev->context == PDF_IN_NONE)
726
if (last) { /* Exit from the clipping path gsave. */
727
int code = pdf_open_contents(pdev, PDF_IN_STREAM);
731
stream_puts(pdev->strm, "Q\n"); /* See none_to_stream. */
732
pdf_close_text_contents(pdev);
734
return pdf_open_contents(pdev, PDF_IN_NONE);
737
/* ------ Resources et al ------ */
739
/* Define the allocator descriptors for the resource types. */
740
const char *const pdf_resource_type_names[] = {
741
PDF_RESOURCE_TYPE_NAMES
743
const gs_memory_struct_type_t *const pdf_resource_type_structs[] = {
744
PDF_RESOURCE_TYPE_STRUCTS
747
/* Cancel a resource (do not write it into PDF). */
749
pdf_cancel_resource(gx_device_pdf * pdev, pdf_resource_t *pres, pdf_resource_type_t rtype)
751
/* fixme : remove *pres from resource chain. */
752
pres->where_used = 0;
753
pres->object->written = true;
754
if (rtype == resourceXObject || rtype == resourceCharProc || rtype == resourceOther
756
int code = cos_stream_release_pieces((cos_stream_t *)pres->object);
761
cos_release(pres->object, "pdf_cancel_resource");
765
/* Remove a resource. */
767
pdf_forget_resource(gx_device_pdf * pdev, pdf_resource_t *pres1, pdf_resource_type_t rtype)
768
{ /* fixme : optimize. */
769
pdf_resource_t **pchain = pdev->resources[rtype].chains;
770
pdf_resource_t *pres;
771
pdf_resource_t **pprev = &pdev->last_resource;
774
for (; (pres = *pprev) != 0; pprev = &pres->prev)
779
for (i = 0; i < NUM_RESOURCE_CHAINS; i++) {
781
for (; (pres = *pprev) != 0; pprev = &pres->next)
784
COS_RELEASE(pres->object, "pdf_forget_resource");
785
gs_free_object(pdev->pdf_memory, pres->object, "pdf_forget_resource");
786
gs_free_object(pdev->pdf_memory, pres, "pdf_forget_resource");
793
nocheck(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1)
799
/* Substitute a resource with a same one. */
801
pdf_substitute_resource(gx_device_pdf *pdev, pdf_resource_t **ppres,
802
pdf_resource_type_t rtype,
803
int (*eq)(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1),
806
pdf_resource_t *pres1 = *ppres;
809
code = pdf_find_same_resource(pdev, rtype, ppres, (eq ? eq : nocheck));
813
code = pdf_cancel_resource(pdev, (pdf_resource_t *)pres1, rtype);
816
pdf_forget_resource(pdev, pres1, rtype);
819
pdf_reserve_object_id(pdev, pres1, gs_no_id);
821
code = cos_write_object(pres1->object, pdev);
824
pres1->object->written = 1;
830
/* Find a resource of a given type by gs_id. */
832
pdf_find_resource_by_gs_id(gx_device_pdf * pdev, pdf_resource_type_t rtype,
835
pdf_resource_t **pchain = PDF_RESOURCE_CHAIN(pdev, rtype, rid);
836
pdf_resource_t **pprev = pchain;
837
pdf_resource_t *pres;
839
for (; (pres = *pprev) != 0; pprev = &pres->next)
840
if (pres->rid == rid) {
841
if (pprev != pchain) {
843
pres->next = *pchain;
851
/* Find resource by resource id. */
853
pdf_find_resource_by_resource_id(gx_device_pdf * pdev, pdf_resource_type_t rtype, gs_id id)
855
pdf_resource_t **pchain = pdev->resources[rtype].chains;
856
pdf_resource_t *pres;
859
for (i = 0; i < NUM_RESOURCE_CHAINS; i++) {
860
for (pres = pchain[i]; pres != 0; pres = pres->next) {
861
if (pres->object->id == id)
869
/* Find same resource. */
871
pdf_find_same_resource(gx_device_pdf * pdev, pdf_resource_type_t rtype, pdf_resource_t **ppres,
872
int (*eq)(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1))
874
pdf_resource_t **pchain = pdev->resources[rtype].chains;
875
pdf_resource_t *pres;
876
cos_object_t *pco0 = (*ppres)->object;
879
for (i = 0; i < NUM_RESOURCE_CHAINS; i++) {
880
for (pres = pchain[i]; pres != 0; pres = pres->next) {
881
if (*ppres != pres) {
883
cos_object_t *pco1 = pres->object;
885
if (cos_type(pco0) != cos_type(pco1))
886
continue; /* don't compare different types */
887
code = pco0->cos_procs->equal(pco0, pco1, pdev);
891
code = eq(pdev, *ppres, pres);
905
/* Drop resources by a condition. */
907
pdf_drop_resources(gx_device_pdf * pdev, pdf_resource_type_t rtype,
908
int (*cond)(gx_device_pdf * pdev, pdf_resource_t *pres))
910
pdf_resource_t **pchain = pdev->resources[rtype].chains;
911
pdf_resource_t **pprev;
912
pdf_resource_t *pres;
915
for (i = 0; i < NUM_RESOURCE_CHAINS; i++) {
917
for (; (pres = *pprev) != 0; ) {
918
if (cond(pdev, pres)) {
920
pres->next = pres; /* A temporary mark - see below */
925
pprev = &pdev->last_resource;
926
for (; (pres = *pprev) != 0; )
927
if (pres->next == pres) {
929
COS_RELEASE(pres->object, "pdf_drop_resources");
930
gs_free_object(pdev->pdf_memory, pres->object, "pdf_drop_resources");
931
gs_free_object(pdev->pdf_memory, pres, "pdf_drop_resources");
936
/* Print resource statistics. */
938
pdf_print_resource_statistics(gx_device_pdf * pdev)
943
for (rtype = 0; rtype < NUM_RESOURCE_TYPES; rtype++) {
944
pdf_resource_t **pchain = pdev->resources[rtype].chains;
945
pdf_resource_t *pres;
946
const char *name = pdf_resource_type_names[rtype];
949
for (i = 0; i < NUM_RESOURCE_CHAINS; i++) {
950
for (pres = pchain[i]; pres != 0; pres = pres->next, n++);
952
dprintf3("Resource type %d (%s) has %d instances.\n", rtype,
953
(name ? name : ""), n);
958
/* Begin an object logically separate from the contents. */
960
pdf_open_separate(gx_device_pdf * pdev, long id)
962
pdf_open_document(pdev);
963
pdev->asides.save_strm = pdev->strm;
964
pdev->strm = pdev->asides.strm;
965
return pdf_open_obj(pdev, id);
968
pdf_begin_separate(gx_device_pdf * pdev)
970
return pdf_open_separate(pdev, 0L);
974
pdf_reserve_object_id(gx_device_pdf * pdev, pdf_resource_t *pres, long id)
976
pres->object->id = (id == 0 ? pdf_obj_ref(pdev) : id);
977
sprintf(pres->rname, "R%ld", pres->object->id);
980
/* Begin an aside (resource, annotation, ...). */
982
pdf_alloc_aside(gx_device_pdf * pdev, pdf_resource_t ** plist,
983
const gs_memory_struct_type_t * pst, pdf_resource_t **ppres,
986
pdf_resource_t *pres;
987
cos_object_t *object;
990
pst = &st_pdf_resource;
991
pres = gs_alloc_struct(pdev->pdf_memory, pdf_resource_t, pst,
992
"pdf_alloc_aside(resource)");
994
return_error(gs_error_VMerror);
995
object = cos_object_alloc(pdev, "pdf_alloc_aside(object)");
997
return_error(gs_error_VMerror);
998
memset(pres + 1, 0, pst->ssize - sizeof(*pres));
999
pres->object = object;
1004
pdf_reserve_object_id(pdev, pres, id);
1005
pres->next = *plist;
1008
pres->prev = pdev->last_resource;
1009
pdev->last_resource = pres;
1010
pres->named = false;
1011
pres->global = false;
1012
pres->where_used = pdev->used_mask;
1017
pdf_begin_aside(gx_device_pdf * pdev, pdf_resource_t ** plist,
1018
const gs_memory_struct_type_t * pst, pdf_resource_t ** ppres)
1020
long id = pdf_begin_separate(pdev);
1024
return pdf_alloc_aside(pdev, plist, pst, ppres, id);
1027
/* Begin a resource of a given type. */
1029
pdf_begin_resource_body(gx_device_pdf * pdev, pdf_resource_type_t rtype,
1030
gs_id rid, pdf_resource_t ** ppres)
1032
int code = pdf_begin_aside(pdev, PDF_RESOURCE_CHAIN(pdev, rtype, rid),
1033
pdf_resource_type_structs[rtype], ppres);
1036
(*ppres)->rid = rid;
1040
pdf_begin_resource(gx_device_pdf * pdev, pdf_resource_type_t rtype, gs_id rid,
1041
pdf_resource_t ** ppres)
1043
int code = pdf_begin_resource_body(pdev, rtype, rid, ppres);
1045
if (code >= 0 && pdf_resource_type_names[rtype] != 0) {
1046
stream *s = pdev->strm;
1048
pprints1(s, "<</Type%s", pdf_resource_type_names[rtype]);
1049
pprintld1(s, "/Name/R%ld", (*ppres)->object->id);
1054
/* Allocate a resource, but don't open the stream. */
1056
pdf_alloc_resource(gx_device_pdf * pdev, pdf_resource_type_t rtype, gs_id rid,
1057
pdf_resource_t ** ppres, long id)
1059
int code = pdf_alloc_aside(pdev, PDF_RESOURCE_CHAIN(pdev, rtype, rid),
1060
pdf_resource_type_structs[rtype], ppres, id);
1063
(*ppres)->rid = rid;
1067
/* Get the object id of a resource. */
1069
pdf_resource_id(const pdf_resource_t *pres)
1071
return pres->object->id;
1074
/* End an aside or other separate object. */
1076
pdf_end_separate(gx_device_pdf * pdev)
1078
int code = pdf_end_obj(pdev);
1080
pdev->strm = pdev->asides.save_strm;
1081
pdev->asides.save_strm = 0;
1085
pdf_end_aside(gx_device_pdf * pdev)
1087
return pdf_end_separate(pdev);
1090
/* End a resource. */
1092
pdf_end_resource(gx_device_pdf * pdev)
1094
return pdf_end_aside(pdev);
1098
* Write the Cos objects for resources local to a content stream. Formerly,
1099
* this procedure also freed such objects, but this doesn't work, because
1100
* resources of one type might refer to resources of another type.
1103
pdf_write_resource_objects(gx_device_pdf *pdev, pdf_resource_type_t rtype)
1107
for (j = 0; j < NUM_RESOURCE_CHAINS && code >= 0; ++j) {
1108
pdf_resource_t *pres = pdev->resources[rtype].chains[j];
1110
for (; pres != 0; pres = pres->next)
1111
if ((!pres->named || pdev->ForOPDFRead)
1112
&& !pres->object->written)
1113
code = cos_write_object(pres->object, pdev);
1120
* Reverse resource chains.
1121
* ps2write uses it with page resources.
1122
* Assuming only the 0th chain contauns something.
1125
pdf_reverse_resource_chain(gx_device_pdf *pdev, pdf_resource_type_t rtype)
1127
pdf_resource_t *pres = pdev->resources[rtype].chains[0];
1128
pdf_resource_t *pres1, *pres0 = pres, *pres2;
1136
pres2 = pres1->next;
1142
pdev->resources[rtype].chains[0] = pres;
1147
* Free unnamed Cos objects for resources local to a content stream,
1148
* since they can't be used again.
1151
pdf_free_resource_objects(gx_device_pdf *pdev, pdf_resource_type_t rtype)
1155
for (j = 0; j < NUM_RESOURCE_CHAINS; ++j) {
1156
pdf_resource_t **prev = &pdev->resources[rtype].chains[j];
1157
pdf_resource_t *pres;
1159
while ((pres = *prev) != 0) {
1160
if (pres->named) { /* named, don't free */
1163
cos_free(pres->object, "pdf_free_resource_objects");
1172
/* Write and free all resource objects. */
1175
pdf_write_and_free_all_resource_objects(gx_device_pdf *pdev)
1177
int i, code = 0, code1;
1179
for (i = 0; i < NUM_RESOURCE_TYPES; ++i) {
1180
code1 = pdf_write_resource_objects(pdev, i);
1184
code1 = pdf_finish_resources(pdev, resourceFontDescriptor,
1185
pdf_release_FontDescriptor_components);
1188
for (i = 0; i < NUM_RESOURCE_TYPES; ++i) {
1189
code1 = pdf_free_resource_objects(pdev, i);
1197
* Store the resource sets for a content stream (page or XObject).
1198
* Sets page->{procsets, resource_ids[]}.
1201
pdf_store_page_resources(gx_device_pdf *pdev, pdf_page_t *page)
1205
/* Write any resource dictionaries. */
1207
for (i = 0; i <= resourceFont; ++i) {
1211
if (i == resourceOther)
1213
page->resource_ids[i] = 0;
1214
for (j = 0; j < NUM_RESOURCE_CHAINS; ++j) {
1215
pdf_resource_t *pres = pdev->resources[i].chains[j];
1217
for (; pres != 0; pres = pres->next) {
1218
if (pres->where_used & pdev->used_mask) {
1219
long id = pdf_resource_id(pres);
1224
page->resource_ids[i] = pdf_begin_separate(pdev);
1226
stream_puts(s, "<<");
1228
pprints1(s, "/%s\n", pres->rname);
1229
pprintld1(s, "%ld 0 R", id);
1230
pres->where_used -= pdev->used_mask;
1235
stream_puts(s, ">>\n");
1236
pdf_end_separate(pdev);
1237
if (i != resourceFont)
1238
pdf_write_resource_objects(pdev, i);
1241
page->procsets = pdev->procsets;
1245
/* Copy data from a temporary file to a stream. */
1247
pdf_copy_data(stream *s, FILE *file, long count, stream_arcfour_state *ss)
1250
byte buf[sbuf_size];
1253
uint copy = min(left, sbuf_size);
1255
fread(buf, 1, copy, file);
1257
s_arcfour_process_buffer(ss, buf, copy);
1258
stream_write(s, buf, copy);
1264
/* Copy data from a temporary file to a stream,
1265
which may be targetted to the same file. */
1267
pdf_copy_data_safe(stream *s, FILE *file, long position, long count)
1272
byte buf[sbuf_size];
1273
long copy = min(left, (long)sbuf_size);
1274
long end_pos = ftell(file);
1276
fseek(file, position + count - left, SEEK_SET);
1277
fread(buf, 1, copy, file);
1278
fseek(file, end_pos, SEEK_SET);
1279
stream_write(s, buf, copy);
1285
/* ------ Pages ------ */
1287
/* Get or assign the ID for a page. */
1288
/* Returns 0 if the page number is out of range. */
1290
pdf_page_id(gx_device_pdf * pdev, int page_num)
1296
if (page_num >= pdev->num_pages) { /* Grow the pages array. */
1297
uint new_num_pages =
1298
max(page_num + 10, pdev->num_pages << 1);
1299
pdf_page_t *new_pages =
1300
gs_resize_object(pdev->pdf_memory, pdev->pages, new_num_pages,
1301
"pdf_page_id(resize pages)");
1305
memset(&new_pages[pdev->num_pages], 0,
1306
(new_num_pages - pdev->num_pages) * sizeof(pdf_page_t));
1307
pdev->pages = new_pages;
1308
pdev->num_pages = new_num_pages;
1310
if ((Page = pdev->pages[page_num - 1].Page) == 0) {
1311
pdev->pages[page_num - 1].Page = Page =
1312
cos_dict_alloc(pdev, "pdf_page_id");
1313
Page->id = pdf_obj_ref(pdev);
1318
/* Get the page structure for the current page. */
1320
pdf_current_page(gx_device_pdf *pdev)
1322
return &pdev->pages[pdev->next_page];
1325
/* Get the dictionary object for the current page. */
1327
pdf_current_page_dict(gx_device_pdf *pdev)
1329
if (pdf_page_id(pdev, pdev->next_page + 1) <= 0)
1331
return pdev->pages[pdev->next_page].Page;
1334
/* Write saved page- or document-level information. */
1336
pdf_write_saved_string(gx_device_pdf * pdev, gs_string * pstr)
1338
if (pstr->data != 0) {
1339
stream_write(pdev->strm, pstr->data, pstr->size);
1340
gs_free_string(pdev->pdf_memory, pstr->data, pstr->size,
1341
"pdf_write_saved_string");
1347
/* Open a page for writing. */
1349
pdf_open_page(gx_device_pdf * pdev, pdf_context_t context)
1351
if (!is_in_page(pdev)) {
1354
if (pdf_page_id(pdev, pdev->next_page + 1) == 0)
1355
return_error(gs_error_VMerror);
1356
code = pdf_open_document(pdev);
1360
/* Note that context may be PDF_IN_NONE here. */
1361
return pdf_open_contents(pdev, context);
1365
/* Go to the unclipped stream context. */
1367
pdf_unclip(gx_device_pdf * pdev)
1369
const int bottom = (pdev->ResourcesBeforeUsage ? 1 : 0);
1370
/* When ResourcesBeforeUsage != 0, one sbstack element
1371
appears from the page contents stream. */
1373
if (pdev->sbstack_depth <= bottom) {
1374
int code = pdf_open_page(pdev, PDF_IN_STREAM);
1379
if (pdev->context > PDF_IN_STREAM) {
1380
int code = pdf_open_contents(pdev, PDF_IN_STREAM);
1385
if (pdev->vgstack_depth > pdev->vgstack_bottom) {
1386
int code = pdf_restore_viewer_state(pdev, pdev->strm);
1390
code = pdf_remember_clip_path(pdev, NULL);
1393
pdev->clip_path_id = pdev->no_clip_path_id;
1399
/* ------ Miscellaneous output ------ */
1401
/* Generate the default Producer string. */
1403
pdf_store_default_Producer(char buf[PDF_MAX_PRODUCER])
1405
sprintf(buf, ((gs_revision % 100) == 0 ? "(%s %1.1f)" : "(%s %1.2f)"),
1406
gs_product, gs_revision / 100.0);
1409
/* Write matrix values. */
1411
pdf_put_matrix(gx_device_pdf * pdev, const char *before,
1412
const gs_matrix * pmat, const char *after)
1414
stream *s = pdev->strm;
1417
stream_puts(s, before);
1418
pprintg6(s, "%g %g %g %g %g %g ",
1419
pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty);
1421
stream_puts(s, after);
1425
* Write a name, with escapes for unusual characters. Since we only support
1426
* PDF 1.2 and above, we can use an escape sequence for anything except a
1427
* null <00>, and the machinery for selecting the put_name_chars procedure
1428
* depending on CompatibilityLevel is no longer needed.
1431
pdf_put_name_chars_1_2(stream *s, const byte *nstr, uint size)
1435
for (i = 0; i < size; ++i) {
1441
if (c >= 0x21 && c <= 0x7e) {
1442
stream_putc(s, (byte)c);
1453
sprintf(hex, "#%02x", c);
1454
stream_puts(s, hex);
1457
stream_puts(s, "BnZr"); /* arbitrary */
1462
pdf_put_name_chars_proc_t
1463
pdf_put_name_chars_proc(const gx_device_pdf *pdev)
1465
return &pdf_put_name_chars_1_2;
1468
pdf_put_name_chars(const gx_device_pdf *pdev, const byte *nstr, uint size)
1470
return pdf_put_name_chars_proc(pdev)(pdev->strm, nstr, size);
1473
pdf_put_name(const gx_device_pdf *pdev, const byte *nstr, uint size)
1475
stream_putc(pdev->strm, '/');
1476
return pdf_put_name_chars(pdev, nstr, size);
1479
/* Write an encoded string with encryption. */
1481
pdf_encrypt_encoded_string(const gx_device_pdf *pdev, const byte *str, uint size, gs_id object_id)
1483
stream sinp, sstr, sout;
1484
stream_PSSD_state st;
1486
byte buf[100], bufo[100];
1487
stream_arcfour_state sarc4;
1489
if (pdf_encrypt_init(pdev, object_id, &sarc4) < 0) {
1490
/* The interface can't pass an error. */
1491
stream_write(pdev->strm, str, size);
1494
s_init(&sinp, NULL);
1495
sread_string(&sinp, str + 1, size);
1496
s_init(&sstr, NULL);
1497
sstr.close_at_eod = false;
1498
s_init_state((stream_state *)&st, &s_PSSD_template, NULL);
1499
s_init_filter(&sstr, (stream_state *)&st, buf, sizeof(buf), &sinp);
1500
s_init(&sout, NULL);
1501
s_init_state(&so, &s_PSSE_template, NULL);
1502
s_init_filter(&sout, &so, bufo, sizeof(bufo), pdev->strm);
1503
stream_putc(pdev->strm, '(');
1506
int code = sgets(&sstr, buf, sizeof(buf), &n);
1509
s_arcfour_process_buffer(&sarc4, buf, n);
1510
stream_write(&sout, buf, n);
1514
if (code < 0 || n < sizeof(buf)) {
1515
/* The interface can't pass an error. */
1519
sclose(&sout); /* Writes ')'. */
1520
return stell(&sinp) + 1;
1523
/* Write an encoded string with possible encryption. */
1525
pdf_put_encoded_string(const gx_device_pdf *pdev, const byte *str, uint size, gs_id object_id)
1527
if (!pdev->KeyLength || object_id == (gs_id)-1) {
1528
stream_write(pdev->strm, str, size);
1531
return pdf_encrypt_encoded_string(pdev, str, size, object_id);
1533
/* Write an encoded hexadecimal string with possible encryption. */
1535
pdf_put_encoded_hex_string(const gx_device_pdf *pdev, const byte *str, uint size, gs_id object_id)
1537
eprintf("Unimplemented function : pdf_put_encoded_hex_string\n");
1538
stream_write(pdev->strm, str, size);
1539
return_error(gs_error_unregistered);
1541
/* Scan an item in a serialized array or dictionary.
1542
This is a very simplified Postscript lexical scanner.
1543
It assumes the serialization with pdf===only defined in gs/lib/gs_pdfwr.ps .
1544
We only need to select strings and encrypt them.
1545
Other items are passed identically.
1546
Note we don't reconstruct the nesting of arrays|dictionaries.
1549
pdf_scan_item(const gx_device_pdf * pdev, const byte * p, uint l, gs_id object_id)
1554
if (*q == ' ' || *q == 't' || *q == '\r' || *q == '\n')
1555
return (l > 0 ? 1 : 0);
1556
for (q++, n--; n; q++, n--) {
1557
if (*q == ' ' || *q == 't' || *q == '\r' || *q == '\n')
1559
if (*q == '/' || *q == '[' || *q == ']' || *q == '{' || *q == '}' || *q == '(' || *q == '<')
1561
/* Note : immediate names are not allowed in PDF. */
1566
/* Write a serialized array or dictionary with possible encryption. */
1568
pdf_put_composite(const gx_device_pdf * pdev, const byte * vstr, uint size, gs_id object_id)
1570
if (!pdev->KeyLength || object_id == (gs_id)-1) {
1571
stream_write(pdev->strm, vstr, size);
1573
const byte *p = vstr;
1578
n = pdf_encrypt_encoded_string(pdev, p, l, object_id);
1580
n = pdf_scan_item(pdev, p, l, object_id);
1581
stream_write(pdev->strm, p, n);
1591
* Write a string in its shortest form ( () or <> ). Note that
1592
* this form is different depending on whether binary data are allowed.
1593
* We wish PDF supported ASCII85 strings ( <~ ~> ), but it doesn't.
1596
pdf_put_string(const gx_device_pdf * pdev, const byte * str, uint size)
1598
psdf_write_string(pdev->strm, str, size,
1599
(pdev->binary_ok ? PRINT_BINARY_OK : 0));
1603
/* Write a value, treating names specially. */
1605
pdf_write_value(const gx_device_pdf * pdev, const byte * vstr, uint size, gs_id object_id)
1607
if (size > 0 && vstr[0] == '/')
1608
return pdf_put_name(pdev, vstr + 1, size - 1);
1609
else if (size > 3 && vstr[0] == 0 && vstr[1] == 0 && vstr[size - 1] == 0)
1610
return pdf_put_name(pdev, vstr + 3, size - 4);
1611
else if (size > 1 && (vstr[0] == '[' || vstr[0] == '{'))
1612
return pdf_put_composite(pdev, vstr, size, object_id);
1613
else if (size > 2 && vstr[0] == '<' && vstr[1] == '<')
1614
return pdf_put_composite(pdev, vstr, size, object_id);
1615
else if (size > 1 && vstr[0] == '(')
1616
return pdf_put_encoded_string(pdev, vstr, size, object_id);
1617
else if (size > 1 && vstr[0] == '<')
1618
return pdf_put_encoded_hex_string(pdev, vstr, size, object_id);
1619
stream_write(pdev->strm, vstr, size);
1623
/* Store filters for a stream. */
1624
/* Currently this only saves parameters for CCITTFaxDecode. */
1626
pdf_put_filters(cos_dict_t *pcd, gx_device_pdf *pdev, stream *s,
1627
const pdf_filter_names_t *pfn)
1629
const char *filter_name = 0;
1630
bool binary_ok = true;
1632
cos_dict_t *decode_parms = 0;
1635
for (; fs != 0; fs = fs->strm) {
1636
const stream_state *st = fs->state;
1637
const stream_template *template = st->template;
1639
#define TEMPLATE_IS(atemp)\
1640
(template->process == (atemp).process)
1641
if (TEMPLATE_IS(s_A85E_template))
1643
else if (TEMPLATE_IS(s_CFE_template)) {
1644
cos_param_list_writer_t writer;
1645
stream_CF_state cfs;
1648
cos_dict_alloc(pdev, "pdf_put_image_filters(decode_parms)");
1649
if (decode_parms == 0)
1650
return_error(gs_error_VMerror);
1651
CHECK(cos_param_list_writer_init(&writer, decode_parms, 0));
1653
* If EndOfBlock is true, we mustn't write a Rows value.
1654
* This is a hack....
1656
cfs = *(const stream_CF_state *)st;
1659
CHECK(s_CF_get_params((gs_param_list *)&writer, &cfs, false));
1660
filter_name = pfn->CCITTFaxDecode;
1661
} else if (TEMPLATE_IS(s_DCTE_template))
1662
filter_name = pfn->DCTDecode;
1663
else if (TEMPLATE_IS(s_zlibE_template))
1664
filter_name = pfn->FlateDecode;
1665
else if (TEMPLATE_IS(s_LZWE_template))
1666
filter_name = pfn->LZWDecode;
1668
else if (TEMPLATE_IS(s_jbig2encode_template))
1669
filter_name = pfn->JBIG2Decode;
1672
else if (TEMPLATE_IS(s_jpxe_template))
1673
filter_name = pfn->JPXDecode;
1675
else if (TEMPLATE_IS(s_PNGPE_template)) {
1676
/* This is a predictor for FlateDecode or LZWEncode. */
1677
const stream_PNGP_state *const ss =
1678
(const stream_PNGP_state *)st;
1681
cos_dict_alloc(pdev, "pdf_put_image_filters(decode_parms)");
1682
if (decode_parms == 0)
1683
return_error(gs_error_VMerror);
1684
CHECK(cos_dict_put_c_key_int(decode_parms, "/Predictor",
1686
CHECK(cos_dict_put_c_key_int(decode_parms, "/Columns",
1688
if (ss->Colors != 1)
1689
CHECK(cos_dict_put_c_key_int(decode_parms, "/Colors",
1691
if (ss->BitsPerComponent != 8)
1692
CHECK(cos_dict_put_c_key_int(decode_parms,
1693
"/BitsPerComponent",
1694
ss->BitsPerComponent));
1695
} else if (TEMPLATE_IS(s_RLE_template))
1696
filter_name = pfn->RunLengthDecode;
1701
CHECK(cos_dict_put_c_strings(pcd, pfn->Filter, filter_name));
1703
CHECK(cos_dict_put_c_key_object(pcd, pfn->DecodeParms,
1704
COS_OBJECT(decode_parms)));
1707
cos_array_alloc(pdev, "pdf_put_image_filters(Filters)");
1710
return_error(gs_error_VMerror);
1711
CHECK(cos_array_add_c_string(pca, pfn->ASCII85Decode));
1712
CHECK(cos_array_add_c_string(pca, filter_name));
1713
CHECK(cos_dict_put_c_key_object(pcd, pfn->Filter,
1716
pca = cos_array_alloc(pdev,
1717
"pdf_put_image_filters(DecodeParms)");
1719
return_error(gs_error_VMerror);
1720
CHECK(cos_array_add_c_string(pca, "null"));
1721
CHECK(cos_array_add_object(pca, COS_OBJECT(decode_parms)));
1722
CHECK(cos_dict_put_c_key_object(pcd, pfn->DecodeParms,
1726
} else if (!binary_ok)
1727
CHECK(cos_dict_put_c_strings(pcd, pfn->Filter, pfn->ASCII85Decode));
1731
/* Add a Flate compression filter to a binary writer. */
1733
pdf_flate_binary(gx_device_pdf *pdev, psdf_binary_writer *pbw)
1735
const stream_template *template = (pdev->CompatibilityLevel < 1.3 ?
1736
&s_LZWE_template : &s_zlibE_template);
1737
stream_state *st = s_alloc_state(pdev->pdf_memory, template->stype,
1738
"pdf_write_function");
1741
return_error(gs_error_VMerror);
1742
if (template->set_defaults)
1743
template->set_defaults(st);
1744
return psdf_encode_binary(pbw, template, st);
1748
* Begin a data stream. The client has opened the object and written
1749
* the << and any desired dictionary keys.
1752
pdf_begin_data(gx_device_pdf *pdev, pdf_data_writer_t *pdw)
1754
return pdf_begin_data_stream(pdev, pdw,
1755
DATA_STREAM_BINARY | DATA_STREAM_COMPRESS, 0);
1759
pdf_append_data_stream_filters(gx_device_pdf *pdev, pdf_data_writer_t *pdw,
1760
int orig_options, gs_id object_id)
1762
stream *s = pdev->strm;
1763
int options = orig_options;
1764
#define USE_ASCII85 1
1766
static const char *const fnames[4] = {
1767
"", "/Filter/ASCII85Decode", "/Filter/FlateDecode",
1768
"/Filter[/ASCII85Decode/FlateDecode]"
1770
static const char *const fnames1_2[4] = {
1771
"", "/Filter/ASCII85Decode", "/Filter/LZWDecode",
1772
"/Filter[/ASCII85Decode/LZWDecode]"
1777
if (options & DATA_STREAM_COMPRESS) {
1778
filters |= USE_FLATE;
1779
options |= DATA_STREAM_BINARY;
1781
if ((options & DATA_STREAM_BINARY) && !pdev->binary_ok)
1782
filters |= USE_ASCII85;
1783
if (!(options & DATA_STREAM_NOLENGTH)) {
1784
stream_puts(s, (pdev->CompatibilityLevel < 1.3 ?
1785
fnames1_2[filters] : fnames[filters]));
1786
if (pdev->ResourcesBeforeUsage) {
1787
pdw->length_pos = stell(s) + 8;
1788
stream_puts(s, "/Length >>stream\n");
1789
pdw->length_id = -1;
1791
pdw->length_pos = -1;
1792
pdw->length_id = pdf_obj_ref(pdev);
1793
pprintld1(s, "/Length %ld 0 R>>stream\n", pdw->length_id);
1796
if (options & DATA_STREAM_ENCRYPT) {
1797
code = pdf_begin_encrypt(pdev, &s, object_id);
1801
pdw->encrypted = true;
1803
pdw->encrypted = false;
1804
if (options & DATA_STREAM_BINARY) {
1805
code = psdf_begin_binary((gx_device_psdf *)pdev, &pdw->binary);
1810
pdw->binary.target = pdev->strm;
1811
pdw->binary.dev = (gx_device_psdf *)pdev;
1812
pdw->binary.strm = pdev->strm;
1814
pdw->start = stell(s);
1815
if (filters & USE_FLATE)
1816
code = pdf_flate_binary(pdev, &pdw->binary);
1823
pdf_begin_data_stream(gx_device_pdf *pdev, pdf_data_writer_t *pdw,
1824
int options, gs_id object_id)
1826
/* object_id is an unused rudiment from the old code,
1827
when the encription was applied when creating the stream.
1828
The new code encrypts than copying stream from the temporary file. */
1829
pdw->pdev = pdev; /* temporary for backward compatibility of pdf_end_data prototype. */
1830
pdw->binary.target = pdev->strm;
1831
pdw->binary.dev = (gx_device_psdf *)pdev;
1832
pdw->binary.strm = 0; /* for GC in case of failure */
1833
code = pdf_open_aside(pdev, resourceOther, gs_no_id, &pdw->pres, !object_id,
1836
pdf_reserve_object_id(pdev, pdw->pres, object_id);
1837
pdw->binary.strm = pdev->strm;
1841
/* End a data stream. */
1843
pdf_end_data(pdf_data_writer_t *pdw)
1846
code = pdf_close_aside(pdw->pdev);
1849
code = COS_WRITE_OBJECT(pdw->pres->object, pdw->pdev);
1855
/* Create a Function object. */
1856
static int pdf_function_array(gx_device_pdf *pdev, cos_array_t *pca,
1857
const gs_function_info_t *pinfo);
1859
pdf_function_scaled(gx_device_pdf *pdev, const gs_function_t *pfn,
1860
const gs_range_t *pranges, cos_value_t *pvalue)
1862
if (pranges == NULL)
1863
return pdf_function(pdev, pfn, pvalue);
1866
* Create a temporary scaled function. Note that the ranges
1867
* represent the inverse scaling from what gs_function_make_scaled
1870
gs_memory_t *mem = pdev->pdf_memory;
1871
gs_function_t *psfn;
1872
gs_range_t *ranges = (gs_range_t *)
1873
gs_alloc_byte_array(mem, pfn->params.n, sizeof(gs_range_t),
1874
"pdf_function_scaled");
1878
return_error(gs_error_VMerror);
1879
for (i = 0; i < pfn->params.n; ++i) {
1880
double rbase = pranges[i].rmin;
1881
double rdiff = pranges[i].rmax - rbase;
1882
double invbase = -rbase / rdiff;
1884
ranges[i].rmin = invbase;
1885
ranges[i].rmax = invbase + 1.0 / rdiff;
1887
code = gs_function_make_scaled(pfn, &psfn, ranges, mem);
1889
code = pdf_function(pdev, psfn, pvalue);
1890
gs_function_free(psfn, true, mem);
1892
gs_free_object(mem, ranges, "pdf_function_scaled");
1897
pdf_function_aux(gx_device_pdf *pdev, const gs_function_t *pfn,
1898
pdf_resource_t **ppres)
1900
gs_function_info_t info;
1901
cos_param_list_writer_t rlist;
1902
pdf_resource_t *pres;
1905
int code = pdf_alloc_resource(pdev, resourceFunction, gs_no_id, &pres, -1);
1912
pcfn = pres->object;
1913
gs_function_get_info(pfn, &info);
1914
if (FunctionType(pfn) == function_type_ArrayedOutput) {
1916
* Arrayed Output Functions are used internally to represent
1917
* Shading Function entries that are arrays of Functions.
1918
* They require special handling.
1922
cos_become(pcfn, cos_type_array);
1923
pca = (cos_array_t *)pcfn;
1924
return pdf_function_array(pdev, pca, &info);
1926
if (info.DataSource != 0) {
1927
psdf_binary_writer writer;
1928
stream *save = pdev->strm;
1932
cos_become(pcfn, cos_type_stream);
1933
pcos = (cos_stream_t *)pcfn;
1934
pcd = cos_stream_dict(pcos);
1935
s = cos_write_stream_alloc(pcos, pdev, "pdf_function");
1937
return_error(gs_error_VMerror);
1939
code = psdf_begin_binary((gx_device_psdf *)pdev, &writer);
1940
if (code >= 0 && info.data_size > 30 /* 30 is arbitrary */
1942
code = pdf_flate_binary(pdev, &writer);
1944
static const pdf_filter_names_t fnames = {
1948
code = pdf_put_filters(pcd, pdev, writer.strm, &fnames);
1951
byte buf[100]; /* arbitrary */
1956
for (pos = 0; pos < info.data_size; pos += count) {
1957
count = min(sizeof(buf), info.data_size - pos);
1958
data_source_access_only(info.DataSource, pos, count, buf,
1960
stream_write(writer.strm, ptr, count);
1962
code = psdf_end_binary(&writer);
1969
cos_become(pcfn, cos_type_dict);
1970
pcd = (cos_dict_t *)pcfn;
1972
if (info.Functions != 0) {
1973
cos_array_t *functions =
1974
cos_array_alloc(pdev, "pdf_function(Functions)");
1978
return_error(gs_error_VMerror);
1979
if ((code = pdf_function_array(pdev, functions, &info)) < 0 ||
1980
(code = cos_dict_put_c_key(pcd, "/Functions",
1981
COS_OBJECT_VALUE(&v, functions))) < 0
1983
COS_FREE(functions, "pdf_function(Functions)");
1987
code = cos_param_list_writer_init(&rlist, pcd, PRINT_BINARY_OK);
1990
return gs_function_get_params(pfn, (gs_param_list *)&rlist);
1993
functions_equal(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1)
1998
pdf_function(gx_device_pdf *pdev, const gs_function_t *pfn, cos_value_t *pvalue)
2000
pdf_resource_t *pres;
2001
int code = pdf_function_aux(pdev, pfn, &pres);
2005
code = pdf_substitute_resource(pdev, &pres, resourceFunction, functions_equal, false);
2008
COS_OBJECT_VALUE(pvalue, pres->object);
2011
static int pdf_function_array(gx_device_pdf *pdev, cos_array_t *pca,
2012
const gs_function_info_t *pinfo)
2017
for (i = 0; i < pinfo->num_Functions; ++i) {
2018
if ((code = pdf_function(pdev, pinfo->Functions[i], &v)) < 0 ||
2019
(code = cos_array_add(pca, &v)) < 0
2028
/* Write a Function object. */
2030
pdf_write_function(gx_device_pdf *pdev, const gs_function_t *pfn, long *pid)
2033
int code = pdf_function(pdev, pfn, &value);
2037
*pid = value.contents.object->id;
2041
/* Write a FontBBox dictionary element. */
2043
pdf_write_font_bbox(gx_device_pdf *pdev, const gs_int_rect *pbox)
2045
stream *s = pdev->strm;
2047
* AR 4 doesn't like fonts with empty FontBBox, which
2048
* happens when the font contains only space characters.
2049
* Small bbox causes AR 4 to display a hairline. So we use
2052
int x = pbox->q.x + ((pbox->p.x == pbox->q.x) ? 1000 : 0);
2053
int y = pbox->q.y + ((pbox->p.y == pbox->q.y) ? 1000 : 0);
2055
pprintd4(s, "/FontBBox[%d %d %d %d]",
2056
pbox->p.x, pbox->p.y, x, y);
2060
/* Write a FontBBox dictionary element using floats for the values. */
2062
pdf_write_font_bbox_float(gx_device_pdf *pdev, const gs_rect *pbox)
2064
stream *s = pdev->strm;
2066
* AR 4 doesn't like fonts with empty FontBBox, which
2067
* happens when the font contains only space characters.
2068
* Small bbox causes AR 4 to display a hairline. So we use
2071
float x = pbox->q.x + ((pbox->p.x == pbox->q.x) ? 1000 : 0);
2072
float y = pbox->q.y + ((pbox->p.y == pbox->q.y) ? 1000 : 0);
2074
pprintg4(s, "/FontBBox[%g %g %g %g]",
2075
pbox->p.x, pbox->p.y, x, y);