diff options
author | Peter Breitenlohner <peb@mppmu.mpg.de> | 2013-09-24 12:19:06 +0000 |
---|---|---|
committer | Peter Breitenlohner <peb@mppmu.mpg.de> | 2013-09-24 12:19:06 +0000 |
commit | b68e9d4dea7036d84321a93391c2f810766a41a0 (patch) | |
tree | 821235fdd65acf69ddee47af44a5dfd6889ce314 /Build | |
parent | 07ebfb83f578495e8f9e6826ca7a408470cf8b22 (diff) |
dvipdf-x: Bug fix for xdvipdfm-res.test (tikz-bug)
git-svn-id: svn://tug.org/texlive/trunk@31738 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build')
28 files changed, 1199 insertions, 864 deletions
diff --git a/Build/source/texk/dvipdf-x/ChangeLog b/Build/source/texk/dvipdf-x/ChangeLog index f563f6a471c..b652d9641bb 100644 --- a/Build/source/texk/dvipdf-x/ChangeLog +++ b/Build/source/texk/dvipdf-x/ChangeLog @@ -1,3 +1,13 @@ +2013-09-24 Peter Breitenlohner <peb@mppmu.mpg.de> + + * spc_xtx.c, xsrc/dpxutil.[ch], xsrc/dvipdfmx.c, xsrc/epdf.[ch], + mpost.c, xsrc/pdfcolor.[ch], xsrc/pdfdev.[ch], xsrc/pdfdoc.[ch], + xsrc/pdfdraw.[ch], xsrc/pdfnames.[ch], xsrc/pdfobj.[ch], + xsrc/pdfximage.[ch], xsrc/spc_pdfm.c, xsrc/specials.c: Adapt to + dvipdfmx files in src/ and fix xdvipdfm-res.test (tikz-bug). + + * tests/annot.{dvi,tex}: Test a broken link annotation. + 2013-09-23 Peter Breitenlohner <peb@mppmu.mpg.de> * src/pdfdoc.c, src/dvipdfmx.c, src/pdfencrypt.c: diff --git a/Build/source/texk/dvipdf-x/spc_xtx.c b/Build/source/texk/dvipdf-x/spc_xtx.c index cf4f668bc5c..ed0b667f8c2 100644 --- a/Build/source/texk/dvipdf-x/spc_xtx.c +++ b/Build/source/texk/dvipdf-x/spc_xtx.c @@ -164,7 +164,7 @@ spc_handler_xtx_grestore (struct spc_env *spe, struct spc_arg *args) * starting a new page. */ pdf_dev_reset_fonts(); - pdf_dev_reset_color(); + pdf_dev_reset_color(0); return 0; } diff --git a/Build/source/texk/dvipdf-x/tests/annot.dvi b/Build/source/texk/dvipdf-x/tests/annot.dvi Binary files differindex 7ea86daa1f5..0cea9bacc12 100644 --- a/Build/source/texk/dvipdf-x/tests/annot.dvi +++ b/Build/source/texk/dvipdf-x/tests/annot.dvi diff --git a/Build/source/texk/dvipdf-x/tests/annot.tex b/Build/source/texk/dvipdf-x/tests/annot.tex index c57f2ca5786..dd10e9fd223 100644 --- a/Build/source/texk/dvipdf-x/tests/annot.tex +++ b/Build/source/texk/dvipdf-x/tests/annot.tex @@ -1,9 +1,12 @@ % \special{pdf:obj @tug <</S/URI /URI (http://www.tug.org)>>} +Add some text and more text and still more text in order to get a link annotation +extending \special{pdf:bann <</Subtype/Link /A @tug>>}% TUG on the web -\special{pdf:eann}% +\special{pdf:eann} +over two lines. \vskip 20 bp diff --git a/Build/source/texk/dvipdf-x/tests/bookm.tex b/Build/source/texk/dvipdf-x/tests/bookm.tex index 72745154473..d42e12a51f4 100644 --- a/Build/source/texk/dvipdf-x/tests/bookm.tex +++ b/Build/source/texk/dvipdf-x/tests/bookm.tex @@ -57,4 +57,4 @@ \noindent The second section -\bye
\ No newline at end of file +\bye diff --git a/Build/source/texk/dvipdf-x/tests/resrc.tex b/Build/source/texk/dvipdf-x/tests/resrc.tex index d82af96a1b5..5c95c930e51 100644 --- a/Build/source/texk/dvipdf-x/tests/resrc.tex +++ b/Build/source/texk/dvipdf-x/tests/resrc.tex @@ -1,78 +1,6 @@ -% -\special{papersize=10cm,10cm} - -\special{pdf:obj @pgfcolorspaces <<>>} - -\special{pdf:obj @pgfpatterns <<>>} - -\special{pdf:put @resources - <</Pattern @pgfpatterns /Colorspace @pgfcolorspaces>>} - -\special{pdf:put @pgfcolorspaces - <</pgfprgb [/Pattern /DeviceRGB]>>} - -\special{pdf:put @pgfpatterns - <</pgfpat6 @pgf@paternobject@6>>} - -\special{pdf:stream @pgf@paternobject@6 (q 0.3985 w 3.08846 0.0 m Q) - <</Type/Pattern>>} - -\bye - -\special{pdf:out 1 - <</Title(Contents)/A<</S/GoTo/D(contents)>>>>} -\special{pdf:out 1 - <</Title(1 First section)/A<</S/GoTo/D(section.1)>>>>} -\special{pdf:out 2 - <</Title(1.1 First subsection)/A<</S/GoTo/D(subsection.1.1)>>>>} -\special{pdf:out 1 - <</Title(2 Second section)/A<</S/GoTo/D(section.2)>>>>} - -\noindent Contents -\special{pdf:dest (contents) [@thispage /XYZ @xpos @ypos null]} - -\vskip 5mm - -\hbox to 60mm{% -\special{pdf:bann<</Type/Annot/Subtype/Link/Border[0 0 0]/C[1 0 0] - /A<</S/GoTo/D(section.1)>>>>}1 First section\special{pdf:eann} -\hfill 2} - -\hbox to 60mm{\hskip 5mm% -\special{pdf:bann<</Type/Annot/Subtype/Link/Border[0 0 0]/C[1 0 0] - /A<</S/GoTo/D(subsection.1.1)>>>>}1.1 First subsection\special{pdf:eann} -\hfill 3} - -\hbox to 60mm{% -\special{pdf:bann<</Type/Annot/Subtype/Link/Border[0 0 0]/C[1 0 0] - /A<</S/GoTo/D(section.2)>>>>}2 Second section\special{pdf:eann} -\hfill 4} - -\vfill\break - -\noindent 1 First section -\special{pdf:dest (section.1) [@thispage /XYZ @xpos @ypos null]} - -\vskip 5mm - -\noindent The first section - -\vfill\break - -\noindent 1.1 First subsection -\special{pdf:dest (subsection.1.1) [@thispage /XYZ @xpos @ypos null]} - -\vskip 5mm - -\noindent The first subsection - -\vfill\break - -\noindent 2 Second section -\special{pdf:dest (section.2) [@thispage /XYZ @xpos @ypos null]} - -\vskip 5mm - -\noindent The second section - -\bye
\ No newline at end of file +\documentclass[dvipdfmx]{article} +\usepackage{tikz} +\usetikzlibrary{patterns} +\begin{document} +\tikz \path[pattern=crosshatch] (0,0) -- (1,0) -- (0,1) -- cycle; +\end{document} diff --git a/Build/source/texk/dvipdf-x/xsrc/dpxutil.c b/Build/source/texk/dvipdf-x/xsrc/dpxutil.c index 98ba7cde9d4..8f752f2dcab 100644 --- a/Build/source/texk/dvipdf-x/xsrc/dpxutil.c +++ b/Build/source/texk/dvipdf-x/xsrc/dpxutil.c @@ -204,6 +204,13 @@ ht_clear_table (struct ht_table *ht) ht->hval_free_fn = NULL; } +long ht_table_size (struct ht_table *ht) +{ + ASSERT(ht); + + return ht->count; +} + static unsigned int get_hash (const void *key, int keylen) { diff --git a/Build/source/texk/dvipdf-x/xsrc/dpxutil.h b/Build/source/texk/dvipdf-x/xsrc/dpxutil.h index f902bb1f2aa..bd8c338d056 100644 --- a/Build/source/texk/dvipdf-x/xsrc/dpxutil.h +++ b/Build/source/texk/dvipdf-x/xsrc/dpxutil.h @@ -77,6 +77,7 @@ struct ht_table { extern void ht_init_table (struct ht_table *ht, hval_free_func hval_free_fn); extern void ht_clear_table (struct ht_table *ht); +extern long ht_table_size (struct ht_table *ht); extern void *ht_lookup_table (struct ht_table *ht, const void *key, int keylen); extern void ht_append_table (struct ht_table *ht, diff --git a/Build/source/texk/dvipdf-x/xsrc/dvipdfmx.c b/Build/source/texk/dvipdf-x/xsrc/dvipdfmx.c index ca79fdf9c35..c31fad7170c 100644 --- a/Build/source/texk/dvipdf-x/xsrc/dvipdfmx.c +++ b/Build/source/texk/dvipdf-x/xsrc/dvipdfmx.c @@ -75,6 +75,7 @@ static long opt_flags = 0; #define OPT_TPIC_TRANSPARENT_FILL (1 << 1) #define OPT_CIDFONT_FIXEDPITCH (1 << 2) #define OPT_FONTMAP_FIRST_MATCH (1 << 3) +#define OPT_PDFDOC_NO_DEST_REMOVE (1 << 4) static char ignore_colors = 0; static double annot_grow = 0.0; @@ -948,7 +949,8 @@ main (int argc, char *argv[]) * bookmark_open: Miximal depth of open bookmarks. */ pdf_open_document(pdf_filename, do_encryption, - paper_width, paper_height, annot_grow, bookmark_open); + paper_width, paper_height, annot_grow, bookmark_open, + !(opt_flags & OPT_PDFDOC_NO_DEST_REMOVE)); /* Ignore_colors placed here since * they are considered as device's capacity. diff --git a/Build/source/texk/dvipdf-x/xsrc/epdf.c b/Build/source/texk/dvipdf-x/xsrc/epdf.c index 53c9fdf554c..ebee0d275fb 100644 --- a/Build/source/texk/dvipdf-x/xsrc/epdf.c +++ b/Build/source/texk/dvipdf-x/xsrc/epdf.c @@ -31,34 +31,38 @@ * TrimBox, BleedBox, ArtBox, Rotate ... */ -#if HAVE_CONFIG_H -#include "config.h" +#ifdef HAVE_CONFIG_H +#include <config.h> #endif #include "system.h" #include "mem.h" #include "mfileio.h" #include "error.h" +#include "dvipdfmx.h" #include "pdfobj.h" #include "pdfdev.h" +#include "pdfdoc.h" + +#ifdef XETEX #include "pdfdraw.h" #include "pdfparse.h" +#endif #include "pdfximage.h" -#include "pdfdoc.h" - #include "epdf.h" +#ifdef XETEX #if HAVE_ZLIB #include <zlib.h> 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 int rect_equal (pdf_obj *rect1, pdf_obj *rect2); +static int concat_stream (pdf_obj *dst, pdf_obj *src); + /* * From PDFReference15_v6.pdf (p.119 and p.834) * @@ -391,109 +395,167 @@ pdf_get_page_content (pdf_obj* page) return contents; } +#endif int -pdf_include_page (pdf_ximage *ximage, FILE *image_file) +pdf_include_page (pdf_ximage *ximage, FILE *image_file, const char *filename) { + pdf_file *pf; xform_info info; - pdf_obj *contents, *contents_dict; - pdf_obj *page_tree; - pdf_obj *matrix; - pdf_obj *bbox = NULL, *resources = NULL; + pdf_obj *contents = NULL, *catalog; + pdf_obj *page = NULL, *resources = NULL, *markinfo = NULL; long page_no; - pdf_file *pf; - char *ident = pdf_ximage_get_ident(ximage); - - pdf_ximage_init_form_info(&info); - pf = pdf_open(ident, image_file); + pf = pdf_open(filename, image_file); if (!pf) return -1; - + + if (pdf_file_get_version(pf) > pdf_get_version()) + goto too_recent; + + pdf_ximage_init_form_info(&info); + /* - * Get Page Tree. + * Get Page. */ page_no = pdf_ximage_get_page(ximage); if (page_no == 0) page_no = 1; - page_tree = pdf_get_page_obj(pf, page_no, &bbox, &resources); - if (page_tree == NULL) { - pdf_close(pf); - return -1; - } - - if (bbox != NULL) { - 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); + page = pdf_doc_get_page(pf, page_no, NULL, &info.bbox, &resources); + if(!page) + goto error_silent; + + catalog = pdf_file_get_catalog(pf); + markinfo = pdf_deref_obj(pdf_lookup_dict(catalog, "MarkInfo")); + if (markinfo) { + pdf_obj *tmp = pdf_deref_obj(pdf_lookup_dict(markinfo, "Marked")); + pdf_release_obj(markinfo); + if (!PDF_OBJ_BOOLEANTYPE(tmp)) { + if (tmp) + pdf_release_obj(tmp); + goto error; + } else if (pdf_boolean_value(tmp)) + WARN("File contains tagged PDF. Ignoring tags."); pdf_release_obj(tmp); } + contents = pdf_deref_obj(pdf_lookup_dict(page, "Contents")); + pdf_release_obj(page); + page = NULL; + /* * Handle page content stream. - * page_tree is now set to the correct page. */ - contents = pdf_get_page_content(page_tree); - pdf_release_obj(page_tree); - if (contents == NULL) { - pdf_close(pf); - return -1; + { + pdf_obj *content_new; + + if (!contents) { + /* + * Empty page + */ + content_new = pdf_new_stream(0); + /* TODO: better don't include anything if the page is empty */ + } else if (PDF_OBJ_STREAMTYPE(contents)) { + /* + * We must import the stream because its dictionary + * may contain indirect references. + */ + content_new = pdf_import_object(contents); + } else if (PDF_OBJ_ARRAYTYPE(contents)) { + /* + * Concatenate all content streams. + */ + int idx, len = pdf_array_length(contents); + content_new = pdf_new_stream(STREAM_COMPRESS); + for (idx = 0; idx < len; idx++) { + pdf_obj *content_seg = pdf_deref_obj(pdf_get_array(contents, idx)); + if (!PDF_OBJ_STREAMTYPE(content_seg) || + pdf_concat_stream(content_new, content_seg) < 0) { + pdf_release_obj(content_seg); + pdf_release_obj(content_new); + goto error; + } + pdf_release_obj(content_seg); + } + } else + goto error; + + if (contents) + pdf_release_obj(contents); + contents = content_new; } + /* + * Add entries to contents stream dictionary. + */ { - pdf_obj *tmp; - - tmp = pdf_import_object(resources); + pdf_obj *contents_dict, *bbox, *matrix; + + contents_dict = pdf_stream_dict(contents); + pdf_add_dict(contents_dict, + pdf_new_name("Type"), + pdf_new_name("XObject")); + pdf_add_dict(contents_dict, + pdf_new_name("Subtype"), + pdf_new_name("Form")); + pdf_add_dict(contents_dict, + pdf_new_name("FormType"), + pdf_new_number(1.0)); + + bbox = pdf_new_array(); + pdf_add_array(bbox, pdf_new_number(info.bbox.llx)); + pdf_add_array(bbox, pdf_new_number(info.bbox.lly)); + pdf_add_array(bbox, pdf_new_number(info.bbox.urx)); + pdf_add_array(bbox, pdf_new_number(info.bbox.ury)); + + pdf_add_dict(contents_dict, pdf_new_name("BBox"), bbox); + + matrix = pdf_new_array(); + pdf_add_array(matrix, pdf_new_number(1.0)); + pdf_add_array(matrix, pdf_new_number(0.0)); + pdf_add_array(matrix, pdf_new_number(0.0)); + pdf_add_array(matrix, pdf_new_number(1.0)); + pdf_add_array(matrix, pdf_new_number(0.0)); + pdf_add_array(matrix, pdf_new_number(0.0)); + + pdf_add_dict(contents_dict, pdf_new_name("Matrix"), matrix); + + pdf_add_dict(contents_dict, pdf_new_name("Resources"), + pdf_import_object(resources)); pdf_release_obj(resources); - resources = tmp; - tmp = pdf_import_object(bbox); - pdf_release_obj(bbox); - bbox = tmp; } pdf_close(pf); - contents_dict = pdf_stream_dict(contents); - pdf_add_dict(contents_dict, - pdf_new_name("Type"), - pdf_new_name("XObject")); - pdf_add_dict(contents_dict, - pdf_new_name("Subtype"), - pdf_new_name("Form")); - pdf_add_dict(contents_dict, - pdf_new_name("FormType"), - pdf_new_number(1.0)); - - pdf_add_dict(contents_dict, pdf_new_name("BBox"), bbox); + pdf_ximage_set_form(ximage, &info, contents); - matrix = pdf_new_array(); - pdf_add_array(matrix, pdf_new_number(1.0)); - pdf_add_array(matrix, pdf_new_number(0.0)); - pdf_add_array(matrix, pdf_new_number(0.0)); - pdf_add_array(matrix, pdf_new_number(1.0)); - pdf_add_array(matrix, pdf_new_number(0.0)); - pdf_add_array(matrix, pdf_new_number(0.0)); + return 0; - pdf_add_dict(contents_dict, pdf_new_name("Matrix"), matrix); + error: + WARN("Cannot parse document. Broken PDF file?"); + error_silent: + if (resources) + pdf_release_obj(resources); + if (markinfo) + pdf_release_obj(markinfo); + if (page) + pdf_release_obj(page); + if (contents) + pdf_release_obj(contents); - pdf_add_dict(contents_dict, pdf_new_name("Resources"), resources); + pdf_close(pf); - pdf_ximage_set_form(ximage, &info, contents); + return -1; - return 0; + too_recent: + pdf_close(pf); + WARN("PDF version of input file more recent than in output file."); + WARN("Use \"-V\" switch to change output PDF version."); + return -1; } +#ifdef XETEX typedef enum { OP_SETCOLOR = 1, OP_CLOSEandCLIP = 2, @@ -904,3 +966,4 @@ concat_stream (pdf_obj *dst, pdf_obj *src) return -1; } +#endif diff --git a/Build/source/texk/dvipdf-x/xsrc/epdf.h b/Build/source/texk/dvipdf-x/xsrc/epdf.h index 698b5140b8e..2740bfc3cd3 100644 --- a/Build/source/texk/dvipdf-x/xsrc/epdf.h +++ b/Build/source/texk/dvipdf-x/xsrc/epdf.h @@ -2,7 +2,7 @@ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - Copyright (C) 2002-2012 by Jin-Hwan Cho and Shunsaku Hirata, + Copyright (C) 2002-2013 by Jin-Hwan Cho and Shunsaku Hirata, the dvipdfmx project team. Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu> @@ -35,7 +35,8 @@ #define pdfbox_art 5 extern int pdf_copy_clip (FILE *image_file, int page_index, double x_user, double y_user); -//extern int pdf_include_page (pdf_ximage *ximage, FILE *file, int page_index, int pdf_box); -extern int pdf_include_page (pdf_ximage *ximage, FILE *file); + +extern int pdf_include_page (pdf_ximage *ximage, FILE *file, + const char *filename); #endif /* _EPDF_H_ */ diff --git a/Build/source/texk/dvipdf-x/xsrc/mpost.c b/Build/source/texk/dvipdf-x/xsrc/mpost.c index dc56d7f4f47..2d610d1f158 100644 --- a/Build/source/texk/dvipdf-x/xsrc/mpost.c +++ b/Build/source/texk/dvipdf-x/xsrc/mpost.c @@ -1213,7 +1213,8 @@ do_operator (const char *token, double x_user, double y_user) pdf_color_cmykcolor(&color, values[0], values[1], values[2], values[3]); - pdf_dev_set_color(&color); + pdf_dev_set_strokingcolor(&color); + pdf_dev_set_nonstrokingcolor(&color); } break; case SETGRAY: @@ -1221,7 +1222,8 @@ do_operator (const char *token, double x_user, double y_user) error = pop_get_numbers(values, 1); if (!error) { pdf_color_graycolor(&color, values[0]); - pdf_dev_set_color(&color); + pdf_dev_set_strokingcolor(&color); + pdf_dev_set_nonstrokingcolor(&color); } break; case SETRGBCOLOR: @@ -1229,7 +1231,8 @@ do_operator (const char *token, double x_user, double y_user) if (!error) { pdf_color_rgbcolor(&color, values[0], values[1], values[2]); - pdf_dev_set_color(&color); + pdf_dev_set_strokingcolor(&color); + pdf_dev_set_nonstrokingcolor(&color); } break; diff --git a/Build/source/texk/dvipdf-x/xsrc/pdfcolor.c b/Build/source/texk/dvipdf-x/xsrc/pdfcolor.c index 77c9c499ea5..559a4b97712 100644 --- a/Build/source/texk/dvipdf-x/xsrc/pdfcolor.c +++ b/Build/source/texk/dvipdf-x/xsrc/pdfcolor.c @@ -26,7 +26,7 @@ */ #ifdef HAVE_CONFIG_H -#include "config.h" +#include <config.h> #endif #include "system.h" @@ -36,7 +36,7 @@ #include "dpxfile.h" #include "pdfdoc.h" -#include "pdfdev.h" +#include "pdfdraw.h" #include "pdfcolor.h" @@ -48,6 +48,17 @@ pdf_color_set_verbose (void) verbose++; } +/* This function returns PDF_COLORSPACE_TYPE_GRAY, + * PDF_COLORSPACE_TYPE_RGB or PDF_COLORSPACE_TYPE_CMYK. + */ +int +pdf_color_type (const pdf_color *color) +{ + ASSERT(color); + + return -color->num_components; +} + int pdf_color_rgbcolor (pdf_color *color, double r, double g, double b) { @@ -133,39 +144,54 @@ pdf_color_copycolor (pdf_color *color1, const pdf_color *color2) memcpy(color1, color2, sizeof(pdf_color)); } +/* Brighten up a color. f == 0 means no change, f == 1 means white. */ +void +pdf_color_brighten_color (pdf_color *dst, const pdf_color *src, double f) +{ + ASSERT(dst && src); + + if (f == 1.0) { + pdf_color_white(dst); + } else { + double f0, f1; + int n; + + n = dst->num_components = src->num_components; + f1 = n == 4 ? 0.0 : f; /* n == 4 is CMYK, others are RGB and Gray */ + f0 = 1.0-f; + + while (n--) + dst->values[n] = f0 * src->values[n] + f1; + } +} + int -pdf_color_is_white (pdf_color *color) +pdf_color_is_white (const pdf_color *color) { - int is_white = 0; + int n; + double f; ASSERT(color); - switch (color->num_components) { - case 1: - if (color->values[0] == 1.0) - is_white = 1; - break; - case 4: - if (color->values[0] == 0.0 && - color->values[1] == 0.0 && - color->values[2] == 0.0 && - color->values[3] == 0.0) { - is_white = 1; - } - break; - case 3: - if (color->values[0] == 1.0 && - color->values[1] == 1.0 && - color->values[2] == 1.0) { - is_white = 1; - } - break; - default: - is_white = 0; - break; - } + n = color->num_components; + f = n == 4 ? 0.0 : 1.0; /* n == 4 is CMYK, others are RGB and Gray */ + + while (n--) + if (color->values[n] != f) + return 0; + + return 1; +} - return is_white; +int +pdf_color_to_string (const pdf_color *color, char *buffer) +{ + int i, len = 0; + + for (i = 0; i < color->num_components; i++) { + len += sprintf(buffer+len, " %g", ROUND(color->values[i], 0.001)); + } + return len; } pdf_color current_fill = { @@ -178,42 +204,26 @@ pdf_color current_stroke = { {0.0, 0.0, 0.0, 0.0} }; -#if 0 /* * This routine is not a real color matching. */ -static int -compare_color (const pdf_color *color1, const pdf_color *color2) +int +pdf_color_compare (const pdf_color *color1, const pdf_color *color2) { - if (color1->num_components != color2->num_components) + int n = color1->num_components; + + if (n != color2->num_components) return -1; - switch (color1->num_components) { - case 4: - if (color1->values[0] == color2->values[0] && - color1->values[1] == color2->values[1] && - color1->values[2] == color2->values[2] && - color1->values[3] == color2->values[3]) - return 0; - break; - case 3: - if (color1->values[0] == color2->values[0] && - color1->values[1] == color2->values[1] && - color1->values[2] == color2->values[2]) - return 0; - break; - case 1: - if (color1->values[0] == color2->values[0]) - return 0; - break; - } + while (n--) + if (color1->values[n] != color2->values[n]) + return -1; - return -1; + return 0; } -#endif int -pdf_color_is_valid (pdf_color *color) +pdf_color_is_valid (const pdf_color *color) { int i, num_components; @@ -277,7 +287,7 @@ pdf_color_push (pdf_color *sc, pdf_color *fc) color_stack.current++; pdf_color_copycolor(&color_stack.stroke[color_stack.current], sc); pdf_color_copycolor(&color_stack.fill[color_stack.current], fc); - pdf_dev_reset_color(); + pdf_dev_reset_color(0); } return; } @@ -289,7 +299,7 @@ pdf_color_pop (void) WARN("Color stack underflow. Just ignore."); } else { color_stack.current--; - pdf_dev_reset_color(); + pdf_dev_reset_color(0); } return; } diff --git a/Build/source/texk/dvipdf-x/xsrc/pdfcolor.h b/Build/source/texk/dvipdf-x/xsrc/pdfcolor.h index 1d5e0f19116..e5edabd09c6 100644 --- a/Build/source/texk/dvipdf-x/xsrc/pdfcolor.h +++ b/Build/source/texk/dvipdf-x/xsrc/pdfcolor.h @@ -51,15 +51,24 @@ typedef struct extern void pdf_color_set_verbose (void); +extern int pdf_color_type (const pdf_color *color); extern int pdf_color_rgbcolor (pdf_color *color, double r, double g, double b); extern int pdf_color_cmykcolor (pdf_color *color, double c, double m, double y, double k); extern int pdf_color_graycolor (pdf_color *color, double g); +#define pdf_color_black(c) pdf_color_graycolor(c, 0.0); +#define pdf_color_white(c) pdf_color_graycolor(c, 1.0); + extern void pdf_color_copycolor (pdf_color *color1, const pdf_color *color2); +extern void pdf_color_brighten_color (pdf_color *dst, const pdf_color *src, double f); + +extern int pdf_color_compare (const pdf_color *color1, const pdf_color *color2); + +extern int pdf_color_is_white (const pdf_color *color); +extern int pdf_color_is_valid (const pdf_color *color); -extern int pdf_color_is_white (pdf_color *color); -extern int pdf_color_is_valid (pdf_color *color); +extern int pdf_color_to_string (const pdf_color *color, char *buffer); /* Not check size */ extern pdf_obj *iccp_get_rendering_intent (const void *profile, long proflen); diff --git a/Build/source/texk/dvipdf-x/xsrc/pdfdev.c b/Build/source/texk/dvipdf-x/xsrc/pdfdev.c index 41e6630c26e..441c959bcfa 100644 --- a/Build/source/texk/dvipdf-x/xsrc/pdfdev.c +++ b/Build/source/texk/dvipdf-x/xsrc/pdfdev.c @@ -1268,148 +1268,6 @@ pdf_dev_reset_fonts (void) text_state.is_mb = 0; } -void -pdf_dev_reset_color(void) -{ - pdf_color *sc, *fc; - - if (pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE)) { - pdf_color_get_current(&sc, &fc); - pdf_dev_set_strokingcolor(sc); - pdf_dev_set_nonstrokingcolor(fc); - } - return; -} - -static int -color_to_string (pdf_color *color, char *buffer) -{ - int i, len = 0; - - for (i = 0; i < color->num_components; i++) { - len += sprintf(format_buffer+len, " %g", ROUND(color->values[i], 0.001)); - } - return len; -} - -void -pdf_dev_set_color (pdf_color *color) -{ - int len; - - if (!pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE)) { - WARN("Ignore color option was set. Just ignore."); - return; - } else if (!(color && pdf_color_is_valid(color))) { - WARN("No valid color is specified. Just ignore."); - return; - } - - graphics_mode(); - len = color_to_string(color, format_buffer); - format_buffer[len++] = ' '; - switch (color->num_components) { - case 3: - format_buffer[len++] = 'R'; - format_buffer[len++] = 'G'; - break; - case 4: - format_buffer[len++] = 'K'; - break; - case 1: - format_buffer[len++] = 'G'; - break; - default: /* already verified the given color */ - break; - } - strncpy(format_buffer+len, format_buffer, len); - len = len << 1; - switch (color->num_components) { - case 3: - format_buffer[len-2] = 'r'; - format_buffer[len-1] = 'g'; - break; - case 4: - format_buffer[len-1] = 'k'; - break; - case 1: - format_buffer[len-1] = 'g'; - break; - default: /* already verified the given color */ - break; - } - pdf_doc_add_page_content(format_buffer, len); - return; -} - -void -pdf_dev_set_strokingcolor (pdf_color *color) -{ - int len; - - if (!pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE)) { - WARN("Ignore color option was set. Just ignore."); - return; - } else if (!(color && pdf_color_is_valid(color))) { - WARN("No valid color is specified. Just ignore."); - return; - } - - graphics_mode(); - len = color_to_string(color, format_buffer); - format_buffer[len++] = ' '; - switch (color->num_components) { - case 3: - format_buffer[len++] = 'R'; - format_buffer[len++] = 'G'; - break; - case 4: - format_buffer[len++] = 'K'; - break; - case 1: - format_buffer[len++] = 'G'; - break; - default: /* already verified the given color */ - break; - } - pdf_doc_add_page_content(format_buffer, len); - return; -} - -void -pdf_dev_set_nonstrokingcolor (pdf_color *color) -{ - int len; - - if (!pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE)) { - WARN("Ignore color option was set. Just ignore."); - return; - } else if (!(color && pdf_color_is_valid(color))) { - WARN("No valid color is specified. Just ignore."); - return; - } - - graphics_mode(); - len = color_to_string(color, format_buffer); - format_buffer[len++] = ' '; - switch (color->num_components) { - case 3: - format_buffer[len++] = 'r'; - format_buffer[len++] = 'g'; - break; - case 4: - format_buffer[len++] = 'k'; - break; - case 1: - format_buffer[len++] = 'g'; - break; - default: /* already verified the given color */ - break; - } - pdf_doc_add_page_content(format_buffer, len); - return; -} - /* Not working */ void pdf_dev_set_origin (double phys_x, double phys_y) @@ -1436,7 +1294,7 @@ pdf_dev_bop (const pdf_tmatrix *M) pdf_dev_concat(M); pdf_dev_reset_fonts(); - pdf_dev_reset_color(); + pdf_dev_reset_color(0); } void diff --git a/Build/source/texk/dvipdf-x/xsrc/pdfdev.h b/Build/source/texk/dvipdf-x/xsrc/pdfdev.h index 25bac2ecd47..20201309431 100644 --- a/Build/source/texk/dvipdf-x/xsrc/pdfdev.h +++ b/Build/source/texk/dvipdf-x/xsrc/pdfdev.h @@ -202,15 +202,10 @@ extern void pdf_dev_set_param (int param_type, int value); * For pdf_doc, pdf_draw and others. */ -/* Force reselecting font and color: +/* Force reselecting font: * XFrom (content grabbing) and Metapost support want them. */ extern void pdf_dev_reset_fonts (void); -extern void pdf_dev_reset_color (void); - -extern void pdf_dev_set_color (pdf_color *color); -extern void pdf_dev_set_strokingcolor (pdf_color *color); -extern void pdf_dev_set_nonstrokingcolor (pdf_color *color); /* Initialization of transformation matrix with M and others. * They are called within pdf_doc_begin_page() and pdf_doc_end_page(). diff --git a/Build/source/texk/dvipdf-x/xsrc/pdfdoc.c b/Build/source/texk/dvipdf-x/xsrc/pdfdoc.c index 05846ff9300..ca9aa40be42 100644 --- a/Build/source/texk/dvipdf-x/xsrc/pdfdoc.c +++ b/Build/source/texk/dvipdf-x/xsrc/pdfdoc.c @@ -26,8 +26,9 @@ * TODO: Many things... * {begin,end}_{bead,article}, box stack, name tree (not limited to dests)... */ -#if HAVE_CONFIG_H -#include "config.h" + +#ifdef HAVE_CONFIG_H +#include <config.h> #endif #include <time.h> @@ -235,6 +236,9 @@ typedef struct pdf_doc struct name_dict *names; + int check_gotos; + struct ht_table gotos; + struct { int outline_open_depth; double annot_grow; @@ -367,9 +371,11 @@ doc_get_page_entry (pdf_doc *p, unsigned long page_no) static void pdf_doc_init_page_tree (pdf_doc *p, double media_width, double media_height); static void pdf_doc_close_page_tree (pdf_doc *p); -static void pdf_doc_init_names (pdf_doc *p); +static void pdf_doc_init_names (pdf_doc *p, int check_gotos); static void pdf_doc_close_names (pdf_doc *p); +static void pdf_doc_add_goto (pdf_obj *annot_dict); + static void pdf_doc_init_docinfo (pdf_doc *p); static void pdf_doc_close_docinfo (pdf_doc *p); @@ -525,8 +531,8 @@ pdf_doc_close_docinfo (pdf_doc *p) } } - banner = NEW(strlen("xdvipdfmx")+strlen(VERSION)+4, char); - sprintf(banner, "%s (%s)", "xdvipdfmx", VERSION); + banner = NEW(strlen("dvipdfmx")+strlen(VERSION)+4, char); + sprintf(banner, "%s (%s)", "dvipdfmx", VERSION); pdf_add_dict(docinfo, pdf_new_name("Producer"), pdf_new_string(banner, strlen(banner))); @@ -871,6 +877,242 @@ pdf_doc_close_page_tree (pdf_doc *p) return; } +/* + * From PDFReference15_v6.pdf (p.119 and p.834) + * + * MediaBox rectangle (Required; inheritable) + * + * The media box defines the boundaries of the physical medium on which the + * page is to be printed. It may include any extended area surrounding the + * finished page for bleed, printing marks, or other such purposes. It may + * also include areas close to the edges of the medium that cannot be marked + * because of physical limitations of the output device. Content falling + * outside this boundary can safely be discarded without affecting the + * meaning of the PDF file. + * + * CropBox rectangle (Optional; inheritable) + * + * The crop box defines the region to which the contents of the page are to be + * clipped (cropped) when displayed or printed. Unlike the other boxes, the + * crop box has no defined meaning in terms of physical page geometry or + * intended use; it merely imposes clipping on the page contents. However, + * in the absence of additional information (such as imposition instructions + * specified in a JDF or PJTF job ticket), the crop box will determine how + * the page's contents are to be positioned on the output medium. The default + * value is the page's media box. + * + * BleedBox rectangle (Optional; PDF 1.3) + * + * The bleed box (PDF 1.3) defines the region to which the contents of the + * page should be clipped when output in a production environment. This may + * include any extra "bleed area" needed to accommodate the physical + * limitations of cutting, folding, and trimming equipment. The actual printed + * page may include printing marks that fall outside the bleed box. + * The default value is the page's crop box. + * + * TrimBox rectangle (Optional; PDF 1.3) + * + * The trim box (PDF 1.3) defines the intended dimensions of the finished page + * after trimming. It may be smaller than the media box, to allow for + * production-related content such as printing instructions, cut marks, or + * color bars. The default value is the page's crop box. + * + * ArtBox rectangle (Optional; PDF 1.3) + * + * The art box (PDF 1.3) defines the extent of the page's meaningful content + * (including potential white space) as intended by the page's creator. + * The default value is the page's crop box. + * + * Rotate integer (Optional; inheritable) + * + * The number of degrees by which the page should be rotated clockwise when + * displayed or printed. The value must be a multiple of 90. Default value: 0. + */ + +pdf_obj * +pdf_doc_get_page (pdf_file *pf, long page_no, long *count_p, + pdf_rect *bbox, pdf_obj **resources_p) { + pdf_obj *page_tree = NULL; + pdf_obj *resources = NULL, *box = NULL, *rotate = NULL; + pdf_obj *catalog; + + catalog = pdf_file_get_catalog(pf); + + page_tree = pdf_deref_obj(pdf_lookup_dict(catalog, "Pages")); + + if (!PDF_OBJ_DICTTYPE(page_tree)) + goto error; + + { + long count; + pdf_obj *tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Count")); + if (!PDF_OBJ_NUMBERTYPE(tmp)) { + if (tmp) + pdf_release_obj(tmp); + goto error; + } + count = pdf_number_value(tmp); + pdf_release_obj(tmp); + if (count_p) + *count_p = count; + if (page_no <= 0 || page_no > count) { + WARN("Page %ld does not exist.", page_no); + goto error_silent; + } + } + + /* + * Seek correct page. Get MediaBox, CropBox and Resources. + * (Note that these entries can be inherited.) + */ + { + pdf_obj *media_box = NULL, *crop_box = NULL, *kids, *tmp; + int depth = PDF_OBJ_MAX_DEPTH; + long page_idx = page_no-1, kids_length = 1, i = 0; + + while (--depth && i != kids_length) { + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "MediaBox")))) { + if (media_box) + pdf_release_obj(media_box); + media_box = tmp; + } + + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "CropBox")))) { + if (crop_box) + pdf_release_obj(crop_box); + crop_box = tmp; + } + + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Rotate")))) { + if (rotate) + pdf_release_obj(rotate); + rotate = tmp; + } + + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Resources")))) { + if (resources) + pdf_release_obj(resources); + resources = tmp; + } + + kids = pdf_deref_obj(pdf_lookup_dict(page_tree, "Kids")); + if (!kids) + break; + else if (!PDF_OBJ_ARRAYTYPE(kids)) { + pdf_release_obj(kids); + goto error; + } + 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)); + if (!PDF_OBJ_DICTTYPE(page_tree)) + goto error; + + tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Count")); + if (PDF_OBJ_NUMBERTYPE(tmp)) { + /* Pages object */ + count = pdf_number_value(tmp); + pdf_release_obj(tmp); + } else if (!tmp) + /* Page object */ + count = 1; + else { + pdf_release_obj(tmp); + goto error; + } + + if (page_idx < count) + break; + + page_idx -= count; + } + + pdf_release_obj(kids); + } + + if (!depth || kids_length == i) { + if (media_box) + pdf_release_obj(media_box); + if (crop_box) + pdf_release_obj(crop_box); + goto error; + } + + if (crop_box) + box = crop_box; + else + if (!(box = pdf_deref_obj(pdf_lookup_dict(page_tree, "ArtBox"))) && + !(box = pdf_deref_obj(pdf_lookup_dict(page_tree, "TrimBox"))) && + !(box = pdf_deref_obj(pdf_lookup_dict(page_tree, "BleedBox"))) && + media_box) { + box = media_box; + media_box = NULL; + } + if (media_box) + pdf_release_obj(media_box); + } + + if (!PDF_OBJ_ARRAYTYPE(box) || pdf_array_length(box) != 4 || + !PDF_OBJ_DICTTYPE(resources)) + goto error; + + if (PDF_OBJ_NUMBERTYPE(rotate)) { + if (pdf_number_value(rotate)) + WARN("<< /Rotate %d >> found. (Not supported yet)", + (int) pdf_number_value(rotate)); + pdf_release_obj(rotate); + rotate = NULL; + } else if (rotate) + goto error; + + { + int i; + + for (i = 4; i--; ) { + double x; + pdf_obj *tmp = pdf_deref_obj(pdf_get_array(box, i)); + if (!PDF_OBJ_NUMBERTYPE(tmp)) { + pdf_release_obj(tmp); + goto error; + } + x = pdf_number_value(tmp); + switch (i) { + case 0: bbox->llx = x; break; + case 1: bbox->lly = x; break; + case 2: bbox->urx = x; break; + case 3: bbox->ury = x; break; + } + pdf_release_obj(tmp); + } + } + + pdf_release_obj(box); + + if (resources_p) + *resources_p = resources; + else if (resources) + pdf_release_obj(resources); + + return page_tree; + + error: + WARN("Cannot parse document. Broken PDF file?"); + error_silent: + if (box) + pdf_release_obj(box); + if (rotate) + pdf_release_obj(rotate); + if (resources) + pdf_release_obj(resources); + if (page_tree) + pdf_release_obj(page_tree); + + return NULL; +} #ifndef BOOKMARKS_OPEN_DEFAULT #define BOOKMARKS_OPEN_DEFAULT 0 @@ -1118,6 +1360,8 @@ pdf_doc_bookmarks_add (pdf_obj *dict, int is_open) p->outlines.current = item; + pdf_doc_add_goto(dict); + return; } @@ -1160,7 +1404,7 @@ static const char *name_dict_categories[] = { #define NUM_NAME_CATEGORY (sizeof(name_dict_categories)/sizeof(name_dict_categories[0])) static void -pdf_doc_init_names (pdf_doc *p) +pdf_doc_init_names (pdf_doc *p, int check_gotos) { int i; @@ -1169,11 +1413,19 @@ pdf_doc_init_names (pdf_doc *p) p->names = NEW(NUM_NAME_CATEGORY + 1, struct name_dict); for (i = 0; i < NUM_NAME_CATEGORY; i++) { p->names[i].category = name_dict_categories[i]; - p->names[i].data = NULL; + p->names[i].data = strcmp(name_dict_categories[i], "Dests") ? + NULL : pdf_new_name_tree(); + /* + * We need a non-null entry for PDF destinations in order to find + * broken links even if no destination is defined in the DVI file. + */ } p->names[NUM_NAME_CATEGORY].category = NULL; p->names[NUM_NAME_CATEGORY].data = NULL; + p->check_gotos = check_gotos; + ht_init_table(&p->gotos, (void (*) (void *)) pdf_release_obj); + return; } @@ -1201,6 +1453,134 @@ pdf_doc_add_names (const char *category, } static void +pdf_doc_add_goto (pdf_obj *annot_dict) +{ + pdf_obj *subtype = NULL, *A = NULL, *S = NULL, *D = NULL, *D_new, *dict; + const char *dest, *key; + + if (!pdoc.check_gotos) + return; + + /* + * An annotation dictionary coming from an annotation special + * must have a "Subtype". An annotation dictionary coming from + * an outline special has none. + */ + subtype = pdf_deref_obj(pdf_lookup_dict(annot_dict, "Subtype")); + if (subtype) { + if (PDF_OBJ_UNDEFINED(subtype)) + goto undefined; + else if (!PDF_OBJ_NAMETYPE(subtype)) + goto error; + else if (strcmp(pdf_name_value(subtype), "Link")) + goto cleanup; + } + + dict = annot_dict; + key = "Dest"; + D = pdf_deref_obj(pdf_lookup_dict(annot_dict, key)); + if (PDF_OBJ_UNDEFINED(D)) + goto undefined; + + A = pdf_deref_obj(pdf_lookup_dict(annot_dict, "A")); + if (A) { + if (PDF_OBJ_UNDEFINED(A)) + goto undefined; + else if (D || !PDF_OBJ_DICTTYPE(A)) + goto error; + else { + S = pdf_deref_obj(pdf_lookup_dict(A, "S")); + if (PDF_OBJ_UNDEFINED(S)) + goto undefined; + else if (!PDF_OBJ_NAMETYPE(S)) + goto error; + else if (strcmp(pdf_name_value(S), "GoTo")) + goto cleanup; + + dict = A; + key = "D"; + D = pdf_deref_obj(pdf_lookup_dict(A, key)); + } + } + + if (PDF_OBJ_STRINGTYPE(D)) + dest = (char *) pdf_string_value(D); +#if 0 + /* Names as destinations are not supported by dvipdfmx */ + else if (PDF_OBJ_NAMETYPE(D)) + dest = pdf_name_value(D); +#endif + else if (PDF_OBJ_ARRAYTYPE(D)) + goto cleanup; + else if (PDF_OBJ_UNDEFINED(D)) + goto undefined; + else + goto error; + + D_new = ht_lookup_table(&pdoc.gotos, dest, strlen(dest)); + if (!D_new) { + char buf[10]; + + /* We use hexadecimal notation for our numeric destinations. + * Other bases (e.g., 10+26 or 10+2*26) would be more efficient. + */ + sprintf(buf, "%lx", ht_table_size(&pdoc.gotos)); + D_new = pdf_new_string(buf, strlen(buf)); + ht_append_table(&pdoc.gotos, dest, strlen(dest), D_new); + } + + { + pdf_obj *key_obj = pdf_new_name(key); + if (!pdf_add_dict(dict, key_obj, pdf_link_obj(D_new))) + pdf_release_obj(key_obj); + } + + cleanup: + if (subtype) + pdf_release_obj(subtype); + if (A) + pdf_release_obj(A); + if (S) + pdf_release_obj(S); + if (D) + pdf_release_obj(D); + + return; + + error: + WARN("Unknown PDF annotation format. Output file may be broken."); + goto cleanup; + + undefined: + WARN("Cannot optimize PDF annotations. Output file may be broken." + " Please restart with option \"-C 0x10\"\n"); + goto cleanup; +} + +static void +warn_undef_dests (struct ht_table *dests, struct ht_table *gotos) +{ + struct ht_iter iter; + + if (ht_set_iter(gotos, &iter) < 0) + return; + + do { + int keylen; + char *key = ht_iter_getkey(&iter, &keylen); + if (!ht_lookup_table(dests, key, keylen)) { + char *dest = NEW(keylen+1, char); + memcpy(dest, key, keylen); + dest[keylen] = 0; + WARN("PDF destination \"%s\" not defined.", dest); + RELEASE(dest); + } + } while (ht_iter_next(&iter) >= 0); + + ht_clear_iter(&iter); +} + +static void pdf_doc_close_names (pdf_doc *p) { pdf_obj *tmp; @@ -1208,15 +1588,30 @@ pdf_doc_close_names (pdf_doc *p) for (i = 0; p->names[i].category != NULL; i++) { if (p->names[i].data) { + struct ht_table *data = p->names[i].data; pdf_obj *name_tree; + long count; + + if (!pdoc.check_gotos || strcmp(p->names[i].category, "Dests")) + name_tree = pdf_names_create_tree(data, &count, NULL); + else { + name_tree = pdf_names_create_tree(data, &count, &pdoc.gotos); + + if (verbose && count < data->count) + MESG("\nRemoved %ld unused PDF destinations\n", data->count-count); + + if (count < pdoc.gotos.count) + warn_undef_dests(data, &pdoc.gotos); + } - name_tree = pdf_names_create_tree(p->names[i].data); - if (!p->root.names) { - p->root.names = pdf_new_dict(); + if (name_tree) { + if (!p->root.names) + p->root.names = pdf_new_dict(); + pdf_add_dict(p->root.names, + pdf_new_name(p->names[i].category), + pdf_ref_obj(name_tree)); + pdf_release_obj(name_tree); } - pdf_add_dict(p->root.names, - pdf_new_name(p->names[i].category), pdf_ref_obj(name_tree)); - pdf_release_obj(name_tree); pdf_delete_name_tree(&p->names[i].data); } } @@ -1243,54 +1638,58 @@ pdf_doc_close_names (pdf_doc *p) RELEASE(p->names); p->names = NULL; + ht_clear_table(&p->gotos); + return; } void -pdf_doc_add_annot (unsigned page_no, const pdf_rect *rect, pdf_obj *annot_dict) +pdf_doc_add_annot (unsigned page_no, const pdf_rect *rect, + pdf_obj *annot_dict, int new_annot) { pdf_doc *p = &pdoc; pdf_page *page; pdf_obj *rect_array; double annot_grow = p->opt.annot_grow; + double xpos, ypos; + pdf_rect mediabox, annbox; page = doc_get_page_entry(p, page_no); if (!page->annots) page->annots = pdf_new_array(); -#if 1 - { - pdf_rect mediabox; - - pdf_doc_get_mediabox(page_no, &mediabox); - if (rect->llx < mediabox.llx || - rect->urx > mediabox.urx || - rect->lly < mediabox.lly || - rect->ury > mediabox.ury) { - WARN("Annotation out of page boundary."); - WARN("Current page's MediaBox: [%g %g %g %g]", - mediabox.llx, mediabox.lly, mediabox.urx, mediabox.ury); - WARN("Annotation: [%g %g %g %g]", - rect->llx, rect->lly, rect->urx, rect->ury); - WARN("Maybe incorrect paper size specified."); - } - if (rect->llx > rect->urx || rect->lly > rect->ury) { - WARN("Rectangle with negative width/height: [%g %g %g %g]", - rect->llx, rect->lly, rect->urx, rect->ury); - } + pdf_doc_get_mediabox(page_no, &mediabox); + pdf_dev_get_coord(&xpos, &ypos); + annbox.llx = rect->llx - xpos; annbox.lly = rect->lly - ypos; + annbox.urx = rect->urx - xpos; annbox.ury = rect->ury - ypos; + + if (annbox.llx < mediabox.llx || annbox.urx > mediabox.urx || + annbox.lly < mediabox.lly || annbox.ury > mediabox.ury) { + WARN("Annotation out of page boundary."); + WARN("Current page's MediaBox: [%g %g %g %g]", + mediabox.llx, mediabox.lly, mediabox.urx, mediabox.ury); + WARN("Annotation: [%g %g %g %g]", + annbox.llx, annbox.lly, annbox.urx, annbox.ury); + WARN("Maybe incorrect paper size specified."); + } + if (annbox.llx > annbox.urx || annbox.lly > annbox.ury) { + WARN("Rectangle with negative width/height: [%g %g %g %g]", + annbox.llx, annbox.lly, annbox.urx, annbox.ury); } -#endif rect_array = pdf_new_array(); - pdf_add_array(rect_array, pdf_new_number(ROUND(rect->llx - annot_grow, 0.001))); - pdf_add_array(rect_array, pdf_new_number(ROUND(rect->lly - annot_grow, 0.001))); - pdf_add_array(rect_array, pdf_new_number(ROUND(rect->urx + annot_grow, 0.001))); - pdf_add_array(rect_array, pdf_new_number(ROUND(rect->ury + annot_grow, 0.001))); + pdf_add_array(rect_array, pdf_new_number(ROUND(annbox.llx - annot_grow, 0.001))); + pdf_add_array(rect_array, pdf_new_number(ROUND(annbox.lly - annot_grow, 0.001))); + pdf_add_array(rect_array, pdf_new_number(ROUND(annbox.urx + annot_grow, 0.001))); + pdf_add_array(rect_array, pdf_new_number(ROUND(annbox.ury + annot_grow, 0.001))); pdf_add_dict (annot_dict, pdf_new_name("Rect"), rect_array); pdf_add_array(page->annots, pdf_ref_obj(annot_dict)); + if (new_annot) + pdf_doc_add_goto(annot_dict); + return; } @@ -1874,14 +2273,15 @@ pdf_doc_finish_page (pdf_doc *p) } -static pdf_color bgcolor = { 1, { 1.0 } }; +static pdf_color bgcolor; + void pdf_doc_set_bgcolor (const pdf_color *color) { if (color) - memcpy(&bgcolor, color, sizeof(pdf_color)); + pdf_color_copycolor(&bgcolor, color); else { /* as clear... */ - pdf_color_graycolor(&bgcolor, 1.0); + pdf_color_white(&bgcolor); } } @@ -1910,10 +2310,8 @@ doc_fill_page_background (pdf_doc *p) currentpage->contents = currentpage->background; pdf_dev_gsave(); - //pdf_color_push(); pdf_dev_set_nonstrokingcolor(&bgcolor); pdf_dev_rectfill(r.llx, r.lly, r.urx - r.llx, r.ury - r.lly); - //pdf_color_pop(); pdf_dev_grestore(); currentpage->contents = saved_content; @@ -1974,7 +2372,8 @@ void pdf_open_document (const char *filename, int do_encryption, double media_width, double media_height, - double annot_grow_amount, int bookmark_open_depth) + double annot_grow_amount, int bookmark_open_depth, + int check_gotos) { pdf_doc *p = &pdoc; @@ -2001,14 +2400,17 @@ pdf_open_document (const char *filename, pdf_doc_init_bookmarks(p, bookmark_open_depth); pdf_doc_init_articles (p); - pdf_doc_init_names (p); + pdf_doc_init_names (p, check_gotos); pdf_doc_init_page_tree(p, media_width, media_height); + pdf_doc_set_bgcolor(NULL); + if (do_encryption) { pdf_obj *encrypt = pdf_encrypt_obj(); - pdf_set_encrypt(encrypt, pdf_enc_id_array()); + pdf_set_encrypt(encrypt); pdf_release_obj(encrypt); } + pdf_set_id(pdf_enc_id_array()); /* Create a default name for thumbnail image files */ if (manual_thumb_enabled) { @@ -2137,6 +2539,8 @@ pdf_doc_begin_grabbing (const char *ident, struct form_list_node *fnode; xform_info info; + pdf_dev_push_gstate(); + fnode = NEW(1, struct form_list_node); fnode->prev = p->pending_forms; @@ -2187,7 +2591,7 @@ pdf_doc_begin_grabbing (const char *ident, * current font and color to the object stream. */ pdf_dev_reset_fonts(); - pdf_dev_reset_color(); + pdf_dev_reset_color(1); /* force color operators to be added to stream */ return xobj_id; } @@ -2229,9 +2633,11 @@ pdf_doc_end_grabbing (pdf_obj *attrib) if (attrib) pdf_release_obj(attrib); p->pending_forms = fnode->prev; + + pdf_dev_pop_gstate(); - /* Here we do not need pdf_dev_reset_color(). */ pdf_dev_reset_fonts(); + pdf_dev_reset_color(0); RELEASE(fnode); @@ -2241,17 +2647,16 @@ pdf_doc_end_grabbing (pdf_obj *attrib) static struct { int dirty; + int broken; pdf_obj *annot_dict; pdf_rect rect; -} breaking_state = {0, NULL, {0.0, 0.0, 0.0, 0.0}}; +} breaking_state = {0, 0, NULL, {0.0, 0.0, 0.0, 0.0}}; static void reset_box (void) { - breaking_state.rect.llx = 10000.0; /* large value */ - breaking_state.rect.lly = 10000.0; /* large value */ - breaking_state.rect.urx = 0.0; /* small value */ - breaking_state.rect.ury = 0.0; /* small value */ + breaking_state.rect.llx = breaking_state.rect.lly = HUGE_VAL; + breaking_state.rect.urx = breaking_state.rect.ury = -HUGE_VAL; breaking_state.dirty = 0; } @@ -2259,6 +2664,7 @@ void pdf_doc_begin_annot (pdf_obj *dict) { breaking_state.annot_dict = dict; + breaking_state.broken = 0; reset_box(); } @@ -2278,9 +2684,11 @@ pdf_doc_break_annot (void) /* Copy dict */ annot_dict = pdf_new_dict(); pdf_merge_dict(annot_dict, breaking_state.annot_dict); - pdf_doc_add_annot(pdf_doc_current_page_number(), - &(breaking_state.rect), annot_dict); + pdf_doc_add_annot(pdf_doc_current_page_number(), &(breaking_state.rect), + annot_dict, !breaking_state.broken); pdf_release_obj(annot_dict); + + breaking_state.broken = 1; } reset_box(); } diff --git a/Build/source/texk/dvipdf-x/xsrc/pdfdoc.h b/Build/source/texk/dvipdf-x/xsrc/pdfdoc.h index 5e65da405e3..5772758af93 100644 --- a/Build/source/texk/dvipdf-x/xsrc/pdfdoc.h +++ b/Build/source/texk/dvipdf-x/xsrc/pdfdoc.h @@ -35,7 +35,8 @@ extern void pdf_doc_set_verbose (void); extern void pdf_open_document (const char *filename, int do_encryption, double media_width, double media_height, - double annot_grow_amount, int bookmark_open_depth); + double annot_grow_amount, int bookmark_open_depth, + int check_gotos); extern void pdf_close_document (void); @@ -55,6 +56,9 @@ extern pdf_obj *pdf_doc_get_reference (const char *category); #define pdf_doc_names() pdf_doc_get_dictionary("Names") #define pdf_doc_this_page() pdf_doc_get_dictionary("@THISPAGE") +extern pdf_obj *pdf_doc_get_page (pdf_file *pf, long page_no, long *count_p, + pdf_rect *bbox, pdf_obj **resources_p); + extern long pdf_doc_current_page_number (void); extern pdf_obj *pdf_doc_current_page_resources (void); @@ -110,7 +114,9 @@ extern void pdf_doc_end_grabbing (pdf_obj *attrib); /* Annotation */ extern void pdf_doc_add_annot (unsigned page_no, - const pdf_rect *rect, pdf_obj *annot_dict); + const pdf_rect *rect, + pdf_obj *annot_dict, + int new_annot); /* Annotation with auto- clip and line (or page) break */ extern void pdf_doc_begin_annot (pdf_obj *dict); diff --git a/Build/source/texk/dvipdf-x/xsrc/pdfdraw.c b/Build/source/texk/dvipdf-x/xsrc/pdfdraw.c index 9f1f0713fc6..878fc164e09 100644 --- a/Build/source/texk/dvipdf-x/xsrc/pdfdraw.c +++ b/Build/source/texk/dvipdf-x/xsrc/pdfdraw.c @@ -1265,6 +1265,61 @@ pdf_dev_currentcolor (pdf_color *color, int is_fill) } #endif /* 0 */ +/* + * mask == 0 means stroking color, mask == 0x20 nonstroking color + * + * force == 1 means that operators will be generated even if + * the color is the same as the current graphics state color + */ +void +pdf_dev_set_color (const pdf_color *color, char mask, int force) +{ + int len; + + pdf_gstate *gs = m_stack_top(&gs_stack); + pdf_color *current = mask ? &gs->fillcolor : &gs->strokecolor; + + ASSERT(pdf_color_is_valid(color)); + + if (!(pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE) && + (force || pdf_color_compare(color, current)))) + /* If "color" is already the current color, then do nothing + * unless a color operator is forced + */ + return; + + graphics_mode(); + len = pdf_color_to_string(color, fmt_buf); + fmt_buf[len++] = ' '; + switch (pdf_color_type(color)) { + case PDF_COLORSPACE_TYPE_RGB: + fmt_buf[len++] = 'R' | mask; + fmt_buf[len++] = 'G' | mask; + break; + case PDF_COLORSPACE_TYPE_CMYK: + fmt_buf[len++] = 'K' | mask; + break; + case PDF_COLORSPACE_TYPE_GRAY: + fmt_buf[len++] = 'G' | mask; + break; + default: /* already verified the given color */ + break; + } + pdf_doc_add_page_content(fmt_buf, len); /* op: RG K G rg k g */ + + pdf_color_copycolor(current, color); +} + +void +pdf_dev_reset_color (int force) +{ + pdf_color *sc, *fc; + + pdf_color_get_current(&sc, &fc); + pdf_dev_set_color(sc, 0, force); + pdf_dev_set_color(fc, 0x20, force); +} + int pdf_dev_concat (const pdf_tmatrix *M) { diff --git a/Build/source/texk/dvipdf-x/xsrc/pdfdraw.h b/Build/source/texk/dvipdf-x/xsrc/pdfdraw.h index f24540ef2bf..27fa74e1f8e 100644 --- a/Build/source/texk/dvipdf-x/xsrc/pdfdraw.h +++ b/Build/source/texk/dvipdf-x/xsrc/pdfdraw.h @@ -164,8 +164,10 @@ extern int pdf_dev_current_depth (void); extern void pdf_dev_grestore_to (int depth); #define pdf_dev_grestoreall() pdf_dev_grestore_to(0); -extern int pdf_dev_currentcolor (pdf_color *color, int is_fill); -extern int pdf_dev_setcolor (const pdf_color *color, int is_fill); +extern void pdf_dev_set_color (const pdf_color *color, char mask, int force); +#define pdf_dev_set_strokingcolor(c) pdf_dev_set_color(c, 0, 0); +#define pdf_dev_set_nonstrokingcolor(c) pdf_dev_set_color(c, 0x20, 0); +extern void pdf_dev_reset_color (int force); extern void pdf_dev_set_fixed_point (double x, double y); extern void pdf_dev_get_fixed_point (pdf_coord *p); diff --git a/Build/source/texk/dvipdf-x/xsrc/pdfnames.c b/Build/source/texk/dvipdf-x/xsrc/pdfnames.c index 83eb997e249..864910b3411 100644 --- a/Build/source/texk/dvipdf-x/xsrc/pdfnames.c +++ b/Build/source/texk/dvipdf-x/xsrc/pdfnames.c @@ -22,8 +22,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#if HAVE_CONFIG_H -#include "config.h" +#ifdef HAVE_CONFIG_H +#include <config.h> #endif #include <ctype.h> @@ -44,9 +44,8 @@ struct obj_data { - pdf_obj *object_ref; pdf_obj *object; - int reserve; /* 1 if object is not actually defined. */ + int closed; /* 1 if object is closed */ }; char * @@ -74,51 +73,17 @@ printable_key (const char *key, int keylen) return (char *) pkey; } -static void -flush_objects (struct ht_table *ht_tab) -{ - struct ht_iter iter; - - if (ht_set_iter(ht_tab, &iter) >= 0) { - do { - char *key; - int keylen; - struct obj_data *value; - - key = ht_iter_getkey(&iter, &keylen); - value = ht_iter_getval(&iter); - if (value->reserve) { - WARN("Unresolved object reference \"%s\" found!!!", - printable_key(key, keylen)); - } - if (value->object) { - pdf_release_obj(value->object); - } - if (value->object_ref) { - pdf_release_obj(value->object_ref); - } - value->object = NULL; - value->object_ref = NULL; - value->reserve = 0; - } while (ht_iter_next(&iter) >= 0); - ht_clear_iter(&iter); - } -} - static void CDECL hval_free (void *hval) { struct obj_data *value; value = (struct obj_data *) hval; - if (value->object) - pdf_release_obj(value->object); - if (value->object_ref) - pdf_release_obj(value->object_ref); - value->object = NULL; - value->object_ref = NULL; - value->reserve = 0; + if (value->object) { + pdf_release_obj(value->object); + value->object = NULL; + } RELEASE(value); @@ -136,12 +101,37 @@ pdf_new_name_tree (void) return names; } +static void +check_objects_defined (struct ht_table *ht_tab) +{ + struct ht_iter iter; + + if (ht_set_iter(ht_tab, &iter) >= 0) { + do { + char *key; + int keylen; + struct obj_data *value; + + key = ht_iter_getkey(&iter, &keylen); + value = ht_iter_getval(&iter); + ASSERT(value->object); + if (PDF_OBJ_UNDEFINED(value->object)) { + pdf_names_add_object(ht_tab, key, keylen, pdf_new_null()); + WARN("Object @%s used, but not defined. Replaced by null.", + printable_key(key, keylen)); + } + } while (ht_iter_next(&iter) >= 0); + ht_clear_iter(&iter); + } +} + void pdf_delete_name_tree (struct ht_table **names) { ASSERT(names && *names); - flush_objects (*names); + check_objects_defined(*names); + ht_clear_table(*names); RELEASE(*names); *names = NULL; @@ -163,64 +153,20 @@ pdf_names_add_object (struct ht_table *names, value = ht_lookup_table(names, key, keylen); if (!value) { value = NEW(1, struct obj_data); - value->object = object; - value->object_ref = NULL; - value->reserve = 0; + value->object = object; + value->closed = 0; ht_append_table(names, key, keylen, value); } else { - if (value->reserve) { - /* null object is used for undefined objects */ - pdf_copy_object(value->object, object); - pdf_release_obj(object); /* PLEASE FIX THIS!!! */ + ASSERT(value->object); + if (PDF_OBJ_UNDEFINED(value->object)) { + pdf_transfer_label(object, value->object); + pdf_release_obj(value->object); + value->object = object; } else { - if (value->object || value->object_ref) { - if (pdf_obj_get_verbose()) { - WARN("Object reference with key \"%s\" is in use.", printable_key(key, keylen)); - } - pdf_release_obj(object); - return -1; - } else { - value->object = object; - } - } - value->reserve = 0; - } - - return 0; -} - -int -pdf_names_add_reference (struct ht_table *names, - const void *key, int keylen, pdf_obj *object_ref) -{ - struct obj_data *value; - - ASSERT(names); - - if (!PDF_OBJ_INDIRECTTYPE(object_ref)) { - WARN("Invalid type: @%s is not reference...", - printable_key(key, keylen)); - return -1; - } - - value = ht_lookup_table(names, key, keylen); - if (!value) { - value = NEW(1, struct obj_data); - value->object = NULL; - value->object_ref = object_ref; - value->reserve = 0; - ht_append_table(names, key, keylen, value); - } else { - if (value->object || value->object_ref) { - WARN("Object reference \"%s\" is in use.", - printable_key(key, keylen)); - WARN("Please close it before redefining."); + WARN("Object @%s already defined.", printable_key(key, keylen)); + pdf_release_obj(object); return -1; - } else { - value->object = NULL; - value->object_ref = object_ref; } - value->reserve = 0; } return 0; @@ -234,29 +180,24 @@ pdf_names_lookup_reference (struct ht_table *names, const void *key, int keylen) { struct obj_data *value; + pdf_obj *object; ASSERT(names); value = ht_lookup_table(names, key, keylen); - /* Reserve object label */ - if (!value) { - value = NEW(1, struct obj_data); - value->object = pdf_new_null(); /* dummy */ - value->object_ref = NULL; - value->reserve = 1; - ht_append_table(names, key, keylen, value); - } - - if (!value->object_ref) { - if (value->object) - value->object_ref = pdf_ref_obj(value->object); - else { - WARN("Object @%s not defined or already closed.", - printable_key(key, keylen)); - } + if (value) { + object = value->object; + } else { + /* A null object as dummy would create problems because as value + * of a dictionary entry, a null object is be equivalent to no entry + * at all. This matters for optimization of PDF destinations. + */ + object = pdf_new_undefined(); + pdf_names_add_object(names, key, keylen, object); } + ASSERT(object); - return pdf_link_obj(value->object_ref); + return pdf_ref_obj(object); } pdf_obj * @@ -268,12 +209,9 @@ pdf_names_lookup_object (struct ht_table *names, ASSERT(names); value = ht_lookup_table(names, key, keylen); - if (!value) + if (!value || PDF_OBJ_UNDEFINED(value->object)) return NULL; - else if (!value->object) { - WARN("Object @%s not defined or already closed.", - printable_key(key, keylen)); - } + ASSERT(value->object); return value->object; } @@ -287,21 +225,19 @@ pdf_names_close_object (struct ht_table *names, ASSERT(names); value = ht_lookup_table(names, key, keylen); - if (!value) { - WARN("Tried to release nonexistent reference: %s", - printable_key(key, keylen)); + if (!value ||PDF_OBJ_UNDEFINED(value->object) ) { + WARN("Cannot close undefined object @%s.", printable_key(key, keylen)); return -1; } + ASSERT(value->object); - if (value->object) { - pdf_release_obj(value->object); - value->object = NULL; - } else { - WARN("Trying to close object @%s twice?", - printable_key(key, keylen)); + if (value->closed) { + WARN("Object @%s already closed.", printable_key(key, keylen)); return -1; } + value->closed = 1; + return 0; } @@ -415,7 +351,8 @@ build_name_tree (struct named_object *first, long num_leaves, int is_root) } static struct named_object * -flat_table (struct ht_table *ht_tab, long *num_entries) +flat_table (struct ht_table *ht_tab, long *num_entries, + struct ht_table *filter) { struct named_object *objects; struct ht_iter iter; @@ -423,64 +360,64 @@ flat_table (struct ht_table *ht_tab, long *num_entries) ASSERT(ht_tab); - *num_entries = count = ht_tab->count; - objects = NEW(count, struct named_object); + objects = NEW(ht_tab->count, struct named_object); + count = 0; if (ht_set_iter(ht_tab, &iter) >= 0) { do { char *key; int keylen; struct obj_data *value; - count--; key = ht_iter_getkey(&iter, &keylen); + + if (filter) { + pdf_obj *new_obj = ht_lookup_table(filter, key, keylen); + + if (!new_obj) + continue; + + key = pdf_string_value(new_obj); + keylen = pdf_string_length(new_obj); + } + value = ht_iter_getval(&iter); - if (value->reserve) { - WARN("Named object \"%s\" not defined!!!", + ASSERT(value->object); + if (PDF_OBJ_UNDEFINED(value->object)) { + WARN("Object @%s\" not defined. Replaced by null.", printable_key(key, keylen)); - WARN("Replacing with null."); objects[count].key = (char *) key; objects[count].keylen = keylen; objects[count].value = pdf_new_null(); - } else if (value->object_ref) { - objects[count].key = (char *) key; - objects[count].keylen = keylen; - objects[count].value = pdf_link_obj(value->object_ref); } else if (value->object) { objects[count].key = (char *) key; objects[count].keylen = keylen; objects[count].value = pdf_link_obj(value->object); - } else { - WARN("Named object \"%s\" not defined!!!", - printable_key(key, keylen)); - WARN("Replacing with null."); - objects[count].key = (char *) key; - objects[count].keylen = keylen; - objects[count].value = pdf_new_null(); } - } while (ht_iter_next(&iter) >= 0 && count > 0); + + count++; + } while (ht_iter_next(&iter) >= 0); ht_clear_iter(&iter); } + *num_entries = count; + objects = RENEW(objects, count, struct named_object); + return objects; } pdf_obj * -pdf_names_create_tree (struct ht_table *names) +pdf_names_create_tree (struct ht_table *names, long *count, + struct ht_table *filter) { pdf_obj *name_tree; struct named_object *flat; - long count; - flat = flat_table(names, &count); + flat = flat_table(names, count, filter); if (!flat) name_tree = NULL; else { - if (count < 1) - name_tree = NULL; - else { - qsort(flat, count, sizeof(struct named_object), cmp_key); - name_tree = build_name_tree(flat, count, 1); - } + qsort(flat, *count, sizeof(struct named_object), cmp_key); + name_tree = build_name_tree(flat, *count, 1); RELEASE(flat); } diff --git a/Build/source/texk/dvipdf-x/xsrc/pdfnames.h b/Build/source/texk/dvipdf-x/xsrc/pdfnames.h index ca4a7dbc0bf..bcf3aec9d98 100644 --- a/Build/source/texk/dvipdf-x/xsrc/pdfnames.h +++ b/Build/source/texk/dvipdf-x/xsrc/pdfnames.h @@ -35,8 +35,6 @@ extern void pdf_delete_name_tree (struct ht_table **names); extern int pdf_names_add_object (struct ht_table *names, const void *key, int keylen, pdf_obj *object); -extern int pdf_names_add_reference (struct ht_table *names, - const void *key, int keylen, pdf_obj *object_ref); extern pdf_obj *pdf_names_lookup_reference (struct ht_table *names, const void *key, int keylen); extern pdf_obj *pdf_names_lookup_object (struct ht_table *names, @@ -45,7 +43,9 @@ extern int pdf_names_close_object (struct ht_table *names, const void *key, int keylen); /* Really create name tree... */ -extern pdf_obj *pdf_names_create_tree (struct ht_table *names); +extern pdf_obj *pdf_names_create_tree (struct ht_table *names, + long *count, + struct ht_table *filter); extern char *printable_key (const char *key, int keylen); diff --git a/Build/source/texk/dvipdf-x/xsrc/pdfobj.c b/Build/source/texk/dvipdf-x/xsrc/pdfobj.c index 6c8d66780f4..78fb8aff21c 100644 --- a/Build/source/texk/dvipdf-x/xsrc/pdfobj.c +++ b/Build/source/texk/dvipdf-x/xsrc/pdfobj.c @@ -22,8 +22,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#if HAVE_CONFIG_H -#include "config.h" +#ifdef HAVE_CONFIG_H +#include <config.h> #endif #include <ctype.h> @@ -117,6 +117,7 @@ struct pdf_stream struct pdf_indirect { pdf_file *pf; + pdf_obj *obj; /* used when PF == NULL */ unsigned long label; unsigned short generation; }; @@ -161,6 +162,7 @@ struct pdf_file FILE *file; pdf_obj *trailer; xref_entry *xref_table; + pdf_obj *catalog; long num_obj; long file_size; int version; @@ -179,6 +181,8 @@ static pdf_obj *xref_stream; /* Internal static routines */ +static int check_for_pdf_version (FILE *file); + 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); @@ -190,6 +194,7 @@ static void release_objstm (pdf_obj *objstm); static void pdf_out_char (FILE *file, char c); static void pdf_out (FILE *file, const void *buffer, long length); +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); @@ -314,13 +319,12 @@ pdf_out_init (const char *filename, int do_encryption) if (filename == NULL) { /* no filename: writing to stdout */ #ifdef WIN32 - setmode(fileno(stdout), _O_BINARY); + setmode(fileno(stdout), _O_BINARY); #endif pdf_output_file = stdout; } else pdf_output_file = MFOPEN(filename, FOPEN_WBIN_MODE); - if (!pdf_output_file) { if (strlen(filename) < 128) ERROR("Unable to open \"%s\".", filename); @@ -510,14 +514,20 @@ pdf_set_info (pdf_obj *object) } void -pdf_set_encrypt (pdf_obj *encrypt, pdf_obj *id) +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; - - pdf_add_dict(trailer_dict, pdf_new_name("ID"), id); } static @@ -588,16 +598,13 @@ void pdf_out_white (FILE *file) ERROR("typecheck: Invalid object type: %d %d (line %d)", (o) ? (o)->type : -1, (t), __LINE__);\ } -#define INVALIDOBJ(o) ((o) == NULL || (o)->type <= 0 || (o)->type > PDF_INDIRECT) +#define INVALIDOBJ(o) ((o) == NULL || (o)->type <= 0 || (o)->type > PDF_UNDEFINED) -pdf_obj * +static pdf_obj * pdf_new_obj(int type) { pdf_obj *result; - if (type > PDF_INDIRECT || type < PDF_UNDEFINED) - ERROR("Invalid object type: %d", type); - result = NEW(1, pdf_obj); result->type = type; result->data = NULL; @@ -606,6 +613,9 @@ pdf_new_obj(int type) result->refcount = 1; result->flags = 0; + if (INVALIDOBJ(result)) + ERROR("Invalid object type: %d", type); + return result; } @@ -634,6 +644,21 @@ pdf_label_obj (pdf_obj *object) } /* + * Transfer the label assigned to the object src to the object dst. + * The object dst must not yet have been labeled. + */ +void +pdf_transfer_label (pdf_obj *dst, pdf_obj *src) +{ + ASSERT(dst && !dst->label && src); + + dst->label = src->label; + dst->generation = src->generation; + src->label = 0; + src->generation = 0; +} + +/* * This doesn't really copy the object, but allows it to be used without * fear that somebody else will free it. */ @@ -664,10 +689,7 @@ pdf_ref_obj (pdf_obj *object) if (PDF_OBJ_INDIRECTTYPE(object)) { return pdf_link_obj(object); } else { - if (object->label == 0) { - pdf_label_obj(object); - } - return pdf_new_indirect(NULL, object->label, object->generation); + return pdf_new_ref(object); } } @@ -688,6 +710,20 @@ write_indirect (pdf_indirect *indirect, FILE *file) pdf_out(file, format_buffer, length); } +/* The undefined object is used as a placeholder in pdfnames.c + * for objects which are referenced before they are defined. + */ +pdf_obj * +pdf_new_undefined (void) +{ + pdf_obj *result; + + result = pdf_new_obj(PDF_UNDEFINED); + result->data = NULL; + + return result; +} + pdf_obj * pdf_new_null (void) { @@ -741,6 +777,7 @@ write_boolean (pdf_boolean *data, FILE *file) } } +#if 0 void pdf_set_boolean (pdf_obj *object, char value) { @@ -751,6 +788,7 @@ pdf_set_boolean (pdf_obj *object, char value) data = object->data; data->value = value; } +#endif char pdf_boolean_value (pdf_obj *object) @@ -824,19 +862,17 @@ 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; - if (length != 0) { - data->length = length; - data->string = NEW(length+1, unsigned char); - memcpy(data->string, str, length); - /* Shouldn't assume NULL terminated. */ - data->string[length] = '\0'; - } else { - data->length = 0; - data->string = NULL; - } + + data->length = length; + data->string = NEW(length+1, unsigned char); + memcpy(data->string, str, length); + /* Shouldn't assume NULL terminated. */ + data->string[length] = '\0'; return result; } @@ -1070,6 +1106,7 @@ release_name (pdf_name *data) RELEASE(data); } +#if 0 void pdf_set_name (pdf_obj *object, const char *name) { @@ -1091,6 +1128,7 @@ pdf_set_name (pdf_obj *object, const char *name) data->name = NULL; } } +#endif char * pdf_name_value (pdf_obj *object) @@ -1268,7 +1306,7 @@ pdf_shift_array (pdf_obj *array) return result; } -#endif /* 0 */ +#endif /* Prepend an object to an array */ void @@ -1309,19 +1347,26 @@ pdf_pop_array (pdf_obj *array) return result; } -#endif /* 0 */ +#endif + static void write_dict (pdf_dict *dict, FILE *file) { +#if 0 pdf_out (file, "<<\n", 3); /* dropping \n saves few kb. */ +#else + pdf_out (file, "<<", 2); +#endif while (dict->key != NULL) { pdf_write_obj(dict->key, file); if (pdf_need_white(PDF_NAME, (dict->value)->type)) { pdf_out_white(file); } pdf_write_obj(dict->value, file); +#if 0 pdf_out_char (file, '\n'); /* removing this saves few kb. */ +#endif dict = dict->next; } pdf_out(file, ">>", 2); @@ -1442,7 +1487,7 @@ pdf_put_dict (pdf_obj *dict, const char *key, pdf_obj *value) data->value = value; } } -#endif /* 0 */ +#endif /* pdf_merge_dict makes a link for each item in dict2 before stealing it */ void @@ -1902,7 +1947,7 @@ pdf_stream_get_flags (pdf_obj *stream) return data->_flags; } -#endif /* 0 */ +#endif static void pdf_write_obj (pdf_obj *object, FILE *file) @@ -1912,7 +1957,7 @@ pdf_write_obj (pdf_obj *object, FILE *file) return; } - if (INVALIDOBJ(object)) + if (INVALIDOBJ(object) || PDF_OBJ_UNDEFINED(object)) ERROR("pdf_write_obj: Invalid object, type = %d\n", object->type); if (file == stderr) @@ -2102,102 +2147,6 @@ pdf_release_obj (pdf_obj *object) } } -/* Copy object data without changing object label. */ -void -pdf_copy_object (pdf_obj *dst, pdf_obj *src) -{ - if (!dst || !src) - return; - - switch (dst->type) { - case PDF_BOOLEAN: release_boolean(dst->data); break; - case PDF_NULL: release_null(dst->data); break; - case PDF_NUMBER: release_number(dst->data); break; - case PDF_STRING: release_string(dst->data); break; - case PDF_NAME: release_name(dst->data); break; - case PDF_ARRAY: release_array(dst->data); break; - case PDF_DICT: release_dict(dst->data); break; - case PDF_STREAM: release_stream(dst->data); break; - case PDF_INDIRECT: release_indirect(dst->data); break; - } - - dst->type = src->type; - switch (src->type) { - case PDF_BOOLEAN: - dst->data = NEW(1, pdf_boolean); - pdf_set_boolean(dst, pdf_boolean_value(src)); - break; - case PDF_NULL: - dst->data = NULL; - break; - case PDF_NUMBER: - dst->data = NEW(1, pdf_number); - pdf_set_number(dst, pdf_number_value(src)); - break; - case PDF_STRING: - dst->data = NEW(1, pdf_string); - pdf_set_string(dst, - pdf_string_value(src), - pdf_string_length(src)); - break; - case PDF_NAME: - dst->data = NEW(1, pdf_name); - pdf_set_name(dst, pdf_name_value(src)); - break; - case PDF_ARRAY: - { - pdf_array *data; - unsigned long i; - - dst->data = data = NEW(1, pdf_array); - data->size = 0; - data->max = 0; - data->values = NULL; - for (i = 0; i < pdf_array_length(src); i++) { - pdf_add_array(dst, pdf_link_obj(pdf_get_array(src, i))); - } - } - break; - case PDF_DICT: - { - pdf_dict *data; - - dst->data = data = NEW(1, pdf_dict); - data->key = NULL; - data->value = NULL; - data->next = NULL; - pdf_merge_dict(dst, src); - } - break; - case PDF_STREAM: - { - pdf_stream *data; - - dst->data = data = NEW(1, pdf_stream); - data->dict = pdf_new_dict(); - data->_flags = ((pdf_stream *)src->data)->_flags; - data->stream_length = 0; - data->max_length = 0; - - pdf_add_stream(dst, pdf_stream_dataptr(src), pdf_stream_length(src)); - pdf_merge_dict(data->dict, pdf_stream_dict(src)); - } - break; - case PDF_INDIRECT: - { - pdf_indirect *data; - - dst->data = data = NEW(1, pdf_indirect); - data->pf = ((pdf_indirect *) (src->data))->pf; - data->label = ((pdf_indirect *) (src->data))->label; - data->generation = ((pdf_indirect *) (src->data))->generation; - } - break; - } - - return; -} - static int backup_line (FILE *pdf_input_file) { @@ -2328,6 +2277,7 @@ pdf_new_indirect (pdf_file *pf, unsigned long obj_num, unsigned short obj_gen) indirect = NEW(1, pdf_indirect); indirect->pf = pf; + indirect->obj = NULL; indirect->label = obj_num; indirect->generation = obj_gen; @@ -2562,27 +2512,53 @@ pdf_get_object (pdf_file *pf, unsigned long obj_num, unsigned short obj_gen) } #define OBJ_FILE(o) (((pdf_indirect *)((o)->data))->pf) +#define OBJ_OBJ(o) (((pdf_indirect *)((o)->data))->obj) #define OBJ_NUM(o) (((pdf_indirect *)((o)->data))->label) #define OBJ_GEN(o) (((pdf_indirect *)((o)->data))->generation) +static pdf_obj * +pdf_new_ref (pdf_obj *object) +{ + pdf_obj *result; + + if (object->label == 0) { + pdf_label_obj(object); + } + result = pdf_new_indirect(NULL, object->label, object->generation); + OBJ_OBJ(result) = object; + return result; +} + /* pdf_deref_obj always returns a link instead of the original */ /* It never return the null object, but the NULL pointer instead */ pdf_obj * pdf_deref_obj (pdf_obj *obj) { + int count = PDF_OBJ_MAX_DEPTH; + if (obj) obj = pdf_link_obj(obj); - while (PDF_OBJ_INDIRECTTYPE(obj)) { + while (PDF_OBJ_INDIRECTTYPE(obj) && --count) { pdf_file *pf = OBJ_FILE(obj); - unsigned long obj_num = OBJ_NUM(obj); - unsigned short obj_gen = OBJ_GEN(obj); - if (!pf) - ERROR("Tried to deref a non-file object"); - pdf_release_obj(obj); - obj = pdf_get_object(pf, obj_num, obj_gen); + if (pf) { + unsigned long obj_num = OBJ_NUM(obj); + unsigned short obj_gen = OBJ_GEN(obj); + pdf_release_obj(obj); + obj = pdf_get_object(pf, obj_num, obj_gen); + } else { + pdf_obj *next_obj = OBJ_OBJ(obj); + if (!next_obj) { + ERROR("Undefined object reference"); + } + pdf_release_obj(obj); + obj = pdf_link_obj(next_obj); + } } + if (!count) + ERROR("Loop in object hierarchy detected. Broken PDF file?"); + if (PDF_OBJ_NULLTYPE(obj)) { pdf_release_obj(obj); return NULL; @@ -2740,7 +2716,7 @@ parse_xrefstm_subsec (pdf_file *pf, static int parse_xref_stream (pdf_file *pf, long xref_pos, pdf_obj **trailer) { - pdf_obj *xrefstm, *size_obj, *W_obj, *index; + pdf_obj *xrefstm, *size_obj, *W_obj, *index_obj; unsigned long size; long length; int W[3], i, wsum = 0; @@ -2780,17 +2756,17 @@ parse_xref_stream (pdf_file *pf, long xref_pos, pdf_obj **trailer) p = pdf_stream_dataptr(xrefstm); - index = pdf_lookup_dict(*trailer, "Index"); - if (index) { + index_obj = pdf_lookup_dict(*trailer, "Index"); + if (index_obj) { unsigned int index_len; - if (!PDF_OBJ_ARRAYTYPE(index) || - ((index_len = pdf_array_length(index)) % 2 )) + if (!PDF_OBJ_ARRAYTYPE(index_obj) || + ((index_len = pdf_array_length(index_obj)) % 2 )) goto error; i = 0; while (i < index_len) { - pdf_obj *first = pdf_get_array(index, i++); - size_obj = pdf_get_array(index, i++); + pdf_obj *first = pdf_get_array(index_obj, i++); + size_obj = pdf_get_array(index_obj, i++); if (!PDF_OBJ_NUMBERTYPE(first) || !PDF_OBJ_NUMBERTYPE(size_obj) || parse_xrefstm_subsec(pf, &p, &length, W, wsum, @@ -2819,7 +2795,6 @@ parse_xref_stream (pdf_file *pf, long xref_pos, pdf_obj **trailer) return 0; } -/* TODO: parse Version entry */ static pdf_obj * read_xref (pdf_file *pf) { @@ -2904,6 +2879,7 @@ pdf_file_new (FILE *file) pf->file = file; pf->trailer = NULL; pf->xref_table = NULL; + pf->catalog = NULL; pf->num_obj = 0; pf->version = 0; @@ -2929,8 +2905,15 @@ pdf_file_free (pdf_file *pf) pdf_release_obj(pf->xref_table[i].indirect); } - RELEASE(pf->xref_table); - pdf_release_obj(pf->trailer); + RELEASE(pf->xref_table); + if (pf->trailer) { + pdf_release_obj(pf->trailer); + pf->trailer = NULL; + } + if (pf->catalog) { + pdf_release_obj(pf->catalog); + pf->catalog = NULL; + } RELEASE(pf); } @@ -2942,45 +2925,90 @@ pdf_files_init (void) ht_init_table(pdf_files, (void (*)(void *)) pdf_file_free); } +int +pdf_file_get_version (pdf_file *pf) +{ + ASSERT(pf); + return pf->version; +} + pdf_obj * pdf_file_get_trailer (pdf_file *pf) { ASSERT(pf); - return pdf_link_obj(pf->trailer); + return pf->trailer; +} + +pdf_obj * +pdf_file_get_catalog (pdf_file *pf) +{ + ASSERT(pf); + return pf->catalog; } pdf_file * -pdf_open (char *ident, FILE *file) +pdf_open (const char *ident, FILE *file) { - pdf_file *pf = NULL; + pdf_file *pf; ASSERT(pdf_files); - if (ident) - pf = (pdf_file *) ht_lookup_table(pdf_files, ident, strlen(ident)); + pf = (pdf_file *) ht_lookup_table(pdf_files, ident, strlen(ident)); if (pf) { pf->file = file; } else { - int version = check_for_pdf(file); - if (!version) { - WARN("pdf_open: Not a PDF 1.[1-5] file."); + int version; + pdf_obj *new_version; + + version = check_for_pdf_version(file); + if (version < 0) { + WARN("Not a PDF file."); return NULL; } pf = pdf_file_new(file); pf->version = version; - if (!(pf->trailer = read_xref(pf))) { - pdf_file_free(pf); - return NULL; + if (!(pf->trailer = read_xref(pf))) + goto error; + + if (pdf_lookup_dict(pf->trailer, "Encrypt")) { + WARN("PDF document is encrypted."); + goto error; + } + + pf->catalog = pdf_deref_obj(pdf_lookup_dict(pf->trailer, "Root")); + if (!PDF_OBJ_DICTTYPE(pf->catalog)) { + WARN("Cannot read PDF document catalog. Broken PDF file?"); + goto error; } - if (ident) - ht_append_table(pdf_files, ident, strlen(ident), pf); + new_version = pdf_deref_obj(pdf_lookup_dict(pf->catalog, "Version")); + if (new_version) { + unsigned int minor; + + if (!PDF_OBJ_NAMETYPE(new_version) || + sscanf(pdf_name_value(new_version), "1.%u", &minor) != 1) { + pdf_release_obj(new_version); + WARN("Illegal Version entry in document catalog. Broken PDF file?"); + goto error; + } + + if (pf->version < minor) + pf->version = minor; + + pdf_release_obj(new_version); + } + + ht_append_table(pdf_files, ident, strlen(ident), pf); } return pf; + + error: + pdf_file_free(pf); + return NULL; } void @@ -2998,24 +3026,21 @@ pdf_files_close (void) RELEASE(pdf_files); } -int -check_for_pdf (FILE *file) +static int +check_for_pdf_version (FILE *file) { - int result = 0; + unsigned int minor; rewind(file); - if (fread(work_buffer, sizeof(char), strlen("%PDF-1.x"), file) == - strlen("%PDF-1.x") && - !strncmp(work_buffer, "%PDF-1.", strlen("%PDF-1."))) { - if (work_buffer[7] >= '0' && work_buffer[7] <= '0' + pdf_version) - result = 1; - else { - WARN("Version of PDF file (1.%c) is newer than version limit specification.", - work_buffer[7]); - } - } - return result; + return (ungetc(fgetc(file), file) == '%' && + fscanf(file, "%%PDF-1.%u", &minor) == 1) ? minor : -1; +} + +int +check_for_pdf (FILE *file) +{ + return (check_for_pdf_version(file) >= 0); } static int CDECL @@ -3035,6 +3060,8 @@ import_dict (pdf_obj *key, pdf_obj *value, void *pdata) return 0; } +static pdf_obj loop_marker = { PDF_OBJ_INVALID, 0, 0, 0, 0, NULL }; + static pdf_obj * pdf_import_indirect (pdf_obj *object) { @@ -3052,15 +3079,16 @@ pdf_import_indirect (pdf_obj *object) } if ((ref = pf->xref_table[obj_num].indirect)) { + if (ref == &loop_marker) + ERROR("Loop in object hierarchy detected. Broken PDF file?"); return pdf_link_obj(ref); } else { pdf_obj *obj, *tmp; obj = pdf_get_object(pf, obj_num, obj_gen); - if (!obj) { - WARN("Could not read object: %lu %u", obj_num, obj_gen); - return NULL; - } + + /* We mark the reference to be able to detect loops */ + pf->xref_table[obj_num].indirect = &loop_marker; tmp = pdf_import_object(obj); @@ -3146,25 +3174,17 @@ pdf_import_object (pdf_obj *object) } +/* returns 0 if indirect references point to the same object */ int pdf_compare_reference (pdf_obj *ref1, pdf_obj *ref2) { pdf_indirect *data1, *data2; - if (!PDF_OBJ_INDIRECTTYPE(ref1) || - !PDF_OBJ_INDIRECTTYPE(ref2)) { - ERROR("Not indirect reference..."); - } + ASSERT(PDF_OBJ_INDIRECTTYPE(ref1) && PDF_OBJ_INDIRECTTYPE(ref2)); data1 = (pdf_indirect *) ref1->data; data2 = (pdf_indirect *) ref2->data; - if (data1->pf != data2->pf) - return (int) (data1->pf - data2->pf); - if (data1->label != data2->label) - return (int) (data1->label - data2->label); - if (data1->generation != data2->generation) - return (int) (data1->generation - data2->generation); - - return 0; + return data1->pf != data2->pf || data1->label != data2->label + || data1->generation != data2->generation; } diff --git a/Build/source/texk/dvipdf-x/xsrc/pdfobj.h b/Build/source/texk/dvipdf-x/xsrc/pdfobj.h index 036e9f53ef4..e95a1bf8196 100644 --- a/Build/source/texk/dvipdf-x/xsrc/pdfobj.h +++ b/Build/source/texk/dvipdf-x/xsrc/pdfobj.h @@ -38,12 +38,15 @@ #define PDF_STREAM 7 #define PDF_NULL 8 #define PDF_INDIRECT 9 +#define PDF_UNDEFINED 10 #define PDF_OBJ_INVALID 0 -#define PDF_UNDEFINED PDF_OBJ_INVALID #define STREAM_COMPRESS (1 << 0) +/* A deeper object hierarchy will be considered as (illegal) loop. */ +#define PDF_OBJ_MAX_DEPTH 30 + typedef struct pdf_obj pdf_obj; typedef struct pdf_file pdf_file; @@ -58,7 +61,6 @@ extern void pdf_out_flush (void); extern void pdf_set_version (unsigned version); extern unsigned pdf_get_version (void); -extern pdf_obj *pdf_new_obj (int type); extern void pdf_release_obj (pdf_obj *object); extern int pdf_obj_typeof (pdf_obj *object); @@ -71,17 +73,23 @@ extern int pdf_obj_typeof (pdf_obj *object); #define PDF_OBJ_DICTTYPE(o) ((o) && pdf_obj_typeof((o)) == PDF_DICT) #define PDF_OBJ_STREAMTYPE(o) ((o) && pdf_obj_typeof((o)) == PDF_STREAM) #define PDF_OBJ_INDIRECTTYPE(o) ((o) && pdf_obj_typeof((o)) == PDF_INDIRECT) +#define PDF_OBJ_UNDEFINED(o) ((o) && pdf_obj_typeof((o)) == PDF_UNDEFINED) #define PDF_OBJ_TYPEOF(o) pdf_obj_typeof((o)) extern pdf_obj *pdf_ref_obj (pdf_obj *object); extern pdf_obj *pdf_link_obj (pdf_obj *object); +extern void pdf_transfer_label (pdf_obj *dst, pdf_obj *src); + +extern pdf_obj *pdf_new_undefined (void); extern pdf_obj *pdf_new_null (void); extern pdf_obj *pdf_new_boolean (char value); +#if 0 extern void pdf_set_boolean (pdf_obj *object, char value); +#endif extern char pdf_boolean_value (pdf_obj *object); extern pdf_obj *pdf_new_number (double value); @@ -95,7 +103,9 @@ extern unsigned pdf_string_length (pdf_obj *object); /* Name does not include the / */ extern pdf_obj *pdf_new_name (const char *name); +#if 0 extern void pdf_set_name (pdf_obj *object, const char *name); +#endif extern char *pdf_name_value (pdf_obj *object); extern pdf_obj *pdf_new_array (void); @@ -107,7 +117,7 @@ extern pdf_obj *pdf_new_array (void); extern void pdf_add_array (pdf_obj *array, pdf_obj *object); #if 0 extern void pdf_put_array (pdf_obj *array, unsigned idx, pdf_obj *object); -#endif /* 0 */ +#endif extern pdf_obj *pdf_get_array (pdf_obj *array, long idx); extern unsigned pdf_array_length (pdf_obj *array); @@ -115,7 +125,7 @@ extern void pdf_unshift_array (pdf_obj *array, pdf_obj *object); #if 0 extern pdf_obj *pdf_shift_array (pdf_obj *array); extern pdf_obj *pdf_pop_array (pdf_obj *array); -#endif /* 0 */ +#endif extern pdf_obj *pdf_new_dict (void); extern void pdf_remove_dict (pdf_obj *dict, const char *key); @@ -132,8 +142,8 @@ extern pdf_obj *pdf_dict_keys (pdf_obj *dict); */ extern int pdf_add_dict (pdf_obj *dict, pdf_obj *key, pdf_obj *value); #if 0 -extern void pdf_put_dict (pdf_obj *dict, const char *key, pdf_obj *value); -#endif /* 0 */ +extern void pdf_put_dict (pdf_obj *dict, const char *key, pdf_obj *value); +#endif /* Apply proc(key, value, pdata) for each key-value pairs in dict, stop if proc() * returned non-zero value (and that value is returned). PDF object is passed for @@ -158,7 +168,7 @@ extern long pdf_stream_length (pdf_obj *stream); #if 0 extern void pdf_stream_set_flags (pdf_obj *stream, int flags); extern int pdf_stream_get_flags (pdf_obj *stream); -#endif /* 0 */ +#endif extern const void *pdf_stream_dataptr (pdf_obj *stream); #if 0 @@ -175,15 +185,18 @@ extern int pdf_compare_reference (pdf_obj *ref1, pdf_obj *ref2); extern void pdf_set_compression (int level); extern void pdf_set_info (pdf_obj *obj); +extern void pdf_set_id (pdf_obj *id); extern void pdf_set_root (pdf_obj *obj); -extern void pdf_set_encrypt (pdf_obj *encrypt, pdf_obj *id); +extern void pdf_set_encrypt (pdf_obj *encrypt); extern void pdf_files_init (void); extern void pdf_files_close (void); extern int check_for_pdf (FILE *file); -extern pdf_file *pdf_open (char *ident, FILE *file); +extern pdf_file *pdf_open (const char *ident, FILE *file); extern void pdf_close (pdf_file *pf); extern pdf_obj *pdf_file_get_trailer (pdf_file *pf); +extern int pdf_file_get_version (pdf_file *pf); +extern pdf_obj *pdf_file_get_catalog (pdf_file *pf); extern pdf_obj *pdf_deref_obj (pdf_obj *object); extern pdf_obj *pdf_import_object (pdf_obj *object); @@ -191,6 +204,5 @@ extern pdf_obj *pdf_import_object (pdf_obj *object); extern int pdfobj_escape_str (char *buffer, int size, const unsigned char *s, int len); extern pdf_obj *pdf_new_indirect (pdf_file *pf, unsigned long label, unsigned short generation); -extern void pdf_copy_object (pdf_obj *dst, pdf_obj *src); #endif /* _PDFOBJ_H_ */ diff --git a/Build/source/texk/dvipdf-x/xsrc/pdfximage.c b/Build/source/texk/dvipdf-x/xsrc/pdfximage.c index f16829f18ba..6f3e6d3558f 100644 --- a/Build/source/texk/dvipdf-x/xsrc/pdfximage.c +++ b/Build/source/texk/dvipdf-x/xsrc/pdfximage.c @@ -22,8 +22,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#if HAVE_CONFIG_H -#include "config.h" +#ifdef HAVE_CONFIG_H +#include <config.h> #endif #include "system.h" @@ -48,7 +48,7 @@ /* From psimage.h */ static int check_for_ps (FILE *fp); -static int ps_include_page (pdf_ximage *ximage, const char *file_name); +static int ps_include_page (pdf_ximage *ximage); #define IMAGE_TYPE_UNKNOWN -1 @@ -71,7 +71,7 @@ struct pdf_ximage_ { char *ident; char res_name[16]; - long page_no, page_count; + long page_no; int subtype; @@ -82,7 +82,7 @@ struct pdf_ximage_ pdf_obj *resource; pdf_obj *attr_dict; - char tempfile; + char tempfile; }; @@ -111,14 +111,16 @@ static struct ic_ _ic = { }; static void -pdf_init_ximage_struct (pdf_ximage *I, const char *ident, const char *filename, pdf_obj *dict) +pdf_init_ximage_struct (pdf_ximage *I, + const char *ident, const char *filename, + long page_no, pdf_obj *dict) { if (ident) { I->ident = NEW(strlen(ident)+1, char); strcpy(I->ident, ident); } else I ->ident = NULL; - I->page_no = I->page_count = 0; + I->page_no = page_no; if (filename) { I->filename = NEW(strlen(filename)+1, char); strcpy(I->filename, filename); @@ -161,7 +163,7 @@ pdf_clean_ximage_struct (pdf_ximage *I) pdf_release_obj(I->resource); if (I->attr_dict) pdf_release_obj(I->attr_dict); - pdf_init_ximage_struct(I, NULL, NULL, NULL); + pdf_init_ximage_struct(I, NULL, NULL, 0, NULL); } @@ -208,6 +210,7 @@ pdf_close_images (void) _opts.cmdtmpl = NULL; } + static int source_image_type (FILE *fp) { @@ -260,8 +263,7 @@ load_image (const char *ident, const char *fullname, int format, FILE *fp, } I = &ic->ximages[id]; - pdf_init_ximage_struct(I, ident, ident, dict); - pdf_ximage_set_page(I, page_no, 0); + pdf_init_ximage_struct(I, ident, fullname, page_no, dict); switch (format) { case IMAGE_TYPE_JPEG: @@ -290,8 +292,14 @@ load_image (const char *ident, const char *fullname, int format, FILE *fp, case IMAGE_TYPE_PDF: if (_opts.verbose) MESG("[PDF]"); - if (pdf_include_page(I, fp) < 0) - goto error; + { + int result = pdf_include_page(I, fp, fullname); + if (result > 0) + /* PDF version too recent */ + result = ps_include_page(I); + if (result < 0) + goto error; + } if (_opts.verbose) MESG(",Page:%ld", I->page_no); I->subtype = PDF_XOBJECT_TYPE_FORM; @@ -300,7 +308,7 @@ load_image (const char *ident, const char *fullname, int format, FILE *fp, default: if (_opts.verbose) MESG(format == IMAGE_TYPE_EPS ? "[PS]" : "[UNKNOWN]"); - if (ps_include_page(I, fullname) < 0) + if (ps_include_page(I) < 0) goto error; if (_opts.verbose) MESG(",Page:%ld", I->page_no); @@ -339,24 +347,31 @@ pdf_ximage_findresource (const char *ident, long page_no, pdf_obj *dict) struct ic_ *ic = &_ic; int id = -1; pdf_ximage *I; - char *fullname; + char *fullname, *f = NULL; int format; FILE *fp; for (id = 0; id < ic->count; id++) { I = &ic->ximages[id]; - if (I->ident && !strcmp(ident, I->ident) && - I->page_no == page_no + (page_no < 0 ? I->page_count+1 : 0) && - I->attr_dict == dict) { - return id; + if (I->ident && !strcmp(ident, I->ident)) { + f = I->filename; + if (I->page_no == page_no && I->attr_dict == dict) { + return id; + } } } - /* try loading image */ - fullname = dpx_find_file(ident, "_pic_", ""); - if (!fullname) { - WARN("Error locating image file \"%s\"", ident); - return -1; + if (f) { + /* we already have converted this file; f is the temporary file name */ + fullname = NEW(strlen(f)+1, char); + strcpy(fullname, f); + } else { + /* try loading image */ + fullname = dpx_find_file(ident, "_pic_", ""); + if (!fullname) { + WARN("Error locating image file \"%s\"", ident); + return -1; + } } fp = dpx_fopen(fullname, FOPEN_RBIN_MODE); @@ -472,12 +487,6 @@ pdf_ximage_init_image_info (ximage_info *info) info->xdensity = info->ydensity = 1.0; } -char * -pdf_ximage_get_ident (pdf_ximage *I) -{ - return I->ident; -} - void pdf_ximage_set_image (pdf_ximage *I, void *image_info, pdf_obj *resource) { @@ -534,14 +543,6 @@ pdf_ximage_get_page (pdf_ximage *I) return I->page_no; } -void -pdf_ximage_set_page (pdf_ximage *I, long page_no, long page_count) -{ - I->page_no = page_no; - I->page_count = page_count; -} - - #define CHECK_ID(c,n) do {\ if ((n) < 0 || (n) >= (c)->count) {\ ERROR("Invalid XObject ID: %d", (n));\ @@ -581,7 +582,7 @@ pdf_ximage_defineresource (const char *ident, I = &ic->ximages[id]; - pdf_init_ximage_struct(I, ident, NULL, NULL); + pdf_init_ximage_struct(I, ident, NULL, 0, NULL); switch (subtype) { case PDF_XOBJECT_TYPE_IMAGE: @@ -614,6 +615,37 @@ pdf_ximage_get_resname (int id) return I->res_name; } +int +pdf_ximage_get_subtype (int id) +{ + struct ic_ *ic = &_ic; + pdf_ximage *I; + + CHECK_ID(ic, id); + + I = GET_IMAGE(ic, id); + + return I->subtype; +} + +void +pdf_ximage_set_attr (int id, long width, long height, double xdensity, double ydensity, double llx, double lly, double urx, double ury) +{ + struct ic_ *ic = &_ic; + pdf_ximage *I; + + CHECK_ID(ic, id); + + I = GET_IMAGE(ic, id); + I->attr.width = width; + I->attr.height = height; + I->attr.xdensity = xdensity; + I->attr.ydensity = ydensity; + I->attr.bbox.llx = llx; + I->attr.bbox.lly = lly; + I->attr.bbox.urx = urx; + I->attr.bbox.ury = ury; +} /* depth... * Dvipdfm treat "depth" as "yoffset" for pdf:image and pdf:uxobj @@ -835,9 +867,10 @@ char *get_distiller_template (void) } static int -ps_include_page (pdf_ximage *ximage, const char *filename) +ps_include_page (pdf_ximage *ximage) { char *distiller_template = _opts.cmdtmpl; + char *filename = ximage->filename; char *temp; FILE *fp; int error = 0; @@ -855,17 +888,6 @@ ps_include_page (pdf_ximage *ximage, const char *filename) return -1; } -#ifdef MIKTEX - { - char *p; - for (p = (char *)filename; *p; p++) { - if (*p == '\\') *p = '/'; - } - for (p = (char *)temp; *p; p++) { - if (*p == '\\') *p = '/'; - } - } -#endif if (keep_cache != -1 && stat(temp, &stat_t)==0 && stat(filename, &stat_o)==0 && stat_t.st_mtime > stat_o.st_mtime) { /* cache exist */ @@ -895,8 +917,7 @@ ps_include_page (pdf_ximage *ximage, const char *filename) return -1; } pdf_set_ximage_tempfile(ximage, temp); -// error = pdf_include_page(ximage, fp, 0, pdfbox_crop); - error = pdf_include_page(ximage, fp); + error = pdf_include_page(ximage, fp, temp); MFCLOSE(fp); /* See pdf_close_images for why we cannot delete temporary files here. */ diff --git a/Build/source/texk/dvipdf-x/xsrc/pdfximage.h b/Build/source/texk/dvipdf-x/xsrc/pdfximage.h index b1746aa3383..6341605b57a 100644 --- a/Build/source/texk/dvipdf-x/xsrc/pdfximage.h +++ b/Build/source/texk/dvipdf-x/xsrc/pdfximage.h @@ -59,6 +59,7 @@ extern void pdf_init_images (void); extern void pdf_close_images (void); extern char *pdf_ximage_get_resname (int xobj_id); +extern int pdf_ximage_get_subtype (int xobj_id); extern pdf_obj *pdf_ximage_get_reference (int xobj_id); @@ -70,10 +71,8 @@ extern int pdf_ximage_defineresource (const char *ident, int subtype, /* Called by pngimage, jpegimage, epdf, mpost, etc. */ extern void pdf_ximage_init_image_info (ximage_info *info); extern void pdf_ximage_init_form_info (xform_info *info); -extern char *pdf_ximage_get_ident (pdf_ximage *ximage); extern void pdf_ximage_set_image (pdf_ximage *ximage, void *info, pdf_obj *resource); extern void pdf_ximage_set_form (pdf_ximage *ximage, void *info, pdf_obj *resource); -extern void pdf_ximage_set_page (pdf_ximage *ximage, long page_no, long page_count); extern long pdf_ximage_get_page (pdf_ximage *I); /* from psimage.h */ @@ -89,4 +88,8 @@ pdf_ximage_scale_image (int id, /* from dvipdfmx.c */ extern void pdf_ximage_disable_ebb (void); + +/* from spc_pdfm.c */ +extern int pdf_ximage_get_subtype (int xobj_id); +extern void pdf_ximage_set_attr (int xobj_id, long width, long height, double xdensity, double ydensity, double llx, double lly, double urx, double ury); #endif /* _PDFXIMAGE_H_ */ diff --git a/Build/source/texk/dvipdf-x/xsrc/spc_pdfm.c b/Build/source/texk/dvipdf-x/xsrc/spc_pdfm.c index 7aa8863ae9b..c7b25c5cc8b 100644 --- a/Build/source/texk/dvipdf-x/xsrc/spc_pdfm.c +++ b/Build/source/texk/dvipdf-x/xsrc/spc_pdfm.c @@ -670,7 +670,7 @@ spc_handler_pdfm_annot (struct spc_env *spe, struct spc_arg *args) if (ident) spc_push_object(ident, pdf_link_obj(annot_dict)); /* This add reference. */ - pdf_doc_add_annot(pdf_doc_current_page_number(), &rect, annot_dict); + pdf_doc_add_annot(pdf_doc_current_page_number(), &rect, annot_dict, 1); if (ident) { spc_flush_object(ident); @@ -832,7 +832,7 @@ spc_handler_pdfm_etrans (struct spc_env *spe, struct spc_arg *args) * starting a new page. */ pdf_dev_reset_fonts(); - pdf_dev_reset_color(); + pdf_dev_reset_color(0); return 0; } diff --git a/Build/source/texk/dvipdf-x/xsrc/specials.c b/Build/source/texk/dvipdf-x/xsrc/specials.c index 0b9800eb81b..e1cc2bb7a9f 100644 --- a/Build/source/texk/dvipdf-x/xsrc/specials.c +++ b/Build/source/texk/dvipdf-x/xsrc/specials.c @@ -22,8 +22,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#if HAVE_CONFIG_H -#include "config.h" +#ifdef HAVE_CONFIG_H +#include <config.h> #endif #include <stdarg.h> @@ -286,31 +286,12 @@ spc_lookup_object (const char *key) void spc_push_object (const char *key, pdf_obj *value) { - int error = 0; + ASSERT(named_objects); if (!key || !value) return; - if (PDF_OBJ_INDIRECTTYPE(value)) { - pdf_names_add_reference(named_objects, - key, strlen(key), value); - } else { - error = pdf_names_add_object(named_objects, - key, strlen(key), value); - if (!error) { - /* _FIXME_: - * Objects created by pdf:obj must always - * be written to output regardless of if - * they are actually used in document. - */ - pdf_obj *obj_ref = pdf_names_lookup_reference(named_objects, - key, strlen(key)); - if (obj_ref) - pdf_release_obj(obj_ref); - } - } - - return; + pdf_names_add_object(named_objects, key, strlen(key), value); } void |