summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfmx/src/epdf.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipdfmx/src/epdf.c')
-rw-r--r--Build/source/texk/dvipdfmx/src/epdf.c301
1 files changed, 131 insertions, 170 deletions
diff --git a/Build/source/texk/dvipdfmx/src/epdf.c b/Build/source/texk/dvipdfmx/src/epdf.c
index 1cb621a4149..2471f4a6152 100644
--- a/Build/source/texk/dvipdfmx/src/epdf.c
+++ b/Build/source/texk/dvipdfmx/src/epdf.c
@@ -1,4 +1,4 @@
-/* $Header: /home/cvsroot/dvipdfmx/src/epdf.c,v 1.16 2007/11/14 03:12:21 chofchof Exp $
+/* $Header: /home/cvsroot/dvipdfmx/src/epdf.c,v 1.22 2008/05/18 14:31:06 matthias Exp $
This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
@@ -40,10 +40,6 @@
#include "mfileio.h"
#include "error.h"
-#if HAVE_ZLIB
-#include <zlib.h>
-#endif
-
#include "pdfobj.h"
#include "pdfdev.h"
@@ -51,10 +47,6 @@
#include "epdf.h"
-#if HAVE_ZLIB
-static int add_stream_flate (pdf_obj *dst, const void *data, long len);
-#endif
-static int concat_stream (pdf_obj *dst, pdf_obj *src);
static void print_bbox_info (pdf_obj *rect, const char *type, pdf_obj *crop_box);
static int rect_equal (pdf_obj *rect1, pdf_obj *rect2);
@@ -145,10 +137,13 @@ print_bbox_info (pdf_obj *rect, const char *type, pdf_obj *crop_box)
int
pdf_include_page (pdf_ximage *ximage, FILE *image_file)
{
+ char *ident = pdf_ximage_get_ident(ximage);
+ pdf_file *pf;
xform_info info;
- pdf_obj *contents, *contents_ref, *contents_dict;
+ pdf_obj *contents, *contents_dict;
pdf_obj *page_tree;
- pdf_obj *bbox, *resources, *rotate, *matrix;
+ pdf_obj *bbox = NULL, *resources = NULL, *rotate = NULL, *matrix;
+ long page_no, page_idx;
pdf_ximage_init_form_info(&info);
/*
@@ -159,24 +154,26 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file)
pdf_obj *trailer, *catalog;
pdf_obj *markinfo, *tmp;
- trailer = pdf_open(image_file);
- if (!trailer) {
- WARN("Trailer not found! Corrupt PDF file?");
- pdf_close();
+ pf = pdf_open(ident, image_file);
+ if (!pf)
return -1;
- }
+
+ trailer = pdf_file_get_trailer(pf);
if (pdf_lookup_dict(trailer, "Encrypt")) {
WARN("This PDF document is encrypted.");
pdf_release_obj(trailer);
- pdf_close();
+ pdf_close(pf);
return -1;
}
catalog = pdf_deref_obj(pdf_lookup_dict(trailer, "Root"));
- if (!catalog) {
- WARN("Catalog isn't where I expect it.");
- pdf_close();
+ if (!PDF_OBJ_DICTTYPE(catalog)) {
+ WARN("Can't read document catalog.");
+ pdf_release_obj(trailer);
+ if (catalog)
+ pdf_release_obj(catalog);
+ pdf_close(pf);
return -1;
}
pdf_release_obj(trailer);
@@ -184,13 +181,9 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file)
markinfo = pdf_deref_obj(pdf_lookup_dict(catalog, "MarkInfo"));
if (markinfo) {
tmp = pdf_lookup_dict(markinfo, "Marked");
+ if (PDF_OBJ_BOOLEANTYPE(tmp) && pdf_boolean_value(tmp))
+ WARN("File contains tagged PDF. Ignoring tags.");
pdf_release_obj(markinfo);
- if (tmp && pdf_boolean_value(tmp)) {
- WARN("Tagged PDF not supported.");
- pdf_release_obj(catalog);
- pdf_close();
- return -1;
- }
}
page_tree = pdf_deref_obj(pdf_lookup_dict(catalog, "Pages"));
@@ -198,35 +191,42 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file)
}
if (!page_tree) {
WARN("Page tree not found.");
- pdf_close();
+ pdf_close(pf);
return -1;
}
/*
- * Seek first page. Get Media/Crop Box.
+ * Negative page numbers are counted from the back.
+ */
+ {
+ long count = pdf_number_value(pdf_lookup_dict(page_tree, "Count"));
+ page_no = pdf_ximage_get_page(ximage);
+ page_idx = page_no + (page_no >= 0 ? -1 : count);
+ if (page_idx < 0 || page_idx >= count) {
+ WARN("Page %ld does not exist.", page_no);
+ pdf_release_obj(page_tree);
+ pdf_close(pf);
+ return -1;
+ }
+ page_no = page_idx+1;
+ pdf_ximage_set_page(ximage, page_no, count);
+ }
+
+ /*
+ * Seek correct page. Get Media/Crop Box.
* Media box and resources can be inherited.
*/
{
pdf_obj *kids_ref, *kids;
- pdf_obj *crop_box;
+ pdf_obj *crop_box = NULL;
pdf_obj *tmp;
- tmp = pdf_lookup_dict(page_tree, "MediaBox");
- bbox = tmp ? pdf_deref_obj(tmp) : NULL;
- tmp = pdf_lookup_dict(page_tree, "CropBox");
- crop_box = tmp ? pdf_deref_obj(tmp) : NULL;
- tmp = pdf_lookup_dict(page_tree, "Rotate");
- rotate = tmp ? pdf_deref_obj(tmp) : NULL;
-
tmp = pdf_lookup_dict(page_tree, "Resources");
resources = tmp ? pdf_deref_obj(tmp) : pdf_new_dict();
- while ((kids_ref = pdf_lookup_dict(page_tree, "Kids")) != NULL) {
- kids = pdf_deref_obj(kids_ref);
- pdf_release_obj(page_tree);
- page_tree = pdf_deref_obj(pdf_get_array(kids, 0));
- pdf_release_obj(kids);
-
+ while (1) {
+ long kids_length, i;
+
if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "MediaBox")))) {
if (bbox)
pdf_release_obj(bbox);
@@ -237,21 +237,24 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file)
if (bbox)
pdf_release_obj(bbox);
bbox = tmp;
- }
+ } else
+ pdf_release_obj(tmp);
}
if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "TrimBox")))) {
if (!rect_equal(tmp, bbox)) {
if (bbox)
pdf_release_obj(bbox);
bbox = tmp;
- }
+ } else
+ pdf_release_obj(tmp);
}
if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "ArtBox")))) {
if (!rect_equal(tmp, bbox)) {
if (bbox)
pdf_release_obj(bbox);
bbox = tmp;
- }
+ } else
+ pdf_release_obj(tmp);
}
if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "CropBox")))) {
if (crop_box)
@@ -271,6 +274,49 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file)
pdf_release_obj(resources);
resources = tmp;
}
+
+ kids_ref = pdf_lookup_dict(page_tree, "Kids");
+ if (!kids_ref)
+ break;
+ kids = pdf_deref_obj(kids_ref);
+ kids_length = pdf_array_length(kids);
+
+ for (i = 0; i < kids_length; i++) {
+ long count;
+
+ pdf_release_obj(page_tree);
+ page_tree = pdf_deref_obj(pdf_get_array(kids, i));
+
+ tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Count"));
+ if (tmp) {
+ /* Pages object */
+ count = pdf_number_value(tmp);
+ pdf_release_obj(tmp);
+ } else
+ /* Page object */
+ count = 1;
+
+ if (page_idx < count)
+ break;
+
+ page_idx -= count;
+ }
+
+ pdf_release_obj(kids);
+
+ if (i == kids_length) {
+ WARN("Page %ld not found! Broken PDF file?", page_no);
+ if (bbox)
+ pdf_release_obj(bbox);
+ if (crop_box)
+ pdf_release_obj(crop_box);
+ if (rotate)
+ pdf_release_obj(rotate);
+ pdf_release_obj(resources);
+ pdf_release_obj(page_tree);
+ pdf_close(pf);
+ return -1;
+ }
}
if (crop_box) {
pdf_release_obj(bbox);
@@ -284,7 +330,7 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file)
pdf_release_obj(resources);
if (rotate)
pdf_release_obj(rotate);
- pdf_close();
+ pdf_close(pf);
return -1;
}
@@ -295,29 +341,41 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file)
rotate = NULL;
}
- info.bbox.llx = pdf_number_value(pdf_get_array(bbox, 0));
- info.bbox.lly = pdf_number_value(pdf_get_array(bbox, 1));
- info.bbox.urx = pdf_number_value(pdf_get_array(bbox, 2));
- info.bbox.ury = pdf_number_value(pdf_get_array(bbox, 3));
+ {
+ pdf_obj *tmp;
+
+ tmp = pdf_deref_obj(pdf_get_array(bbox, 0));
+ info.bbox.llx = pdf_number_value(tmp);
+ pdf_release_obj(tmp);
+ tmp = pdf_deref_obj(pdf_get_array(bbox, 1));
+ info.bbox.lly = pdf_number_value(tmp);
+ pdf_release_obj(tmp);
+ tmp = pdf_deref_obj(pdf_get_array(bbox, 2));
+ info.bbox.urx = pdf_number_value(tmp);
+ pdf_release_obj(tmp);
+ tmp = pdf_deref_obj(pdf_get_array(bbox, 3));
+ info.bbox.ury = pdf_number_value(tmp);
+ pdf_release_obj(tmp);
+ }
/*
* Handle page content stream.
- * page_tree is now set to the first page.
+ * page_tree is now set to the correct page.
*/
- contents_ref = contents = NULL;
{
contents = pdf_deref_obj(pdf_lookup_dict(page_tree, "Contents"));
pdf_release_obj(page_tree);
- if (!contents) {
- pdf_release_obj(bbox);
- pdf_close();
- return -1;
- }
- /*
- * Concatinate all content streams.
- */
- if (PDF_OBJ_ARRAYTYPE(contents)) {
+ if (!contents) {
+ /* empty page */
+ if (contents)
+ pdf_release_obj(contents);
+ /* TODO: better don't include anything if the page is empty */
+ contents = pdf_new_stream(0);
+ } else if (PDF_OBJ_ARRAYTYPE(contents)) {
+ /*
+ * Concatenate all content streams.
+ */
pdf_obj *content_seg, *content_new;
int idx = 0;
content_new = pdf_new_stream(STREAM_COMPRESS);
@@ -325,19 +383,17 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file)
content_seg = pdf_deref_obj(pdf_get_array(contents, idx));
if (!content_seg)
break;
- else if (PDF_OBJ_NULLTYPE(content_seg)) {
- /* Silently ignore. */
- } else if (!PDF_OBJ_STREAMTYPE(content_seg)) {
+ else if (!PDF_OBJ_STREAMTYPE(content_seg)) {
WARN("Page content not a stream object. Broken PDF file?");
pdf_release_obj(content_new);
pdf_release_obj(bbox);
- pdf_close();
+ pdf_close(pf);
return -1;
- } else if (concat_stream(content_new, content_seg) < 0) {
+ } else if (pdf_concat_stream(content_new, content_seg) < 0) {
WARN("Could not handle content stream with multiple segment.");
pdf_release_obj(content_new);
pdf_release_obj(bbox);
- pdf_close();
+ pdf_close(pf);
return -1;
}
pdf_release_obj(content_seg);
@@ -345,10 +401,11 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file)
}
pdf_release_obj(contents);
contents = content_new;
- }
- if (!contents) {
+ } else if (pdf_obj_typeof(contents) != PDF_STREAM) {
+ WARN("Page content not a stream object.");
+ pdf_release_obj(contents);
pdf_release_obj(bbox);
- pdf_close();
+ pdf_close(pf);
return -1;
}
}
@@ -359,9 +416,12 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file)
tmp = pdf_import_object(resources);
pdf_release_obj(resources);
resources = tmp;
+ tmp = pdf_import_object(bbox);
+ pdf_release_obj(bbox);
+ bbox = tmp;
}
- pdf_close();
+ pdf_close(pf);
contents_dict = pdf_stream_dict(contents);
pdf_add_dict(contents_dict,
@@ -392,102 +452,3 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file)
return 0;
}
-
-#define WBUF_SIZE 4096
-#if HAVE_ZLIB
-static int
-add_stream_flate (pdf_obj *dst, const void *data, long len)
-{
- z_stream z;
- Bytef wbuf[WBUF_SIZE];
-
- z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL;
-
- z.next_in = (Bytef *) data; z.avail_in = len;
- z.next_out = (Bytef *) wbuf; z.avail_out = WBUF_SIZE;
-
- if (inflateInit(&z) != Z_OK) {
- WARN("inflateInit() failed.");
- return -1;
- }
-
- for (;;) {
- int status;
- status = inflate(&z, Z_NO_FLUSH);
- if (status == Z_STREAM_END)
- break;
- else if (status != Z_OK) {
- WARN("inflate() failed. Broken PDF file?");
- inflateEnd(&z);
- return -1;
- }
-
- if (z.avail_out == 0) {
- pdf_add_stream(dst, wbuf, WBUF_SIZE);
- z.next_out = wbuf;
- z.avail_out = WBUF_SIZE;
- }
- }
-
- if (WBUF_SIZE - z.avail_out > 0)
- pdf_add_stream(dst, wbuf, WBUF_SIZE - z.avail_out);
-
- return (inflateEnd(&z) == Z_OK ? 0 : -1);
-}
-#endif
-
-static int
-concat_stream (pdf_obj *dst, pdf_obj *src)
-{
- const char *stream_data;
- long stream_length;
- pdf_obj *stream_dict;
- pdf_obj *filter;
-
- if (!PDF_OBJ_STREAMTYPE(dst) || !PDF_OBJ_STREAMTYPE(src))
- ERROR("Invalid type.");
-
- stream_data = pdf_stream_dataptr(src);
- stream_length = pdf_stream_length (src);
- stream_dict = pdf_stream_dict (src);
-
- if (pdf_lookup_dict(stream_dict, "DecodeParms")) {
- WARN("DecodeParams not supported.");
- return -1;
- }
-
- filter = pdf_lookup_dict(stream_dict, "Filter");
- if (!filter) {
- pdf_add_stream(dst, stream_data, stream_length);
- return 0;
-#if HAVE_ZLIB
- } else {
- char *filter_name;
- if (PDF_OBJ_NAMETYPE(filter)) {
- filter_name = pdf_name_value(filter);
- if (filter_name && !strcmp(filter_name, "FlateDecode"))
- return add_stream_flate(dst, stream_data, stream_length);
- else {
- WARN("DecodeFilter \"%s\" not supported.", filter_name);
- return -1;
- }
- } else if (PDF_OBJ_ARRAYTYPE(filter)) {
- if (pdf_array_length(filter) > 1) {
- WARN("Multiple DecodeFilter not supported.");
- return -1;
- } else {
- filter_name = pdf_name_value(pdf_get_array(filter, 0));
- if (filter_name && !strcmp(filter_name, "FlateDecode"))
- return add_stream_flate(dst, stream_data, stream_length);
- else {
- WARN("DecodeFilter \"%s\" not supported.", filter_name);
- return -1;
- }
- }
- } else
- ERROR("Broken PDF file?");
-#endif /* HAVE_ZLIB */
- }
-
- return -1;
-}