summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfm-x/pdfobj.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipdfm-x/pdfobj.c')
-rw-r--r--Build/source/texk/dvipdfm-x/pdfobj.c1216
1 files changed, 722 insertions, 494 deletions
diff --git a/Build/source/texk/dvipdfm-x/pdfobj.c b/Build/source/texk/dvipdfm-x/pdfobj.c
index 7cae7295356..9be1744ba2d 100644
--- a/Build/source/texk/dvipdfm-x/pdfobj.c
+++ b/Build/source/texk/dvipdfm-x/pdfobj.c
@@ -1,6 +1,6 @@
/* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
- Copyright (C) 2007-2020 by Jin-Hwan Cho and Shunsaku Hirata,
+ Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
the dvipdfmx project team.
Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
@@ -35,6 +35,7 @@
#include "mfileio.h"
#include "dpxconf.h"
#include "dpxutil.h"
+
#include "pdflimits.h"
#include "pdfencrypt.h"
#include "pdfparse.h"
@@ -60,13 +61,12 @@
/* Any of these types can be represented as follows */
struct pdf_obj
{
- int type;
+ int type;
- unsigned int label; /* Only used for indirect objects
- all other "label" to zero */
- unsigned short generation; /* Only used if "label" is used */
- unsigned refcount; /* Number of links to this object */
- int flags;
+ uint32_t label; /* Only used for indirect objects all other "label" to zero */
+ uint16_t generation; /* Only used if "label" is used */
+ int refcount; /* Number of links to this object */
+ int32_t flags;
void *data;
#if defined(PDFOBJ_DEBUG)
@@ -81,7 +81,7 @@ static int cur_obj_id = 0;
struct pdf_boolean
{
- char value;
+ char value;
};
struct pdf_number
@@ -92,7 +92,7 @@ struct pdf_number
struct pdf_string
{
unsigned char *string;
- unsigned short length;
+ size_t length;
};
struct pdf_name
@@ -102,8 +102,8 @@ struct pdf_name
struct pdf_array
{
- unsigned int max;
- unsigned int size;
+ size_t max;
+ size_t size;
struct pdf_obj **values;
};
@@ -138,18 +138,18 @@ struct pdf_stream
struct pdf_obj *dict;
unsigned char *stream;
int *objstm_data; /* used for object streams */
- unsigned int stream_length;
- unsigned int max_length;
+ size_t stream_length;
+ size_t max_length;
int32_t _flags;
struct decode_parms decodeparms;
};
struct pdf_indirect
{
- pdf_file *pf;
- pdf_obj *obj; /* used when PF == NULL */
- unsigned label;
- unsigned short generation;
+ pdf_file *pf;
+ pdf_obj *obj; /* used when PF == NULL */
+ uint32_t label;
+ uint16_t generation;
};
typedef void pdf_null;
@@ -162,101 +162,182 @@ typedef struct pdf_dict pdf_dict;
typedef struct pdf_stream pdf_stream;
typedef struct pdf_indirect pdf_indirect;
-static FILE *pdf_output_file = NULL;
-
-static int pdf_output_file_position = 0;
-static int pdf_output_line_position = 0;
-static int compression_saved = 0;
-
-#define FORMAT_BUF_SIZE 4096
-static char format_buffer[FORMAT_BUF_SIZE];
-
typedef struct xref_entry
{
- unsigned char type; /* object storage type */
- unsigned int field2; /* offset in file or object stream */
- unsigned short field3; /* generation or index */
- pdf_obj *direct; /* used for imported objects */
- pdf_obj *indirect; /* used for imported objects */
+ uint8_t type; /* object storage type */
+ uint32_t field2; /* offset in file or object stream */
+ uint16_t field3; /* generation or index */
+ pdf_obj *direct; /* used for imported objects */
+ pdf_obj *indirect; /* used for imported objects */
} xref_entry;
-static xref_entry *output_xref;
-
-static unsigned int pdf_max_ind_objects;
-static unsigned int next_label;
-
-static unsigned int startxref;
-
struct pdf_file
{
- FILE *file;
- pdf_obj *trailer;
- xref_entry *xref_table;
- pdf_obj *catalog;
- int num_obj;
- int file_size;
- int version;
+ FILE *file;
+ pdf_obj *trailer;
+ xref_entry *xref_table;
+ pdf_obj *catalog;
+ int num_obj;
+ int file_size;
+ int version;
};
-static pdf_obj *output_stream;
+static int error_out = 0;
#define OBJSTM_MAX_OBJS 200
/* the limit is only 100 for linearized PDF */
-static int enc_mode;
-static int doc_enc_mode;
+struct pdf_out {
+ struct {
+ int enc_mode; /* boolean */
+ } state;
+
+ unsigned char id1[16];
+ unsigned char id2[16];
+
+ struct {
+ int major;
+ int minor;
+ } version;
+
+ struct {
+ struct {
+ int level;
+ int use_predictor;
+ } compression;
+
+ int enable_encrypt;
+ int use_objstm;
+ } options;
+
+ struct {
+ FILE *file;
+ size_t file_position;
+ int line_position;
+ size_t compression_saved;
+#if defined(LIBDPX)
+ size_t file_stats;
+#endif /* LIBDPX */
+ } output;
-static pdf_obj *trailer_dict;
-static pdf_obj *xref_stream;
+ struct {
+ uint32_t next_label;
+ uint32_t max_ind_objects;
+ } obj;
-/* Internal static routines */
+ pdf_sec *sec_data;
-static int check_for_pdf_version (FILE *file);
+ pdf_obj *trailer;
+ uint32_t startxref;
+ xref_entry * xref_table;
-static void pdf_flush_obj (pdf_obj *object, FILE *file);
-static void pdf_label_obj (pdf_obj *object);
-static void pdf_write_obj (pdf_obj *object, FILE *file);
+ pdf_obj *xref_stream;
+ pdf_obj *output_stream;
+ pdf_obj *current_objstm;
+};
-static void set_objstm_data (pdf_obj *objstm, int *data);
-static int *get_objstm_data (pdf_obj *objstm);
-static void release_objstm (pdf_obj *objstm);
+/* Underway to reform PDF related code... For a moment place pdf_out
+ * object as a static variable. */
+static pdf_out pout;
-static void pdf_out_char (FILE *file, char c);
-static void pdf_out (FILE *file, const void *buffer, int length);
+static pdf_out *
+current_output (void)
+{
+ return &pout;
+}
-static pdf_obj *pdf_new_ref (pdf_obj *object);
-static void release_indirect (pdf_indirect *data);
-static void write_indirect (pdf_indirect *indirect, FILE *file);
+static void
+init_pdf_out_struct (pdf_out *p)
+{
+ ASSERT(p);
-static void release_boolean (pdf_obj *data);
-static void write_boolean (pdf_boolean *data, FILE *file);
+ p->state.enc_mode = 0;
-static void write_null (FILE *file);
+ memset(p->id1, 0, 16);
+ memset(p->id2, 0, 16);
-static void release_number (pdf_number *number);
-static void write_number (pdf_number *number, FILE *file);
+ p->version.major = 1;
+ p->version.minor = PDF_VERSION_DEFAULT;
-static void write_string (pdf_string *str, FILE *file);
-static void release_string (pdf_string *str);
+ p->options.compression.level = 9;
+ p->options.compression.use_predictor = 1;
+ p->options.enable_encrypt = 0;
+ p->options.use_objstm = 1;
-static void write_name (pdf_name *name, FILE *file);
-static void release_name (pdf_name *name);
+ p->output.file = NULL;
+ p->output.file_position = 0;
+ p->output.line_position = 0;
+ p->output.compression_saved = 0;
+#if defined(LIBDPX)
+ p->output.file_stats = 0;
+#endif /* LIBDPX */
-static void write_array (pdf_array *array, FILE *file);
-static void release_array (pdf_array *array);
+ p->obj.next_label = 1;
+ p->obj.max_ind_objects = 0;
-static void write_dict (pdf_dict *dict, FILE *file);
-static void release_dict (pdf_dict *dict);
+ p->sec_data = NULL;
+ p->trailer = NULL;
+ p->startxref = 0;
+ p->xref_table = NULL;
-static void write_stream (pdf_stream *stream, FILE *file);
-static void release_stream (pdf_stream *stream);
+ p->xref_stream = NULL;
+ p->output_stream = NULL;
+ p->current_objstm = NULL;
+}
-static char compression_level = 9;
-static char compression_use_predictor = 1;
+static void
+clean_pdf_out_struct (pdf_out *p)
+{
+ memset(p, 0, sizeof(pdf_out));
+}
-void
-pdf_set_compression (int level)
+/* Internal static routines */
+
+static int check_for_pdf_version (FILE *file);
+
+static void pdf_flush_obj (pdf_out *p, pdf_obj *object);
+static void pdf_label_obj (pdf_out *p, pdf_obj *object);
+static void pdf_write_obj (pdf_out *p, pdf_obj *object);
+
+static void set_objstm_data (pdf_obj *objstm, int *data);
+static int *get_objstm_data (pdf_obj *objstm);
+static void release_objstm (pdf_obj *objstm);
+
+static void pdf_out_char (pdf_out *p, char c);
+static void pdf_out_str (pdf_out *p, const void *buffer, size_t length);
+
+static pdf_obj *pdf_new_ref (pdf_out *p, pdf_obj *object);
+static void release_indirect (pdf_indirect *data);
+static void write_indirect (pdf_out *p, pdf_indirect *indirect);
+
+static void release_boolean (pdf_obj *data);
+static void write_boolean (pdf_out *p, pdf_boolean *data);
+
+static void write_null (pdf_out *p);
+
+static void release_number (pdf_number *number);
+static void write_number (pdf_out *p, pdf_number *number);
+
+static void write_string (pdf_out *p, pdf_string *str);
+static void release_string (pdf_string *str);
+
+static void write_name (pdf_out *p, pdf_name *name);
+static void release_name (pdf_name *name);
+
+static void write_array (pdf_out *p, pdf_array *array);
+static void release_array (pdf_array *array);
+
+static void write_dict (pdf_out *p, pdf_dict *dict);
+static void release_dict (pdf_dict *dict);
+
+static void write_stream (pdf_out *p, pdf_stream *stream);
+static void release_stream (pdf_stream *stream);
+
+static void
+pdf_out_set_compression (pdf_out *p, int level)
{
+ ASSERT(p);
+
#ifndef HAVE_ZLIB
ERROR("You don't have compression compiled in. Possibly libz wasn't found by configure.");
#else
@@ -265,7 +346,7 @@ pdf_set_compression (int level)
WARN("Unable to set compression level -- your zlib doesn't have compress2().");
#endif
if (level >= 0 && level <= 9)
- compression_level = level;
+ p->options.compression.level = level;
else {
ERROR("set_compression: invalid compression level: %d", level);
}
@@ -277,156 +358,233 @@ pdf_set_compression (int level)
FILE *
pdf_get_output_file (void)
{
- return pdf_output_file;
+ pdf_out *p = current_output();
+ return p->output.file;
}
-static int pdf_version = PDF_VERSION_DEFAULT;
-
-void
-pdf_set_version (int version)
+static void
+pdf_out_set_version (pdf_out *p, int ver_major, int ver_minor)
{
+ int version;
+
+ ASSERT(p);
+
+ version = ver_major * 10 + ver_minor;
/* Don't forget to update CIDFont_stdcc_def[] in cid.c too! */
if (version >= PDF_VERSION_MIN && version <= PDF_VERSION_MAX) {
- pdf_version = version;
+ p->version.major = ver_major;
+ p->version.minor = ver_minor;
+ } else {
+ WARN("Unsupported PDF version %d.%d ... Ignoring.", ver_major, ver_minor);
}
}
int
pdf_get_version (void)
{
- return pdf_version;
+ pdf_out *p = current_output();
+ return (p->version.major * 10 + p->version.minor);
}
int
pdf_get_version_major (void)
{
- return pdf_version/10;
+ pdf_out *p = current_output();
+ return p->version.major;
}
int
pdf_get_version_minor (void)
{
- return pdf_version%10;
+ pdf_out *p = current_output();
+ return p->version.minor;
}
int
pdf_check_version (int major, int minor)
{
- return (pdf_version >= major*10+minor) ? 0 : -1;
-}
+ pdf_out *p = current_output();
+ if (p->version.major > major)
+ return 0;
+ else if (p->version.major < major)
+ return -1;
+ else {
+ return (p->version.minor >= minor) ? 0 : -1;
+ }
-static pdf_obj *current_objstm = NULL;
-static int do_objstm;
+ return -1;
+}
static void
-add_xref_entry (unsigned label, unsigned char type, unsigned int field2, unsigned short field3)
+add_xref_entry (pdf_out *p,
+ uint32_t label, uint8_t type, uint32_t field2, uint16_t field3)
{
- if (label >= pdf_max_ind_objects) {
- pdf_max_ind_objects = (label/IND_OBJECTS_ALLOC_SIZE+1)*IND_OBJECTS_ALLOC_SIZE;
- output_xref = RENEW(output_xref, pdf_max_ind_objects, xref_entry);
+ ASSERT(p);
+
+ if (label >= p->obj.max_ind_objects) {
+ p->obj.max_ind_objects = (label/IND_OBJECTS_ALLOC_SIZE+1)*IND_OBJECTS_ALLOC_SIZE;
+ p->xref_table = RENEW(p->xref_table, p->obj.max_ind_objects, xref_entry);
}
- output_xref[label].type = type;
- output_xref[label].field2 = field2;
- output_xref[label].field3 = field3;
- output_xref[label].direct = NULL;
- output_xref[label].indirect = NULL;
+ p->xref_table[label].type = type;
+ p->xref_table[label].field2 = field2;
+ p->xref_table[label].field3 = field3;
+ p->xref_table[label].direct = NULL;
+ p->xref_table[label].indirect = NULL;
}
#define BINARY_MARKER "%\344\360\355\370\n"
-void
+pdf_out *
pdf_out_init (const char *filename,
- int do_encryption, int enable_objstm, int enable_predictor)
+ const unsigned char *id1,
+ const unsigned char *id2,
+ int ver_major, int ver_minor, int compression_level,
+ int enable_encrypt,
+ int enable_objstm,
+ int enable_predictor)
{
- char v;
+ pdf_out *p = current_output();
+ char v;
+
+ init_pdf_out_struct(p);
+
+ pdf_out_set_version(p, ver_major, ver_minor);
+ pdf_out_set_compression(p, compression_level);
- output_xref = NULL;
- pdf_max_ind_objects = 0;
- add_xref_entry(0, 0, 0, 0xffff);
- next_label = 1;
+ add_xref_entry(p, 0, 0, 0, 0xffff);
- if (pdf_version >= 15) {
+ /* This must be set before pdf_set_root() is called */
+ p->options.enable_encrypt = enable_encrypt;
+ if (pdf_check_version(1, 5) == 0) {
if (enable_objstm) {
- xref_stream = pdf_new_stream(STREAM_COMPRESS);
- xref_stream->flags |= OBJ_NO_ENCRYPT;
- trailer_dict = pdf_stream_dict(xref_stream);
- pdf_add_dict(trailer_dict, pdf_new_name("Type"), pdf_new_name("XRef"));
- do_objstm = 1;
+ p->xref_stream = pdf_new_stream(STREAM_COMPRESS);
+ p->xref_stream->flags |= OBJ_NO_ENCRYPT;
+ p->trailer = pdf_stream_dict(p->xref_stream);
+ pdf_add_dict(p->trailer, pdf_new_name("Type"), pdf_new_name("XRef"));
+ p->options.use_objstm = 1;
} else {
- trailer_dict = pdf_new_dict();
- do_objstm = 0;
+ p->xref_stream = NULL;
+ p->trailer = pdf_new_dict();
+ p->options.use_objstm = 0;
}
} else {
- xref_stream = NULL;
- trailer_dict = pdf_new_dict();
- do_objstm = 0;
+ p->xref_stream = NULL;
+ p->trailer = pdf_new_dict();
+ p->options.use_objstm = 0;
}
- output_stream = NULL;
+ p->output_stream = NULL;
if (filename == NULL) { /* no filename: writing to stdout */
#ifdef WIN32
setmode(fileno(stdout), _O_BINARY);
#endif
- pdf_output_file = stdout;
+ p->output.file = stdout;
} else {
- pdf_output_file = MFOPEN(filename, FOPEN_WBIN_MODE);
- if (!pdf_output_file) {
+ p->output.file = MFOPEN(filename, FOPEN_WBIN_MODE);
+ if (!p->output.file) {
if (strlen(filename) < 128)
ERROR("Unable to open \"%s\".", filename);
else
ERROR("Unable to open file.");
}
}
- pdf_out(pdf_output_file, "%PDF-", strlen("%PDF-"));
- v = '0' + (pdf_version / 10);
- pdf_out(pdf_output_file, &v, 1);
- pdf_out(pdf_output_file, ".", 1);
- v = '0' + (pdf_version % 10);
- pdf_out(pdf_output_file, &v, 1);
- pdf_out(pdf_output_file, "\n", 1);
- pdf_out(pdf_output_file, BINARY_MARKER, strlen(BINARY_MARKER));
+ pdf_out_str(p, "%PDF-", strlen("%PDF-"));
+ v = '0' + p->version.major;
+ pdf_out_str(p, &v, 1);
+ pdf_out_str(p, ".", 1);
+ v = '0' + p->version.minor;
+ pdf_out_str(p, &v, 1);
+ pdf_out_str(p, "\n", 1);
+ pdf_out_str(p, BINARY_MARKER, strlen(BINARY_MARKER));
+
+ /* Set trailer ID and setup security handler */
+ {
+ pdf_obj *id_array;
+
+ memcpy(p->id1, id1, 16);
+ memcpy(p->id2, id2, 16);
+ id_array = pdf_new_array();
+ pdf_add_array(id_array, pdf_new_string(p->id1, 16));
+ pdf_add_array(id_array, pdf_new_string(p->id2, 16));
+ pdf_add_dict(p->trailer, pdf_new_name("ID"), id_array);
+ }
+ p->state.enc_mode = 0;
+ p->options.compression.use_predictor = enable_predictor;
- enc_mode = 0;
- doc_enc_mode = do_encryption;
- compression_use_predictor = enable_predictor;
+ return p;
+}
+
+void
+pdf_out_set_encrypt (int keybits, int32_t permission,
+ const char *opasswd, const char *upasswd,
+ int use_aes, int encrypt_metadata)
+{
+ pdf_out *p = current_output();
+
+ pdf_obj *encrypt, *extension, *catalog;
+
+ p->sec_data = pdf_enc_init(p->id1, keybits, permission,
+ opasswd, upasswd, use_aes, encrypt_metadata);
+ if (!p->sec_data) {
+ p->options.enable_encrypt = 0;
+ return;
+ }
+
+ encrypt = pdf_enc_get_encrypt_dict(p->sec_data);
+ pdf_add_dict(p->trailer,
+ pdf_new_name("Encrypt"), pdf_ref_obj(encrypt));
+ encrypt->flags |= OBJ_NO_ENCRYPT;
+ encrypt->flags |= OBJ_NO_OBJSTM;
+ pdf_release_obj(encrypt);
+
+ extension = pdf_enc_get_extension_dict(p->sec_data);
+ if (extension) {
+ catalog = pdf_doc_catalog();
+ pdf_add_dict(catalog, pdf_new_name("Extensions"), extension);
+ }
}
static void
-dump_xref_table (void)
+dump_xref_table (pdf_out *p)
{
- int length;
- unsigned int i;
+ int i, length;
+ char buf[32];
- pdf_out(pdf_output_file, "xref\n", 5);
+ ASSERT(p);
- length = sprintf(format_buffer, "%d %u\n", 0, next_label);
- pdf_out(pdf_output_file, format_buffer, length);
+ pdf_out_str(p, "xref\n", 5);
+
+ length = sprintf(buf, "%d %u\n", 0, p->obj.next_label);
+ pdf_out_str(p, buf, length);
/*
* Every space counts. The space after the 'f' and 'n' is * *essential*.
* The PDF spec says the lines must be 20 characters long including the
* end of line character.
*/
- for (i = 0; i < next_label; i++) {
- unsigned char type = output_xref[i].type;
+ for (i = 0; i < p->obj.next_label; i++) {
+ uint8_t type = p->xref_table[i].type;
if (type > 1)
ERROR("object type %hu not allowed in xref table", type);
- length = sprintf(format_buffer, "%010u %05hu %c \n",
- output_xref[i].field2, output_xref[i].field3,
- type ? 'n' : 'f');
- pdf_out(pdf_output_file, format_buffer, length);
+ length = sprintf(buf, "%010u %05hu %c \n",
+ p->xref_table[i].field2, p->xref_table[i].field3,
+ type ? 'n' : 'f');
+ pdf_out_str(p, buf, length);
}
}
static void
-dump_trailer_dict (void)
+dump_trailer (pdf_out *p)
{
- pdf_out(pdf_output_file, "trailer\n", 8);
- enc_mode = 0;
- write_dict(trailer_dict->data, pdf_output_file);
- pdf_release_obj(trailer_dict);
- pdf_out_char(pdf_output_file, '\n');
+ ASSERT(p);
+
+ pdf_out_str(p, "trailer\n", 8);
+ p->state.enc_mode = 0;
+ write_dict(p, p->trailer->data);
+ pdf_release_obj(p->trailer);
+ p->trailer = NULL;
+ pdf_out_char(p, '\n');
}
/*
@@ -434,16 +592,17 @@ dump_trailer_dict (void)
* contributed by Matthias Franz (March 21, 2007)
*/
static void
-dump_xref_stream (void)
+dump_xref_stream (pdf_out *p)
{
- unsigned int pos, i;
- unsigned poslen;
+ uint32_t pos, i;
+ uint32_t poslen;
unsigned char buf[7] = {0, 0, 0, 0, 0};
+ pdf_obj *w;
- pdf_obj *w;
+ ASSERT(p);
/* determine the necessary size of the offset field */
- pos = startxref; /* maximal offset value */
+ pos = p->startxref; /* maximal offset value */
poslen = 1;
while (pos >>= 8)
poslen++;
@@ -452,48 +611,52 @@ dump_xref_stream (void)
pdf_add_array(w, pdf_new_number(1)); /* type */
pdf_add_array(w, pdf_new_number(poslen)); /* offset (big-endian) */
pdf_add_array(w, pdf_new_number(2)); /* generation */
- pdf_add_dict(trailer_dict, pdf_new_name("W"), w);
+ pdf_add_dict(p->trailer, pdf_new_name("W"), w);
/* We need the xref entry for the xref stream right now */
- add_xref_entry(next_label-1, 1, startxref, 0);
+ add_xref_entry(p, p->obj.next_label - 1, 1, p->startxref, 0);
- for (i = 0; i < next_label; i++) {
- unsigned j;
- unsigned short f3;
- buf[0] = output_xref[i].type;
- pos = output_xref[i].field2;
+ for (i = 0; i < p->obj.next_label; i++) {
+ size_t j;
+ uint16_t f3;
+ buf[0] = p->xref_table[i].type;
+ pos = p->xref_table[i].field2;
for (j = poslen; j--; ) {
buf[1+j] = (unsigned char) pos;
pos >>= 8;
}
- f3 = output_xref[i].field3;
+ f3 = p->xref_table[i].field3;
buf[poslen+1] = (unsigned char) (f3 >> 8);
buf[poslen+2] = (unsigned char) (f3);
- pdf_add_stream(xref_stream, &buf, poslen+3);
+ pdf_add_stream(p->xref_stream, &buf, poslen+3);
}
- pdf_release_obj(xref_stream);
+ pdf_release_obj(p->xref_stream);
+ p->xref_stream = NULL;
}
#if defined(LIBDPX)
-static long pdf_output_file_stats = 0;
long
pdf_output_stats (void)
{
- return pdf_output_file_stats;
+ pdf_out *p = current_output();
+ return p->output.file_stats;
}
#endif /* LIBDPX */
void
pdf_out_flush (void)
{
- if (pdf_output_file) {
- int length;
+ pdf_out *p = current_output();
+ char buf[16];
+
+ if (p->output.file) {
+ int length;
/* Flush current object stream */
- if (current_objstm) {
- release_objstm(current_objstm);
- current_objstm =NULL;
+ if (p->current_objstm) {
+ release_objstm(p->current_objstm);
+ p->current_objstm =NULL;
}
/*
@@ -501,53 +664,56 @@ pdf_out_flush (void)
* for the xref stream dictionary (= trailer).
* Labelling it in pdf_out_init (with 1) does not work (why?).
*/
- if (xref_stream)
- pdf_label_obj(xref_stream);
+ if (p->xref_stream)
+ pdf_label_obj(p, p->xref_stream);
/* Record where this xref is for trailer */
- startxref = pdf_output_file_position;
+ p->startxref = p->output.file_position;
- pdf_add_dict(trailer_dict, pdf_new_name("Size"),
- pdf_new_number(next_label));
+ pdf_add_dict(p->trailer,
+ pdf_new_name("Size"), pdf_new_number(p->obj.next_label));
- if (xref_stream)
- dump_xref_stream();
+ if (p->xref_stream)
+ dump_xref_stream(p);
else {
- dump_xref_table();
- dump_trailer_dict();
+ dump_xref_table(p);
+ dump_trailer(p);
}
/* Done with xref table */
- RELEASE(output_xref);
+ RELEASE(p->xref_table);
+ p->xref_table = NULL;
- pdf_out(pdf_output_file, "startxref\n", 10);
- length = sprintf(format_buffer, "%u\n", startxref);
- pdf_out(pdf_output_file, format_buffer, length);
- pdf_out(pdf_output_file, "%%EOF\n", 6);
+ pdf_out_str(p, "startxref\n", 10);
+ length = sprintf(buf, "%u\n", p->startxref);
+ pdf_out_str(p, buf, length);
+ pdf_out_str(p, "%%EOF\n", 6);
#if !defined(LIBDPX)
MESG("\n");
#endif /* !LIBDPX */
if (dpx_conf.verbose_level > 0) {
- if (compression_level > 0) {
- MESG("Compression saved %ld bytes%s\n", compression_saved,
- pdf_version < 15 ? ". Try \"-V 1.5\" for better compression" : "");
+ if (p->options.compression.level > 0) {
+ MESG("Compression saved %ld bytes%s\n", p->output.compression_saved);
}
}
#if !defined(LIBDPX)
- MESG("%ld bytes written", pdf_output_file_position);
+ MESG("%ld bytes written", p->output.file_position);
#else
- pdf_output_file_stats = pdf_output_file_position;
+ p->output.file_stats = p->output.file_position;
#endif /* !LIBDPX */
- MFCLOSE(pdf_output_file);
- pdf_output_file_position = 0;
- pdf_output_line_position = 0;
- pdf_output_file = NULL;
+ MFCLOSE(p->output.file);
+ p->output.file = NULL;
+ p->output.file_position = 0;
+ p->output.line_position = 0;
}
+ if (p->sec_data)
+ pdf_enc_close(&p->sec_data);
#if defined(PDFOBJ_DEBUG)
{
int i;
+ error_out = 1;
MESG("\ndebug>> %d PDF objects created.", cur_obj_id);
for (i = 0; i < cur_obj_id; i++) {
pdf_obj *obj = bucket[i];
@@ -555,110 +721,113 @@ pdf_out_flush (void)
if (obj->label > 0) {
WARN("Object obj_id=<%lu, %u> unreleased...", obj->label, obj->generation);
WARN("Reference count=%d", obj->refcount);
+ pdf_write_obj(p, obj);
+ MESG("\n");
} else {
- WARN("Unreleased object found: %d", i);
- pdf_write_obj(obj, stderr);
+ WARN("Unreleased object found: (unlabeled) id=%d", i);
+ pdf_write_obj(p, obj);
MESG("\n");
}
}
}
}
#endif
+ clean_pdf_out_struct(p);
}
void
pdf_error_cleanup (void)
{
+ pdf_out *p = current_output();
/*
* This routine is the cleanup required for an abnormal exit.
* For now, simply close the file.
*/
- if (pdf_output_file)
- MFCLOSE(pdf_output_file);
- pdf_output_file = NULL;
+ if (p->output.file)
+ MFCLOSE(p->output.file);
+ p->output.file = NULL;
}
void
pdf_set_root (pdf_obj *object)
{
- if (pdf_add_dict(trailer_dict, pdf_new_name("Root"), pdf_ref_obj(object))) {
+ pdf_out *p = current_output();
+
+ if (pdf_lookup_dict(p->trailer, "Root"))
ERROR("Root object already set!");
- }
+ pdf_add_dict(p->trailer, pdf_new_name("Root"), pdf_ref_obj(object));
/* Adobe Readers don't like a document catalog inside an encrypted
* object stream, although the PDF v1.5 spec seems to allow this.
* Note that we don't set OBJ_NO_ENCRYPT since the name dictionary in
* a document catalog may contain strings, which should be encrypted.
*/
- if (doc_enc_mode)
+ if (p->options.enable_encrypt)
object->flags |= OBJ_NO_OBJSTM;
}
void
pdf_set_info (pdf_obj *object)
{
- if (pdf_add_dict(trailer_dict, pdf_new_name("Info"), pdf_ref_obj(object))) {
+ pdf_out *p = current_output();
+
+ if (pdf_lookup_dict(p->trailer, "Info"))
ERROR ("Info object already set!");
- }
+ pdf_add_dict(p->trailer, pdf_new_name("Info"), pdf_ref_obj(object));
}
-void
-pdf_set_id (pdf_obj *id)
-{
- if (pdf_add_dict(trailer_dict, pdf_new_name("ID"), id)) {
- ERROR ("ID already set!");
- }
-}
-void
-pdf_set_encrypt (pdf_obj *encrypt)
-{
- if (pdf_add_dict(trailer_dict, pdf_new_name("Encrypt"), pdf_ref_obj(encrypt))) {
- ERROR("Encrypt object already set!");
- }
- encrypt->flags |= OBJ_NO_ENCRYPT;
-}
-static
-void pdf_out_char (FILE *file, char c)
+static void
+pdf_out_char (pdf_out *p, char c)
{
- if (output_stream && file == pdf_output_file)
- pdf_add_stream(output_stream, &c, 1);
- else {
- fputc(c, file);
- /* Keep tallys for xref table *only* if writing a pdf file. */
- if (file == pdf_output_file) {
- pdf_output_file_position += 1;
+ ASSERT(p);
+
+ if (error_out) {
+ fputc(c, stderr);
+ } else {
+ if (p->output_stream)
+ pdf_add_stream(p->output_stream, &c, 1);
+ else {
+ fputc(c, p->output.file);
+ p->output.file_position += 1;
if (c == '\n')
- pdf_output_line_position = 0;
+ p->output.line_position = 0;
else
- pdf_output_line_position += 1;
+ p->output.line_position += 1;
}
}
}
static char xchar[] = "0123456789abcdef";
-#define pdf_out_xchar(f,c) do {\
- pdf_out_char((f), xchar[((c) >> 4) & 0x0f]);\
- pdf_out_char((f), xchar[(c) & 0x0f]);\
-} while (0)
+static void
+pdf_out_xchar (pdf_out *p, char c)
+{
+ ASSERT(p);
-static
-void pdf_out (FILE *file, const void *buffer, int length)
+ pdf_out_char(p, xchar[(c >> 4) & 0x0f]);
+ pdf_out_char(p, xchar[c & 0x0f]);
+}
+
+static void
+pdf_out_str (pdf_out *p, const void *buffer, size_t length)
{
- if (output_stream && file == pdf_output_file)
- pdf_add_stream(output_stream, buffer, length);
+ ASSERT(p);
+
+ if (error_out)
+ fwrite(buffer, 1, length, stderr);
else {
- fwrite(buffer, 1, length, file);
- /* Keep tallys for xref table *only* if writing a pdf file */
- if (file == pdf_output_file) {
- pdf_output_file_position += length;
- pdf_output_line_position += length;
+ if (p->output_stream)
+ pdf_add_stream(p->output_stream, buffer, length);
+ else {
+ fwrite(buffer, 1, length, p->output.file);
+ p->output.file_position += length;
+ p->output.line_position += length;
/* "foo\nbar\n "... */
if (length > 0 &&
- ((const char *)buffer)[length-1] == '\n')
- pdf_output_line_position = 0;
+ ((const char *)buffer)[length-1] == '\n')
+ p->output.line_position = 0;
}
}
}
@@ -674,12 +843,14 @@ int pdf_need_white (int type1, int type2)
}
static
-void pdf_out_white (FILE *file)
+void pdf_out_white (pdf_out *p)
{
- if (file == pdf_output_file && pdf_output_line_position >= 80) {
- pdf_out_char(file, '\n');
+ ASSERT(p);
+
+ if (p->output.line_position >= 80) {
+ pdf_out_char(p, '\n');
} else {
- pdf_out_char(file, ' ');
+ pdf_out_char(p, ' ');
}
}
@@ -724,8 +895,10 @@ pdf_obj_typeof (pdf_obj *object)
}
static void
-pdf_label_obj (pdf_obj *object)
+pdf_label_obj (pdf_out *p, pdf_obj *object)
{
+ ASSERT(p);
+
if (INVALIDOBJ(object))
ERROR("pdf_label_obj(): passed invalid object.");
@@ -733,7 +906,7 @@ pdf_label_obj (pdf_obj *object)
* Don't change label on an already labeled object. Ignore such calls.
*/
if (object->label == 0) {
- object->label = next_label++;
+ object->label = p->obj.next_label++;
object->generation = 0;
}
}
@@ -772,19 +945,23 @@ pdf_link_obj (pdf_obj *object)
pdf_obj *
pdf_ref_obj (pdf_obj *object)
{
+ pdf_out *p = current_output();
+
if (INVALIDOBJ(object))
ERROR("pdf_ref_obj(): passed invalid object.");
if (object->refcount == 0) {
MESG("\nTrying to refer already released object!!!\n");
- pdf_write_obj(object, stderr);
+ error_out = 1;
+ pdf_write_obj(p, object);
ERROR("Cannot continue...");
+ error_out = 0;
}
if (PDF_OBJ_INDIRECTTYPE(object)) {
return pdf_link_obj(object);
} else {
- return pdf_new_ref(object);
+ return pdf_new_ref(p, object);
}
}
@@ -795,14 +972,17 @@ release_indirect (pdf_indirect *data)
}
static void
-write_indirect (pdf_indirect *indirect, FILE *file)
+write_indirect (pdf_out *p, pdf_indirect *indirect)
{
- int length;
+ int length;
+ char buf[64];
+ ASSERT(p);
ASSERT(!indirect->pf);
- length = sprintf(format_buffer, "%u %hu R", indirect->label, indirect->generation);
- pdf_out(file, format_buffer, length);
+ length = sprintf(buf, "%u %hu R",
+ indirect->label, indirect->generation);
+ pdf_out_str(p, buf, length);
}
/* The undefined object is used as a placeholder in pdfnames.c
@@ -831,9 +1011,9 @@ pdf_new_null (void)
}
static void
-write_null (FILE *file)
+write_null (pdf_out *p)
{
- pdf_out(file, "null", 4);
+ pdf_out_str(p, "null", 4);
}
pdf_obj *
@@ -857,12 +1037,12 @@ release_boolean (pdf_obj *data)
}
static void
-write_boolean (pdf_boolean *data, FILE *file)
+write_boolean (pdf_out *p, pdf_boolean *data)
{
if (data->value) {
- pdf_out(file, "true", 4);
+ pdf_out_str(p, "true", 4);
} else {
- pdf_out(file, "false", 5);
+ pdf_out_str(p, "false", 5);
}
}
@@ -899,13 +1079,14 @@ release_number (pdf_number *data)
}
static void
-write_number (pdf_number *number, FILE *file)
+write_number (pdf_out *p, pdf_number *number)
{
- int count;
+ int count;
+ char buf[512];
- count = pdf_sprint_number(format_buffer, number->value);
+ count = pdf_sprint_number(buf, number->value);
- pdf_out(file, format_buffer, count);
+ pdf_out_str(p, buf, count);
}
@@ -938,20 +1119,20 @@ pdf_new_string (const void *str, unsigned length)
pdf_obj *result;
pdf_string *data;
+ ASSERT(str);
+
result = pdf_new_obj(PDF_STRING);
data = NEW(1, pdf_string);
result->data = data;
data->length = length;
- if (str && length > 0) {
+ if (length) {
data->string = NEW(length+1, unsigned char);
memcpy(data->string, str, length);
/* Shouldn't assume NULL terminated. */
data->string[length] = '\0';
- } else {
+ } else
data->string = NULL;
- data->length = 0;
- }
return result;
}
@@ -977,7 +1158,7 @@ pdf_string_length (pdf_obj *object)
data = object->data;
- return (unsigned) (data->length);
+ return (unsigned) data->length;
}
/*
@@ -987,8 +1168,8 @@ pdf_string_length (pdf_obj *object)
int
pdfobj_escape_str (char *buffer, int bufsize, const unsigned char *s, int len)
{
- int result = 0;
- int i;
+ size_t result = 0;
+ size_t i;
for (i = 0; i < len; i++) {
unsigned char ch;
@@ -1031,21 +1212,22 @@ pdfobj_escape_str (char *buffer, int bufsize, const unsigned char *s, int len)
}
}
- return result;
+ return (int) result;
}
static void
-write_string (pdf_string *str, FILE *file)
+write_string (pdf_out *p, pdf_string *str)
{
- unsigned char *s = NULL;
- char wbuf[FORMAT_BUF_SIZE]; /* Shouldn't use format_buffer[]. */
- int nescc = 0, i, count;
- size_t len = 0;
+ unsigned char *s = NULL;
+ size_t i, nescc = 0;
+ size_t len = 0;
- if (enc_mode) {
- pdf_encrypt_data(str->string, str->length, &s, &len);
+ ASSERT(p);
+
+ if (p->state.enc_mode) {
+ pdf_encrypt_data(p->sec_data, str->string, str->length, &s, &len);
} else {
- s = str->string;
+ s = str->string;
len = str->length;
}
@@ -1061,13 +1243,22 @@ write_string (pdf_string *str, FILE *file)
* ASCII hex string.
*/
if (nescc > len / 3) {
- pdf_out_char(file, '<');
+ pdf_out_char(p, '<');
for (i = 0; i < len; i++) {
- pdf_out_xchar(file, s[i]);
+ pdf_out_xchar(p, s[i]);
}
- pdf_out_char(file, '>');
+ pdf_out_char(p, '>');
} else {
- pdf_out_char(file, '(');
+ char *buf;
+ size_t size, count;
+
+ /* At most len/3 is to be escaped here. (see above)
+ * Thus 4*len/3 + 2*len/3 + 2 is enough for buffer size.
+ */
+ size = len * 2 + 3;
+ buf = NEW(size, char);
+
+ pdf_out_char(p, '(');
/*
* This section of code probably isn't speed critical. Escaping the
* characters in the string one at a time may seem slow, but it's
@@ -1077,12 +1268,14 @@ write_string (pdf_string *str, FILE *file)
* handled as quickly as possible since there are so many of them.
*/
for (i = 0; i < len; i++) {
- count = pdfobj_escape_str(wbuf, FORMAT_BUF_SIZE, &(s[i]), 1);
- pdf_out(file, wbuf, count);
+ count = pdfobj_escape_str(buf, size, &(s[i]), 1);
+ pdf_out_str(p, buf, count);
}
- pdf_out_char(file, ')');
+ pdf_out_char(p, ')');
+ RELEASE(buf);
}
- if (enc_mode && s)
+
+ if (p->state.enc_mode && s)
RELEASE(s);
}
@@ -1123,7 +1316,7 @@ pdf_obj *
pdf_new_name (const char *name)
{
pdf_obj *result;
- unsigned length;
+ size_t length;
pdf_name *data;
result = pdf_new_obj(PDF_NAME);
@@ -1142,10 +1335,12 @@ pdf_new_name (const char *name)
}
static void
-write_name (pdf_name *name, FILE *file)
+write_name (pdf_out *p, pdf_name *name)
{
- char *s;
- int i, length;
+ char *s;
+ size_t i, length;
+
+ ASSERT(p);
s = name->name;
length = name->name ? strlen(name->name) : 0;
@@ -1169,14 +1364,14 @@ write_name (pdf_name *name, FILE *file)
(c) == '{' || (c) == '}' || \
(c) == '%')
#endif
- pdf_out_char(file, '/');
+ pdf_out_char(p, '/');
for (i = 0; i < length; i++) {
if (s[i] < '!' || s[i] > '~' || s[i] == '#' || is_delim(s[i])) {
/* ^ "space" is here. */
- pdf_out_char (file, '#');
- pdf_out_xchar(file, s[i]);
+ pdf_out_char (p, '#');
+ pdf_out_xchar(p, s[i]);
} else {
- pdf_out_char (file, s[i]);
+ pdf_out_char (p, s[i]);
}
}
}
@@ -1225,25 +1420,27 @@ pdf_new_array (void)
}
static void
-write_array (pdf_array *array, FILE *file)
+write_array (pdf_out *p, pdf_array *array)
{
- pdf_out_char(file, '[');
+ ASSERT(p);
+
+ pdf_out_char(p, '[');
if (array->size > 0) {
- unsigned int i;
- int type1 = PDF_UNDEFINED, type2;
+ size_t i;
+ int type1 = PDF_UNDEFINED, type2;
for (i = 0; i < array->size; i++) {
if (array->values[i]) {
- type2 = array->values[i]->type;
- if (type1 != PDF_UNDEFINED && pdf_need_white(type1, type2))
- pdf_out_white(file);
- type1 = type2;
- pdf_write_obj(array->values[i], file);
+ type2 = array->values[i]->type;
+ if (type1 != PDF_UNDEFINED && pdf_need_white(type1, type2))
+ pdf_out_white(p);
+ type1 = type2;
+ pdf_write_obj(p, array->values[i]);
} else
- WARN("PDF array element #ld undefined.", i);
+ WARN("PDF array element #ld undefined.", i);
}
}
- pdf_out_char(file, ']');
+ pdf_out_char(p, ']');
}
pdf_obj *
@@ -1264,7 +1461,7 @@ pdf_get_array (pdf_obj *array, int idx)
return result;
}
-unsigned int
+unsigned
pdf_array_length (pdf_obj *array)
{
pdf_array *data;
@@ -1273,13 +1470,13 @@ pdf_array_length (pdf_obj *array)
data = (pdf_array *) array->data;
- return (unsigned int) data->size;
+ return (unsigned) data->size;
}
static void
release_array (pdf_array *data)
{
- unsigned int i;
+ size_t i;
if (data->values) {
for (i = 0; i < data->size; i++) {
@@ -1316,7 +1513,7 @@ pdf_add_array (pdf_obj *array, pdf_obj *object)
#if 0
void
-pdf_put_array (pdf_obj *array, unsigned idx, pdf_obj *object)
+pdf_put_array (pdf_obj *array, int idx, pdf_obj *object)
{
pdf_array *data;
int i;
@@ -1357,7 +1554,7 @@ pdf_shift_array (pdf_obj *array)
data = array->data;
if (data->size > 0) {
- int i;
+ size_t i;
result = data->values[0];
for (i = 1; i < data->size; i++)
@@ -1409,25 +1606,25 @@ pdf_pop_array (pdf_obj *array)
#endif
static void
-write_dict (pdf_dict *dict, FILE *file)
+write_dict (pdf_out *p, pdf_dict *dict)
{
#if 0
- pdf_out (file, "<<\n", 3); /* dropping \n saves few kb. */
+ pdf_out_str (p, "<<\n", 3); /* dropping \n saves few kb. */
#else
- pdf_out (file, "<<", 2);
+ pdf_out_str(p, "<<", 2);
#endif
while (dict->key != NULL) {
- pdf_write_obj(dict->key, file);
+ pdf_write_obj(p, dict->key);
if (pdf_need_white(PDF_NAME, (dict->value)->type)) {
- pdf_out_white(file);
+ pdf_out_white(p);
}
- pdf_write_obj(dict->value, file);
+ pdf_write_obj(p, dict->value);
#if 0
pdf_out_char (file, '\n'); /* removing this saves few kb. */
#endif
dict = dict->next;
}
- pdf_out (file, ">>", 2);
+ pdf_out_str(p, ">>", 2);
}
pdf_obj *
@@ -1826,7 +2023,9 @@ filter_PNG15_apply_filter (unsigned char *raster,
return dst;
}
-/* This modifies "raster" itself! */
+/* TIFF predictor filter support
+ * This modifies "raster" itself!
+ */
static void
apply_filter_TIFF2_1_2_4 (unsigned char *raster,
int32_t width, int32_t height,
@@ -1880,7 +2079,8 @@ apply_filter_TIFF2_1_2_4 (unsigned char *raster,
}
}
if (outbits > 0) {
- raster[k] = (outbuf << (8 - outbits)); k++;
+ raster[k] = (outbuf << (8 - outbits));
+ k++;
}
}
RELEASE(prev);
@@ -1966,17 +2166,19 @@ filter_create_predictor_dict (int predictor, int32_t columns,
}
static void
-write_stream (pdf_stream *stream, FILE *file)
+write_stream (pdf_out *p, pdf_stream *stream)
{
unsigned char *filtered;
- unsigned int filtered_length;
+ size_t filtered_length;
#ifdef HAVE_ZLIB
uLong buffer_length;
#else
- unsigned int buffer_length;
+ size_t buffer_length;
#endif
unsigned char *buffer;
+ ASSERT(p);
+
/*
* Always work from a copy of the stream. All filters read from
* "filtered" and leave their result in "filtered".
@@ -2001,11 +2203,11 @@ write_stream (pdf_stream *stream, FILE *file)
/* Apply compression filter if requested */
if (stream->stream_length > 0 &&
(stream->_flags & STREAM_COMPRESS) &&
- compression_level > 0) {
+ p->options.compression.level > 0) {
pdf_obj *filters;
/* First apply predictor filter if requested. */
- if ( compression_use_predictor &&
+ if ( p->options.compression.use_predictor &&
(stream->_flags & STREAM_USE_PREDICTOR) &&
!pdf_lookup_dict(stream->dict, "DecodeParms")) {
int bits_per_pixel = stream->decodeparms.colors *
@@ -2071,18 +2273,19 @@ write_stream (pdf_stream *stream, FILE *file)
}
#ifdef HAVE_ZLIB_COMPRESS2
if (compress2(buffer, &buffer_length, filtered,
- filtered_length, compression_level)) {
+ filtered_length, p->options.compression.level)) {
ERROR("Zlib error");
}
#else
if (compress(buffer, &buffer_length, filtered,
- filtered_length)) {
+ filtered_length)) {
ERROR ("Zlib error");
}
#endif /* HAVE_ZLIB_COMPRESS2 */
RELEASE(filtered);
- compression_saved += filtered_length - buffer_length
- - (filters ? strlen("/FlateDecode "): strlen("/Filter/FlateDecode\n"));
+ p->output.compression_saved +=
+ filtered_length - buffer_length
+ - (filters ? strlen("/FlateDecode "): strlen("/Filter/FlateDecode\n"));
filtered = buffer;
filtered_length = buffer_length;
@@ -2090,10 +2293,10 @@ write_stream (pdf_stream *stream, FILE *file)
#endif /* HAVE_ZLIB */
/* AES will change the size of data! */
- if (enc_mode) {
+ if (p->state.enc_mode) {
unsigned char *cipher = NULL;
size_t cipher_len = 0;
- pdf_encrypt_data(filtered, filtered_length, &cipher, &cipher_len);
+ pdf_encrypt_data(p->sec_data, filtered, filtered_length, &cipher, &cipher_len);
RELEASE(filtered);
filtered = cipher;
filtered_length = cipher_len;
@@ -2115,12 +2318,12 @@ write_stream (pdf_stream *stream, FILE *file)
pdf_add_dict(stream->dict,
pdf_new_name("Length"), pdf_new_number(filtered_length));
- pdf_write_obj(stream->dict, file);
+ pdf_write_obj(p, stream->dict);
- pdf_out(file, "\nstream\n", 8);
+ pdf_out_str(p, "\nstream\n", 8);
if (filtered_length > 0)
- pdf_out(file, filtered, filtered_length);
+ pdf_out_str(p, filtered, filtered_length);
RELEASE(filtered);
/*
@@ -2130,8 +2333,8 @@ write_stream (pdf_stream *stream, FILE *file)
* filters, this could be a problem.
*/
- pdf_out(file, "\n", 1);
- pdf_out(file, "endstream", 9);
+ pdf_out_str(p, "\n", 1);
+ pdf_out_str(p, "endstream", 9);
}
static void
@@ -2497,7 +2700,7 @@ filter_stream_decode_FlateDecode (const void *data, size_t len, struct decode_pa
WARN("Ignoring zlib error: status=%d, message=\"%s\"", status, z.msg);
break;
} else if (status != Z_OK) {
- WARN("inflate() failed (status=%d, message=\"%s\").", status, z.msg);
+ WARN("inflate() failed. Broken PDF file?");
inflateEnd(&z);
pdf_release_obj(tmp);
return NULL;
@@ -2861,76 +3064,83 @@ pdf_stream_get_flags (pdf_obj *stream)
#endif
static void
-pdf_write_obj (pdf_obj *object, FILE *file)
+pdf_write_obj (pdf_out *p, pdf_obj *object)
{
+ ASSERT(p);
+
if (object == NULL) {
- write_null(file);
+ write_null(p);
return;
}
if (INVALIDOBJ(object) || PDF_OBJ_UNDEFINED(object))
ERROR("pdf_write_obj: Invalid object, type = %d\n", object->type);
- if (file == stderr)
+ if (error_out)
fprintf(stderr, "{%d}", object->refcount);
switch (object->type) {
case PDF_BOOLEAN:
- write_boolean(object->data, file);
+ write_boolean(p, object->data);
break;
case PDF_NUMBER:
- write_number (object->data, file);
+ write_number (p, object->data);
break;
case PDF_STRING:
- write_string (object->data, file);
+ write_string (p, object->data);
break;
case PDF_NAME:
- write_name(object->data, file);
+ write_name(p, object->data);
break;
case PDF_ARRAY:
- write_array(object->data, file);
+ write_array(p, object->data);
break;
case PDF_DICT:
- write_dict (object->data, file);
+ write_dict (p, object->data);
break;
case PDF_STREAM:
- write_stream(object->data, file);
+ write_stream(p, object->data);
break;
case PDF_NULL:
- write_null(file);
+ write_null(p);
break;
case PDF_INDIRECT:
- write_indirect(object->data, file);
+ write_indirect(p, object->data);
break;
}
}
/* Write the object to the file */
static void
-pdf_flush_obj (pdf_obj *object, FILE *file)
+pdf_flush_obj (pdf_out *p, pdf_obj *object)
{
- int length;
+ size_t length;
+ char buf[64];
/*
* Record file position
*/
- add_xref_entry(object->label, 1,
- pdf_output_file_position, object->generation);
- length = sprintf(format_buffer, "%u %hu obj\n", object->label, object->generation);
- enc_mode = doc_enc_mode && !(object->flags & OBJ_NO_ENCRYPT);
- pdf_enc_set_label(object->label);
- pdf_enc_set_generation(object->generation);
- pdf_out(file, format_buffer, length);
- pdf_write_obj(object, file);
- pdf_out(file, "\nendobj\n", 8);
+ add_xref_entry(p, object->label, 1,
+ p->output.file_position, object->generation);
+ length = sprintf(buf, "%u %hu obj\n", object->label, object->generation);
+ p->state.enc_mode =
+ (p->options.enable_encrypt && !(object->flags & OBJ_NO_ENCRYPT)) ? 1 : 0;
+ if (p->state.enc_mode) {
+ pdf_enc_set_label(p->sec_data, object->label);
+ pdf_enc_set_generation(p->sec_data, object->generation);
+ }
+ pdf_out_str(p, buf, length);
+ pdf_write_obj(p, object);
+ pdf_out_str(p, "\nendobj\n", 8);
}
static int
-pdf_add_objstm (pdf_obj *objstm, pdf_obj *object)
+pdf_add_objstm (pdf_out *p, pdf_obj *objstm, pdf_obj *object)
{
int *data, pos;
TYPECHECK(objstm, PDF_STREAM);
+ ASSERT(p);
data = get_objstm_data(objstm);
pos = ++data[0];
@@ -2938,14 +3148,14 @@ pdf_add_objstm (pdf_obj *objstm, pdf_obj *object)
data[2*pos] = object->label;
data[2*pos+1] = pdf_stream_length(objstm);
- add_xref_entry(object->label, 2, objstm->label, pos-1);
+ add_xref_entry(p, object->label, 2, objstm->label, pos-1);
/* redirect output into objstm */
- output_stream = objstm;
- enc_mode = 0;
- pdf_write_obj(object, pdf_output_file);
- pdf_out_char(pdf_output_file, '\n');
- output_stream = NULL;
+ p->output_stream = objstm;
+ p->state.enc_mode = 0;
+ pdf_write_obj(p, object);
+ pdf_out_char(p, '\n');
+ p->output_stream = NULL;
return pos;
}
@@ -2958,7 +3168,7 @@ release_objstm (pdf_obj *objstm)
pdf_obj *dict;
pdf_stream *stream;
unsigned char *old_buf;
- unsigned int old_length;
+ size_t old_length;
stream = (pdf_stream *) objstm->data;
/* Precede stream data by offset table */
@@ -2971,8 +3181,9 @@ release_objstm (pdf_obj *objstm)
{
int i = 2*pos, *val = data+2;
while (i--) {
- int length = sprintf(format_buffer, "%d ", *(val++));
- pdf_add_stream(objstm, format_buffer, length);
+ char buf[32];
+ size_t length = sprintf(buf, "%d ", *(val++));
+ pdf_add_stream(objstm, buf, length);
}
}
@@ -2989,13 +3200,17 @@ release_objstm (pdf_obj *objstm)
void
pdf_release_obj (pdf_obj *object)
{
+ pdf_out *p = current_output();
+
if (object == NULL)
return;
if (INVALIDOBJ(object) || object->refcount <= 0) {
MESG("\npdf_release_obj: object=%p, type=%d, refcount=%d\n",
- object, object->type, object->refcount);
- pdf_write_obj(object, stderr);
+ object, object->type, object->refcount);
+ error_out = 1;
+ pdf_write_obj(p, object);
ERROR("pdf_release_obj: Called with invalid object.");
+ error_out = 0;
}
object->refcount -= 1;
if (object->refcount == 0) {
@@ -3006,23 +3221,23 @@ pdf_release_obj (pdf_obj *object)
* Nothing is using this object so it's okay to remove it.
* Nonzero "label" means object needs to be written before it's destroyed.
*/
- if (object->label && pdf_output_file != NULL) {
- if (!do_objstm || object->flags & OBJ_NO_OBJSTM
- || (doc_enc_mode && object->flags & OBJ_NO_ENCRYPT)
- || object->generation)
- pdf_flush_obj(object, pdf_output_file);
+ if (object->label && p->output.file != NULL) {
+ if (!p->options.use_objstm || object->flags & OBJ_NO_OBJSTM ||
+ (p->options.enable_encrypt && (object->flags & OBJ_NO_ENCRYPT)) ||
+ object->generation)
+ pdf_flush_obj(p, object);
else {
- if (!current_objstm) {
- int *data = NEW(2*OBJSTM_MAX_OBJS+2, int);
- data[0] = data[1] = 0;
- current_objstm = pdf_new_stream(STREAM_COMPRESS);
- set_objstm_data(current_objstm, data);
- pdf_label_obj(current_objstm);
- }
- if (pdf_add_objstm(current_objstm, object) == OBJSTM_MAX_OBJS) {
- release_objstm(current_objstm);
- current_objstm = NULL;
- }
+ if (!p->current_objstm) {
+ int *data = NEW(2*OBJSTM_MAX_OBJS+2, int);
+ data[0] = data[1] = 0;
+ p->current_objstm = pdf_new_stream(STREAM_COMPRESS);
+ set_objstm_data(p->current_objstm, data);
+ pdf_label_obj(p, p->current_objstm);
+ }
+ if (pdf_add_objstm(p, p->current_objstm, object) == OBJSTM_MAX_OBJS) {
+ release_objstm(p->current_objstm);
+ p->current_objstm = NULL;
+ }
}
}
switch (object->type) {
@@ -3060,6 +3275,9 @@ pdf_release_obj (pdf_obj *object)
}
}
+/* Reading external PDF files
+ *
+ */
static int
backup_line (FILE *pdf_input_file)
{
@@ -3086,11 +3304,11 @@ backup_line (FILE *pdf_input_file)
static int
find_xref (FILE *pdf_input_file)
{
- int xref_pos = 0;
- int len, tries = 10;
+ size_t len, xref_pos = 0;
+ int tries = 10;
do {
- int currentpos;
+ size_t currentpos;
if (!backup_line(pdf_input_file)) {
tries = 0;
@@ -3162,10 +3380,11 @@ parse_trailer (pdf_file *pf)
* :-(
*/
static int
-next_object_offset (pdf_file *pf, unsigned int obj_num)
+next_object_offset (pdf_file *pf, uint32_t obj_num)
{
- int next = pf->file_size; /* Worst case */
- int i, curr;
+ uint32_t next = pf->file_size; /* Worst case */
+ size_t i;
+ uint32_t curr;
curr = pf->xref_table[obj_num].field2;
/* Check all other type 1 objects to find next one */
@@ -3184,7 +3403,7 @@ next_object_offset (pdf_file *pf, unsigned int obj_num)
((pf)->xref_table[(n)].type == 2 && !(g))))
pdf_obj *
-pdf_new_indirect (pdf_file *pf, unsigned obj_num, unsigned short obj_gen)
+pdf_new_indirect (pdf_file *pf, uint32_t obj_num, uint16_t obj_gen)
{
pdf_obj *result;
pdf_indirect *indirect;
@@ -3202,13 +3421,12 @@ pdf_new_indirect (pdf_file *pf, unsigned obj_num, unsigned short obj_gen)
}
static pdf_obj *
-pdf_read_object (unsigned int obj_num, unsigned short obj_gen,
- pdf_file *pf, int offset, int limit)
+pdf_read_object (uint32_t obj_num, uint16_t obj_gen, pdf_file *pf, size_t offset, size_t limit)
{
- int length;
- char *buffer;
+ pdf_obj *result = NULL;
+ size_t length;
+ char *buffer;
const char *p, *endptr;
- pdf_obj *result;
length = limit - offset;
@@ -3227,7 +3445,7 @@ pdf_read_object (unsigned int obj_num, unsigned short obj_gen,
{
const char *q = p; /* <== p */
char *sp;
- unsigned int n, g;
+ uint32_t n, g;
skip_white(&q, endptr);
sp = parse_unsigned(&q, endptr);
@@ -3279,16 +3497,16 @@ pdf_read_object (unsigned int obj_num, unsigned short obj_gen,
}
static pdf_obj *
-read_objstm (pdf_file *pf, unsigned int num)
+read_objstm (pdf_file *pf, uint32_t num)
{
- unsigned int offset = pf->xref_table[num].field2;
- unsigned short gen = pf->xref_table[num].field3;
- int limit = next_object_offset(pf, num), n, first, *header = NULL;
- char *data = NULL, *q;
+ size_t offset = pf->xref_table[num].field2;
+ uint16_t gen = pf->xref_table[num].field3;
+ size_t limit = next_object_offset(pf, num);
+ int n, first, *header = NULL;
+ char *data = NULL, *q;
const char *p, *endptr;
- int i;
-
- pdf_obj *objstm, *dict, *type, *n_obj, *first_obj;
+ int i;
+ pdf_obj *objstm, *dict, *type, *n_obj, *first_obj;
objstm = pdf_read_object(num, gen, pf, offset, limit);
@@ -3365,7 +3583,7 @@ read_objstm (pdf_file *pf, unsigned int num)
* several cross-reference sections.
*/
static pdf_obj *
-pdf_get_object (pdf_file *pf, unsigned int obj_num, unsigned short obj_gen)
+pdf_get_object (pdf_file *pf, uint32_t obj_num, uint16_t obj_gen)
{
pdf_obj *result;
@@ -3381,27 +3599,27 @@ pdf_get_object (pdf_file *pf, unsigned int obj_num, unsigned short obj_gen)
if (pf->xref_table[obj_num].type == 1) {
/* type == 1 */
- unsigned int offset;
- int limit;
+ uint32_t offset;
+ size_t limit;
offset = pf->xref_table[obj_num].field2;
limit = next_object_offset(pf, obj_num);
result = pdf_read_object(obj_num, obj_gen, pf, offset, limit);
} else {
/* type == 2 */
- unsigned int objstm_num = pf->xref_table[obj_num].field2;
- unsigned short index = pf->xref_table[obj_num].field3;
- pdf_obj *objstm;
- int *data, n, first, length;
+ uint32_t objstm_num = pf->xref_table[obj_num].field2;
+ uint16_t index = pf->xref_table[obj_num].field3;
+ pdf_obj *objstm;
+ int *data, n, first, length;
const char *p, *q;
if (objstm_num >= pf->num_obj ||
- pf->xref_table[objstm_num].type != 1 ||
- !((objstm = pf->xref_table[objstm_num].direct) ||
- (objstm = read_objstm(pf, objstm_num))))
+ pf->xref_table[objstm_num].type != 1 ||
+ !((objstm = pf->xref_table[objstm_num].direct) ||
+ (objstm = read_objstm(pf, objstm_num))))
goto error;
- data = get_objstm_data(objstm);
- n = *(data++);
+ data = get_objstm_data(objstm);
+ n = *(data++);
first = *(data++);
if (index >= n || data[2*index] != obj_num)
@@ -3431,12 +3649,14 @@ pdf_get_object (pdf_file *pf, unsigned int obj_num, unsigned short obj_gen)
#define OBJ_GEN(o) (((pdf_indirect *)((o)->data))->generation)
static pdf_obj *
-pdf_new_ref (pdf_obj *object)
+pdf_new_ref (pdf_out *p, pdf_obj *object)
{
pdf_obj *result;
+ ASSERT(p);
+
if (object->label == 0) {
- pdf_label_obj(object);
+ pdf_label_obj(p, object);
}
result = pdf_new_indirect(NULL, object->label, object->generation);
OBJ_OBJ(result) = object;
@@ -3456,8 +3676,8 @@ pdf_deref_obj (pdf_obj *obj)
while (PDF_OBJ_INDIRECTTYPE(obj) && --count) {
pdf_file *pf = OBJ_FILE(obj);
if (pf) {
- unsigned int obj_num = OBJ_NUM(obj);
- unsigned short obj_gen = OBJ_GEN(obj);
+ uint32_t obj_num = OBJ_NUM(obj);
+ uint16_t obj_gen = OBJ_GEN(obj);
pdf_release_obj(obj);
obj = pdf_get_object(pf, obj_num, obj_gen);
} else {
@@ -3481,9 +3701,9 @@ pdf_deref_obj (pdf_obj *obj)
}
static void
-extend_xref (pdf_file *pf, int new_size)
+extend_xref (pdf_file *pf, size_t new_size)
{
- unsigned int i;
+ size_t i;
pf->xref_table = RENEW(pf->xref_table, new_size, xref_entry);
for (i = pf->num_obj; i < new_size; i++) {
@@ -3498,12 +3718,12 @@ extend_xref (pdf_file *pf, int new_size)
/* Returns < 0 for error, 1 for success, and 0 when xref stream found. */
static int
-parse_xref_table (pdf_file *pf, int xref_pos)
+parse_xref_table (pdf_file *pf, size_t xref_pos)
{
FILE *pdf_input_file = pf->file;
const char *p, *endptr;
char buf[256]; /* See, PDF ref. v.1.7, p.91 for "255+1" here. */
- int len;
+ size_t len;
/*
* This routine reads one xref segment. It may be called multiple times
@@ -3535,10 +3755,10 @@ parse_xref_table (pdf_file *pf, int xref_pos)
/* Next line in file has first item and size of table */
for (;;) {
- char flag;
- unsigned int current_pos;
- int i;
- uint32_t first, size, offset, obj_gen;
+ char flag;
+ size_t current_pos, size, offset;
+ int i;
+ uint32_t first, obj_gen;
current_pos = tell_position(pdf_input_file);
len = mfreadln(buf, 255, pdf_input_file);
@@ -3702,10 +3922,10 @@ parse_xref_table (pdf_file *pf, int xref_pos)
return 1;
}
-static unsigned int
-parse_xrefstm_field (const char **p, int length, unsigned int def)
+static uint32_t
+parse_xrefstm_field (const char **p, size_t length, uint32_t def)
{
- unsigned int val = 0;
+ uint32_t val = 0;
if (!length)
return def;
@@ -3720,9 +3940,9 @@ parse_xrefstm_field (const char **p, int length, unsigned int def)
static int
parse_xrefstm_subsec (pdf_file *pf,
- const char **p, int *length,
- int *W, int wsum,
- int first, int size) {
+ const char **p, size_t *length,
+ int *W, int wsum, int first, int size)
+{
xref_entry *e;
if ((*length -= wsum*size) < 0)
@@ -3733,9 +3953,9 @@ parse_xrefstm_subsec (pdf_file *pf,
e = pf->xref_table + first;
while (size--) {
- unsigned char type;
- unsigned int field2;
- unsigned short field3;
+ uint8_t type;
+ uint32_t field2;
+ uint16_t field3;
type = (unsigned char) parse_xrefstm_field(p, W[0], 1);
if (type > 2)
@@ -3746,8 +3966,8 @@ parse_xrefstm_subsec (pdf_file *pf,
return -1;
#endif
- field2 = (unsigned int) parse_xrefstm_field(p, W[1], 0);
- field3 = (unsigned short) parse_xrefstm_field(p, W[2], 0);
+ field2 = (uint32_t) parse_xrefstm_field(p, W[1], 0);
+ field3 = (uint16_t) parse_xrefstm_field(p, W[2], 0);
if (!e->field2) {
e->type = type;
@@ -3761,12 +3981,12 @@ parse_xrefstm_subsec (pdf_file *pf,
}
static int
-parse_xref_stream (pdf_file *pf, int xref_pos, pdf_obj **trailer)
+parse_xref_stream (pdf_file *pf, size_t xref_pos, pdf_obj **trailer)
{
- pdf_obj *xrefstm, *size_obj, *W_obj, *index_obj;
- unsigned int size;
- int length;
- int W[3], i, wsum = 0;
+ pdf_obj *xrefstm, *size_obj, *W_obj, *index_obj;
+ uint32_t size;
+ size_t length;
+ int W[3], i, wsum = 0;
const char *p;
xrefstm = pdf_read_object(0, 0, pf, xref_pos, pf->file_size);
@@ -3786,7 +4006,7 @@ parse_xref_stream (pdf_file *pf, int xref_pos, pdf_obj **trailer)
size_obj = pdf_lookup_dict(*trailer, "Size");
if (!PDF_OBJ_NUMBERTYPE(size_obj))
goto error;
- size = (unsigned int) pdf_number_value(size_obj);
+ size = (uint32_t) pdf_number_value(size_obj);
length = pdf_stream_length(xrefstm);
@@ -3805,7 +4025,7 @@ parse_xref_stream (pdf_file *pf, int xref_pos, pdf_obj **trailer)
index_obj = pdf_lookup_dict(*trailer, "Index");
if (index_obj) {
- unsigned int index_len;
+ size_t index_len;
if (!PDF_OBJ_ARRAYTYPE(index_obj) ||
((index_len = pdf_array_length(index_obj)) % 2 ))
goto error;
@@ -3845,7 +4065,7 @@ static pdf_obj *
read_xref (pdf_file *pf)
{
pdf_obj *trailer = NULL, *main_trailer = NULL;
- int xref_pos;
+ size_t xref_pos;
if (!(xref_pos = find_xref(pf->file)))
goto error;
@@ -3859,37 +4079,37 @@ read_xref (pdf_file *pf)
pdf_obj *xrefstm;
if (!(trailer = parse_trailer(pf)))
- goto error;
+ goto error;
if (!main_trailer)
- main_trailer = pdf_link_obj(trailer);
+ main_trailer = pdf_link_obj(trailer);
if ((xrefstm = pdf_lookup_dict(trailer, "XRefStm"))) {
- pdf_obj *new_trailer = NULL;
- if (PDF_OBJ_NUMBERTYPE(xrefstm) &&
- parse_xref_stream(pf, (int) pdf_number_value(xrefstm),
+ pdf_obj *new_trailer = NULL;
+ if (PDF_OBJ_NUMBERTYPE(xrefstm) &&
+ parse_xref_stream(pf, (int) pdf_number_value(xrefstm),
&new_trailer))
- pdf_release_obj(new_trailer);
- else
- WARN("Skipping hybrid reference section.");
- /* Many PDF 1.5 xref streams use DecodeParms, which we cannot
- parse. This way we can use at least xref tables in hybrid
- documents. Or should we better stop parsing the file?
- */
+ pdf_release_obj(new_trailer);
+ else
+ WARN("Skipping hybrid reference section.");
+ /* Many PDF 1.5 xref streams use DecodeParms, which we cannot
+ * parse. This way we can use at least xref tables in hybrid
+ * documents. Or should we better stop parsing the file?
+ */
}
} else if (!res && parse_xref_stream(pf, xref_pos, &trailer)) {
/* cross-reference stream */
if (!main_trailer)
- main_trailer = pdf_link_obj(trailer);
+ main_trailer = pdf_link_obj(trailer);
} else
goto error;
if ((prev = pdf_lookup_dict(trailer, "Prev"))) {
if (PDF_OBJ_NUMBERTYPE(prev))
- xref_pos = (int) pdf_number_value(prev);
+ xref_pos = (size_t) pdf_number_value(prev);
else
- goto error;
+ goto error;
} else
xref_pos = 0;
@@ -3938,7 +4158,7 @@ pdf_file_new (FILE *file)
static void
pdf_file_free (pdf_file *pf)
{
- unsigned int i;
+ size_t i;
if (!pf) {
return;
@@ -3995,6 +4215,7 @@ pdf_file_get_catalog (pdf_file *pf)
pdf_file *
pdf_open (const char *ident, FILE *file)
{
+ pdf_out *p = current_output();
pdf_file *pf = NULL;
ASSERT(pdf_files);
@@ -4008,15 +4229,21 @@ pdf_open (const char *ident, FILE *file)
pdf_obj *new_version;
int version = check_for_pdf_version(file);
- if (version < 10)
- WARN("Unrecognized PDF version specified for input PDF file: %d.%d",
- pdf_version/10, pdf_version%10);
- else if (version > pdf_version) {
- WARN("Trying to include PDF file with version (%d.%d), which is " \
- "newer than current output PDF setting (%d.%d).",
- version/10, version%10, pdf_version/10, pdf_version%10);
- }
+ if (!dpx_conf.is_xbb) {
+ int ver_major, ver_minor;
+ ver_major = version / 10;
+ ver_minor = version % 10;
+
+ if (version < 10)
+ WARN("Unrecognized PDF version specified for input PDF file: %d.%d",
+ ver_major, ver_minor);
+ else if (pdf_check_version(ver_major, ver_minor) < 0) {
+ WARN("Trying to include PDF file with version (%d.%d), which is " \
+ "newer than current output PDF setting (%d.%d).",
+ ver_major, ver_minor, p->version.major, p->version.minor);
+ }
+ }
pf = pdf_file_new(file);
pf->version = version;
@@ -4096,7 +4323,7 @@ check_for_pdf (FILE *file)
if (version < 0) /* not a PDF file */
return 0;
- if (version <= pdf_version)
+ if (version <= pdf_get_version())
return 1;
return 1;
@@ -4122,10 +4349,11 @@ import_dict (pdf_obj *key, pdf_obj *value, void *pdata)
static pdf_obj *
pdf_import_indirect (pdf_obj *object)
{
+ pdf_out *p = current_output();
pdf_file *pf = OBJ_FILE(object);
- unsigned int obj_num = OBJ_NUM(object);
- unsigned short obj_gen = OBJ_GEN(object);
- pdf_obj *ref;
+ uint32_t obj_num = OBJ_NUM(object);
+ uint16_t obj_gen = OBJ_GEN(object);
+ pdf_obj *ref;
ASSERT(pf);
@@ -4154,7 +4382,7 @@ pdf_import_indirect (pdf_obj *object)
* are completely read.
*/
reserved = pdf_new_null(); /* for reservation of label */
- pf->xref_table[obj_num].indirect = ref = pdf_new_ref(reserved);
+ pf->xref_table[obj_num].indirect = ref = pdf_new_ref(p, reserved);
imported = pdf_import_object(obj);
if (imported) {
if (imported->label) {
@@ -4187,7 +4415,7 @@ pdf_import_object (pdf_obj *object)
{
pdf_obj *imported;
pdf_obj *tmp;
- int i;
+ size_t i;
switch (pdf_obj_typeof(object)) {
@@ -4233,8 +4461,8 @@ pdf_import_object (pdf_obj *object)
for (i = 0; i < pdf_array_length(object); i++) {
tmp = pdf_import_object(pdf_get_array(object, i));
if (!tmp) {
- pdf_release_obj(imported);
- return NULL;
+ pdf_release_obj(imported);
+ return NULL;
}
pdf_add_array(imported, tmp);
}