diff options
Diffstat (limited to 'Build/source/texk/dvipdfmx/src/epdf.c')
-rw-r--r-- | Build/source/texk/dvipdfmx/src/epdf.c | 301 |
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; -} |