diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/image')
15 files changed, 1887 insertions, 2279 deletions
diff --git a/Build/source/texk/web2c/luatexdir/image/epdf.c b/Build/source/texk/web2c/luatexdir/image/epdf.c deleted file mode 100644 index cf86a38fa34..00000000000 --- a/Build/source/texk/web2c/luatexdir/image/epdf.c +++ /dev/null @@ -1,81 +0,0 @@ -/* epdf.c - - Copyright 1996-2006 Han The Thanh <thanh@pdftex.org> - Copyright 2006-2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - -#include "ptexlib.h" -#include "inc-epdf.h" - -#include <string.h> - -static const char _svn_version[] = - "$Id: epdf.c 2599 2009-06-25 10:35:26Z taco $ " - "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.40.6/source/texk/web2c/luatexdir/image/epdf.c $"; - -fd_entry *epdf_create_fontdescriptor(fm_entry * fm, int stemV) -{ - fd_entry *fd; - if ((fd = lookup_fd_entry(fm->ff_name, fm->slant, fm->extend)) == NULL) { - fm->in_use = true; - fd = new_fd_entry(); - fd->fm = fm; - register_fd_entry(fd); - fd->fd_objnum = pdf_new_objnum(); - assert(fm->ps_name != NULL); - fd->fontname = xstrdup(fm->ps_name); /* just fallback */ - // stemV must be copied - fd->font_dim[STEMV_CODE].val = stemV; - fd->font_dim[STEMV_CODE].set = true; - fd->gl_tree = avl_create(comp_string_entry, NULL, &avl_xallocator); - assert(fd->gl_tree != NULL); - } - return fd; -} - -/*********************************************************************** - * Mark glyphs used by embedded PDF file: - * 1. build fontdescriptor, if not yet existing - * 2. mark glyphs directly there - * - * Input charset from xpdf is a string of glyph names including - * leading slashes, but without blanks between them, like: /a/b/c -***********************************************************************/ - -void epdf_mark_glyphs(fd_entry * fd, char *charset) -{ - char *p, *q, *s; - char *glyph; - void **aa; - if (charset == NULL) - return; - assert(fd != NULL); - for (s = charset + 1, q = charset + strlen(charset); s < q; s = p + 1) { - for (p = s; *p != '\0' && *p != '/'; p++); - *p = '\0'; - if ((char *) avl_find(fd->gl_tree, s) == NULL) { - glyph = xstrdup(s); - aa = avl_probe(fd->gl_tree, glyph); - assert(aa != NULL); - } - } -} - -void epdf_free(void) -{ - epdf_check_mem(); -} diff --git a/Build/source/texk/web2c/luatexdir/image/epdf.h b/Build/source/texk/web2c/luatexdir/image/epdf.h index c619b20f08f..6d2632b0e54 100644 --- a/Build/source/texk/web2c/luatexdir/image/epdf.h +++ b/Build/source/texk/web2c/luatexdir/image/epdf.h @@ -1,8 +1,7 @@ /* epdf.h Copyright 1996-2006 Han The Thanh <thanh@pdftex.org> - Copyright 2006-2009 Taco Hoekwater <taco@luatex.org> - + Copyright 2006-2010 Taco Hoekwater <taco@luatex.org> This file is part of LuaTeX. LuaTeX is free software; you can redistribute it and/or modify it under @@ -18,11 +17,50 @@ You should have received a copy of the GNU General Public License along with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ -/* $Id: epdf.h 2327 2009-04-18 12:47:21Z hhenkel $ */ +/* $Id: epdf.h 3407 2010-01-28 16:27:39Z taco $ */ + +// this is the common header file for C++ sources pdftoepdf.cc and lepdflib.cc + +#ifndef EPDF_H +# define EPDF_H + +# include <stdlib.h> +# include <math.h> +# include <stddef.h> +# include <stdio.h> +# include <string.h> +# include <kpathsea/c-ctype.h> +# include <sys/stat.h> +# ifdef POPPLER_VERSION +# define GString GooString +# include <dirent.h> +# include <poppler-config.h> +# include <goo/GooString.h> +# include <goo/gmem.h> +# include <goo/gfile.h> +# else +# include <aconf.h> +# include <GString.h> +# include <gmem.h> +# include <gfile.h> +# include <assert.h> +# endif +# include "Object.h" +# include "Stream.h" +# include "Array.h" +# include "Dict.h" +# include "XRef.h" +# include "Catalog.h" +# include "Link.h" +# include "Page.h" +# include "GfxFont.h" +# include "PDFDoc.h" +# include "GlobalParams.h" +# include "Error.h" extern "C" { -#include <kpathsea/c-auto.h> +# include <kpathsea/c-auto.h> extern char *xstrdup(const char *); @@ -30,91 +68,106 @@ extern "C" { typedef const char *const_string; /* including kpathsea/types.h doesn't work on some systems */ -#define KPATHSEA_CONFIG_H /* avoid including other kpathsea header files */ +# define KPATHSEA_CONFIG_H /* avoid including other kpathsea header files */ /* from web2c/config.h */ -#ifdef CONFIG_H /* CONFIG_H has been defined by some xpdf */ -# undef CONFIG_H /* header file */ -#endif +# ifdef CONFIG_H /* CONFIG_H has been defined by some xpdf */ +# undef CONFIG_H /* header file */ +# endif -#include <web2c/c-auto.h> /* define SIZEOF_LONG */ -#include <web2c/config.h> /* define type integer */ +# include <web2c/c-auto.h> /* define SIZEOF_LONG */ -#include <web2c/luatexdir/ptexmac.h> -#include "openbsd-compat.h" -#include "image.h" -#include "../utils/avlstuff.h" +# include "openbsd-compat.h" +# include "image.h" +# include "utils/avlstuff.h" +# include "pdf/pdftypes.h" - extern void unrefPdfDocument(char *); +# include "lua51/lua.h" +# include "lua51/lauxlib.h" - extern integer epdf_page_box; - extern void *epdf_xref; - extern integer epdf_lastGroupObjectNum; - - extern integer pdf_box_spec_media; - extern integer pdf_box_spec_crop; - extern integer pdf_box_spec_bleed; - extern integer pdf_box_spec_trim; - extern integer pdf_box_spec_art; - - extern longinteger pdf_stream_length; - extern longinteger pdf_ptr; - extern integer pool_ptr; - typedef unsigned char eight_bits; - extern eight_bits *pdf_buf; - extern integer pdf_buf_size; - extern integer pdf_os_mode; - extern eight_bits pdf_last_byte; - extern integer fixed_inclusion_copy_font; - - extern char notdef[]; - - extern integer fixed_replace_font; - - extern int is_subsetable(struct fm_entry *); - extern struct fm_entry *lookup_fontmap(char *); - extern integer get_fontfile(struct fm_entry *); - extern integer get_fontname(struct fm_entry *); - extern integer pdf_new_objnum(void); - extern void read_pdf_info(image_dict *, integer, integer); - extern void embed_whole_font(struct fd_entry *); - extern void epdf_check_mem(void); + /* pdfgen.c */ + __attribute__ ((format(printf, 2, 3))) + extern void pdf_printf(PDF, const char *fmt, ...); + extern void pdf_puts(PDF, const char *); + extern void pdf_begin_obj(PDF, int, bool); + extern void pdf_end_obj(PDF); + extern void pdf_begin_stream(PDF); + extern void pdf_end_stream(PDF); + extern void pdf_room(PDF, int); +# define pdf_out(B,A) do { pdf_room(B,1); B->buf[B->ptr++] = A; } while (0) + + /* pdftables.c */ + extern int pdf_new_objnum(PDF); + + /* epdf.c */ extern void epdf_free(void); + + /* pdftoepdf.cc */ + extern void read_pdf_info(image_dict *, int, int, img_readtype_e); + extern void write_epdf(PDF, image_dict *); + extern void unrefPdfDocument(char *); + extern void epdf_check_mem(void); + + /* utils.c */ __attribute__ ((format(printf, 1, 2))) - extern void pdf_printf(const char *fmt, ...); - extern void pdf_puts(const char *); - extern void pdf_begin_stream(void); - extern void pdf_end_obj(void); - extern void pdf_end_stream(void); - extern void pdf_flush(void); + extern void pdftex_warn(const char *fmt, ...); __attribute__ ((noreturn, format(printf, 1, 2))) extern void pdftex_fail(const char *fmt, ...); - __attribute__ ((format(printf, 1, 2))) - extern void pdftex_warn(const char *fmt, ...); - __attribute__ ((format(printf, 1, 2))) - extern void tex_printf(const char *, ...); - extern void write_epdf(image_dict *); - extern void write_additional_epdf_objects(void); - extern void zpdf_begin_dict(integer, bool); - extern void zpdf_begin_obj(integer, bool); - extern void zpdf_create_obj(integer, integer); - extern void zpdf_new_dict(integer, integer, bool); - extern void zpdf_os_get_os_buf(integer); - -/* epdf.c */ - extern int get_fd_objnum(struct fd_entry *); - extern int get_fn_objnum(struct fd_entry *); - -#include "../inc-epdf.h" - -/* utils.c */ extern char *convertStringToPDFString(char *in, int len); extern char *stripzeros(char *a); -/* config.c */ - extern integer cfgpar(integer); - -/* avlstuff.c */ - extern void avl_put_obj(integer, integer); - extern integer avl_find_obj(integer, integer, integer); -} + /* lepdflib.c */ + int luaopen_epdf(lua_State * L); + +}; + +/**********************************************************************/ + +// PdfObject encapsulates the xpdf Object type, +// and properly frees its resources on destruction. +// Use obj-> to access members of the Object, +// and &obj to get a pointer to the object. +// It is no longer necessary to call Object::free explicitely. + +// *INDENT-OFF* +class PdfObject { + public: + PdfObject() { // nothing + } + ~PdfObject() { + iObject.free(); + } + Object *operator->() { + return &iObject; + } + Object *operator&() { + return &iObject; + } + private: // no copying or assigning + PdfObject(const PdfObject &); + void operator=(const PdfObject &); + public: + Object iObject; +}; +// *INDENT-ON* + +/**********************************************************************/ + +struct InObj { + Ref ref; // ref in original PDF + int num; // new object number in output PDF + InObj *next; // next entry in list of indirect objects +}; + +struct PdfDocument { + char *file_path; // full file name including path + char *checksum; // for reopening + PDFDoc *doc; + InObj *inObjList; // temporary linked list + avl_table *ObjMapTree; // permanent over luatex run + int occurences; // number of references to the PdfDocument; it can be deleted when occurences == 0 +}; + +PdfDocument *refPdfDocument(char *file_path); + +#endif /* EPDF_H */ diff --git a/Build/source/texk/web2c/luatexdir/image/epdf.w b/Build/source/texk/web2c/luatexdir/image/epdf.w new file mode 100644 index 00000000000..c52f148ffdf --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/epdf.w @@ -0,0 +1,34 @@ +% epdf.w + +% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org> +% Copyright 2006-2009 Taco Hoekwater <taco@@luatex.org> + +% This file is part of LuaTeX. + +% LuaTeX is free software; you can redistribute it and/or modify it under +% the terms of the GNU General Public License as published by the Free +% Software Foundation; either version 2 of the License, or (at your +% option) any later version. + +% LuaTeX is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +% License for more details. + +% You should have received a copy of the GNU General Public License along +% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. + +@ @c +static const char _svn_version[] = + "$Id: epdf.w 3584 2010-04-02 17:45:55Z hhenkel $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/image/epdf.w $"; + +#include "ptexlib.h" + +@ This must the be shortest C file we have that actually does something. + +@c +void epdf_free(void) +{ + epdf_check_mem(); +} diff --git a/Build/source/texk/web2c/luatexdir/image/image.h b/Build/source/texk/web2c/luatexdir/image/image.h index a2d47f6a471..c4d0c3963f7 100644 --- a/Build/source/texk/web2c/luatexdir/image/image.h +++ b/Build/source/texk/web2c/luatexdir/image/image.h @@ -1,7 +1,7 @@ /* image.h Copyright 1996-2006 Han The Thanh <thanh@pdftex.org> - Copyright 2006-2009 Taco Hoekwater <taco@luatex.org> + Copyright 2006-2010 Taco Hoekwater <taco@luatex.org> This file is part of LuaTeX. @@ -18,23 +18,20 @@ You should have received a copy of the GNU General Public License along with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ -/* $Id: image.h 2336 2009-04-19 08:38:24Z hhenkel $ */ +/* $Id: image.h 3388 2010-01-26 10:59:04Z taco $ */ #ifndef IMAGE_H # define IMAGE_H # include <png.h> +# include "pdf/pdftypes.h" /* for scaled_whd */ # define JPG_UINT16 unsigned int # define JPG_UINT32 unsigned long # define JPG_UINT8 unsigned char -# define IMAGE_COLOR_B 1 -# define IMAGE_COLOR_C 2 -# define IMAGE_COLOR_I 4 - -extern integer zround(double); /* from zround.c */ -# define bp2int(p) zround(p * (one_hundred_bp / 100.0)) +extern int do_zround(double r); /* from utils.c */ +# define bp2int(p) do_zround(p * (one_hundred_bp / 100.0)) # define int2bp(i) (i * 100.0 / one_hundred_bp) # define TYPE_IMG "image" @@ -83,31 +80,33 @@ typedef enum { PDF_BOX_SPEC_NONE, PDF_BOX_SPEC_MEDIA, PDF_BOX_SPEC_CROP, /**********************************************************************/ typedef struct { - integer objnum; - integer index; /* /Im1, /Im2, ... */ - integer x_size; /* dimensions in pixel counts as in JPG/PNG/JBIG2 file */ - integer y_size; - integer x_orig; /* origin in sp for PDF files */ - integer y_orig; - integer x_res; /* pixel resolution as in JPG/PNG/JBIG2 file */ - integer y_res; - integer rotation; /* rotation (multiples of 90 deg.) for PDF files */ - integer colorspace; /* number of /ColorSpace object */ - integer group_ref; /* if it's <=0, the page has no group */ - integer total_pages; - integer page_num; /* requested page (by number) */ + int objnum; + int index; /* /Im1, /Im2, ... */ + scaled_whd dimen; /* TeX dimensions given to \pdfximage */ + int transform; /* transform given to \pdfximage */ + int x_size; /* dimensions in pixel counts as in JPG/PNG/JBIG2 file */ + int y_size; + int x_orig; /* origin in sp for PDF files */ + int y_orig; + int x_res; /* pixel resolution as in JPG/PNG/JBIG2 file */ + int y_res; + int rotation; /* rotation (multiples of 90 deg.) for PDF files */ + int colorspace; /* number of /ColorSpace object */ + int group_ref; /* if it's <=0, the page has no group */ + int total_pages; + int page_num; /* requested page (by number) */ char *pagename; /* requested page (by name) */ char *filename; /* requested raw file name */ char *filepath; /* full file path after kpathsea */ char *attr; /* additional image dict entries */ FILE *file; imgtype_e image_type; - int color_space; /* used color space. See JPG_ constants */ + int procset; /* /ProcSet flags */ int color_depth; /* color depth */ pdfboxspec_e page_box_spec; /* PDF page box spec.: media/crop/bleed/trim/art */ - integer bbox[4]; + int bbox[4]; dict_state state; - integer flags; + int flags; union { pdf_stream_struct *pdfstream; png_img_struct *png; @@ -118,6 +117,11 @@ typedef struct { # define img_objnum(N) ((N)->objnum) # define img_index(N) ((N)->index) +# define img_dimen(N) ((N)->dimen) +# define img_width(N) ((N)->dimen.wd) +# define img_height(N) ((N)->dimen.ht) +# define img_depth(N) ((N)->dimen.dp) +# define img_transform(N) ((N)->transform) # define img_xsize(N) ((N)->x_size) # define img_ysize(N) ((N)->y_size) # define img_xorig(N) ((N)->x_orig) @@ -135,11 +139,12 @@ typedef struct { # define img_attr(N) ((N)->attr) # define img_file(N) ((N)->file) # define img_type(N) ((N)->image_type) -# define img_color(N) ((N)->color_space) +# define img_procset(N) ((N)->procset) # define img_colordepth(N) ((N)->color_depth) # define img_pagebox(N) ((N)->page_box_spec) # define img_bbox(N) ((N)->bbox) # define img_state(N) ((N)->state) +# define img_flags(N) ((N)->flags) # define img_pdfstream_ptr(N) ((N)->img_struct.pdfstream) # define img_pdfstream_stream(N) ((N)->img_struct.pdfstream->stream) @@ -154,42 +159,39 @@ typedef struct { # define img_jb2_ptr(N) ((N)->img_struct.jb2) # define F_FLAG_BBOX (1 << 0) +# define F_FLAG_GROUP (1 << 1) # define img_set_bbox(N) (img_flags(N) |= F_FLAG_BBOX) # define img_unset_bbox(N) (img_flags(N) &= ~F_FLAG_BBOX) # define img_is_bbox(N) ((img_flags(N) & F_FLAG_BBOX) != 0) +# define img_set_group(N) (img_flags(N) |= F_FLAG_GROUP) +# define img_unset_group(N) (img_flags(N) &= ~F_FLAG_GROUP) +# define img_is_group(N) ((img_flags(N) & F_FLAG_GROUP) != 0) + +# define epdf_xsize(a) img_xsize(idict_array[a]) +# define epdf_ysize(a) img_ysize(idict_array[a]) +# define epdf_orig_x(a) img_xorig(idict_array[a]) +# define epdf_orig_y(a) img_yorig(idict_array[a]) + +# define is_pdf_image(a) (img_type(idict_array[a]) == IMG_TYPE_PDF) +# define is_png_image(a) (img_type(idict_array[a]) == IMG_TYPE_PNG) + +# define img_is_refered(N) (img_index(N) != -1) + /**********************************************************************/ +/* image structure corresponds to pdfrefximage node */ typedef struct { - integer width; /* requested/actual TeX dimensions */ - integer height; - integer depth; - integer transform; - integer flags; + scaled_whd dimen; /* requested/actual TeX dimensions */ + int transform; image_dict *dict; - int array_idx; /* index within img_array */ int dict_ref; /* luaL_ref() reference */ } image; -# define img_width(N) ((N)->width) -# define img_height(N) ((N)->height) -# define img_depth(N) ((N)->depth) -# define img_transform(N) ((N)->transform) -# define img_flags(N) ((N)->flags) # define img_dict(N) ((N)->dict) -# define img_arrayidx(N) ((N)->array_idx) # define img_dictref(N) ((N)->dict_ref) -# define img_is_refered(N) (img_arrayidx(N) != -1) - -# define F_FLAG_SCALED (1 << 0) - -# define img_flags(N) ((N)->flags) -# define img_set_scaled(N) (img_flags(N) |= F_FLAG_SCALED) -# define img_unset_scaled(N) (img_flags(N) &= ~F_FLAG_SCALED) -# define img_is_scaled(N) ((img_flags(N) & F_FLAG_SCALED) != 0) - # define set_wd_running(N) (img_width(N) = null_flag) # define set_ht_running(N) (img_height(N) = null_flag) # define set_dp_running(N) (img_depth(N) = null_flag) diff --git a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc index 536c6398cd7..8a177163a76 100644 --- a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc +++ b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc @@ -1,7 +1,7 @@ /* pdftoepdf.cc - + Copyright 1996-2006 Han The Thanh <thanh@pdftex.org> - Copyright 2006-2008 Taco Hoekwater <taco@luatex.org> + Copyright 2006-2010 Taco Hoekwater <taco@luatex.org> This file is part of LuaTeX. @@ -18,46 +18,13 @@ You should have received a copy of the GNU General Public License along with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ -#include <stdlib.h> -#include <math.h> -#include <stddef.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#ifdef POPPLER_VERSION -# define GString GooString -# include <dirent.h> -# include <poppler-config.h> -# include <goo/GooString.h> -# include <goo/gmem.h> -# include <goo/gfile.h> -#else -# include <aconf.h> -# include <GString.h> -# include <gmem.h> -# include <gfile.h> -# include <assert.h> -#endif -#include "Object.h" -#include "Stream.h" -#include "Array.h" -#include "Dict.h" -#include "XRef.h" -#include "Catalog.h" -#include "Link.h" -#include "Page.h" -#include "GfxFont.h" -#include "PDFDoc.h" -#include "GlobalParams.h" -#include "Error.h" +static const char _svn_version[] = + "$Id: pdftoepdf.cc 3431 2010-02-17 20:35:50Z oneiros $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/image/pdftoepdf.cc $"; #include "epdf.h" -static const char _svn_version[] = - "$Id: pdftoepdf.cc 2448 2009-06-08 07:43:50Z taco $ " - "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.40.6/source/texk/web2c/luatexdir/image/pdftoepdf.cc $"; - -#define one_hundred_bp 6578176 /* 7227 * 65536 / 72 */ +#define one_hundred_bp 6578176 // one_hundred_bp = 7227 * 65536 / 72 // This file is mostly C and not very much C++; it's just used to interface // the functions of xpdf, which happens to be written in C++. @@ -67,81 +34,16 @@ static const char _svn_version[] = #define pdfkeyprefix "PTEX" -// PdfObject encapsulates the xpdf Object type, -// and properly frees its resources on destruction. -// Use obj-> to access members of the Object, -// and &obj to get a pointer to the object. -// It is no longer necessary to call Object::free explicitely. - -/* *INDENT-OFF* */ -class PdfObject { - public: - PdfObject() { // nothing - } - ~PdfObject() { - iObject.free(); - } - Object *operator->() { - return &iObject; - } - Object *operator&() { - return &iObject; - } - private: // no copying or assigning - PdfObject(const PdfObject &); - void operator=(const PdfObject &); - public: - Object iObject; -}; -/* *INDENT-ON* */ - -// When copying the Resources of the selected page, all objects are copied -// recusively top-down. Indirect objects however are not fetched during -// copying, but get a new object number from pdfTeX and then will be -// appended into a linked list. Duplicates are checked and removed from the -// list of indirect objects during appending. - -enum InObjType { objFont, objFontDesc, objOther }; - -struct InObj { - Ref ref; // ref in original PDF - InObjType type; // object type - integer num; // new object number in output PDF - fd_entry *fd; // pointer to /FontDescriptor object structure - integer enc_objnum; // Encoding for objFont - int written; // has it been written to output PDF? - InObj *next; // next entry in list of indirect objects -}; - -struct UsedEncoding { - integer enc_objnum; - GfxFont *font; - UsedEncoding *next; -}; - -static XRef *xref = NULL; -static InObj *inObjList = NULL; -static UsedEncoding *encodingList; static GBool isInit = gFalse; -static bool groupIsIndirect; -static PdfObject lastGroup; //********************************************************************** -// Maintain AVL tree of open embedded PDF files +// Maintain AVL tree of all PDF files for embedding static avl_table *PdfDocumentTree = NULL; -struct PdfDocument { - char *file_path; // full file name including path - PDFDoc *doc; - XRef *xref; - InObj *inObjList; - int occurences; // number of references to the PdfDocument; it can be deleted when occurences == 0 -}; - -/* AVL sort PdfDocument into PdfDocumentTree by file_path */ +// AVL sort PdfDocument into PdfDocumentTree by file_path -static int CompPdfDocument(const void *pa, const void *pb, void *p) +static int CompPdfDocument(const void *pa, const void *pb, void * /*p */ ) { return strcmp(((const PdfDocument *) pa)->file_path, ((const PdfDocument *) pb)->file_path); @@ -154,8 +56,7 @@ static PdfDocument *findPdfDocument(char *file_path) PdfDocument *pdf_doc, tmp; assert(file_path != NULL); if (PdfDocumentTree == NULL) - PdfDocumentTree = avl_create(CompPdfDocument, NULL, &avl_xallocator); - assert(PdfDocumentTree != NULL); + return NULL; tmp.file_path = file_path; pdf_doc = (PdfDocument *) avl_find(PdfDocumentTree, &tmp); return pdf_doc; @@ -164,26 +65,35 @@ static PdfDocument *findPdfDocument(char *file_path) // Returns pointer to PdfDocument structure for PDF file. // Creates a new structure if it doesn't exist yet. -static PdfDocument *refPdfDocument(char *file_path) +char *get_file_checksum(char *a); + +PdfDocument *refPdfDocument(char *file_path) { PdfDocument *pdf_doc = findPdfDocument(file_path); if (pdf_doc == NULL) { + if (PdfDocumentTree == NULL) + PdfDocumentTree = + avl_create(CompPdfDocument, NULL, &avl_xallocator); pdf_doc = new PdfDocument; pdf_doc->file_path = xstrdup(file_path); + pdf_doc->checksum = get_file_checksum(file_path); void **aa = avl_probe(PdfDocumentTree, pdf_doc); assert(aa != NULL); + pdf_doc->ObjMapTree = NULL; + pdf_doc->doc = NULL; + } + if (pdf_doc->doc == NULL) { GString *docName = new GString(pdf_doc->file_path); pdf_doc->doc = new PDFDoc(docName); // takes ownership of docName if (!pdf_doc->doc->isOk() || !pdf_doc->doc->okToPrint()) pdftex_fail("xpdf: reading PDF image failed"); - pdf_doc->xref = NULL; pdf_doc->inObjList = NULL; pdf_doc->occurences = 0; // 0 = unreferenced + } #ifdef DEBUG - fprintf(stderr, "\nluatex Debug: Creating %s (%d)\n", - pdf_doc->file_path, pdf_doc->occurences); + fprintf(stderr, "\nluatex Debug: Creating %s (%d)\n", + pdf_doc->file_path, pdf_doc->occurences); #endif - } pdf_doc->occurences++; #ifdef DEBUG fprintf(stderr, "\nluatex Debug: Incrementing %s (%d)\n", @@ -192,293 +102,94 @@ static PdfDocument *refPdfDocument(char *file_path) return pdf_doc; } -static void deletePdfDocument(PdfDocument *); +//********************************************************************** +// AVL sort ObjMap into ObjMapTree by object number and generation -// Called when an image has been written and its resources in image_tab are -// freed and it's not referenced anymore. +// keep the ObjMap struct small, as these are accumulated until the end -void unrefPdfDocument(char *file_path) +struct ObjMap { + Ref in; // object num/gen in orig. PDF file + int out_num; // object num after embedding (gen == 0) +}; + +static int CompObjMap(const void *pa, const void *pb, void * /*p */ ) { - PdfDocument *pdf_doc = findPdfDocument(file_path); - assert(pdf_doc != NULL); - assert(pdf_doc->occurences > 0); // aim for point landing - pdf_doc->occurences--; -#ifdef DEBUG - fprintf(stderr, "\nluatex Debug: Decrementing %s (%d)\n", - pdf_doc->file_path, pdf_doc->occurences); -#endif - if (pdf_doc->occurences == 0) { -#ifdef DEBUG - fprintf(stderr, "\nluatex Debug: Deleting %s\n", pdf_doc->file_path); -#endif - void *a = avl_delete(PdfDocumentTree, pdf_doc); - assert((PdfDocument *) a == pdf_doc); - deletePdfDocument(pdf_doc); - } + const Ref *a = &(((const ObjMap *) pa)->in); + const Ref *b = &(((const ObjMap *) pb)->in); + if (a->num > b->num) + return 1; + if (a->num < b->num) + return -1; + if (a->gen == b->gen) // most likely gen == 0 anyway + return 0; + if (a->gen < b->gen) + return -1; + return 1; } -//********************************************************************** - -// Replacement for -// Object *initDict(Dict *dict1){ initObj(objDict); dict = dict1; return this; } - -static void initDictFromDict(PdfObject & obj, Dict * dict) +static ObjMap *findObjMap(PdfDocument * pdf_doc, Ref in) { - obj->initDict(xref); - for (int i = 0, l = dict->getLength(); i < l; i++) { - Object obj1; - obj->dictAdd(copyString(dict->getKey(i)), dict->getValNF(i, &obj1)); - } + ObjMap *obj_map, tmp; + assert(pdf_doc != NULL); + if (pdf_doc->ObjMapTree == NULL) + return NULL; + tmp.in = in; + obj_map = (ObjMap *) avl_find(pdf_doc->ObjMapTree, &tmp); + return obj_map; } -static int addEncoding(GfxFont * gfont) +static void addObjMap(PdfDocument * pdf_doc, Ref in, int out_num) { - UsedEncoding *n; - n = new UsedEncoding; - n->next = encodingList; - encodingList = n; - n->font = gfont; - n->enc_objnum = pdf_new_objnum(); - return n->enc_objnum; + ObjMap *obj_map = NULL; + assert(findObjMap(pdf_doc, in) == NULL); + if (pdf_doc->ObjMapTree == NULL) + pdf_doc->ObjMapTree = avl_create(CompObjMap, NULL, &avl_xallocator); + obj_map = new ObjMap; + obj_map->in = in; + obj_map->out_num = out_num; + void **aa = avl_probe(pdf_doc->ObjMapTree, obj_map); + assert(aa != NULL); } -#define addFont(ref, fd, enc_objnum) \ - addInObj(objFont, ref, fd, enc_objnum) +// When copying the Resources of the selected page, all objects are +// copied recursively top-down. The findObjMap() function checks if an +// object has already been copied; if so, instead of copying just the +// new object number will be referenced. The ObjMapTree guarantees, +// that during the entire LuaTeX run any object from any embedded PDF +// file will end up max. once in the output PDF file. Indirect objects +// are not fetched during copying, but get a new object number from +// LuaTeX and then will be appended into a linked list. -// addFontDesc is only used to avoid writing the original FontDescriptor -// from the PDF file. - -#define addFontDesc(ref, fd) \ - addInObj(objFontDesc, ref, fd, 0) - -#define addOther(ref) \ - addInObj(objOther, ref, NULL, 0) - -static int addInObj(InObjType type, Ref ref, fd_entry * fd, integer e) +static int addInObj(PDF pdf, PdfDocument * pdf_doc, Ref ref) { - InObj *p, *q, *n = new InObj; - if (ref.num == 0) - pdftex_fail("PDF inclusion: invalid reference"); + ObjMap *obj_map; + InObj *p, *q, *n; + if (ref.num == 0) { + pdftex_fail("PDF inclusion: reference to invalid object" + " (is the included pdf broken?)"); + } + if ((obj_map = findObjMap(pdf_doc, ref)) != NULL) + return obj_map->out_num; + n = new InObj; n->ref = ref; - n->type = type; n->next = NULL; - n->fd = fd; - n->enc_objnum = e; - n->written = 0; - if (inObjList == NULL) - inObjList = n; + n->num = pdf_new_objnum(pdf); + addObjMap(pdf_doc, ref, n->num); + if (pdf_doc->inObjList == NULL) + pdf_doc->inObjList = n; else { - for (p = inObjList; p != NULL; p = p->next) { - if (p->ref.num == ref.num && p->ref.gen == ref.gen) { - delete n; - return p->num; - } - q = p; - } // it is important to add new objects at the end of the list, // because new objects are being added while the list is being // written out by writeRefs(). + for (p = pdf_doc->inObjList; p != NULL; p = p->next) + q = p; q->next = n; } - if (type == objFontDesc) - n->num = get_fd_objnum(fd); - else - n->num = pdf_new_objnum(); return n->num; } -static void copyName(char *s) -{ - pdf_puts("/"); - for (; *s != 0; s++) { - if (isdigit(*s) || isupper(*s) || islower(*s) || *s == '_' || - *s == '.' || *s == '-' || *s == '+') - pdfout(*s); - else - pdf_printf("#%.2X", *s & 0xFF); - } -} - -static int getNewObjectNumber(Ref ref) -{ - InObj *p; - if (inObjList == 0) { - pdftex_fail("No objects copied yet"); - } else { - for (p = inObjList; p != 0; p = p->next) { - if (p->ref.num == ref.num && p->ref.gen == ref.gen) { - return p->num; - } - } - pdftex_fail("Object not yet copied: %i %i", ref.num, ref.gen); - } -} - -static void copyObject(Object *); - -static void copyDictEntry(Object * obj, int i) -{ - PdfObject obj1; - copyName(obj->dictGetKey(i)); - pdf_puts(" "); - obj->dictGetValNF(i, &obj1); - copyObject(&obj1); - pdf_puts("\n"); -} - -static void copyDict(Object * obj) -{ - int i, l; - if (!obj->isDict()) - pdftex_fail("PDF inclusion: invalid dict type <%s>", - obj->getTypeName()); - for (i = 0, l = obj->dictGetLength(); i < l; ++i) - copyDictEntry(obj, i); -} - -static void copyFontDict(Object * obj, InObj * r) -{ - int i, l; - char *key; - if (!obj->isDict()) - pdftex_fail("PDF inclusion: invalid dict type <%s>", - obj->getTypeName()); - pdf_puts("<<\n"); - assert(r->type == objFont); // FontDescriptor is in fd_tree - for (i = 0, l = obj->dictGetLength(); i < l; ++i) { - key = obj->dictGetKey(i); - if (strncmp("FontDescriptor", key, strlen("FontDescriptor")) == 0 - || strncmp("BaseFont", key, strlen("BaseFont")) == 0 - || strncmp("Encoding", key, strlen("Encoding")) == 0) - continue; // skip original values - copyDictEntry(obj, i); - } - // write new FontDescriptor, BaseFont, and Encoding - pdf_printf("/FontDescriptor %d 0 R\n", (int) get_fd_objnum(r->fd)); - pdf_printf("/BaseFont %d 0 R\n", (int) get_fn_objnum(r->fd)); - pdf_printf("/Encoding %d 0 R\n", (int) r->enc_objnum); - pdf_puts(">>"); -} - -static void copyStream(Stream * str) -{ - int c; - str->reset(); - while ((c = str->getChar()) != EOF) { - pdfout(c); - pdf_last_byte = c; - } -} - -static void copyProcSet(Object * obj) -{ - int i, l; - PdfObject procset; - if (!obj->isArray()) - pdftex_fail("PDF inclusion: invalid ProcSet array type <%s>", - obj->getTypeName()); - pdf_puts("/ProcSet [ "); - for (i = 0, l = obj->arrayGetLength(); i < l; ++i) { - obj->arrayGetNF(i, &procset); - if (!procset->isName()) - pdftex_fail("PDF inclusion: invalid ProcSet entry type <%s>", - procset->getTypeName()); - copyName(procset->getName()); - pdf_puts(" "); - } - pdf_puts("]\n"); -} - -#define REPLACE_TYPE1C true - -static void copyFont(char *tag, Object * fontRef) -{ - PdfObject fontdict, subtype, basefont, fontdescRef, fontdesc, charset, - fontfile, ffsubtype, stemV; - GfxFont *gfont; - fd_entry *fd; - fm_entry *fontmap; - // Check whether the font has already been embedded before analysing it. - InObj *p; - Ref ref = fontRef->getRef(); - for (p = inObjList; p; p = p->next) { - if (p->ref.num == ref.num && p->ref.gen == ref.gen) { - copyName(tag); - pdf_printf(" %d 0 R ", (int) p->num); - return; - } - } - // Only handle included Type1 (and Type1C) fonts; anything else will be copied. - // Type1C fonts are replaced by Type1 fonts, if REPLACE_TYPE1C is true. - if (!fixed_inclusion_copy_font && fontRef->fetch(xref, &fontdict)->isDict() - && fontdict->dictLookup("Subtype", &subtype)->isName() - && !strcmp(subtype->getName(), "Type1") - && fontdict->dictLookup("BaseFont", &basefont)->isName() - && fontdict->dictLookupNF("FontDescriptor", &fontdescRef)->isRef() - && fontdescRef->fetch(xref, &fontdesc)->isDict() - && (fontdesc->dictLookup("FontFile", &fontfile)->isStream() - || (REPLACE_TYPE1C - && fontdesc->dictLookup("FontFile3", &fontfile)->isStream() - && fontfile->streamGetDict()->lookup("Subtype", - &ffsubtype)->isName() - && !strcmp(ffsubtype->getName(), "Type1C"))) - && (fontmap = lookup_fontmap(basefont->getName())) != NULL) { - // copy the value of /StemV - fontdesc->dictLookup("StemV", &stemV); - fd = epdf_create_fontdescriptor(fontmap, stemV->getInt()); - if (fontdesc->dictLookup("CharSet", &charset) && - charset->isString() && is_subsetable(fontmap)) - epdf_mark_glyphs(fd, charset->getString()->getCString()); - else - embed_whole_font(fd); - addFontDesc(fontdescRef->getRef(), fd); - copyName(tag); - gfont = GfxFont::makeFont(xref, tag, fontRef->getRef(), - fontdict->getDict()); - pdf_printf(" %d 0 R ", addFont(fontRef->getRef(), fd, - addEncoding(gfont))); - } else { - copyName(tag); - pdf_puts(" "); - copyObject(fontRef); - } -} - -static void copyFontResources(Object * obj) -{ - PdfObject fontRef; - int i, l; - if (!obj->isDict()) - pdftex_fail("PDF inclusion: invalid font resources dict type <%s>", - obj->getTypeName()); - pdf_puts("/Font << "); - for (i = 0, l = obj->dictGetLength(); i < l; ++i) { - obj->dictGetValNF(i, &fontRef); - if (fontRef->isRef()) - copyFont(obj->dictGetKey(i), &fontRef); - else - pdftex_fail("PDF inclusion: invalid font in reference type <%s>", - fontRef->getTypeName()); - } - pdf_puts(">>\n"); -} - -static void copyOtherResources(Object * obj, char *key) -{ - // copies all other resources (write_epdf handles Fonts and ProcSets), - // but gives a warning if an object is not a dictionary. - - if (!obj->isDict()) - //FIXME: Write the message only to the log file - pdftex_warn("PDF inclusion: invalid other resource which is no dict" - " (key '%s', type <%s>); copying it anyway.", - key, obj->getTypeName()); - copyName(key); - pdf_puts(" "); - copyObject(obj); -} - -// Function onverts double to string; very small and very large numbers +//********************************************************************** +// Function converts double to string; very small and very large numbers // are NOT converted to scientific notation. // n must be a number or real conforming to the implementation limits // of PDF as specified in appendix C.1 of the PDF Ref. @@ -536,165 +247,215 @@ static char *convertNumToPDF(double n) return (char *) buf; } -static void copyObject(Object * obj) +static void copyObject(PDF, PdfDocument *, Object *); + +static void copyString(PDF pdf, GString * string) { - PdfObject obj1; - int i, l, c; - Ref ref; char *p; - GString *s; - if (obj->isBool()) { - pdf_printf("%s", obj->getBool()? "true" : "false"); - } else if (obj->isInt()) { - pdf_printf("%i", obj->getInt()); - } else if (obj->isReal()) { - pdf_printf("%s", convertNumToPDF(obj->getReal())); - } else if (obj->isNum()) { - pdf_printf("%s", convertNumToPDF(obj->getNum())); - } else if (obj->isString()) { - s = obj->getString(); - p = s->getCString(); - l = s->getLength(); - if (strlen(p) == (unsigned int) l) { - pdf_puts("("); - for (; *p != 0; p++) { - c = (unsigned char) *p; - if (c == '(' || c == ')' || c == '\\') - pdf_printf("\\%c", c); - else if (c < 0x20 || c > 0x7F) - pdf_printf("\\%03o", c); - else - pdfout(c); - } - pdf_puts(")"); - } else { - pdf_puts("<"); - for (i = 0; i < l; i++) { - c = s->getChar(i) & 0xFF; - pdf_printf("%.2x", c); - } - pdf_puts(">"); - } - } else if (obj->isName()) { - copyName(obj->getName()); - } else if (obj->isNull()) { - pdf_puts("null"); - } else if (obj->isArray()) { - pdf_puts("["); - for (i = 0, l = obj->arrayGetLength(); i < l; ++i) { - obj->arrayGetNF(i, &obj1); - if (!obj1->isName()) - pdf_puts(" "); - copyObject(&obj1); + unsigned char c; + size_t i, l; + p = string->getCString(); + l = (size_t) string->getLength(); + if (strlen(p) == l) { + pdf_puts(pdf, "("); + for (; *p != 0; p++) { + c = (unsigned char) *p; + if (c == '(' || c == ')' || c == '\\') + pdf_printf(pdf, "\\%c", c); + else if (c < 0x20 || c > 0x7F) + pdf_printf(pdf, "\\%03o", (int) c); + else + pdf_out(pdf, c); } - pdf_puts("]"); - } else if (obj->isDict()) { - pdf_puts("<<\n"); - copyDict(obj); - pdf_puts(">>"); - } else if (obj->isStream()) { - initDictFromDict(obj1, obj->streamGetDict()); - obj->streamGetDict()->incRef(); - pdf_puts("<<\n"); - copyDict(&obj1); - pdf_puts(">>\n"); - pdf_puts("stream\n"); - copyStream(obj->getStream()->getUndecodedStream()); - if (pdf_last_byte != '\n') - pdf_puts("\n"); - pdf_puts("endstream"); // can't simply write pdf_end_stream() - } else if (obj->isRef()) { - ref = obj->getRef(); - if (ref.num == 0) { - pdftex_fail - ("PDF inclusion: reference to invalid object" - " (is the included pdf broken?)"); - } else - pdf_printf("%d 0 R", addOther(ref)); + pdf_puts(pdf, ")"); } else { - pdftex_fail("PDF inclusion: type <%s> cannot be copied", - obj->getTypeName()); + pdf_puts(pdf, "<"); + for (i = 0; i < l; i++) { + c = (unsigned char) string->getChar(i); + pdf_printf(pdf, "%.2x", (int) c); + } + pdf_puts(pdf, ">"); } } -static void writeRefs() +static void copyName(PDF pdf, char *s) { - InObj *r; - for (r = inObjList; r != NULL; r = r->next) { - if (!r->written) { - Object obj1; - r->written = 1; - xref->fetch(r->ref.num, r->ref.gen, &obj1); - if (r->type == objFont) { - assert(!obj1.isStream()); - zpdf_begin_obj(r->num, 2); // \pdfobjcompresslevel = 2 is for this - copyFontDict(&obj1, r); - pdf_puts("\n"); - pdf_end_obj(); - } else if (r->type != objFontDesc) { // /FontDescriptor is written via write_fontdescriptor() - if (obj1.isStream()) - zpdf_begin_obj(r->num, 0); - else - zpdf_begin_obj(r->num, 2); // \pdfobjcompresslevel = 2 is for this - copyObject(&obj1); - pdf_puts("\n"); - pdf_end_obj(); - } - obj1.free(); - } + pdf_puts(pdf, "/"); + for (; *s != 0; s++) { + if (isdigit(*s) || isupper(*s) || islower(*s) || *s == '_' || + *s == '.' || *s == '-' || *s == '+') + pdf_out(pdf, *s); + else + pdf_printf(pdf, "#%.2X", *s & 0xFF); } } -static void writeEncodings() +static void copyArray(PDF pdf, PdfDocument * pdf_doc, Array * array) { - UsedEncoding *r, *n; - char *glyphNames[256], *s; - int i; - for (r = encodingList; r != NULL; r = r->next) { - for (i = 0; i < 256; i++) { - if (r->font->isCIDFont()) { - pdftex_fail - ("PDF inclusion: CID fonts are not supported" - " (try to disable font replacement to fix this)"); - } - if ((s = ((Gfx8BitFont *) r->font)->getCharName(i)) != NULL) - glyphNames[i] = s; - else - glyphNames[i] = notdef; - } - epdf_write_enc(glyphNames, r->enc_objnum); + int i, l; + PdfObject obj1; + pdf_puts(pdf, "["); + for (i = 0, l = array->getLength(); i < l; ++i) { + array->getNF(i, &obj1); + if (!obj1->isName()) + pdf_puts(pdf, " "); + copyObject(pdf, pdf_doc, &obj1); + } + pdf_puts(pdf, "]"); +} + +static void copyDict(PDF pdf, PdfDocument * pdf_doc, Dict * dict) +{ + int i, l; + PdfObject obj1; + pdf_puts(pdf, "<<"); + for (i = 0, l = dict->getLength(); i < l; ++i) { + copyName(pdf, dict->getKey(i)); + pdf_puts(pdf, " "); + dict->getValNF(i, &obj1); + copyObject(pdf, pdf_doc, &obj1); + pdf_puts(pdf, "\n"); + } + pdf_puts(pdf, ">>"); +} + +static void copyStreamStream(PDF pdf, Stream * str) +{ + int c; + str->reset(); + while ((c = str->getChar()) != EOF) { + pdf_out(pdf, c); + pdf->last_byte = c; + } +} + +static void copyStream(PDF pdf, PdfDocument * pdf_doc, Stream * stream) +{ + copyDict(pdf, pdf_doc, stream->getDict()); + pdf_puts(pdf, "stream\n"); + copyStreamStream(pdf, stream->getUndecodedStream()); + if (pdf->last_byte != '\n') + pdf_puts(pdf, "\n"); + pdf_puts(pdf, "endstream"); // can't simply write pdf_end_stream() +} + +static void copyObject(PDF pdf, PdfDocument * pdf_doc, Object * obj) +{ + switch (obj->getType()) { + case objBool: + pdf_printf(pdf, "%s", obj->getBool()? "true" : "false"); + break; + case objInt: + pdf_printf(pdf, "%i", obj->getInt()); + break; + case objReal: + pdf_printf(pdf, "%s", convertNumToPDF(obj->getReal())); + break; + // not needed: + // GBool isNum() { return type == objInt || type == objReal; } + case objString: + copyString(pdf, obj->getString()); + break; + case objName: + copyName(pdf, obj->getName()); + break; + case objNull: + pdf_puts(pdf, "null"); + break; + case objArray: + copyArray(pdf, pdf_doc, obj->getArray()); + break; + case objDict: + copyDict(pdf, pdf_doc, obj->getDict()); + break; + case objStream: + copyStream(pdf, pdf_doc, obj->getStream()); + break; + case objRef: + pdf_printf(pdf, "%d 0 R", addInObj(pdf, pdf_doc, obj->getRef())); + break; + case objCmd: + case objError: + case objEOF: + case objNone: + pdftex_fail("PDF inclusion: type <%s> cannot be copied", + obj->getTypeName()); + break; + default: + assert(0); // xpdf doesn't have any other types } - for (r = encodingList; r != NULL; r = n) { +} + +//********************************************************************** + +static void writeRefs(PDF pdf, PdfDocument * pdf_doc) +{ + InObj *r, *n; + XRef *xref; + xref = pdf_doc->doc->getXRef(); + for (r = pdf_doc->inObjList; r != NULL;) { + PdfObject obj1; + xref->fetch(r->ref.num, r->ref.gen, &obj1); + if (obj1->isStream()) + pdf_begin_obj(pdf, r->num, 0); + else + pdf_begin_obj(pdf, r->num, 2); // \pdfobjcompresslevel = 2 is for this + copyObject(pdf, pdf_doc, &obj1); + pdf_puts(pdf, "\n"); + pdf_end_obj(pdf); n = r->next; -#ifdef POPPLER_VERSION - r->font->decRefCnt(); -#else - delete r->font; -#endif delete r; + pdf_doc->inObjList = r = n; } } -// get the pagebox according to the pagebox_spec +// get the pagebox coordinates according to the pagebox_spec -static PDFRectangle *get_pagebox(Page * page, integer pagebox_spec) +static PDFRectangle *get_pagebox(Page * page, int pagebox_spec) { - if (pagebox_spec == pdf_box_spec_media) + switch (pagebox_spec) { + case PDF_BOX_SPEC_MEDIA: return page->getMediaBox(); - else if (pagebox_spec == pdf_box_spec_crop) + break; + case PDF_BOX_SPEC_CROP: return page->getCropBox(); - else if (pagebox_spec == pdf_box_spec_bleed) + break; + case PDF_BOX_SPEC_BLEED: return page->getBleedBox(); - else if (pagebox_spec == pdf_box_spec_trim) + break; + case PDF_BOX_SPEC_TRIM: return page->getTrimBox(); - else if (pagebox_spec == pdf_box_spec_art) + break; + case PDF_BOX_SPEC_ART: return page->getArtBox(); - else + break; + default: pdftex_fail("PDF inclusion: unknown value of pagebox spec (%i)", (int) pagebox_spec); + } return page->getMediaBox(); // to make the compiler happy } +#define PDF_CHECKSUM_SIZE 32 +char *get_file_checksum(char *a) +{ + struct stat finfo; + char *ck = NULL; + if (stat(a, &finfo) == 0) { + off_t size = finfo.st_size; + time_t mtime = finfo.st_mtime; + ck = (char *) malloc(PDF_CHECKSUM_SIZE); + if (ck == NULL) + pdftex_fail("PDF inclusion: out of memory while processing '%s'", + a); + snprintf(ck, PDF_CHECKSUM_SIZE, "%llu_%llu", (unsigned long long) size, + (unsigned long long) mtime); + } else { + pdftex_fail("PDF inclusion: could not stat() file '%s'", a); + } + return ck; +} + // Reads various information about the PDF and sets it up for later inclusion. // This will fail if the PDF version of the PDF is higher than // minor_pdf_version_wanted or page_name is given and can not be found. @@ -702,47 +463,37 @@ static PDFRectangle *get_pagebox(Page * page, integer pagebox_spec) // Returns the page number. void -read_pdf_info(image_dict * idict, integer minor_pdf_version_wanted, - integer pdf_inclusion_errorlevel) +read_pdf_info(image_dict * idict, int minor_pdf_version_wanted, + int pdf_inclusion_errorlevel, img_readtype_e readtype) { PdfDocument *pdf_doc; Page *page; int rotate; + char *checksum; PDFRectangle *pagebox; -#ifdef HAVE_GETPDFMAJORVERSION - int pdf_major_version_found, pdf_minor_version_found; -#else - float pdf_version_found, pdf_version_wanted; -#endif - float xsize, ysize, xorig, yorig; + float pdf_version_found, pdf_version_wanted, xsize, ysize, xorig, yorig; assert(idict != NULL); assert(img_type(idict) == IMG_TYPE_PDF); + assert(readtype == IMG_CLOSEINBETWEEN); // only this is implemented // initialize if (isInit == gFalse) { globalParams = new GlobalParams(); globalParams->setErrQuiet(gFalse); isInit = gTrue; } + // calculate a checksum string + checksum = get_file_checksum(img_filepath(idict)); // open PDF file pdf_doc = refPdfDocument(img_filepath(idict)); + if (strncmp(pdf_doc->checksum, checksum, PDF_CHECKSUM_SIZE) != 0) { + pdftex_fail("PDF inclusion: file has changed '%s'", + img_filename(idict)); + } + free(checksum); // check PDF version // this works only for PDF 1.x -- but since any versions of PDF newer // than 1.x will not be backwards compatible to PDF 1.x, pdfTeX will // then have to changed drastically anyway. -#ifdef HAVE_GETPDFMAJORVERSION - pdf_major_version_found = pdf_doc->doc->getPDFMajorVersion(); - pdf_minor_version_found = pdf_doc->doc->getPDFMinorVersion(); - if ((pdf_major_version_found > 1) - || (pdf_minor_version_found > minor_pdf_version_wanted)) { - const char *msg = - "PDF inclusion: found PDF version <%d.%d>, but at most version <1.%d> allowed"; - if (pdf_inclusion_errorlevel > 0) { - pdftex_fail(msg, pdf_major_version_found, pdf_minor_version_found, minor_pdf_version_wanted); - } else { - pdftex_warn(msg, pdf_major_version_found, pdf_minor_version_found, minor_pdf_version_wanted); - } - } -#else pdf_version_found = pdf_doc->doc->getPDFVersion(); pdf_version_wanted = 1 + (minor_pdf_version_wanted * 0.1); if (pdf_version_found > pdf_version_wanted + 0.01) { @@ -754,7 +505,6 @@ read_pdf_info(image_dict * idict, integer minor_pdf_version_wanted, pdftex_warn(msg, pdf_version_found, pdf_version_wanted); } } -#endif img_totalpages(idict) = pdf_doc->doc->getCatalog()->getNumPages(); if (img_pagename(idict)) { // get page by name @@ -777,11 +527,10 @@ read_pdf_info(image_dict * idict, integer minor_pdf_version_wanted, pdftex_fail("PDF inclusion: required page <%i> does not exist", (int) img_pagenum(idict)); } - pdf_doc->xref = pdf_doc->doc->getXRef(); // get the required page page = pdf_doc->doc->getCatalog()->getPage(img_pagenum(idict)); - // get the pagebox (media, crop...) to use. + // get the pagebox coordinates (media, crop,...) to use. pagebox = get_pagebox(page, img_pagebox(idict)); if (pagebox->x2 > pagebox->x1) { xorig = pagebox->x1; @@ -824,67 +573,60 @@ read_pdf_info(image_dict * idict, integer minor_pdf_version_wanted, ("PDF inclusion: " "/Rotate parameter in PDF file not multiple of 90 degrees."); } - if (page->getGroup() != NULL) { - initDictFromDict(lastGroup, page->getGroup()); - if (lastGroup->dictGetLength() > 0) { - groupIsIndirect = lastGroup->isRef(); - if (groupIsIndirect) { - // FIXME: Here we already copy the object. It would be - // better to do this only after write_epdf, otherwise we - // may copy ununsed /Group objects - copyObject(&lastGroup); - epdf_lastGroupObjectNum = - getNewObjectNumber(lastGroup->getRef()); - } else { - // make the group an indirect object; copying is done later - // by write_additional_epdf_objects after write_epdf - epdf_lastGroupObjectNum = pdf_new_objnum(); - } - pdf_puts("\n"); - } - } else { - epdf_lastGroupObjectNum = 0; - } + // currently unused info whether PDF contains a /Group + if (page->getGroup() != NULL) + img_set_group(idict); + + if (readtype == IMG_CLOSEINBETWEEN) + unrefPdfDocument(img_filepath(idict)); } +//********************************************************************** // Writes the current epf_doc. -// Here the included PDF is copied, so most errors that can happen during PDF -// inclusion will arise here. +// Here the included PDF is copied, so most errors that can happen +// during PDF inclusion will arise here. -static void write_epdf1(image_dict * idict) +static void write_epdf1(PDF pdf, image_dict * idict) { + PdfDocument *pdf_doc; Page *page; - PdfObject contents, obj1, obj2; - PdfObject metadata, pieceinfo, separationInfo; - Object info; - char *key; + PdfObject info, contents, metadata, obj1; + Object *metadataNF, *resourcesNF; + char *checksum; char s[256]; int i, l; - PdfDocument *pdf_doc = (PdfDocument *) findPdfDocument(img_filepath(idict)); - assert(pdf_doc != NULL); - xref = pdf_doc->xref; - inObjList = pdf_doc->inObjList; - encodingList = NULL; + assert(idict != NULL); + // calculate a checksum string + checksum = get_file_checksum(img_filepath(idict)); + // open PDF file + pdf_doc = refPdfDocument(img_filepath(idict)); + if (strncmp(pdf_doc->checksum, checksum, PDF_CHECKSUM_SIZE) != 0) { + pdftex_fail("PDF inclusion: file has changed '%s'", + img_filename(idict)); + } + free(checksum); + (void) pdf_doc->doc->getCatalog()->getPage(img_pagenum(idict)); page = pdf_doc->doc->getCatalog()->getPage(img_pagenum(idict)); PDFRectangle *pagebox; float bbox[4]; // write the Page header - pdf_puts("/Type /XObject\n/Subtype /Form\n"); + pdf_puts(pdf, "/Type /XObject\n/Subtype /Form\n"); if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) - pdf_printf("%s\n", img_attr(idict)); - pdf_puts("/FormType 1\n"); + pdf_printf(pdf, "%s\n", img_attr(idict)); + pdf_puts(pdf, "/FormType 1\n"); // write additional information - pdf_printf("/%s.FileName (%s)\n", pdfkeyprefix, + pdf_printf(pdf, "/%s.FileName (%s)\n", pdfkeyprefix, convertStringToPDFString(pdf_doc->file_path, strlen(pdf_doc->file_path))); - pdf_printf("/%s.PageNumber %i\n", pdfkeyprefix, (int) img_pagenum(idict)); + pdf_printf(pdf, "/%s.PageNumber %i\n", pdfkeyprefix, + (int) img_pagenum(idict)); pdf_doc->doc->getDocInfoNF(&info); - if (info.isRef()) { + if (info->isRef()) { // the info dict must be indirect (PDF Ref p. 61) - pdf_printf("/%s.InfoDict ", pdfkeyprefix); - pdf_printf("%d 0 R\n", addOther(info.getRef())); + pdf_printf(pdf, "/%s.InfoDict ", pdfkeyprefix); + pdf_printf(pdf, "%d 0 R\n", addInObj(pdf, pdf_doc, info->getRef())); } if (img_is_bbox(idict)) { bbox[0] = int2bp(img_bbox(idict)[0]); @@ -892,7 +634,7 @@ static void write_epdf1(image_dict * idict) bbox[2] = int2bp(img_bbox(idict)[2]); bbox[3] = int2bp(img_bbox(idict)[3]); } else { - // get the pagebox (media, crop...) to use. + // get the pagebox coordinates (media, crop,...) to use. pagebox = get_pagebox(page, img_pagebox(idict)); bbox[0] = pagebox->x1; bbox[1] = pagebox->y1; @@ -901,77 +643,57 @@ static void write_epdf1(image_dict * idict) } sprintf(s, "/BBox [%.8f %.8f %.8f %.8f]\n", bbox[0], bbox[1], bbox[2], bbox[3]); - pdf_puts(stripzeros(s)); + pdf_puts(pdf, stripzeros(s)); // The /Matrix calculation is replaced by transforms in out_img(). - // write the page Group if it's there - if (epdf_lastGroupObjectNum > 0) { - if (page->getGroup() != NULL) { - initDictFromDict(lastGroup, page->getGroup()); - if (lastGroup->dictGetLength() > 0) { - pdf_puts("/Group "); - groupIsIndirect = lastGroup->isRef(); - pdf_printf("%d 0 R", (int) epdf_lastGroupObjectNum); - pdf_puts("\n"); - } - } + // Now all relevant parts of the /Page dictionary are copied: + + // write the /Resources dictionary + if (page->getResourceDict() == NULL) { + // Resources can be missing (files without them have been spotted + // in the wild); in which case the /Resouces of the /Page will be used. + // "This practice is not recommended". + pdftex_warn + ("PDF inclusion: /Resources missing. 'This practice is not recommended' (PDF Ref.)"); + } else { +#if 0 // TEMP, waiting for XPDF patch + resourcesNF = page->getResourcesNF(); + pdf_puts(pdf, "/Resources "); + copyObject(pdf, pdf_doc, resourcesNF); +#endif } - // write the page Metadata if it's there + // write the page /Metadata if it's there (as a stream it must be indirect) if (page->getMetadata() != NULL) { - metadata->initStream(page->getMetadata()); - pdf_puts("/Metadata "); - copyObject(&metadata); - pdf_puts("\n"); +#if 0 // TEMP, waiting for XPDF patch + metadataNF = page->getMetadataNF(); // *NF = "don't resolve indirects" + if (!metadataNF->isRef()) + pdftex_warn("PDF inclusion: /Metadata must be indirect object"); + else { + pdf_printf(pdf, "/Metadata %d 0 R", + addInObj(pdf, pdf_doc, metadataNF->getRef())); + } +#endif } - // write the page PieceInfo if it's there + // write the page /Group if it's there + if (page->getGroup() != NULL) { + pdf_puts(pdf, "/Group "); + copyDict(pdf, pdf_doc, page->getGroup()); + } + // write the page /PieceInfo if it's there if (page->getPieceInfo() != NULL) { - initDictFromDict(pieceinfo, page->getPieceInfo()); - if (pieceinfo->dictGetLength() > 0) { - pdf_puts("/PieceInfo "); - copyObject(&pieceinfo); - pdf_puts("\n"); - } + pdf_puts(pdf, "/PieceInfo "); + copyDict(pdf, pdf_doc, page->getPieceInfo()); + } + // write the page /SeparationInfo if it's there + if (page->getSeparationInfo() != NULL) { + pdf_puts(pdf, "/SeparationInfo "); + copyDict(pdf, pdf_doc, page->getSeparationInfo()); } // copy LastModified (needed when PieceInfo is there) if (page->getLastModified() != NULL) { - pdf_printf("/LastModified (%s)\n", + pdf_printf(pdf, "/LastModified (%s)\n", page->getLastModified()->getCString()); } - // write the page SeparationInfo if it's there - if (page->getSeparationInfo() != NULL) { - initDictFromDict(separationInfo, page->getSeparationInfo()); - if (separationInfo->dictGetLength() > 0) { - pdf_puts("/SeparationInfo "); - copyObject(&separationInfo); - pdf_puts("\n"); - } - } - // write the Resources dictionary - if (page->getResourceDict() == NULL) { - // Resources can be missing (files without them have been spotted - // in the wild); in which case the /Resouces of the /Page will be used. - // "This practice is not recommended". - pdftex_warn - ("PDF inclusion: /Resources missing. 'This practice is not recommended' (PDF Ref)"); - } else { - initDictFromDict(obj1, page->getResourceDict()); - page->getResourceDict()->incRef(); - if (!obj1->isDict()) - pdftex_fail("PDF inclusion: invalid resources dict type <%s>", - obj1->getTypeName()); - pdf_puts("/Resources <<\n"); - for (i = 0, l = obj1->dictGetLength(); i < l; ++i) { - obj1->dictGetVal(i, &obj2); - key = obj1->dictGetKey(i); - if (strcmp("Font", key) == 0) - copyFontResources(&obj2); - else if (strcmp("ProcSet", key) == 0) - copyProcSet(&obj2); - else - copyOtherResources(&obj2, key); - } - pdf_puts(">>\n"); - } // write the page contents page->getContents(&contents); if (contents->isStream()) { @@ -979,84 +701,108 @@ static void write_epdf1(image_dict * idict) // of \pdfcompresslevel // // pdfbeginstream(); - // copyStream(contents->getStream()); + // copyStreamStream(contents->getStream()); // pdfendstream(); // Variant B: copy stream without recompressing // - contents->streamGetDict()->lookup("F", &obj1); + contents->streamGetDict()->lookup((char *) "F", &obj1); if (!obj1->isNull()) { pdftex_fail("PDF inclusion: Unsupported external stream"); } - contents->streamGetDict()->lookup("Length", &obj1); + contents->streamGetDict()->lookup((char *) "Length", &obj1); assert(!obj1->isNull()); - pdf_puts("/Length "); - copyObject(&obj1); - pdf_puts("\n"); - contents->streamGetDict()->lookup("Filter", &obj1); + pdf_puts(pdf, "/Length "); + copyObject(pdf, pdf_doc, &obj1); + pdf_puts(pdf, "\n"); + contents->streamGetDict()->lookup((char *) "Filter", &obj1); if (!obj1->isNull()) { - pdf_puts("/Filter "); - copyObject(&obj1); - pdf_puts("\n"); - contents->streamGetDict()->lookup("DecodeParms", &obj1); + pdf_puts(pdf, "/Filter "); + copyObject(pdf, pdf_doc, &obj1); + pdf_puts(pdf, "\n"); + contents->streamGetDict()->lookup((char *) "DecodeParms", &obj1); if (!obj1->isNull()) { - pdf_puts("/DecodeParms "); - copyObject(&obj1); - pdf_puts("\n"); + pdf_puts(pdf, "/DecodeParms "); + copyObject(pdf, pdf_doc, &obj1); + pdf_puts(pdf, "\n"); } } - pdf_puts(">>\nstream\n"); - copyStream(contents->getStream()->getBaseStream()); - pdf_end_stream(); + pdf_puts(pdf, ">>\nstream\n"); + copyStreamStream(pdf, contents->getStream()->getBaseStream()); + pdf_end_stream(pdf); } else if (contents->isArray()) { - pdf_begin_stream(); + pdf_begin_stream(pdf); for (i = 0, l = contents->arrayGetLength(); i < l; ++i) { - Object contentsobj; - copyStream((contents->arrayGet(i, &contentsobj))->getStream()); - contentsobj.free(); + PdfObject contentsobj; + copyStreamStream(pdf, + (contents->arrayGet(i, &contentsobj))-> + getStream()); + if (i < (l - 1)) { + // put a space between streams to be on the safe side (streams + // should have a trailing space here, but one never knows) + pdf_puts(pdf, " "); + } } - pdf_end_stream(); + pdf_end_stream(pdf); } else { // the contents are optional, but we need to include an empty stream - pdf_begin_stream(); - pdf_end_stream(); + pdf_begin_stream(pdf); + pdf_end_stream(pdf); } // write out all indirect objects - writeRefs(); - // write out all used encodings (and delete list) - writeEncodings(); - // save object list - pdf_doc->inObjList = inObjList; - assert(xref == pdf_doc->xref); // xref should be unchanged + writeRefs(pdf, pdf_doc); } -void write_epdf(image_dict * idict) +// this relay function is needed to keep some destructor quiet (???) + +void write_epdf(PDF pdf, image_dict * idict) { - assert(idict != NULL); - write_epdf1(idict); + write_epdf1(pdf, idict); unrefPdfDocument(img_filepath(idict)); } //********************************************************************** // Deallocate a PdfDocument with all its resources -static void deletePdfDocument(PdfDocument * pdf_doc) +static void deletePdfDocumentPdfDoc(PdfDocument * pdf_doc) { - assert(pdf_doc != NULL); - // free PdfDocument's resources InObj *r, *n; + assert(pdf_doc != NULL); + // this may be probably needed for an emergency destroyPdfDocument() for (r = pdf_doc->inObjList; r != NULL; r = n) { n = r->next; delete r; } delete pdf_doc->doc; - xfree(pdf_doc->file_path); - delete pdf_doc; + pdf_doc->doc = NULL; } -static void destroyPdfDocument(void *pa, void *pb) +static void destroyPdfDocument(void *pa, void * /*pb */ ) { PdfDocument *pdf_doc = (PdfDocument *) pa; - deletePdfDocument(pdf_doc); + deletePdfDocumentPdfDoc(pdf_doc); + // TODO: delete rest of pdf_doc +} + +// Called when an image has been written and its resources in image_tab are +// freed and it's not referenced anymore. + +void unrefPdfDocument(char *file_path) +{ + PdfDocument *pdf_doc = findPdfDocument(file_path); + assert(pdf_doc != NULL); + assert(pdf_doc->occurences > 0); // aim for point landing + pdf_doc->occurences--; +#ifdef DEBUG + fprintf(stderr, "\nluatex Debug: Decrementing %s (%d)\n", + pdf_doc->file_path, pdf_doc->occurences); +#endif + if (pdf_doc->occurences == 0) { +#ifdef DEBUG + fprintf(stderr, "\nluatex Debug: Deleting %s\n", pdf_doc->file_path); +#endif + assert(pdf_doc->inObjList == NULL); // should be eaten up already + deletePdfDocumentPdfDoc(pdf_doc); + } } // Called when PDF embedding system is finalized. @@ -1071,14 +817,3 @@ void epdf_check_mem() delete globalParams; isInit = gFalse; } - -// Called after the xobject generated by write_epdf has been finished; used to -// write out objects that have been made indirect -void write_additional_epdf_objects(void) -{ - if ((epdf_lastGroupObjectNum > 0) && !groupIsIndirect) { - zpdf_begin_obj(epdf_lastGroupObjectNum, 2); - copyObject(&lastGroup); - pdf_end_obj(); - } -} diff --git a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.h b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.h index 50d89c0a861..05bb85eeaa5 100644 --- a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.h +++ b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.h @@ -18,22 +18,20 @@ You should have received a copy of the GNU General Public License along with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ -/* $Id: pdftoepdf.h 2331 2009-04-18 16:39:50Z hhenkel $ */ +/* $Id: pdftoepdf.h 3319 2009-12-27 20:05:36Z hhenkel $ */ #ifndef PDFTOEPDF_H # define PDFTOEPDF_H # include "image.h" -void read_pdf_info(image_dict *, integer, integer); +void read_pdf_info(image_dict *, int, int, img_readtype_e); void unrefPdfDocument(char *); -void write_additional_epdf_objects(void); -void write_epdf(image_dict *); +void write_epdf(PDF, image_dict *); void epdf_check_mem(void); /* epdf.c --- this should go in an own header file */ -extern integer get_fontfile_num(int); -extern integer get_fontname_num(int); + extern void epdf_free(void); #endif /* PDFTOEPDF_H */ diff --git a/Build/source/texk/web2c/luatexdir/image/writeimg.c b/Build/source/texk/web2c/luatexdir/image/writeimg.c deleted file mode 100644 index f570fd46996..00000000000 --- a/Build/source/texk/web2c/luatexdir/image/writeimg.c +++ /dev/null @@ -1,959 +0,0 @@ -/* writeimg.c - - Copyright 1996-2006 Han The Thanh <thanh@pdftex.org> - Copyright 2006-2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - -#include <assert.h> -#include "ptexlib.h" -#include <kpathsea/c-auto.h> -#include <kpathsea/c-memstr.h> - -#include "image.h" -#include "writejpg.h" -#include "writepng.h" -#include "writejbig2.h" -#include "pdftoepdf.h" - -#include <../lua51/lua.h> -#include <../lua51/lauxlib.h> - -static const char _svn_version[] = - "$Id: writeimg.c 2448 2009-06-08 07:43:50Z taco $ " - "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.40.6/source/texk/web2c/luatexdir/image/writeimg.c $"; - -/**********************************************************************/ -/* - Patch ImageTypeDetection 2003/02/08 by Heiko Oberdiek. - - Function "readimage" performs some basic initializations. - Then it looks at the file extension to determine the - image type and calls specific code/functions. - The main disadvantage is that standard file extensions - have to be used, otherwise pdfTeX is not able to detect - the correct image type. - - The patch now looks at the file header first regardless of - the file extension. This is implemented in function - "check_type_by_header". If this check fails, the traditional - test of standard file extension is tried, done in function - "check_type_by_extension". - - Magic headers: - - * "PNG (Portable Network Graphics) Specification", Version 1.2 - (http://www.libpng.org/pub/png): - - | 3.1. PNG file signature - | - | The first eight bytes of a PNG file always contain the following - | (decimal) values: - | - | 137 80 78 71 13 10 26 10 - - Translation to C: "\x89PNG\r\n\x1A\n" - - * "JPEG File Interchange Format", Version 1.02: - - | o you can identify a JFIF file by looking for the following - | sequence: X'FF', SOI X'FF', APP0, <2 bytes to be skipped>, - | "JFIF", X'00'. - - Function "check_type_by_header" only looks at the first two bytes: - "\xFF\xD8" - - * ISO/IEC JTC 1/SC 29/WG 1 - (ITU-T SG8) - Coding of Still Pictures - Title: 14492 FCD - Source: JBIG Committee - Project: JTC 1.29.10 - Status: Final Committee Draft - - | D.4.1, ID string - | - | This is an 8-byte sequence containing 0x97 0x4A 0x42 0x32 0x0D 0x0A - | 0x1A 0x0A. - - * "PDF Reference", third edition: - * The first line should contain "%PDF-1.0" until "%PDF-1.4" - (section 3.4.1 "File Header"). - * The "implementation notes" say: - - | 3.4.1, File Header - | 12. Acrobat viewers require only that the header appear - | somewhere within the first 1024 bytes of the file. - | 13. Acrobat viewers will also accept a header of the form - | %!PS-Adobe-N.n PDF-M.m - - The check in function "check_type_by_header" only implements - the first issue. The implementation notes are not considered. - Therefore files with garbage at start of file must have the - standard extension. - - Functions "check_type_by_header" and "check_type_by_extension": - img_type(img) is set to IMG_TYPE_NONE by new_image_dict(). - Both functions try to detect a type and set img_type(img). - Thus a value other than IMG_TYPE_NONE indicates that a - type has been found. -*/ - -#define HEADER_JPG "\xFF\xD8" -#define HEADER_PNG "\x89PNG\r\n\x1A\n" -#define HEADER_JBIG2 "\x97\x4A\x42\x32\x0D\x0A\x1A\x0A" -#define HEADER_PDF "%PDF-1." -#define MAX_HEADER (sizeof(HEADER_PNG)-1) - -integer epdf_lastGroupObjectNum; - -static void check_type_by_header(image_dict * idict) -{ - int i; - FILE *file = NULL; - char header[MAX_HEADER]; - - assert(idict != NULL); - if (img_type(idict) != IMG_TYPE_NONE) /* nothing to do */ - return; - /* read the header */ - file = xfopen(img_filepath(idict), FOPEN_RBIN_MODE); - for (i = 0; (unsigned) i < MAX_HEADER; i++) { - header[i] = xgetc(file); - if (feof(file)) - pdftex_fail("reading image file failed"); - } - xfclose(file, img_filepath(idict)); - /* tests */ - if (strncmp(header, HEADER_JPG, sizeof(HEADER_JPG) - 1) == 0) - img_type(idict) = IMG_TYPE_JPG; - else if (strncmp(header, HEADER_PNG, sizeof(HEADER_PNG) - 1) == 0) - img_type(idict) = IMG_TYPE_PNG; - else if (strncmp(header, HEADER_JBIG2, sizeof(HEADER_JBIG2) - 1) == 0) - img_type(idict) = IMG_TYPE_JBIG2; - else if (strncmp(header, HEADER_PDF, sizeof(HEADER_PDF) - 1) == 0) - img_type(idict) = IMG_TYPE_PDF; -} - -static void check_type_by_extension(image_dict * idict) -{ - char *image_suffix; - - assert(idict != NULL); - if (img_type(idict) != IMG_TYPE_NONE) /* nothing to do */ - return; - /* tests */ - if ((image_suffix = strrchr(img_filename(idict), '.')) == 0) - img_type(idict) = IMG_TYPE_NONE; - else if (strcasecmp(image_suffix, ".png") == 0) - img_type(idict) = IMG_TYPE_PNG; - else if (strcasecmp(image_suffix, ".jpg") == 0 || - strcasecmp(image_suffix, ".jpeg") == 0) - img_type(idict) = IMG_TYPE_JPG; - else if (strcasecmp(image_suffix, ".jbig2") == 0 || - strcasecmp(image_suffix, ".jb2") == 0) - img_type(idict) = IMG_TYPE_JBIG2; - else if (strcasecmp(image_suffix, ".pdf") == 0) - img_type(idict) = IMG_TYPE_PDF; -} - -/**********************************************************************/ - -void new_img_pdfstream_struct(image_dict * p) -{ - assert(p != NULL); - assert(img_pdfstream_ptr(p) == NULL); - img_pdfstream_ptr(p) = xtalloc(1, pdf_stream_struct); - img_pdfstream_stream(p) = NULL; -} - -/**********************************************************************/ - -void init_image(image * p) -{ - assert(p != NULL); - set_wd_running(p); - set_ht_running(p); - set_dp_running(p); - img_transform(p) = 0; - img_flags(p) = 0; - img_unset_scaled(p); - img_dict(p) = NULL; - img_arrayidx(p) = -1; /* -1 = unused, used count from 0 */ - img_dictref(p) = LUA_NOREF; -} - -image *new_image(void) -{ - image *p = xtalloc(1, image); - init_image(p); - return p; -} - -void init_image_dict(image_dict * p) -{ - assert(p != NULL); - img_objnum(p) = 0; - img_index(p) = 0; - img_xsize(p) = 0; - img_ysize(p) = 0; - img_xorig(p) = 0; - img_yorig(p) = 0; - img_xres(p) = 0; - img_yres(p) = 0; - img_rotation(p) = 0; - img_colorspace(p) = 0; - img_group_ref(p) = 0; - img_totalpages(p) = 0; - img_pagenum(p) = 1; - img_pagename(p) = NULL; - img_filename(p) = NULL; - img_filepath(p) = NULL; - img_attr(p) = NULL; - img_file(p) = NULL; - img_type(p) = IMG_TYPE_NONE; - img_color(p) = 0; - img_colordepth(p) = 0; - img_pagebox(p) = PDF_BOX_SPEC_MEDIA; - img_bbox(p)[0] = 0; - img_bbox(p)[1] = 0; - img_bbox(p)[2] = 0; - img_bbox(p)[3] = 0; - img_unset_bbox(p); - img_state(p) = DICT_NEW; - img_png_ptr(p) = NULL; /* union */ -} - -image_dict *new_image_dict(void) -{ - image_dict *p = xtalloc(1, image_dict); - init_image_dict(p); - return p; -} - -static void free_dict_strings(image_dict * p) -{ - if (img_filename(p) != NULL) - xfree(img_filename(p)); - img_filename(p) = NULL; - if (img_filepath(p) != NULL) - xfree(img_filepath(p)); - img_filepath(p) = NULL; - if (img_attr(p) != NULL) - xfree(img_attr(p)); - img_attr(p) = NULL; - if (img_pagename(p) != NULL) - xfree(img_pagename(p)); - img_pagename(p) = NULL; -} - -void free_image_dict(image_dict * p) -{ - if (ini_version) - return; /* The image may be \dump{}ed to a format */ - /* called from limglib.c */ - assert(img_state(p) < DICT_REFERED); - switch (img_type(p)) { - case IMG_TYPE_PDF: - unrefPdfDocument(img_filepath(p)); - break; - case IMG_TYPE_PNG: /* assuming IMG_CLOSEINBETWEEN */ - assert(img_png_ptr(p) == NULL); - break; - case IMG_TYPE_JPG: /* assuming IMG_CLOSEINBETWEEN */ - assert(img_jpg_ptr(p) == NULL); - break; - case IMG_TYPE_JBIG2: /* todo: writejbig2.c cleanup */ - break; - case IMG_TYPE_PDFSTREAM: - if (img_pdfstream_ptr(p) != NULL) { - if (img_pdfstream_stream(p) != NULL) - xfree(img_pdfstream_stream(p)); - xfree(img_pdfstream_ptr(p)); - } - break; - case IMG_TYPE_NONE: - break; - default: - assert(0); - } - free_dict_strings(p); - assert(img_file(p) == NULL); - xfree(p); -} - -/**********************************************************************/ - -void pdf_print_resname_prefix(void) -{ - if (pdf_resname_prefix != 0) - pdf_printf(makecstring(pdf_resname_prefix)); -} - -void read_img(image_dict * idict, integer pdf_minor_version, - integer pdf_inclusion_errorlevel) -{ - char *filepath; - int callback_id; - assert(idict != NULL); - if (img_filename(idict) == NULL) - pdftex_fail("image file name missing"); - callback_id = callback_defined(find_image_file_callback); - if (img_filepath(idict) == NULL) { - if (callback_id > 0 - && run_callback(callback_id, "S->S", img_filename(idict), - &filepath)) { - if (filepath && (strlen(filepath) > 0)) - img_filepath(idict) = strdup(filepath); - } else - img_filepath(idict) = - kpse_find_file(img_filename(idict), kpse_tex_format, true); - } - if (img_filepath(idict) == NULL) - pdftex_fail("cannot find image file"); - recorder_record_input(img_filename(idict)); - /* type checks */ - check_type_by_header(idict); - check_type_by_extension(idict); - /* read image */ - switch (img_type(idict)) { - case IMG_TYPE_PDF: - read_pdf_info(idict, pdf_minor_version, pdf_inclusion_errorlevel); - img_group_ref(idict) = epdf_lastGroupObjectNum; - break; - case IMG_TYPE_PNG: - read_png_info(idict, IMG_CLOSEINBETWEEN); - break; - case IMG_TYPE_JPG: - read_jpg_info(idict, IMG_CLOSEINBETWEEN); - break; - case IMG_TYPE_JBIG2: - if (pdf_minor_version < 4) { - pdftex_fail - ("JBIG2 images only possible with at least PDF 1.4; you are generating PDF 1.%i", - (int) pdf_minor_version); - } - read_jbig2_info(idict); - break; - default: - pdftex_fail("internal error: unknown image type (2)"); - } - cur_file_name = NULL; - if (img_state(idict) < DICT_FILESCANNED) - img_state(idict) = DICT_FILESCANNED; -} - -// Within scale_img() only image width and height matter; -// the offsets and positioning are not interesting here. -// But one needs rotation info to swap width and height. -// img_rotation() comes from the optional /Rotate key in the PDF file. - -void scale_img(image * img) -{ - integer x, y, xr, yr, tmp; /* size and resolution of image */ - scaled w = 0, h = 0; /* indeed size corresponds to image resolution */ - integer default_res; - image_dict *idict; - assert(img != NULL); - idict = img_dict(img); - assert(idict != NULL); - if ((img_type(idict) == IMG_TYPE_PDF - || img_type(idict) == IMG_TYPE_PDFSTREAM) && img_is_bbox(idict)) { - x = img_xsize(idict) = img_bbox(idict)[2] - img_bbox(idict)[0]; /* dimensions from image.bbox */ - y = img_ysize(idict) = img_bbox(idict)[3] - img_bbox(idict)[1]; - img_xorig(idict) = img_bbox(idict)[0]; - img_yorig(idict) = img_bbox(idict)[1]; - } else { - x = img_xsize(idict); /* dimensions, resolutions from image file */ - y = img_ysize(idict); - } - xr = img_xres(idict); - yr = img_yres(idict); - if (x <= 0 || y <= 0 || xr < 0 || yr < 0) - pdftex_fail("ext1: invalid image dimensions"); - if (xr > 65535 || yr > 65535) { - xr = 0; - yr = 0; - pdftex_warn("ext1: too large image resolution ignored"); - } - if (((img_transform(img) - img_rotation(idict)) & 1) == 1) { - tmp = x; - x = y; - y = tmp; - tmp = xr; - xr = yr; - yr = tmp; - } - if (img_type(idict) == IMG_TYPE_PDF - || img_type(idict) == IMG_TYPE_PDFSTREAM) { - w = x; - h = y; - } else { - default_res = fix_int(get_pdf_image_resolution(), 0, 65535); - if (default_res > 0 && (xr == 0 || yr == 0)) { - xr = default_res; - yr = default_res; - } - if (is_wd_running(img) && is_ht_running(img)) { - if (xr > 0 && yr > 0) { - w = ext_xn_over_d(one_hundred_inch, x, 100 * xr); - h = ext_xn_over_d(one_hundred_inch, y, 100 * yr); - } else { - w = ext_xn_over_d(one_hundred_inch, x, 7200); - h = ext_xn_over_d(one_hundred_inch, y, 7200); - } - } - } - if (is_wd_running(img) && is_ht_running(img) && is_dp_running(img)) { - img_width(img) = w; - img_height(img) = h; - img_depth(img) = 0; - } else if (is_wd_running(img)) { - /* image depth or height is explicitly specified */ - if (is_ht_running(img)) { - /* image depth is explicitly specified */ - img_width(img) = ext_xn_over_d(h, x, y); - img_height(img) = h - img_depth(img); - } else if (is_dp_running(img)) { - /* image height is explicitly specified */ - img_width(img) = ext_xn_over_d(img_height(img), x, y); - img_depth(img) = 0; - } else { - /* both image depth and height are explicitly specified */ - img_width(img) = - ext_xn_over_d(img_height(img) + img_depth(img), x, y); - } - } else { - /* image width is explicitly specified */ - if (is_ht_running(img) && is_dp_running(img)) { - /* both image depth and height are not specified */ - img_height(img) = ext_xn_over_d(img_width(img), y, x); - img_depth(img) = 0; - } - /* image depth is explicitly specified */ - else if (is_ht_running(img)) { - img_height(img) = - ext_xn_over_d(img_width(img), y, x) - img_depth(img); - } - /* image height is explicitly specified */ - else if (is_dp_running(img)) { - img_depth(img) = 0; - } - /* else both image depth and height are explicitly specified */ - } - img_set_scaled(img); -} - -static void out_img(image * img, pdfstructure * p, scaledpos * pos) -{ - float a[6]; /* transformation matrix */ - float xoff, yoff, tmp; - int r; /* number of digits after the decimal point */ - int k; - scaled wd, ht, dp; - scaledpos tmppos; - pdffloat cm[6]; - image_dict *idict; - integer groupref; /* added from web for 1.40.8 */ - assert(img != 0); - idict = img_dict(img); - assert(idict != 0); - wd = img_width(img); - ht = img_height(img); - dp = img_depth(img); - a[0] = a[3] = 1.0e6; - a[1] = a[2] = 0; - if (img_type(idict) == IMG_TYPE_PDF - || img_type(idict) == IMG_TYPE_PDFSTREAM) { - a[0] /= img_xsize(idict); - a[3] /= img_ysize(idict); - xoff = (float) img_xorig(idict) / img_xsize(idict); - yoff = (float) img_yorig(idict) / img_ysize(idict); - r = 6; - } else { - /* added from web for 1.40.8 */ - if (img_type(idict) == IMG_TYPE_PNG) { - groupref = img_group_ref(idict); - if ((groupref > 0) && (pdf_page_group_val < 1)) - pdf_page_group_val = groupref; - } - /* /added from web */ - a[0] /= one_hundred_bp; - a[3] = a[0]; - xoff = yoff = 0; - r = 4; - } - if ((img_transform(img) & 7) > 3) { // mirror cases - a[0] *= -1; - xoff *= -1; - } - switch ((img_transform(img) + img_rotation(idict)) & 3) { - case 0: /* no transform */ - break; - case 1: /* rot. 90 deg. (counterclockwise) */ - a[1] = a[0]; - a[2] = -a[3]; - a[3] = a[0] = 0; - tmp = yoff; - yoff = xoff; - xoff = -tmp; - break; - case 2: /* rot. 180 deg. (counterclockwise) */ - a[0] *= -1; - a[3] *= -1; - xoff *= -1; - yoff *= -1; - break; - case 3: /* rot. 270 deg. (counterclockwise) */ - a[1] = -a[0]; - a[2] = a[3]; - a[3] = a[0] = 0; - tmp = yoff; - yoff = -xoff; - xoff = tmp; - break; - default:; - } - xoff *= wd; - yoff *= ht + dp; - a[0] *= wd; - a[1] *= ht + dp; - a[2] *= wd; - a[3] *= ht + dp; - a[4] = pos->h - xoff; - a[5] = pos->v - yoff; - k = img_transform(img) + img_rotation(idict); - if ((img_transform(img) & 7) > 3) - k++; - switch (k & 3) { - case 0: /* no transform */ - break; - case 1: /* rot. 90 deg. (counterclockwise) */ - a[4] += wd; - break; - case 2: /* rot. 180 deg. */ - a[4] += wd; - a[5] += ht + dp; - break; - case 3: /* rot. 270 deg. */ - a[5] += ht + dp; - break; - default:; - } - /* the following is a kludge, TODO: use pdfpage.c functions */ - setpdffloat(cm[0], round(a[0]), r); - setpdffloat(cm[1], round(a[1]), r); - setpdffloat(cm[2], round(a[2]), r); - setpdffloat(cm[3], round(a[3]), r); - tmppos.h = round(a[4]); - tmppos.v = round(a[5]); - (void) calc_pdfpos(p, &tmppos); - cm[4] = p->cm[4]; - cm[5] = p->cm[5]; - pdf_goto_pagemode(); - if (pdf_page_group_val < 1) - pdf_page_group_val = img_group_ref(idict); /* added from web for 1.40.8 */ - pdf_printf("q\n"); - pdf_print_cm(cm); - pdf_printf("/Im"); - pdf_print_int(img_index(idict)); - pdf_print_resname_prefix(); - pdf_printf(" Do\nQ\n"); - if (img_state(idict) < DICT_OUTIMG) - img_state(idict) = DICT_OUTIMG; -} - -void write_img(image_dict * idict) -{ - assert(idict != NULL); - if (img_state(idict) < DICT_WRITTEN) { - if (tracefilenames) - tex_printf(" <%s", img_filepath(idict)); - switch (img_type(idict)) { - case IMG_TYPE_PNG: - write_png(idict); - break; - case IMG_TYPE_JPG: - write_jpg(idict); - break; - case IMG_TYPE_JBIG2: - write_jbig2(idict); - break; - case IMG_TYPE_PDF: - write_epdf(idict); - epdf_lastGroupObjectNum = img_group_ref(idict); - break; - case IMG_TYPE_PDFSTREAM: - write_pdfstream(idict); - break; - default: - pdftex_fail("internal error: unknown image type (1)"); - } - if (tracefilenames) - tex_printf(">"); - if (img_type(idict) == IMG_TYPE_PDF) { - write_additional_epdf_objects(); - } else { - if (img_type(idict) == IMG_TYPE_PNG) { - write_additional_png_objects(); - } - } - } - if (img_state(idict) < DICT_WRITTEN) - img_state(idict) = DICT_WRITTEN; -} - -/**********************************************************************/ - -void check_pdfstream_dict(image_dict * idict) -{ - if (!img_is_bbox(idict)) - pdftex_fail("image.stream: no bbox given"); - if (img_state(idict) < DICT_FILESCANNED) - img_state(idict) = DICT_FILESCANNED; -} - -void write_pdfstream(image_dict * idict) -{ - char s[256]; - assert(img_pdfstream_ptr(idict) != NULL); - assert(img_is_bbox(idict)); - pdf_puts("/Type /XObject\n/Subtype /Form\n"); - if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) - pdf_printf("%s\n", img_attr(idict)); - pdf_puts("/FormType 1\n"); - sprintf(s, "/BBox [%.8f %.8f %.8f %.8f]\n", int2bp(img_bbox(idict)[0]), - int2bp(img_bbox(idict)[1]), int2bp(img_bbox(idict)[2]), - int2bp(img_bbox(idict)[3])); - pdf_printf(stripzeros(s)); - pdf_begin_stream(); - if (img_pdfstream_stream(idict) != NULL) - pdf_puts(img_pdfstream_stream(idict)); - pdf_end_stream(); -} - -/**********************************************************************/ - -typedef image *img_entry; -/* define img_ptr, img_array, & img_limit */ -/* avoid use of size_t */ -img_entry *img_ptr, *img_array = NULL; -size_t img_limit; - -integer img_to_array(image * img) -{ - assert(img != NULL); - alloc_array(img, 1, SMALL_BUF_SIZE); - *img_ptr = img; - return img_ptr++ - img_array; /* now img is read-only */ -} - -/**********************************************************************/ - -/* To allow the use of \pdfrefximage inside saved boxes in -ini mode, - * the information in the array has to be (un)dumped with the format. - * The next two routines take care of that. - * - * Most of the work involved in setting up the images is simply - * executed again. This solves the many possible errors resulting from - * the split in two separate runs. - - * There was only one problem remaining: The pdfversion and - * pdfinclusionerrorlevel can have changed inbetween the call to - * readimage() and dump time. That is why they are passed as arguments - * to undumpimagemeta once more. - */ - -/* some of the dumped values are really type int, not integer, - * but since the macro falls back to generic_dump anyway, that - * does not matter. - */ - -#define dumpinteger generic_dump -#define undumpinteger generic_undump - -/* (un)dumping a string means dumping the allocation size, followed - * by the bytes. The trailing \0 is dumped as well, because that - * makes the code simpler. - */ - -#define dumpcharptr(a) \ - do { \ - integer x; \ - if (a!=NULL) { \ - x = strlen(a)+1; \ - dumpinteger(x); dump_things(*a, x); \ - } else { \ - x = 0; dumpinteger(x); \ - } \ - } while (0) - -#define undumpcharptr(s) \ - do { \ - integer x; \ - char *a; \ - undumpinteger (x); \ - if (x>0) { \ - a = malloc(x); \ - undump_things(*a,x); \ - s = a ; \ - } else { s = NULL; } \ - } while (0) - -void dumpimagemeta(void) -{ - int cur_image, i; - image *img; - image_dict *idict; - - dumpinteger(img_limit); - cur_image = (img_ptr - img_array); - dumpinteger(cur_image); - - for (i = 0; i < cur_image; i++) { - img = img_array[i]; - assert(img != NULL); - idict = img_dict(img); - dumpcharptr(img_filename(idict)); - dumpinteger(img_type(idict)); - dumpinteger(img_color(idict)); - dumpinteger(img_width(img)); - dumpinteger(img_height(img)); - dumpinteger(img_xres(idict)); - dumpinteger(img_yres(idict)); - dumpinteger(img_totalpages(idict)); - dumpinteger(img_colorspace(idict)); - dumpinteger(img_group_ref(idict)); - - /* the image_struct is not dumped at all, except for a few - variables that are needed to restore the contents */ - - if (img_type(idict) == IMG_TYPE_PDF) { - dumpinteger(img_pagebox(idict)); - dumpinteger(img_pagenum(idict)); - } else if (img_type(idict) == IMG_TYPE_JBIG2) { - dumpinteger(img_pagenum(idict)); - } - - } -} - -void undumpimagemeta(integer pdfversion, integer pdfinclusionerrorlevel) -{ - int cur_image, i; - image *img; - image_dict *idict; - - undumpinteger(img_limit); - - img_array = xtalloc(img_limit, img_entry); - undumpinteger(cur_image); - img_ptr = img_array + cur_image; - - for (i = 0; i < cur_image; i++) { - img = new_image(); - assert(img_arrayidx(img) == -1); - img_arrayidx(img) = img_to_array(img); - idict = img_dict(img) = new_image_dict(); - assert(idict != NULL); - undumpcharptr(img_filename(idict)); - undumpinteger(img_type(idict)); - undumpinteger(img_color(idict)); - undumpinteger(img_width(img)); - undumpinteger(img_height(img)); - undumpinteger(img_xres(idict)); - undumpinteger(img_yres(idict)); - undumpinteger(img_totalpages(idict)); - undumpinteger(img_colorspace(idict)); - undumpinteger(img_group_ref(idict)); - - switch (img_type(idict)) { - case IMG_TYPE_PDF: - undumpinteger(img_pagebox(idict)); - undumpinteger(img_pagenum(idict)); - break; - case IMG_TYPE_PNG: - break; - case IMG_TYPE_JPG: - break; - case IMG_TYPE_JBIG2: - if (pdfversion < 4) { - pdftex_fail - ("JBIG2 images only possible with at least PDF 1.4; you are generating PDF 1.%i", - (int) pdfversion); - } - undumpinteger(img_pagenum(idict)); - break; - default: - pdftex_fail("unknown type of image"); - } - read_img(idict, pdfversion, pdfinclusionerrorlevel); - } -} - -/**********************************************************************/ -/* stuff to be accessible from TeX */ - -integer read_image(integer objnum, integer index, str_number filename, - integer page_num, str_number page_name, str_number attr, - integer colorspace, integer page_box, - integer pdf_minor_version, integer pdf_inclusion_errorlevel) -{ - image_dict *idict; - image *a = new_image(); - assert(img_arrayidx(a) == -1); - img_arrayidx(a) = img_to_array(a); - idict = img_dict(a) = new_image_dict(); - assert(idict != NULL); - img_objnum(idict) = objnum; - img_index(idict) = index; - /* img_xsize, img_ysize, img_xres, img_yres set by read_img() */ - img_colorspace(idict) = colorspace; - img_pagenum(idict) = page_num; - /* img_totalpages set by read_img() */ - if (page_name != 0) - img_pagename(idict) = xstrdup(makecstring(page_name)); - cur_file_name = makecfilename(filename); - assert(cur_file_name != NULL); - img_filename(idict) = xstrdup(cur_file_name); - if (attr != 0) - img_attr(idict) = xstrdup(makecstring(attr)); - img_pagebox(idict) = page_box; - read_img(idict, pdf_minor_version, pdf_inclusion_errorlevel); - img_unset_scaled(a); - return img_arrayidx(a); -} - -void set_image_dimensions(integer ref, integer wd, integer ht, integer dp) -{ - image *a = img_array[ref]; - img_width(a) = wd; - img_height(a) = ht; - img_depth(a) = dp; -} - -void scale_image(integer ref) -{ - scale_img(img_array[ref]); -} - -void out_image(integer ref, scaled hpos, scaled vpos) -{ - image *a = img_array[ref]; - scaledpos pos; - pos.h = hpos; - pos.v = vpos; - out_img(a, pstruct, &pos); -} - -void write_image(integer ref) -{ - write_img(img_dict(img_array[ref])); -} - -integer image_pages(integer ref) -{ - return img_totalpages(img_dict(img_array[ref])); -} - -integer image_colordepth(integer ref) -{ - return img_colordepth(img_dict(img_array[ref])); -} - -#if 0 /* unused */ -static integer image_group_ref(integer ref) -{ - return img_group_ref(img_dict(img_array[ref])); -} -#endif - -/* The following five functions are for \pdfximagebbox */ - -integer epdf_xsize(integer ref) -{ - return img_xsize(img_dict(img_array[ref])); -} - -integer epdf_ysize(integer ref) -{ - return img_ysize(img_dict(img_array[ref])); -} - -integer epdf_orig_x(integer ref) -{ - return img_xorig(img_dict(img_array[ref])); -} - -integer epdf_orig_y(integer ref) -{ - return img_yorig(img_dict(img_array[ref])); -} - -boolean is_pdf_image(integer ref) -{ - return img_type(img_dict(img_array[ref])) == IMG_TYPE_PDF; -} - -boolean is_png_image(integer ref) -{ - return img_type(img_dict(img_array[ref])) == IMG_TYPE_PNG; -} - -integer image_objnum(integer ref) -{ - return img_objnum(img_dict(img_array[ref])); -} - -integer image_index(integer ref) -{ - return img_index(img_dict(img_array[ref])); -} - -integer image_width(integer ref) -{ - return img_width(img_array[ref]); -} - -integer image_height(integer ref) -{ - return img_height(img_array[ref]); -} - -integer image_depth(integer ref) -{ - return img_depth(img_array[ref]); -} - -void update_image_procset(integer ref) -{ - pdf_image_procset |= img_color(img_dict(img_array[ref])); -} - -boolean check_image_b(integer procset) -{ - return procset & IMAGE_COLOR_B; -} - -boolean check_image_c(integer procset) -{ - return procset & IMAGE_COLOR_C; -} - -boolean check_image_i(integer procset) -{ - return procset & IMAGE_COLOR_I; -} diff --git a/Build/source/texk/web2c/luatexdir/image/writeimg.h b/Build/source/texk/web2c/luatexdir/image/writeimg.h index bee82acaa97..66ef946d842 100644 --- a/Build/source/texk/web2c/luatexdir/image/writeimg.h +++ b/Build/source/texk/web2c/luatexdir/image/writeimg.h @@ -18,50 +18,35 @@ You should have received a copy of the GNU General Public License along with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ -/* $Id: writeimg.h 2448 2009-06-08 07:43:50Z taco $ */ +/* $Id: writeimg.h 3388 2010-01-26 10:59:04Z taco $ */ #ifndef WRITEIMG_H # define WRITEIMG_H +# include "dvi/dvigen.h" /* for scaled_whd only */ # include "image.h" +# include "pdf/pdfpage.h" -boolean check_image_b(integer); -boolean check_image_c(integer); -boolean check_image_i(integer); -boolean is_pdf_image(integer); -boolean is_png_image(integer); -image_dict *new_image_dict(void); +typedef image_dict *idict_entry; +idict_entry *idict_array; + +void new_img_pdfstream_struct(image_dict *); image *new_image(void); -integer epdf_orig_x(integer i); -integer epdf_orig_y(integer i); -integer epdf_xsize(integer i); -integer epdf_ysize(integer i); -integer image_colordepth(integer img); -integer image_depth(integer); -integer image_height(integer); -integer image_index(integer); -integer image_objnum(integer); -integer image_pages(integer); -integer image_width(integer); -integer img_to_array(image *); -integer read_image(integer, integer, str_number, integer, str_number, - str_number, integer, integer, integer, integer); +/*void init_image_dict(image_dict *);*/ +image_dict *new_image_dict(void); +void free_image_dict(image_dict * p); +void read_img(PDF, image_dict *, int, int); +void scan_pdfximage(PDF pdf); +void scan_pdfrefximage(PDF pdf); +scaled_whd tex_scale(scaled_whd nat, scaled_whd tex); +scaled_whd scale_img(image_dict *, scaled_whd, int); +void write_img(PDF, image_dict *); +void pdf_write_image(PDF pdf, int n); void check_pdfstream_dict(image_dict *); +void write_pdfstream(PDF, image_dict *); +void idict_to_array(image_dict *); void dumpimagemeta(void); -void free_image_dict(image_dict * p); -void init_image_dict(image_dict *); -void init_image(image *); -void new_img_pdfstream_struct(image_dict *); -void out_image(integer, scaled, scaled); -void pdf_print_resname_prefix(void); -void read_img(image_dict *, integer, integer); -void scale_image(integer); -void scale_img(image *); -void set_image_dimensions(integer, integer, integer, integer); -void undumpimagemeta(integer, integer); -void update_image_procset(integer); -void write_image(integer); -void write_img(image_dict *); -void write_pdfstream(image_dict *); +void undumpimagemeta(PDF, int, int); +scaled_whd scan_alt_rule(void); #endif /* WRITEIMG_H */ diff --git a/Build/source/texk/web2c/luatexdir/image/writeimg.w b/Build/source/texk/web2c/luatexdir/image/writeimg.w new file mode 100644 index 00000000000..a6b03ee4290 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/writeimg.w @@ -0,0 +1,823 @@ +% writeimg.w + +% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org> +% Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org> + +% This file is part of LuaTeX. + +% LuaTeX is free software; you can redistribute it and/or modify it under +% the terms of the GNU General Public License as published by the Free +% Software Foundation; either version 2 of the License, or (at your +% option) any later version. + +% LuaTeX is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +% License for more details. + +% You should have received a copy of the GNU General Public License along +% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. + +@* Image inclusion. + +@ @c +static const char _svn_version[] = + "$Id: writeimg.w 3584 2010-04-02 17:45:55Z hhenkel $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/image/writeimg.w $"; + +#include <assert.h> +#include "ptexlib.h" +#include <kpathsea/c-auto.h> +#include <kpathsea/c-memstr.h> + +@ @c +#include "image/image.h" +#include "image/writejpg.h" +#include "image/writepng.h" +#include "image/writejbig2.h" + +#include "lua51/lua.h" /* for |LUA_NOREF| */ +#include "lua51/lauxlib.h" + +@ @c +#define pdf_image_resolution int_par(pdf_image_resolution_code) +#define pdf_pagebox int_par(pdf_pagebox_code) + +@* Patch ImageTypeDetection 2003/02/08 by Heiko Oberdiek. + + Function |readimage| performs some basic initializations. + Then it looks at the file extension to determine the + image type and calls specific code/functions. + + The main disadvantage is that standard file extensions + have to be used, otherwise pdfTeX is not able to detect + the correct image type. + + The patch now looks at the file header first regardless of + the file extension. This is implemented in function + |check_type_by_header|. If this check fails, the traditional + test of standard file extension is tried, done in function + |check_type_by_extension|. + + Magic headers: + + * "PNG (Portable Network Graphics) Specification", Version 1.2 + (http://www.libpng.org/pub/png): + + 3.1. PNG file signature + + The first eight bytes of a PNG file always contain the following + (decimal) values: + + 137 80 78 71 13 10 26 10 + + Translation to C: |"\x89PNG\r\n\x1A\n"| + + * "JPEG File Interchange Format", Version 1.02: + + o you can identify a JFIF file by looking for the following + sequence: X'FF', SOI X'FF', APP0, <2 bytes to be skipped>, + "JFIF", X'00'. + + Function |check_type_by_header| only looks at the first two bytes: + |"\xFF\xD8"| + + * ISO/IEC JTC 1/SC 29/WG 1 + (ITU-T SG8) + Coding of Still Pictures + Title: 14492 FCD + Source: JBIG Committee + Project: JTC 1.29.10 + Status: Final Committee Draft + + D.4.1, ID string + + This is an 8-byte sequence containing 0x97 0x4A 0x42 0x32 0x0D 0x0A + 0x1A 0x0A. + + * "PDF Reference", third edition: + + * The first line should contain "\%PDF-1.0" until "\%PDF-1.4" + (section 3.4.1 "File Header"). + * The "implementation notes" say: + + 3.4.1, File Header + 12. Acrobat viewers require only that the header appear + somewhere within the first 1024 bytes of the file. + 13. Acrobat viewers will also accept a header of the form + \%!PS-Adobe-N.n PDF-M.m + + The check in function |check_type_by_header| only implements + the first issue. The implementation notes are not considered. + Therefore files with garbage at start of file must have the + standard extension. + + Functions |check_type_by_header| and |check_type_by_extension|: + |img_type(img)| is set to |IMG_TYPE_NONE| by |new_image_dict()|. + Both functions try to detect a type and set |img_type(img)|. + Thus a value other than |IMG_TYPE_NONE| indicates that a + type has been found. + +@c +#define HEADER_JPG "\xFF\xD8" +#define HEADER_PNG "\x89PNG\r\n\x1A\n" +#define HEADER_JBIG2 "\x97\x4A\x42\x32\x0D\x0A\x1A\x0A" +#define HEADER_PDF "%PDF-1." +#define MAX_HEADER (sizeof(HEADER_PNG)-1) + +static void check_type_by_header(image_dict * idict) +{ + int i; + FILE *file = NULL; + char header[MAX_HEADER]; + + assert(idict != NULL); + if (img_type(idict) != IMG_TYPE_NONE) /* nothing to do */ + return; + /* read the header */ + file = xfopen(img_filepath(idict), FOPEN_RBIN_MODE); + for (i = 0; (unsigned) i < MAX_HEADER; i++) { + header[i] = (char) xgetc(file); + if (feof(file)) + pdftex_fail("reading image file failed"); + } + xfclose(file, img_filepath(idict)); + /* tests */ + if (strncmp(header, HEADER_JPG, sizeof(HEADER_JPG) - 1) == 0) + img_type(idict) = IMG_TYPE_JPG; + else if (strncmp(header, HEADER_PNG, sizeof(HEADER_PNG) - 1) == 0) + img_type(idict) = IMG_TYPE_PNG; + else if (strncmp(header, HEADER_JBIG2, sizeof(HEADER_JBIG2) - 1) == 0) + img_type(idict) = IMG_TYPE_JBIG2; + else if (strncmp(header, HEADER_PDF, sizeof(HEADER_PDF) - 1) == 0) + img_type(idict) = IMG_TYPE_PDF; +} + +@ @c +static void check_type_by_extension(image_dict * idict) +{ + char *image_suffix; + + assert(idict != NULL); + if (img_type(idict) != IMG_TYPE_NONE) /* nothing to do */ + return; + /* tests */ + if ((image_suffix = strrchr(img_filename(idict), '.')) == 0) + img_type(idict) = IMG_TYPE_NONE; + else if (strcasecmp(image_suffix, ".png") == 0) + img_type(idict) = IMG_TYPE_PNG; + else if (strcasecmp(image_suffix, ".jpg") == 0 || + strcasecmp(image_suffix, ".jpeg") == 0) + img_type(idict) = IMG_TYPE_JPG; + else if (strcasecmp(image_suffix, ".jbig2") == 0 || + strcasecmp(image_suffix, ".jb2") == 0) + img_type(idict) = IMG_TYPE_JBIG2; + else if (strcasecmp(image_suffix, ".pdf") == 0) + img_type(idict) = IMG_TYPE_PDF; +} + +@ @c +void new_img_pdfstream_struct(image_dict * p) +{ + assert(p != NULL); + assert(img_pdfstream_ptr(p) == NULL); + img_pdfstream_ptr(p) = xtalloc(1, pdf_stream_struct); + img_pdfstream_stream(p) = NULL; +} + +@ @c +static void init_image(image * p) +{ + assert(p != NULL); + set_wd_running(p); + set_ht_running(p); + set_dp_running(p); + img_transform(p) = 0; + img_dict(p) = NULL; + img_dictref(p) = LUA_NOREF; +} + +@ @c +image *new_image(void) +{ + image *p = xtalloc(1, image); + init_image(p); + return p; +} + +@ @c +static void init_image_dict(image_dict * p) +{ + assert(p != NULL); + memset(p, 0, sizeof(image_dict)); + set_wd_running(p); + set_ht_running(p); + set_dp_running(p); + img_transform(p) = 0; + img_pagenum(p) = 1; + img_type(p) = IMG_TYPE_NONE; + img_pagebox(p) = PDF_BOX_SPEC_MEDIA; + img_unset_bbox(p); + img_unset_group(p); + img_state(p) = DICT_NEW; + img_index(p) = -1; /* -1 = unused, used count from 0 */ +} + +@ @c +image_dict *new_image_dict(void) +{ + image_dict *p = xtalloc(1, image_dict); + init_image_dict(p); + return p; +} + +@ @c +static void free_dict_strings(image_dict * p) +{ + xfree(img_filename(p)); + xfree(img_filepath(p)); + xfree(img_attr(p)); + xfree(img_pagename(p)); +} + +@ @c +void free_image_dict(image_dict * p) +{ + if (ini_version) + return; /* The image may be \.{\\dump}ed to a format */ + /* called from limglib.c */ + assert(img_state(p) < DICT_REFERED); + switch (img_type(p)) { + case IMG_TYPE_PDF: + unrefPdfDocument(img_filepath(p)); + break; + case IMG_TYPE_PNG: /* assuming |IMG_CLOSEINBETWEEN| */ + assert(img_png_ptr(p) == NULL); + break; + case IMG_TYPE_JPG: /* assuming |IMG_CLOSEINBETWEEN| */ + assert(img_jpg_ptr(p) == NULL); + break; + case IMG_TYPE_JBIG2: /* todo: writejbig2.w cleanup */ + break; + case IMG_TYPE_PDFSTREAM: + if (img_pdfstream_ptr(p) != NULL) { + xfree(img_pdfstream_stream(p)); + xfree(img_pdfstream_ptr(p)); + } + break; + case IMG_TYPE_NONE: + break; + default: + assert(0); + } + free_dict_strings(p); + assert(img_file(p) == NULL); + xfree(p); +} + +@ @c +void read_img(PDF pdf, + image_dict * idict, int minor_version, int inclusion_errorlevel) +{ + char *filepath; + int callback_id; + assert(idict != NULL); + if (img_filename(idict) == NULL) + pdftex_fail("image file name missing"); + callback_id = callback_defined(find_image_file_callback); + if (img_filepath(idict) == NULL) { + if (callback_id > 0 + && run_callback(callback_id, "S->S", img_filename(idict), + &filepath)) { + if (filepath && (strlen(filepath) > 0)) + img_filepath(idict) = strdup(filepath); + } else + img_filepath(idict) = + kpse_find_file(img_filename(idict), kpse_tex_format, true); + if (img_filepath(idict) == NULL) + pdftex_fail("cannot find image file"); + } + recorder_record_input(img_filename(idict)); + /* type checks */ + check_type_by_header(idict); + check_type_by_extension(idict); + /* read image */ + switch (img_type(idict)) { + case IMG_TYPE_PDF: + assert(pdf != NULL); /* TODO! */ + read_pdf_info(idict, minor_version, inclusion_errorlevel, + IMG_CLOSEINBETWEEN); + break; + case IMG_TYPE_PNG: + read_png_info(pdf, idict, IMG_CLOSEINBETWEEN); + break; + case IMG_TYPE_JPG: + read_jpg_info(pdf, idict, IMG_CLOSEINBETWEEN); + break; + case IMG_TYPE_JBIG2: + if (minor_version < 4) { + pdftex_fail + ("JBIG2 images only possible with at least PDF 1.4; you are generating PDF 1.%i", + (int) minor_version); + } + read_jbig2_info(idict); + break; + default: + pdftex_fail("internal error: unknown image type (2)"); + } + cur_file_name = NULL; + if (img_state(idict) < DICT_FILESCANNED) + img_state(idict) = DICT_FILESCANNED; +} + +@ @c +static image_dict *read_image(PDF pdf, char *file_name, int page_num, + char *page_name, int colorspace, + int page_box, int minor_version, + int inclusion_errorlevel) +{ + image *a = new_image(); + image_dict *idict = img_dict(a) = new_image_dict(); + incr(pdf->ximage_count); + pdf_create_obj(pdf, obj_type_ximage, pdf->ximage_count); + img_objnum(idict) = pdf->obj_ptr; + img_index(idict) = pdf->ximage_count; + set_obj_data_ptr(pdf, img_objnum(idict), img_index(idict)); + idict_to_array(idict); + img_colorspace(idict) = colorspace; + img_pagenum(idict) = page_num; + img_pagename(idict) = page_name; + assert(file_name != NULL); + cur_file_name = file_name; + img_filename(idict) = file_name; + img_pagebox(idict) = page_box; + read_img(pdf, idict, minor_version, inclusion_errorlevel); + return idict; +} + +@ scans PDF pagebox specification +@c +static pdfboxspec_e scan_pdf_box_spec(void) +{ + if (scan_keyword("mediabox")) + return PDF_BOX_SPEC_MEDIA; + else if (scan_keyword("cropbox")) + return PDF_BOX_SPEC_CROP; + else if (scan_keyword("bleedbox")) + return PDF_BOX_SPEC_BLEED; + else if (scan_keyword("trimbox")) + return PDF_BOX_SPEC_TRIM; + else if (scan_keyword("artbox")) + return PDF_BOX_SPEC_ART; + return PDF_BOX_SPEC_NONE; +} + +@ @c +void scan_pdfximage(PDF pdf) +{ + scaled_whd alt_rule; + image_dict *idict; + int transform = 0, page = 1, pagebox, colorspace = 0; + char *named = NULL, *attr = NULL, *file_name = NULL; + alt_rule = scan_alt_rule(); /* scans |<rule spec>| to |alt_rule| */ + if (scan_keyword("attr")) { + scan_pdf_ext_toks(); + attr = tokenlist_to_cstring(def_ref, true, NULL); + delete_token_ref(def_ref); + } + if (scan_keyword("named")) { + scan_pdf_ext_toks(); + named = tokenlist_to_cstring(def_ref, true, NULL); + delete_token_ref(def_ref); + page = 0; + } else if (scan_keyword("page")) { + scan_int(); + page = cur_val; + } + if (scan_keyword("colorspace")) { + scan_int(); + colorspace = cur_val; + } + pagebox = scan_pdf_box_spec(); + if (pagebox == PDF_BOX_SPEC_NONE) { + pagebox = pdf_pagebox; + if (pagebox == PDF_BOX_SPEC_NONE) + pagebox = PDF_BOX_SPEC_CROP; + } + scan_pdf_ext_toks(); + file_name = tokenlist_to_cstring(def_ref, true, NULL); + assert(file_name != NULL); + delete_token_ref(def_ref); + idict = + read_image(pdf, file_name, page, named, colorspace, pagebox, + pdf_minor_version, pdf_inclusion_errorlevel); + img_attr(idict) = attr; + img_dimen(idict) = alt_rule; + img_transform(idict) = transform; + pdf_last_ximage = img_objnum(idict); + pdf_last_ximage_pages = img_totalpages(idict); + pdf_last_ximage_colordepth = img_colordepth(idict); +} + +@ @c +#define tail cur_list.tail_field + +void scan_pdfrefximage(PDF pdf) +{ + int transform = 0; /* one could scan transform as well */ + image_dict *idict; + scaled_whd alt_rule, dim; + alt_rule = scan_alt_rule(); /* scans |<rule spec>| to |alt_rule| */ + scan_int(); + check_obj_exists(pdf, obj_type_ximage, cur_val); + new_whatsit(pdf_refximage_node); + idict = idict_array[obj_data_ptr(pdf, cur_val)]; + if (alt_rule.wd != null_flag || alt_rule.ht != null_flag + || alt_rule.dp != null_flag) + dim = scale_img(idict, alt_rule, transform); + else + dim = scale_img(idict, img_dimen(idict), img_transform(idict)); + width(tail) = dim.wd; + height(tail) = dim.ht; + depth(tail) = dim.dp; + pdf_ximage_transform(tail) = transform; + pdf_ximage_index(tail) = img_index(idict); +} + +@ |tex_scale()| sequence of decisions: + +{\obeylines\obeyspaces\tt +wd ht dp : res = tex; +wd ht -- +wd -- dp +wd -- -- +-- ht dp +-- ht -- +-- -- dp +-- -- -- : res = nat; +} + +@c +scaled_whd tex_scale(scaled_whd nat, scaled_whd tex) +{ + scaled_whd res; + if (!is_running(tex.wd) && !is_running(tex.ht) && !is_running(tex.dp)) { + /* width, height, and depth specified */ + res = tex; + } else /* max. 2 dimensions are specified */ if (!is_running(tex.wd)) { + res.wd = tex.wd; + if (!is_running(tex.ht)) { + res.ht = tex.ht; + /* width and height specified */ + res.dp = ext_xn_over_d(tex.ht, nat.dp, nat.ht); + } else if (!is_running(tex.dp)) { + res.dp = tex.dp; + /* width and depth specified */ + res.ht = ext_xn_over_d(tex.wd, nat.ht + nat.dp, nat.wd) - tex.dp; + } else { + /* only width specified */ + res.ht = ext_xn_over_d(tex.wd, nat.ht, nat.wd); + res.dp = ext_xn_over_d(tex.wd, nat.dp, nat.wd); + } + } else if (!is_running(tex.ht)) { + res.ht = tex.ht; + if (!is_running(tex.dp)) { + res.dp = tex.dp; + /* height and depth specified */ + res.wd = ext_xn_over_d(tex.ht + tex.dp, nat.wd, nat.ht + nat.dp); + } else { + /* only height specified */ + res.wd = ext_xn_over_d(tex.ht, nat.wd, nat.ht); + res.dp = ext_xn_over_d(tex.ht, nat.dp, nat.ht); + } + } else if (!is_running(tex.dp)) { + res.dp = tex.dp; + /* only depth specified */ + res.ht = nat.ht - (tex.dp - nat.dp); + res.wd = nat.wd; + } else { + /* nothing specified */ + res = nat; + } + return res; +} + +@ Within |scale_img()| only image width and height matter; +the offsets and positioning are not interesting here. +But one needs rotation info to swap width and height. +|img_rotation()| comes from the optional /Rotate key in the PDF file. + +@c +scaled_whd scale_img(image_dict * idict, scaled_whd alt_rule, int transform) +{ + int x, y, xr, yr, tmp; /* size and resolution of image */ + scaled_whd nat; /* natural size corresponding to image resolution */ + int default_res; + assert(idict != NULL); + if ((img_type(idict) == IMG_TYPE_PDF + || img_type(idict) == IMG_TYPE_PDFSTREAM) && img_is_bbox(idict)) { + x = img_xsize(idict) = img_bbox(idict)[2] - img_bbox(idict)[0]; /* dimensions from image.bbox */ + y = img_ysize(idict) = img_bbox(idict)[3] - img_bbox(idict)[1]; + img_xorig(idict) = img_bbox(idict)[0]; + img_yorig(idict) = img_bbox(idict)[1]; + } else { + x = img_xsize(idict); /* dimensions, resolutions from image file */ + y = img_ysize(idict); + } + xr = img_xres(idict); + yr = img_yres(idict); + if (x <= 0 || y <= 0 || xr < 0 || yr < 0) + pdftex_fail("ext1: invalid image dimensions"); + if (xr > 65535 || yr > 65535) { + xr = 0; + yr = 0; + pdftex_warn("ext1: too large image resolution ignored"); + } + if (((transform - img_rotation(idict)) & 1) == 1) { + tmp = x; + x = y; + y = tmp; + tmp = xr; + xr = yr; + yr = tmp; + } + nat.dp = 0; /* always for images */ + if (img_type(idict) == IMG_TYPE_PDF + || img_type(idict) == IMG_TYPE_PDFSTREAM) { + nat.wd = x; + nat.ht = y; + } else { + default_res = fix_int(pdf_image_resolution, 0, 65535); + if (default_res > 0 && (xr == 0 || yr == 0)) { + xr = default_res; + yr = default_res; + } + if (xr > 0 && yr > 0) { + nat.wd = ext_xn_over_d(one_hundred_inch, x, 100 * xr); + nat.ht = ext_xn_over_d(one_hundred_inch, y, 100 * yr); + } else { + nat.wd = ext_xn_over_d(one_hundred_inch, x, 7200); + nat.ht = ext_xn_over_d(one_hundred_inch, y, 7200); + } + } + return tex_scale(nat, alt_rule); +} + +@ @c +void write_img(PDF pdf, image_dict * idict) +{ + assert(idict != NULL); + if (img_state(idict) < DICT_WRITTEN) { + if (tracefilenames) + tex_printf(" <%s", img_filepath(idict)); + switch (img_type(idict)) { + case IMG_TYPE_PNG: + write_png(pdf, idict); + break; + case IMG_TYPE_JPG: + write_jpg(pdf, idict); + break; + case IMG_TYPE_JBIG2: + write_jbig2(pdf, idict); + break; + case IMG_TYPE_PDF: + write_epdf(pdf, idict); + break; + case IMG_TYPE_PDFSTREAM: + write_pdfstream(pdf, idict); + break; + default: + pdftex_fail("internal error: unknown image type (1)"); + } + if (tracefilenames) + tex_printf(">"); + if (img_type(idict) == IMG_TYPE_PNG) { + write_additional_png_objects(pdf); + } + } + if (img_state(idict) < DICT_WRITTEN) + img_state(idict) = DICT_WRITTEN; +} + +@ write an image +@c +void pdf_write_image(PDF pdf, int n) +{ + pdf_begin_dict(pdf, n, 0); + if (pdf->draftmode == 0) + write_img(pdf, idict_array[obj_data_ptr(pdf, n)]); +} + +@ @c +void check_pdfstream_dict(image_dict * idict) +{ + if (!img_is_bbox(idict)) + pdftex_fail("image.stream: no bbox given"); + if (img_state(idict) < DICT_FILESCANNED) + img_state(idict) = DICT_FILESCANNED; +} + +@ @c +void write_pdfstream(PDF pdf, image_dict * idict) +{ + char s[256]; + assert(img_pdfstream_ptr(idict) != NULL); + assert(img_is_bbox(idict)); + pdf_puts(pdf, "/Type /XObject\n/Subtype /Form\n"); + if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) + pdf_printf(pdf, "%s\n", img_attr(idict)); + pdf_puts(pdf, "/FormType 1\n"); + sprintf(s, "/BBox [%.8f %.8f %.8f %.8f]\n", int2bp(img_bbox(idict)[0]), + int2bp(img_bbox(idict)[1]), int2bp(img_bbox(idict)[2]), + int2bp(img_bbox(idict)[3])); + pdf_printf(pdf, stripzeros(s)); + pdf_begin_stream(pdf); + if (img_pdfstream_stream(idict) != NULL) + pdf_puts(pdf, img_pdfstream_stream(idict)); + pdf_end_stream(pdf); +} + +@ @c +/* define |idict_ptr|, |idict_array|, and |idict_limit| */ +idict_entry *idict_ptr, *idict_array = NULL; +size_t idict_limit; + +void idict_to_array(image_dict * idict) +{ + assert(idict != NULL); + if (idict_ptr - idict_array == 0) { /* align to count from 1 */ + alloc_array(idict, 1, SMALL_BUF_SIZE); /* /Im0 unused */ + idict_ptr++; + } + alloc_array(idict, 1, SMALL_BUF_SIZE); + *idict_ptr = idict; + assert(img_index(idict) == idict_ptr - idict_array); + idict_ptr++; +} + + +@ To allow the use of \.{\\pdfrefximage} inside saved boxes in -ini mode, +the information in the array has to be (un)dumped with the format. +The next two routines take care of that. + +Most of the work involved in setting up the images is simply +executed again. This solves the many possible errors resulting from +the split in two separate runs. + +There was only one problem remaining: The pdfversion and +pdfinclusionerrorlevel can have changed inbetween the call to +|readimage()| and dump time. That is why they are passed as arguments +to undumpimagemeta once more. + +some of the dumped values are really type int, not integer, +but since the macro falls back to |generic_dump| anyway, that +does not matter. + +@c +#define dumpinteger generic_dump +#define undumpinteger generic_undump + +@ (un)dumping a string means dumping the allocation size, followed + by the bytes. The trailing \.{\\0} is dumped as well, because that + makes the code simpler. + +@c +#define dumpcharptr(a) \ + do { \ + int x; \ + if (a!=NULL) { \ + x = (int)strlen(a)+1; \ + dumpinteger(x); dump_things(*a, x); \ + } else { \ + x = 0; dumpinteger(x); \ + } \ + } while (0) + +#define undumpcharptr(s) \ + do { \ + int x; \ + char *a; \ + undumpinteger (x); \ + if (x>0) { \ + a = xmalloc((unsigned)x); \ + undump_things(*a,x); \ + s = a ; \ + } else { s = NULL; } \ + } while (0) + +@ @c +void dumpimagemeta(void) +{ + int cur_index, i; + image_dict *idict; + + i = (int) idict_limit; + dumpinteger(i); + cur_index = (int) (idict_ptr - idict_array); + dumpinteger(cur_index); + + for (i = 1; i < cur_index; i++) { + idict = idict_array[i]; + assert(idict != NULL); + dumpcharptr(img_filename(idict)); + dumpinteger(img_type(idict)); + dumpinteger(img_procset(idict)); + dumpinteger(img_xsize(idict)); + dumpinteger(img_ysize(idict)); + dumpinteger(img_xres(idict)); + dumpinteger(img_yres(idict)); + dumpinteger(img_totalpages(idict)); + dumpinteger(img_colorspace(idict)); + + /* the |image_struct| is not dumped at all, except for a few + variables that are needed to restore the contents */ + + if (img_type(idict) == IMG_TYPE_PDF) { + dumpinteger(img_pagebox(idict)); + dumpinteger(img_pagenum(idict)); + } else if (img_type(idict) == IMG_TYPE_JBIG2) { + dumpinteger(img_pagenum(idict)); + } + + } +} + +@ @c +void undumpimagemeta(PDF pdf, int pdfversion, int pdfinclusionerrorlevel) +{ + int cur_index, i; + image_dict *idict; + + assert(pdf != NULL); + undumpinteger(i); + idict_limit = (size_t) i; + + idict_array = xtalloc(idict_limit, idict_entry); + undumpinteger(cur_index); + idict_ptr = idict_array + cur_index; + + for (i = 1; i < cur_index; i++) { + idict = new_image_dict(); + assert(idict != NULL); + assert(img_index(idict) == -1); + idict_to_array(idict); + undumpcharptr(img_filename(idict)); + undumpinteger(img_type(idict)); + undumpinteger(img_procset(idict)); + undumpinteger(img_xsize(idict)); + undumpinteger(img_ysize(idict)); + undumpinteger(img_xres(idict)); + undumpinteger(img_yres(idict)); + undumpinteger(img_totalpages(idict)); + undumpinteger(img_colorspace(idict)); + + switch (img_type(idict)) { + case IMG_TYPE_PDF: + undumpinteger(img_pagebox(idict)); + undumpinteger(img_pagenum(idict)); + break; + case IMG_TYPE_PNG: + break; + case IMG_TYPE_JPG: + break; + case IMG_TYPE_JBIG2: + if (pdfversion < 4) { + pdftex_fail + ("JBIG2 images only possible with at least PDF 1.4; you are generating PDF 1.%i", + (int) pdfversion); + } + undumpinteger(img_pagenum(idict)); + break; + default: + pdftex_fail("unknown type of image"); + } + read_img(pdf, idict, pdfversion, pdfinclusionerrorlevel); + } +} + +@ scans rule spec to |alt_rule| +@c +scaled_whd scan_alt_rule(void) +{ + scaled_whd alt_rule; + alt_rule.wd = null_flag; + alt_rule.ht = null_flag; + alt_rule.dp = null_flag; + RESWITCH: + if (scan_keyword("width")) { + scan_normal_dimen(); + alt_rule.wd = cur_val; + goto RESWITCH; + } + if (scan_keyword("height")) { + scan_normal_dimen(); + alt_rule.ht = cur_val; + goto RESWITCH; + } + if (scan_keyword("depth")) { + scan_normal_dimen(); + alt_rule.dp = cur_val; + goto RESWITCH; + } + return alt_rule; +} diff --git a/Build/source/texk/web2c/luatexdir/image/writejbig2.h b/Build/source/texk/web2c/luatexdir/image/writejbig2.h index f28e91281fe..a5715d5732e 100644 --- a/Build/source/texk/web2c/luatexdir/image/writejbig2.h +++ b/Build/source/texk/web2c/luatexdir/image/writejbig2.h @@ -18,15 +18,15 @@ You should have received a copy of the GNU General Public License along with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ -/* $Id: writejbig2.h 2327 2009-04-18 12:47:21Z hhenkel $ */ +/* $Id: writejbig2.h 2579 2009-06-23 14:12:23Z taco $ */ #ifndef WRITEJBIG2_H # define WRITEJBIG2_H # include "image.h" -void flush_jbig2_page0_objects(void); +void flush_jbig2_page0_objects(PDF); void read_jbig2_info(image_dict *); -void write_jbig2(image_dict *); +void write_jbig2(PDF, image_dict *); #endif /* WRITEJBIG"_H */ diff --git a/Build/source/texk/web2c/luatexdir/image/writejbig2.c b/Build/source/texk/web2c/luatexdir/image/writejbig2.w index c22c27e11b6..936ae29c6bd 100644 --- a/Build/source/texk/web2c/luatexdir/image/writejbig2.c +++ b/Build/source/texk/web2c/luatexdir/image/writejbig2.w @@ -1,24 +1,24 @@ -/* writejbig2.c +% writejbig2.w - Copyright 1996-2006 Han The Thanh <thanh@pdftex.org> - Copyright 2006-2009 Taco Hoekwater <taco@luatex.org> +% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org> +% Copyright 2006-2009 Taco Hoekwater <taco@@luatex.org> - This file is part of LuaTeX. +% This file is part of LuaTeX. - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. +% LuaTeX is free software; you can redistribute it and/or modify it under +% the terms of the GNU General Public License as published by the Free +% Software Foundation; either version 2 of the License, or (at your +% option) any later version. - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. +% LuaTeX is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +% License for more details. - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ +% You should have received a copy of the GNU General Public License along +% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. -/*********************************************************************** +@ This is experimental JBIG2 image support to pdfTeX. JBIG2 image decoding is part of Adobe PDF-1.4, and requires Acroread 5.0 or later. @@ -40,21 +40,21 @@ http://partners.adobe.com/public/developer/en/pdf/PDFReference16.pdf News ==== -31 May 2006: no need to wait for endoffileflag in sequential access +31 May 2006: no need to wait for |endoffileflag| in sequential access organization. -10 May 2006: ygetc() for some catching of broken JBIG2 files; modify to +10 May 2006: |ygetc()| for some catching of broken JBIG2 files; modify to accept Example 3.4 from PDFRef 5th ed. with short end-of-file segment. -09 May 2006: pages_maketree() and segments_maketree() by AVL tree, +09 May 2006: |pages_maketree()| and |segments_maketree()| by AVL tree, some cleaning up. -06 May 2006: File list replaced by AVL tree; new_fileinfo(), -new_pageinfo(). +06 May 2006: File list replaced by AVL tree; |new_fileinfo()|, +|new_pageinfo()|. 04 May 2006: Updated for pdftex-1.40-beta-20060213. -08 Jan. 2003: Added flushjbig2page0objects() function. Now at the end +08 Jan. 2003: Added |flushjbig2page0objects()| function. Now at the end of the pdfTeX run all pending page0 objects are written out. 08 Jan. 2003: Release on private webpage. @@ -78,11 +78,10 @@ object exists, reference it. Else create fresh one. 09 Dec. 2002: JBIG2 seg. page numbers > 0 are now set to 1, see PDF Ref. -***********************************************************************/ - +@ @c static const char _svn_version[] = - "$Id: writejbig2.c 2315 2009-04-17 23:34:42Z hhenkel $ " - "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.40.6/source/texk/web2c/luatexdir/image/writejbig2.c $"; + "$Id: writejbig2.w 3584 2010-04-02 17:45:55Z hhenkel $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/image/writejbig2.w $"; #undef DEBUG @@ -90,11 +89,9 @@ static const char _svn_version[] = #include <stdio.h> #include <assert.h> #include "ptexlib.h" -#include "ptexmac.h" -#include "image.h" - -/**********************************************************************/ +#include "image/image.h" +@ @c /* 7.3 Segment types */ #define M_SymbolDictionary 0 #define M_IntermediateTextRegion 4 @@ -118,8 +115,7 @@ static const char _svn_version[] = #define M_Tables 53 #define M_Extension 62 -/**********************************************************************/ - +@ @c typedef enum { INITIAL, HAVEINFO, WRITEPDF } PHASE; typedef struct _LITEM { @@ -177,13 +173,12 @@ typedef struct _FILEINFO { unsigned int filehdrflags; /* set by readfilehdr() */ boolean sequentialaccess; /* set by readfilehdr() */ unsigned long numofpages; /* set by readfilehdr() */ - unsigned long streamstart; /* set by get_jbig2_info() */ + unsigned long streamstart; /* set by |get_jbig2_info()| */ unsigned long pdfpage0objnum; PHASE phase; } FILEINFO; -/**********************************************************************/ - +@ @c static struct avl_table *file_tree = NULL; static int comp_file_entry(const void *pa, const void *pb, void *p) @@ -196,17 +191,18 @@ static int comp_file_entry(const void *pa, const void *pb, void *p) static int comp_page_entry(const void *pa, const void *pb, void *p) { (void) p; - return ((const PAGEINFO *) pa)->pagenum - ((const PAGEINFO *) pb)->pagenum; + return (int) (((const PAGEINFO *) pa)->pagenum - + ((const PAGEINFO *) pb)->pagenum); } static int comp_segment_entry(const void *pa, const void *pb, void *p) { (void) p; - return ((const SEGINFO *) pa)->segnum - ((const SEGINFO *) pb)->segnum; + return (int) (((const SEGINFO *) pa)->segnum - + ((const SEGINFO *) pb)->segnum); } -/**********************************************************************/ - +@ @c static int ygetc(FILE * stream) { int c = getc(stream); @@ -219,8 +215,7 @@ static int ygetc(FILE * stream) return c; } -/**********************************************************************/ - +@ @c static void initlinkedlist(LIST * lp) { lp->first = NULL; @@ -245,8 +240,7 @@ static LIST *litem_append(LIST * lp) return lp; } -/**********************************************************************/ - +@ @c static FILEINFO *new_fileinfo(void) { FILEINFO *fip; @@ -265,6 +259,7 @@ static FILEINFO *new_fileinfo(void) return fip; } +@ @c static PAGEINFO *new_pageinfo(void) { PAGEINFO *pip; @@ -281,6 +276,7 @@ static PAGEINFO *new_pageinfo(void) return pip; } +@ @c static void init_seginfo(SEGINFO * sip) { sip->segnum = 0; @@ -304,8 +300,7 @@ static void init_seginfo(SEGINFO * sip) sip->endoffileflag = false; } -/**********************************************************************/ - +@ @c static void pages_maketree(LIST * plp) { LITEM *ip; @@ -319,6 +314,7 @@ static void pages_maketree(LIST * plp) } } +@ @c static void segments_maketree(LIST * slp) { LITEM *ip; @@ -332,8 +328,7 @@ static void segments_maketree(LIST * slp) } } -/**********************************************************************/ - +@ @c static PAGEINFO *find_pageinfo(LIST * plp, unsigned long pagenum) { PAGEINFO tmp; @@ -342,6 +337,7 @@ static PAGEINFO *find_pageinfo(LIST * plp, unsigned long pagenum) return (PAGEINFO *) avl_find(plp->tree, &tmp); } +@ @c static SEGINFO *find_seginfo(LIST * slp, unsigned long segnum) { SEGINFO tmp; @@ -350,22 +346,21 @@ static SEGINFO *find_seginfo(LIST * slp, unsigned long segnum) return (SEGINFO *) avl_find(slp->tree, &tmp); } -/**********************************************************************/ - +@ @c static unsigned int read2bytes(FILE * f) { - unsigned int c = ygetc(f); - return (c << 8) + ygetc(f); + unsigned int c = (unsigned int) ygetc(f); + return (c << 8) + (unsigned int) ygetc(f); } +@ @c static unsigned long read4bytes(FILE * f) { unsigned int l = read2bytes(f); return (l << 16) + read2bytes(f); } -/**********************************************************************/ - +@ @c static unsigned long getstreamlen(LITEM * slip, boolean refer) { SEGINFO *sip; @@ -378,8 +373,7 @@ static unsigned long getstreamlen(LITEM * slip, boolean refer) return len; } -/**********************************************************************/ - +@ @c static void readfilehdr(FILEINFO * fip) { unsigned int i; @@ -392,7 +386,7 @@ static void readfilehdr(FILEINFO * fip) pdftex_fail ("readfilehdr(): reading JBIG2 image file failed: ID string missing"); /* Annex D.4.2 File header flags */ - fip->filehdrflags = ygetc(fip->file); + fip->filehdrflags = (unsigned int) ygetc(fip->file); fip->sequentialaccess = (fip->filehdrflags & 0x01) ? true : false; if (fip->sequentialaccess) { /* Annex D.1 vs. Annex D.2 */ xfseek(fip->file, 0, SEEK_END, fip->filepath); @@ -405,8 +399,7 @@ static void readfilehdr(FILEINFO * fip) /* --- at end of file header --- */ } -/**********************************************************************/ - +@ @c static void checkseghdrflags(SEGINFO * sip) { sip->endofstripeflag = false; @@ -453,9 +446,9 @@ static void checkseghdrflags(SEGINFO * sip) } } -/**********************************************************************/ -/* for first reading of file; return value tells if header been read */ +@ for first reading of file; return value tells if header been read +@c static boolean readseghdr(FILEINFO * fip, SEGINFO * sip) { unsigned int i; @@ -471,7 +464,7 @@ static boolean readseghdr(FILEINFO * fip, SEGINFO * sip) printf(" segnum %d\n", sip->segnum); #endif /* 7.2.3 Segment header flags */ - sip->seghdrflags = ygetc(fip->file); + sip->seghdrflags = (unsigned int) ygetc(fip->file); #ifdef DEBUG printf(" hdrflags %d\n", sip->seghdrflags & 0x3f); #endif @@ -510,18 +503,17 @@ static boolean readseghdr(FILEINFO * fip, SEGINFO * sip) } /* 7.2.6 Segment page association */ if (sip->pageassocsizeflag) - sip->segpage = read4bytes(fip->file); + sip->segpage = (long int) read4bytes(fip->file); else sip->segpage = ygetc(fip->file); /* 7.2.7 Segment data length */ sip->segdatalen = read4bytes(fip->file); - sip->hdrend = (long) xftello(fip->file, fip->filepath); + sip->hdrend = (unsigned long) xftello(fip->file, fip->filepath); /* ---- at end of segment header ---- */ return true; } -/**********************************************************************/ - +@ @c static void checkseghdr(FILEINFO * fip, SEGINFO * sip); static void markpage0seg(FILEINFO * fip, unsigned long referedseg) @@ -537,10 +529,10 @@ static void markpage0seg(FILEINFO * fip, unsigned long referedseg) } } -/**********************************************************************/ -/* for writing, marks refered page0 segments, sets segpage > 0 to 1 */ +@ for writing, marks refered page0 segments, sets segpage > 0 to 1 -static void writeseghdr(FILEINFO * fip, SEGINFO * sip) +@c +static void writeseghdr(PDF pdf, FILEINFO * fip, SEGINFO * sip) { unsigned int i; unsigned long referedseg = 0; @@ -548,25 +540,25 @@ static void writeseghdr(FILEINFO * fip, SEGINFO * sip) /* 7.2.3 Segment header flags */ /* 7.2.4 Referred-to segment count and retention flags */ for (i = 0; i < 5 + sip->fieldlen; i++) - pdfout(ygetc(fip->file)); + pdf_out(pdf, ygetc(fip->file)); /* 7.2.5 Referred-to segment numbers */ for (i = 0; i < sip->countofrefered; i++) { switch (sip->segnumwidth) { case 1: - referedseg = ygetc(fip->file); - pdfout(referedseg); + referedseg = (unsigned long) ygetc(fip->file); + pdf_out(pdf, referedseg); break; case 2: referedseg = read2bytes(fip->file); - pdfout((referedseg >> 8) & 0xff); - pdfout(referedseg & 0xff); + pdf_out(pdf, (referedseg >> 8) & 0xff); + pdf_out(pdf, referedseg & 0xff); break; case 4: referedseg = read4bytes(fip->file); - pdfout((referedseg >> 24) & 0xff); - pdfout((referedseg >> 16) & 0xff); - pdfout((referedseg >> 8) & 0xff); - pdfout(referedseg & 0xff); + pdf_out(pdf, (referedseg >> 24) & 0xff); + pdf_out(pdf, (referedseg >> 16) & 0xff); + pdf_out(pdf, (referedseg >> 8) & 0xff); + pdf_out(pdf, referedseg & 0xff); break; } if (fip->page0.last != NULL && !sip->refers) @@ -578,19 +570,18 @@ static void writeseghdr(FILEINFO * fip, SEGINFO * sip) if (sip->pageassocsizeflag) for (i = 0; i < 3; i++) { (void) ygetc(fip->file); - pdfout(0); + pdf_out(pdf, 0); } (void) ygetc(fip->file); - pdfout((sip->segpage > 0) ? 1 : 0); + pdf_out(pdf, (unsigned char) ((sip->segpage > 0) ? 1 : 0)); /* 7.2.7 Segment data length */ for (i = 0; i < 4; i++) - pdfout(ygetc(fip->file)); + pdf_out(pdf, ygetc(fip->file)); /* ---- at end of segment header ---- */ } -/**********************************************************************/ -/* for recursive marking of refered page0 segments */ - +@ for recursive marking of refered page0 segments +@c static void checkseghdr(FILEINFO * fip, SEGINFO * sip) { unsigned int i; @@ -603,7 +594,7 @@ static void checkseghdr(FILEINFO * fip, SEGINFO * sip) for (i = 0; i < sip->countofrefered; i++) { switch (sip->segnumwidth) { case 1: - referedseg = ygetc(fip->file); + referedseg = (unsigned long) ygetc(fip->file); break; case 2: referedseg = read2bytes(fip->file); @@ -626,8 +617,7 @@ static void checkseghdr(FILEINFO * fip, SEGINFO * sip) /* ---- at end of segment header ---- */ } -/**********************************************************************/ - +@ @c static unsigned long findstreamstart(FILEINFO * fip) { SEGINFO tmp; @@ -640,8 +630,7 @@ static unsigned long findstreamstart(FILEINFO * fip) return fip->streamstart; } -/**********************************************************************/ - +@ @c static void rd_jbig2_info(FILEINFO * fip) { unsigned long seekdist = 0; /* for sequential-access only */ @@ -667,7 +656,7 @@ static void rd_jbig2_info(FILEINFO * fip) if (sip->segpage > (int) currentpage) { plp = litem_append(&(fip->pages)); plp->last->d = new_pageinfo(); - currentpage = sip->segpage; + currentpage = (unsigned long) sip->segpage; } pip = fip->pages.last->d; } else { @@ -689,31 +678,31 @@ static void rd_jbig2_info(FILEINFO * fip) sip->dataend = sip->datastart + sip->segdatalen; if (!fip->sequentialaccess && (sip->pageinfoflag || sip->endofstripeflag)) - xfseeko(fip->file, sip->datastart, SEEK_SET, fip->filepath); + xfseeko(fip->file, (off_t) sip->datastart, SEEK_SET, fip->filepath); seekdist = sip->segdatalen; /* 7.4.8 Page information segment syntax */ if (sip->pageinfoflag) { - pip->pagenum = sip->segpage; - pip->width = read4bytes(fip->file); - pip->height = read4bytes(fip->file); - pip->xres = read4bytes(fip->file); - pip->yres = read4bytes(fip->file); - pip->pagesegmentflags = ygetc(fip->file); + pip->pagenum = (unsigned long) sip->segpage; + pip->width = (unsigned) read4bytes(fip->file); + pip->height = (unsigned) read4bytes(fip->file); + pip->xres = (unsigned) read4bytes(fip->file); + pip->yres = (unsigned) read4bytes(fip->file); + pip->pagesegmentflags = (unsigned) ygetc(fip->file); /* 7.4.8.6 Page striping information */ pip->stripinginfo = read2bytes(fip->file); seekdist -= 19; } if (sip->endofstripeflag) { - pip->stripedheight = read4bytes(fip->file); + pip->stripedheight = (unsigned) read4bytes(fip->file); seekdist -= 4; } if (!fip->sequentialaccess && (sip->pageinfoflag || sip->endofstripeflag)) - xfseeko(fip->file, sip->hdrend, SEEK_SET, fip->filepath); + xfseeko(fip->file, (off_t) sip->hdrend, SEEK_SET, fip->filepath); if (!fip->sequentialaccess) streampos += sip->segdatalen; if (fip->sequentialaccess) - xfseeko(fip->file, seekdist, SEEK_CUR, fip->filepath); + xfseeko(fip->file, (off_t) seekdist, SEEK_CUR, fip->filepath); if (sip->endofpageflag && currentpage && (pip->stripinginfo >> 15)) pip->height = pip->stripedheight; } @@ -723,9 +712,8 @@ static void rd_jbig2_info(FILEINFO * fip) xfclose(fip->file, fip->filepath); } -/**********************************************************************/ - -static void wr_jbig2(FILEINFO * fip, unsigned long page) +@ @c +static void wr_jbig2(PDF pdf, FILEINFO * fip, unsigned long page) { LITEM *slip; PAGEINFO *pip; @@ -734,47 +722,48 @@ static void wr_jbig2(FILEINFO * fip, unsigned long page) if (page > 0) { pip = find_pageinfo(&(fip->pages), page); assert(pip != NULL); - pdf_puts("/Type /XObject\n/Subtype /Image\n"); - pdf_printf("/Width %i\n", pip->width); - pdf_printf("/Height %i\n", pip->height); - pdf_puts("/ColorSpace /DeviceGray\n"); - pdf_puts("/BitsPerComponent 1\n"); - pdf_printf("/Length %lu\n", getstreamlen(pip->segments.first, true)); - pdf_puts("/Filter [/JBIG2Decode]\n"); + pdf_puts(pdf, "/Type /XObject\n/Subtype /Image\n"); + pdf_printf(pdf, "/Width %i\n", pip->width); + pdf_printf(pdf, "/Height %i\n", pip->height); + pdf_puts(pdf, "/ColorSpace /DeviceGray\n"); + pdf_puts(pdf, "/BitsPerComponent 1\n"); + pdf_printf(pdf, "/Length %lu\n", + getstreamlen(pip->segments.first, true)); + pdf_puts(pdf, "/Filter [/JBIG2Decode]\n"); if (fip->page0.last != NULL) { if (fip->pdfpage0objnum == 0) { - pdf_create_obj(0, 0); - fip->pdfpage0objnum = obj_ptr; + pdf_create_obj(pdf, obj_type_others, 0); + fip->pdfpage0objnum = (unsigned long) pdf->obj_ptr; } - pdf_printf("/DecodeParms [<< /JBIG2Globals %lu 0 R >>]\n", + pdf_printf(pdf, "/DecodeParms [<< /JBIG2Globals %lu 0 R >>]\n", fip->pdfpage0objnum); } } else { pip = find_pageinfo(&(fip->page0), page); assert(pip != NULL); - pdf_begin_dict(fip->pdfpage0objnum, 0); - pdf_printf("/Length %lu\n", getstreamlen(pip->segments.first, false)); + pdf_begin_dict(pdf, (int) fip->pdfpage0objnum, 0); + pdf_printf(pdf, "/Length %lu\n", + getstreamlen(pip->segments.first, false)); } - pdf_puts(">>\n"); - pdf_puts("stream\n"); + pdf_puts(pdf, ">>\n"); + pdf_puts(pdf, "stream\n"); fip->file = xfopen(fip->filepath, FOPEN_RBIN_MODE); for (slip = pip->segments.first; slip != NULL; slip = slip->next) { /* loop over page segments */ sip = slip->d; if (sip->isrefered || page > 0) { - xfseeko(fip->file, sip->hdrstart, SEEK_SET, fip->filepath); + xfseeko(fip->file, (off_t) sip->hdrstart, SEEK_SET, fip->filepath); /* mark refered-to page 0 segments, change segpages > 1 to 1 */ - writeseghdr(fip, sip); - xfseeko(fip->file, sip->datastart, SEEK_SET, fip->filepath); + writeseghdr(pdf, fip, sip); + xfseeko(fip->file, (off_t) sip->datastart, SEEK_SET, fip->filepath); for (i = sip->datastart; i < sip->dataend; i++) - pdfout(ygetc(fip->file)); + pdf_out(pdf, ygetc(fip->file)); } } - pdf_end_stream(); + pdf_end_stream(pdf); xfclose(fip->file, fip->filepath); } -/**********************************************************************/ - +@ @c void read_jbig2_info(image_dict * idict) { FILEINFO *fip, tmp; @@ -807,19 +796,20 @@ void read_jbig2_info(image_dict * idict) segments_maketree(&(pip->segments)); } } - pip = find_pageinfo(&(fip->pages), img_pagenum(idict)); + pip = find_pageinfo(&(fip->pages), (unsigned long) img_pagenum(idict)); if (pip == NULL) pdftex_fail("read_jbig2_info(): page %d not found in JBIG2 image file", (int) img_pagenum(idict)); - img_totalpages(idict) = fip->numofpages; - img_xsize(idict) = pip->width; - img_ysize(idict) = pip->height; + img_totalpages(idict) = (int) fip->numofpages; + img_xsize(idict) = (int) pip->width; + img_ysize(idict) = (int) pip->height; img_xres(idict) = (int) (pip->xres * 0.0254 + 0.5); img_yres(idict) = (int) (pip->yres * 0.0254 + 0.5); img_colordepth(idict) = 1; } -void write_jbig2(image_dict * idict) +@ @c +void write_jbig2(PDF pdf, image_dict * idict) { FILEINFO *fip, tmp; PAGEINFO *pip; @@ -828,14 +818,15 @@ void write_jbig2(image_dict * idict) tmp.filepath = img_filepath(idict); fip = (FILEINFO *) avl_find(file_tree, &tmp); assert(fip != NULL); - assert(fip->phase == HAVEINFO); /* don't write before rd_jbig2_info() call */ - pip = find_pageinfo(&(fip->pages), img_pagenum(idict)); + assert(fip->phase == HAVEINFO); /* don't write before |rd_jbig2_info()| call */ + pip = find_pageinfo(&(fip->pages), (unsigned long) img_pagenum(idict)); assert(pip != NULL); - wr_jbig2(fip, pip->pagenum); + wr_jbig2(pdf, fip, pip->pagenum); img_file(idict) = NULL; } -void flush_jbig2_page0_objects(void) +@ @c +void flush_jbig2_page0_objects(PDF pdf) { FILEINFO *fip; struct avl_traverser t; @@ -844,9 +835,7 @@ void flush_jbig2_page0_objects(void) for (fip = avl_t_first(&t, file_tree); fip != NULL; fip = avl_t_next(&t)) { if (fip->page0.last != NULL) - wr_jbig2(fip, 0); + wr_jbig2(pdf, fip, 0); } } } - -/**********************************************************************/ diff --git a/Build/source/texk/web2c/luatexdir/image/writejpg.h b/Build/source/texk/web2c/luatexdir/image/writejpg.h index bd497c9e114..d3c7cdb806a 100644 --- a/Build/source/texk/web2c/luatexdir/image/writejpg.h +++ b/Build/source/texk/web2c/luatexdir/image/writejpg.h @@ -18,14 +18,14 @@ You should have received a copy of the GNU General Public License along with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ -/* $Id: writejpg.h 2327 2009-04-18 12:47:21Z hhenkel $ */ +/* $Id: writejpg.h 2653 2009-06-27 14:30:05Z taco $ */ #ifndef WRITEJPG_H # define WRITEJPG_H # include "image.h" -void read_jpg_info(image_dict *, img_readtype_e); -void write_jpg(image_dict *); +void read_jpg_info(PDF, image_dict *, img_readtype_e); +void write_jpg(PDF, image_dict *); #endif /* WRITEJPG_H */ diff --git a/Build/source/texk/web2c/luatexdir/image/writejpg.c b/Build/source/texk/web2c/luatexdir/image/writejpg.w index 187c55ea6c2..cb0e2fedcde 100644 --- a/Build/source/texk/web2c/luatexdir/image/writejpg.c +++ b/Build/source/texk/web2c/luatexdir/image/writejpg.w @@ -1,32 +1,33 @@ -/* writejpg.c +% writejpg.w - Copyright 1996-2006 Han The Thanh <thanh@pdftex.org> - Copyright 2006-2009 Taco Hoekwater <taco@luatex.org> +% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org> +% Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org> - This file is part of LuaTeX. +% This file is part of LuaTeX. - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. +% LuaTeX is free software; you can redistribute it and/or modify it under +% the terms of the GNU General Public License as published by the Free +% Software Foundation; either version 2 of the License, or (at your +% option) any later version. - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. +% LuaTeX is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +% License for more details. - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ +% You should have received a copy of the GNU General Public License along +% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. + +@ @c +static const char _svn_version[] = + "$Id: writejpg.w 3584 2010-04-02 17:45:55Z hhenkel $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/image/writejpg.w $"; #include <assert.h> #include "ptexlib.h" -#include "image.h" -#include "writejpg.h" - -static const char _svn_version[] = - "$Id: writejpg.c 2320 2009-04-18 08:52:30Z hhenkel $ " - "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.40.6/source/texk/web2c/luatexdir/image/writejpg.c $"; +#include "image/image.h" +@ @c #define JPG_GRAY 1 /* Gray color space, use /DeviceGray */ #define JPG_RGB 3 /* RGB color space, use /DeviceRGB */ #define JPG_CMYK 4 /* CMYK color space, use /DeviceCMYK */ @@ -98,12 +99,14 @@ typedef enum { /* JPEG marker codes */ M_ERROR = 0x100 /* dummy marker, internal use only */ } JPEG_MARKER; +@ @c static JPG_UINT16 read2bytes(FILE * f) { int c = xgetc(f); - return (c << 8) + xgetc(f); + return (JPG_UINT16) ((c << 8) + (int) xgetc(f)); } +@ @c static void close_and_cleanup_jpg(image_dict * idict) { assert(idict != NULL); @@ -116,7 +119,8 @@ static void close_and_cleanup_jpg(image_dict * idict) img_jpg_ptr(idict) = NULL; } -void read_jpg_info(image_dict * idict, img_readtype_e readtype) +@ @c +void read_jpg_info(PDF pdf, image_dict * idict, img_readtype_e readtype) { int i, units = 0; unsigned char jpg_id[] = "JFIF"; @@ -134,7 +138,7 @@ void read_jpg_info(image_dict * idict, img_readtype_e readtype) xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict)); if (read2bytes(img_file(idict)) != 0xFFD8) pdftex_fail("reading JPEG image failed (no JPEG header found)"); - /* currently only true JFIF files allow extracting img_xres and img_yres */ + /* currently only true JFIF files allow extracting |img_xres| and |img_yres| */ if (read2bytes(img_file(idict)) == 0xFFE0) { /* check for JFIF */ (void) read2bytes(img_file(idict)); for (i = 0; i < 5; i++) { @@ -144,20 +148,27 @@ void read_jpg_info(image_dict * idict, img_readtype_e readtype) if (i == 5) { /* it's JFIF */ read2bytes(img_file(idict)); units = xgetc(img_file(idict)); - img_xres(idict) = read2bytes(img_file(idict)); - img_yres(idict) = read2bytes(img_file(idict)); + img_xres(idict) = (int) read2bytes(img_file(idict)); + img_yres(idict) = (int) read2bytes(img_file(idict)); switch (units) { case 1: break; /* pixels per inch */ case 2: - img_xres(idict) *= 2.54; - img_yres(idict) *= 2.54; + img_xres(idict) = (int) ((double) img_xres(idict) * 2.54); + img_yres(idict) = (int) ((double) img_yres(idict) * 2.54); break; /* pixels per cm */ default: img_xres(idict) = img_yres(idict) = 0; break; } } + /* if either xres or yres is 0 but the other isn't, set it to the value of the other */ + if ((img_xres(idict) == 0) && (img_yres(idict) != 0)) { + img_xres(idict) = img_yres(idict); + } + if ((img_yres(idict) == 0) && (img_xres(idict) != 0)) { + img_yres(idict) = img_xres(idict); + } } xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict)); while (1) { @@ -177,26 +188,26 @@ void read_jpg_info(image_dict * idict, img_readtype_e readtype) case M_SOF15: pdftex_fail("unsupported type of compression"); case M_SOF2: - if (fixed_pdf_minor_version <= 2) + if (pdf->minor_version <= 2) pdftex_fail("cannot use progressive DCT with PDF-1.2"); case M_SOF0: case M_SOF1: case M_SOF3: (void) read2bytes(img_file(idict)); /* read segment length */ img_colordepth(idict) = xgetc(img_file(idict)); - img_ysize(idict) = read2bytes(img_file(idict)); - img_xsize(idict) = read2bytes(img_file(idict)); + img_ysize(idict) = (int) read2bytes(img_file(idict)); + img_xsize(idict) = (int) read2bytes(img_file(idict)); img_jpg_color(idict) = xgetc(img_file(idict)); xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict)); switch (img_jpg_color(idict)) { case JPG_GRAY: - img_color(idict) = IMAGE_COLOR_B; + img_procset(idict) |= PROCSET_IMAGE_B; break; case JPG_RGB: - img_color(idict) = IMAGE_COLOR_C; + img_procset(idict) |= PROCSET_IMAGE_C; break; case JPG_CMYK: - img_color(idict) = IMAGE_COLOR_C; + img_procset(idict) |= PROCSET_IMAGE_C; break; default: pdftex_fail("Unsupported color space %i", @@ -226,56 +237,58 @@ void read_jpg_info(image_dict * idict, img_readtype_e readtype) assert(0); } -static void reopen_jpg(image_dict * idict) +@ @c +static void reopen_jpg(PDF pdf, image_dict * idict) { - integer width, height, xres, yres; + int width, height, xres, yres; width = img_xsize(idict); height = img_ysize(idict); xres = img_xres(idict); yres = img_yres(idict); - read_jpg_info(idict, IMG_KEEPOPEN); + read_jpg_info(pdf, idict, IMG_KEEPOPEN); if (width != img_xsize(idict) || height != img_ysize(idict) || xres != img_xres(idict) || yres != img_yres(idict)) pdftex_fail("writejpg: image dimensions have changed"); } -void write_jpg(image_dict * idict) +@ @c +void write_jpg(PDF pdf, image_dict * idict) { long unsigned l; FILE *f; assert(idict != NULL); if (img_file(idict) == NULL) - reopen_jpg(idict); + reopen_jpg(pdf, idict); assert(img_jpg_ptr(idict) != NULL); - pdf_puts("/Type /XObject\n/Subtype /Image\n"); + pdf_puts(pdf, "/Type /XObject\n/Subtype /Image\n"); if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) - pdf_printf("%s\n", img_attr(idict)); - pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n/Length %i\n", + pdf_printf(pdf, "%s\n", img_attr(idict)); + pdf_printf(pdf, "/Width %i\n/Height %i\n/BitsPerComponent %i\n/Length %i\n", (int) img_xsize(idict), (int) img_ysize(idict), (int) img_colordepth(idict), (int) img_jpg_ptr(idict)->length); - pdf_puts("/ColorSpace "); + pdf_puts(pdf, "/ColorSpace "); if (img_colorspace(idict) != 0) { - pdf_printf("%i 0 R\n", (int) img_colorspace(idict)); + pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict)); } else { switch (img_jpg_color(idict)) { case JPG_GRAY: - pdf_puts("/DeviceGray\n"); + pdf_puts(pdf, "/DeviceGray\n"); break; case JPG_RGB: - pdf_puts("/DeviceRGB\n"); + pdf_puts(pdf, "/DeviceRGB\n"); break; case JPG_CMYK: - pdf_puts("/DeviceCMYK\n/Decode [1 0 1 0 1 0 1 0]\n"); + pdf_puts(pdf, "/DeviceCMYK\n/Decode [1 0 1 0 1 0 1 0]\n"); break; default: pdftex_fail("Unsupported color space %i", (int) img_jpg_color(idict)); } } - pdf_puts("/Filter /DCTDecode\n>>\nstream\n"); + pdf_puts(pdf, "/Filter /DCTDecode\n>>\nstream\n"); for (l = img_jpg_ptr(idict)->length, f = img_file(idict); l > 0; l--) - pdfout(xgetc(f)); - pdf_end_stream(); + pdf_out(pdf, xgetc(f)); + pdf_end_stream(pdf); close_and_cleanup_jpg(idict); } diff --git a/Build/source/texk/web2c/luatexdir/image/writepng.h b/Build/source/texk/web2c/luatexdir/image/writepng.h index 4683e694a0c..56a96436389 100644 --- a/Build/source/texk/web2c/luatexdir/image/writepng.h +++ b/Build/source/texk/web2c/luatexdir/image/writepng.h @@ -18,15 +18,15 @@ You should have received a copy of the GNU General Public License along with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ -/* $Id: writepng.h 2327 2009-04-18 12:47:21Z hhenkel $ */ +/* $Id: writepng.h 2580 2009-06-23 15:55:52Z taco $ */ #ifndef WRITEPNG_H # define WRITEPNG_H # include "image.h" -void read_png_info(image_dict *, img_readtype_e); -void write_additional_png_objects(void); -void write_png(image_dict *); +void read_png_info(PDF, image_dict *, img_readtype_e); +void write_additional_png_objects(PDF); +void write_png(PDF, image_dict *); #endif /* WRITEPNG_H */ diff --git a/Build/source/texk/web2c/luatexdir/image/writepng.c b/Build/source/texk/web2c/luatexdir/image/writepng.w index 154a8a351c2..1b8ecb56b49 100644 --- a/Build/source/texk/web2c/luatexdir/image/writepng.c +++ b/Build/source/texk/web2c/luatexdir/image/writepng.w @@ -1,32 +1,33 @@ -/* writepng.c +% writepng.w - Copyright 1996-2006 Han The Thanh <thanh@pdftex.org> - Copyright 2006-2009 Taco Hoekwater <taco@luatex.org> +% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org> +% Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org> - This file is part of LuaTeX. +% This file is part of LuaTeX. - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. +% LuaTeX is free software; you can redistribute it and/or modify it under +% the terms of the GNU General Public License as published by the Free +% Software Foundation; either version 2 of the License, or (at your +% option) any later version. - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. +% LuaTeX is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +% License for more details. - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ +% You should have received a copy of the GNU General Public License along +% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. + +@ @c +static const char _svn_version[] = + "$Id: writepng.w 3584 2010-04-02 17:45:55Z hhenkel $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/image/writepng.w $"; #include <assert.h> #include "ptexlib.h" -#include "image.h" -#include "writepng.h" - -static const char _svn_version[] = - "$Id: writepng.c 2317 2009-04-18 00:12:18Z hhenkel $ " - "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.40.6/source/texk/web2c/luatexdir/image/writepng.c $"; +#include "image/image.h" +@ @c static int transparent_page_group = -1; static void close_and_cleanup_png(image_dict * idict) @@ -43,7 +44,8 @@ static void close_and_cleanup_png(image_dict * idict) img_png_ptr(idict) = NULL; } -void read_png_info(image_dict * idict, img_readtype_e readtype) +@ @c +void read_png_info(PDF pdf, image_dict * idict, img_readtype_e readtype) { double gamma; png_structp png_p; @@ -73,43 +75,43 @@ void read_png_info(image_dict * idict, img_readtype_e readtype) png_set_tRNS_to_alpha(png_p); } /* alpha channel support */ - if (fixed_pdf_minor_version < 4 && png_p->color_type | PNG_COLOR_MASK_ALPHA) + if (pdf->minor_version < 4 && png_p->color_type | PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(png_p); /* 16bit depth support */ - if (fixed_pdf_minor_version < 5) - fixed_image_hicolor = 0; - if (info_p->bit_depth == 16 && !fixed_image_hicolor) + if (pdf->minor_version < 5) + pdf->image_hicolor = 0; + if ((info_p->bit_depth == 16) && (pdf->image_hicolor == 0)) png_set_strip_16(png_p); /* gamma support */ - if (fixed_image_apply_gamma) { + if (pdf->image_apply_gamma) { if (png_get_gAMA(png_p, info_p, &gamma)) - png_set_gamma(png_p, (fixed_gamma / 1000.0), gamma); + png_set_gamma(png_p, (pdf->gamma / 1000.0), gamma); else - png_set_gamma(png_p, (fixed_gamma / 1000.0), - (1000.0 / fixed_image_gamma)); + png_set_gamma(png_p, (pdf->gamma / 1000.0), + (1000.0 / pdf->image_gamma)); } /* reset structure */ png_read_update_info(png_p, info_p); /* resolution support */ - img_xsize(idict) = info_p->width; - img_ysize(idict) = info_p->height; + img_xsize(idict) = (int) info_p->width; + img_ysize(idict) = (int) info_p->height; if (info_p->valid & PNG_INFO_pHYs) { img_xres(idict) = - round(0.0254 * png_get_x_pixels_per_meter(png_p, info_p)); + round(0.0254 * (double) png_get_x_pixels_per_meter(png_p, info_p)); img_yres(idict) = - round(0.0254 * png_get_y_pixels_per_meter(png_p, info_p)); + round(0.0254 * (double) png_get_y_pixels_per_meter(png_p, info_p)); } switch (info_p->color_type) { case PNG_COLOR_TYPE_PALETTE: - img_color(idict) = IMAGE_COLOR_C | IMAGE_COLOR_I; + img_procset(idict) |= PROCSET_IMAGE_C | PROCSET_IMAGE_I; break; case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_GRAY_ALPHA: - img_color(idict) = IMAGE_COLOR_B; + img_procset(idict) |= PROCSET_IMAGE_B; break; case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: - img_color(idict) = IMAGE_COLOR_C; + img_procset(idict) |= PROCSET_IMAGE_C; break; default: pdftex_fail("unsupported type of color_type <%i>", info_p->color_type); @@ -119,32 +121,33 @@ void read_png_info(image_dict * idict, img_readtype_e readtype) close_and_cleanup_png(idict); } +@ @c #define write_gray_pixel_16(r) \ - if (j % 4 == 0||j % 4 == 1) pdf_buf[pdf_ptr++] = *r++; \ + if (j % 4 == 0||j % 4 == 1) pdf_quick_out(pdf,*r++); \ else smask[smask_ptr++] = *r++ #define write_gray_pixel_8(r) \ - if (j % 2 == 0) pdf_buf[pdf_ptr++] = *r++; \ + if (j % 2 == 0) pdf_quick_out(pdf,*r++); \ else smask[smask_ptr++] = *r++ #define write_rgb_pixel_16(r) \ - if (!(j % 8 == 6||j % 8 == 7)) pdf_buf[pdf_ptr++] = *r++; \ + if (!(j % 8 == 6||j % 8 == 7)) pdf_quick_out(pdf,*r++); \ else smask[smask_ptr++] = *r++ #define write_rgb_pixel_8(r) \ - if (j % 4 != 3) pdf_buf[pdf_ptr++] = *r++; \ + if (j % 4 != 3) pdf_quick_out(pdf,*r++); \ else smask[smask_ptr++] = *r++ -#define write_simple_pixel(r) pdf_buf[pdf_ptr++] = *r++ +#define write_simple_pixel(r) pdf_quick_out(pdf,*r++) #define write_noninterlaced(outmac) \ for (i = 0; i < (int)info_p->height; i++) { \ png_read_row(png_p, row, NULL); \ r = row; \ - k = info_p->rowbytes; \ + k = (int)info_p->rowbytes; \ while(k > 0) { \ - l = (k > pdf_buf_size)? pdf_buf_size : k; \ - pdfroom(l); \ + l = (k > pdf->buf_size)? pdf->buf_size : k; \ + pdf_room(pdf,l); \ for (j = 0; j < l; j++) { \ outmac; \ } \ @@ -155,10 +158,10 @@ void read_png_info(image_dict * idict, img_readtype_e readtype) #define write_interlaced(outmac) \ for (i = 0; i < (int)info_p->height; i++) { \ row = rows[i]; \ - k = info_p->rowbytes; \ + k = (int)info_p->rowbytes; \ while(k > 0) { \ - l = (k > pdf_buf_size)? pdf_buf_size : k;\ - pdfroom(l); \ + l = (k > pdf->buf_size)?pdf->buf_size: k;\ + pdf_room(pdf,l); \ for (j = 0; j < l; j++) { \ outmac; \ } \ @@ -167,22 +170,23 @@ void read_png_info(image_dict * idict, img_readtype_e readtype) xfree(rows[i]); \ } -static void write_png_palette(image_dict * idict) +@ @c +static void write_png_palette(PDF pdf, image_dict * idict) { int i, j, k, l; png_structp png_p = img_png_png_ptr(idict); png_infop info_p = img_png_info_ptr(idict); png_bytep row, r, *rows; - integer palette_objnum = 0; + int palette_objnum = 0; if (img_colorspace(idict) != 0) { - pdf_printf("%i 0 R\n", (int) img_colorspace(idict)); + pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict)); } else { - pdf_create_obj(0, 0); - palette_objnum = obj_ptr; - pdf_printf("[/Indexed /DeviceRGB %i %i 0 R]\n", + pdf_create_obj(pdf, obj_type_others, 0); + palette_objnum = pdf->obj_ptr; + pdf_printf(pdf, "[/Indexed /DeviceRGB %i %i 0 R]\n", (int) (info_p->num_palette - 1), (int) palette_objnum); } - pdf_begin_stream(); + pdf_begin_stream(pdf); if (info_p->interlace_type == PNG_INTERLACE_NONE) { row = xtalloc(info_p->rowbytes, png_byte); write_noninterlaced(write_simple_pixel(r)); @@ -198,32 +202,33 @@ static void write_png_palette(image_dict * idict) write_interlaced(write_simple_pixel(row)); xfree(rows); } - pdf_end_stream(); + pdf_end_stream(pdf); if (palette_objnum > 0) { - pdf_begin_dict(palette_objnum, 0); - pdf_begin_stream(); + pdf_begin_dict(pdf, palette_objnum, 0); + pdf_begin_stream(pdf); for (i = 0; (unsigned) i < info_p->num_palette; i++) { - pdfroom(3); - pdf_buf[pdf_ptr++] = info_p->palette[i].red; - pdf_buf[pdf_ptr++] = info_p->palette[i].green; - pdf_buf[pdf_ptr++] = info_p->palette[i].blue; + pdf_room(pdf, 3); + pdf_quick_out(pdf, info_p->palette[i].red); + pdf_quick_out(pdf, info_p->palette[i].green); + pdf_quick_out(pdf, info_p->palette[i].blue); } - pdf_end_stream(); + pdf_end_stream(pdf); } } -static void write_png_gray(image_dict * idict) +@ @c +static void write_png_gray(PDF pdf, image_dict * idict) { int i, j, k, l; png_structp png_p = img_png_png_ptr(idict); png_infop info_p = img_png_info_ptr(idict); png_bytep row, r, *rows; if (img_colorspace(idict) != 0) { - pdf_printf("%i 0 R\n", (int) img_colorspace(idict)); + pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict)); } else { - pdf_puts("/DeviceGray\n"); + pdf_puts(pdf, "/DeviceGray\n"); } - pdf_begin_stream(); + pdf_begin_stream(pdf); if (info_p->interlace_type == PNG_INTERLACE_NONE) { row = xtalloc(info_p->rowbytes, png_byte); write_noninterlaced(write_simple_pixel(r)); @@ -239,34 +244,35 @@ static void write_png_gray(image_dict * idict) write_interlaced(write_simple_pixel(row)); xfree(rows); } - pdf_end_stream(); + pdf_end_stream(pdf); } -static void write_png_gray_alpha(image_dict * idict) +@ @c +static void write_png_gray_alpha(PDF pdf, image_dict * idict) { int i, j, k, l; png_structp png_p = img_png_png_ptr(idict); png_infop info_p = img_png_info_ptr(idict); png_bytep row, r, *rows; - integer smask_objnum = 0; + int smask_objnum = 0; png_bytep smask; - integer smask_ptr = 0; - integer smask_size = 0; + int smask_ptr = 0; + int smask_size = 0; int bitdepth; if (img_colorspace(idict) != 0) { - pdf_printf("%i 0 R\n", (int) img_colorspace(idict)); + pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict)); } else { - pdf_puts("/DeviceGray\n"); + pdf_puts(pdf, "/DeviceGray\n"); } - pdf_create_obj(0, 0); - smask_objnum = obj_ptr; - pdf_printf("/SMask %i 0 R\n", (int) smask_objnum); - smask_size = (info_p->rowbytes / 2) * info_p->height; - smask = xtalloc(smask_size, png_byte); - pdf_begin_stream(); + pdf_create_obj(pdf, obj_type_others, 0); + smask_objnum = pdf->obj_ptr; + pdf_printf(pdf, "/SMask %i 0 R\n", (int) smask_objnum); + smask_size = (int) ((info_p->rowbytes / 2) * info_p->height); + smask = xtalloc((unsigned) smask_size, png_byte); + pdf_begin_stream(pdf); if (info_p->interlace_type == PNG_INTERLACE_NONE) { row = xtalloc(info_p->rowbytes, png_byte); - if ((info_p->bit_depth == 16) && fixed_image_hicolor) { + if ((info_p->bit_depth == 16) && (pdf->image_hicolor != 0)) { write_noninterlaced(write_gray_pixel_16(r)); } else { write_noninterlaced(write_gray_pixel_8(r)); @@ -280,49 +286,50 @@ static void write_png_gray_alpha(image_dict * idict) for (i = 0; (unsigned) i < info_p->height; i++) rows[i] = xtalloc(info_p->rowbytes, png_byte); png_read_image(png_p, rows); - if ((info_p->bit_depth == 16) && fixed_image_hicolor) { + if ((info_p->bit_depth == 16) && (pdf->image_hicolor != 0)) { write_interlaced(write_gray_pixel_16(row)); } else { write_interlaced(write_gray_pixel_8(row)); } xfree(rows); } - pdf_end_stream(); - pdf_flush(); + pdf_end_stream(pdf); + pdf_flush(pdf); /* now write the Smask object */ bitdepth = (int) info_p->bit_depth; - pdf_begin_dict(smask_objnum, 0); - pdf_puts("/Type /XObject\n/Subtype /Image\n"); + pdf_begin_dict(pdf, smask_objnum, 0); + pdf_puts(pdf, "/Type /XObject\n/Subtype /Image\n"); if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) - pdf_printf("%s\n", img_attr(idict)); - pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n", + pdf_printf(pdf, "%s\n", img_attr(idict)); + pdf_printf(pdf, "/Width %i\n/Height %i\n/BitsPerComponent %i\n", (int) info_p->width, (int) info_p->height, (bitdepth == 16 ? 8 : bitdepth)); - pdf_puts("/ColorSpace /DeviceGray\n"); - pdf_begin_stream(); + pdf_puts(pdf, "/ColorSpace /DeviceGray\n"); + pdf_begin_stream(pdf); for (i = 0; i < smask_size; i++) { if (i % 8 == 0) - pdfroom(8); - pdf_buf[pdf_ptr++] = smask[i]; + pdf_room(pdf, 8); + pdf_quick_out(pdf, smask[i]); if (bitdepth == 16) i++; } - pdf_end_stream(); + pdf_end_stream(pdf); xfree(smask); } -static void write_png_rgb(image_dict * idict) +@ @c +static void write_png_rgb(PDF pdf, image_dict * idict) { int i, j, k, l; png_structp png_p = img_png_png_ptr(idict); png_infop info_p = img_png_info_ptr(idict); png_bytep row, r, *rows; if (img_colorspace(idict) != 0) { - pdf_printf("%i 0 R\n", (int) img_colorspace(idict)); + pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict)); } else { - pdf_puts("/DeviceRGB\n"); + pdf_puts(pdf, "/DeviceRGB\n"); } - pdf_begin_stream(); + pdf_begin_stream(pdf); if (info_p->interlace_type == PNG_INTERLACE_NONE) { row = xtalloc(info_p->rowbytes, png_byte); write_noninterlaced(write_simple_pixel(r)); @@ -338,34 +345,35 @@ static void write_png_rgb(image_dict * idict) write_interlaced(write_simple_pixel(row)); xfree(rows); } - pdf_end_stream(); + pdf_end_stream(pdf); } -static void write_png_rgb_alpha(image_dict * idict) +@ @c +static void write_png_rgb_alpha(PDF pdf, image_dict * idict) { int i, j, k, l; png_structp png_p = img_png_png_ptr(idict); png_infop info_p = img_png_info_ptr(idict); png_bytep row, r, *rows; - integer smask_objnum = 0; + int smask_objnum = 0; png_bytep smask; - integer smask_ptr = 0; - integer smask_size = 0; + int smask_ptr = 0; + int smask_size = 0; int bitdepth; if (img_colorspace(idict) != 0) { - pdf_printf("%i 0 R\n", (int) img_colorspace(idict)); + pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict)); } else { - pdf_puts("/DeviceRGB\n"); + pdf_puts(pdf, "/DeviceRGB\n"); } - pdf_create_obj(0, 0); - smask_objnum = obj_ptr; - pdf_printf("/SMask %i 0 R\n", (int) smask_objnum); - smask_size = (info_p->rowbytes / 2) * info_p->height; - smask = xtalloc(smask_size, png_byte); - pdf_begin_stream(); + pdf_create_obj(pdf, obj_type_others, 0); + smask_objnum = pdf->obj_ptr; + pdf_printf(pdf, "/SMask %i 0 R\n", (int) smask_objnum); + smask_size = (int) ((info_p->rowbytes / 2) * info_p->height); + smask = xtalloc((unsigned) smask_size, png_byte); + pdf_begin_stream(pdf); if (info_p->interlace_type == PNG_INTERLACE_NONE) { row = xtalloc(info_p->rowbytes, png_byte); - if ((info_p->bit_depth == 16) && fixed_image_hicolor) { + if ((info_p->bit_depth == 16) && (pdf->image_hicolor != 0)) { write_noninterlaced(write_rgb_pixel_16(r)); } else { write_noninterlaced(write_rgb_pixel_8(r)); @@ -379,51 +387,50 @@ static void write_png_rgb_alpha(image_dict * idict) for (i = 0; (unsigned) i < info_p->height; i++) rows[i] = xtalloc(info_p->rowbytes, png_byte); png_read_image(png_p, rows); - if ((info_p->bit_depth == 16) && fixed_image_hicolor) { + if ((info_p->bit_depth == 16) && (pdf->image_hicolor != 0)) { write_interlaced(write_rgb_pixel_16(row)); } else { write_interlaced(write_rgb_pixel_8(row)); } xfree(rows); } - pdf_end_stream(); - pdf_flush(); + pdf_end_stream(pdf); + pdf_flush(pdf); /* now write the Smask object */ if (smask_objnum > 0) { bitdepth = (int) info_p->bit_depth; - pdf_begin_dict(smask_objnum, 0); - pdf_puts("/Type /XObject\n/Subtype /Image\n"); + pdf_begin_dict(pdf, smask_objnum, 0); + pdf_puts(pdf, "/Type /XObject\n/Subtype /Image\n"); if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) - pdf_printf("%s\n", img_attr(idict)); - pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n", + pdf_printf(pdf, "%s\n", img_attr(idict)); + pdf_printf(pdf, "/Width %i\n/Height %i\n/BitsPerComponent %i\n", (int) info_p->width, (int) info_p->height, (bitdepth == 16 ? 8 : bitdepth)); - pdf_puts("/ColorSpace /DeviceGray\n"); - pdf_begin_stream(); + pdf_puts(pdf, "/ColorSpace /DeviceGray\n"); + pdf_begin_stream(pdf); for (i = 0; i < smask_size; i++) { if (i % 8 == 0) - pdfroom(8); - pdf_buf[pdf_ptr++] = smask[i]; + pdf_room(pdf, 8); + pdf_quick_out(pdf, smask[i]); if (bitdepth == 16) i++; } xfree(smask); - pdf_end_stream(); + pdf_end_stream(pdf); } } -/**********************************************************************/ -/* - * The |copy_png| function is from Hartmut Henkel. The goal is to use - * pdf's native FlateDecode support if that is possible. - * - * Only a subset of the png files allows this, but when possible it - * greatly improves inclusion speed. - * - * Code cheerfully gleaned from Thomas Merz' PDFlib, - * file p_png.c "SPNG - Simple PNG" - */ +@ The |copy_png| function is from Hartmut Henkel. The goal is to use +pdf's native FlateDecode support if that is possible. +Only a subset of the png files allows this, but when possible it +greatly improves inclusion speed. + +Code cheerfully gleaned from Thomas Merz' PDFlib, +file |p_png.c| "SPNG - Simple PNG" + + +@c static int spng_getint(FILE * fp) { unsigned char buf[4]; @@ -435,7 +442,7 @@ static int spng_getint(FILE * fp) #define SPNG_CHUNK_IDAT 0x49444154 #define SPNG_CHUNK_IEND 0x49454E44 -static void copy_png(image_dict * idict) +static void copy_png(PDF pdf, image_dict * idict) { png_structp png_p; png_infop info_p; @@ -464,7 +471,7 @@ static void copy_png(image_dict * idict) pdftex_fail("writepng: fseek in PNG file failed"); } } while (endflag == false); - pdf_printf("/Length %d\n" + pdf_printf(pdf, "/Length %d\n" "/Filter/FlateDecode\n" "/DecodeParms<<" "/Colors %d" @@ -486,17 +493,17 @@ static void copy_png(image_dict * idict) pdftex_fail("writepng: IDAT chunk sequence broken"); idat = 1; while (len > 0) { - i = (len > pdf_buf_size) ? pdf_buf_size : len; - pdfroom(i); - fread(&pdf_buf[pdf_ptr], 1, i, fp); - pdf_ptr += i; + i = (len > pdf->buf_size) ? pdf->buf_size : len; + pdf_room(pdf, i); + fread(&pdf->buf[pdf->ptr], 1, (size_t) i, fp); + pdf->ptr += i; len -= i; } if (fseek(fp, 4, SEEK_CUR) != 0) pdftex_fail("writepng: fseek in PNG file failed"); break; case SPNG_CHUNK_IEND: /* done */ - pdf_end_stream(); + pdf_end_stream(pdf); endflag = true; break; default: @@ -508,97 +515,99 @@ static void copy_png(image_dict * idict) } while (endflag == false); } -static void reopen_png(image_dict * idict) +@ @c +static void reopen_png(PDF pdf, image_dict * idict) { - integer width, height, xres, yres; + int width, height, xres, yres; width = img_xsize(idict); /* do consistency check */ height = img_ysize(idict); xres = img_xres(idict); yres = img_yres(idict); - read_png_info(idict, IMG_KEEPOPEN); + read_png_info(pdf, idict, IMG_KEEPOPEN); if (width != img_xsize(idict) || height != img_ysize(idict) || xres != img_xres(idict) || yres != img_yres(idict)) pdftex_fail("writepng: image dimensions have changed"); } +@ @c static boolean last_png_needs_page_group; -void write_png(image_dict * idict) +void write_png(PDF pdf, image_dict * idict) { double gamma, checked_gamma; int i; - integer palette_objnum = 0; + int palette_objnum = 0; png_structp png_p; png_infop info_p; assert(idict != NULL); last_png_needs_page_group = false; if (img_file(idict) == NULL) - reopen_png(idict); + reopen_png(pdf, idict); assert(img_png_ptr(idict) != NULL); png_p = img_png_png_ptr(idict); info_p = img_png_info_ptr(idict); - if (fixed_pdf_minor_version < 5) - fixed_image_hicolor = 0; - pdf_puts("/Type /XObject\n/Subtype /Image\n"); + if (pdf->minor_version < 5) + pdf->image_hicolor = 0; + pdf_puts(pdf, "/Type /XObject\n/Subtype /Image\n"); if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) - pdf_printf("%s\n", img_attr(idict)); - pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n", + pdf_printf(pdf, "%s\n", img_attr(idict)); + pdf_printf(pdf, "/Width %i\n/Height %i\n/BitsPerComponent %i\n", (int) info_p->width, (int) info_p->height, (int) info_p->bit_depth); - pdf_puts("/ColorSpace "); + pdf_puts(pdf, "/ColorSpace "); checked_gamma = 1.0; - if (fixed_image_apply_gamma) { + if (pdf->image_apply_gamma) { if (png_get_gAMA(png_p, info_p, &gamma)) { - checked_gamma = (fixed_gamma / 1000.0) * gamma; + checked_gamma = (pdf->gamma / 1000.0) * gamma; } else { - checked_gamma = - (fixed_gamma / 1000.0) * (1000.0 / fixed_image_gamma); + checked_gamma = (pdf->gamma / 1000.0) * (1000.0 / pdf->image_gamma); } } /* the switching between |info_p| and |png_p| queries has been trial and error. */ - if (fixed_pdf_minor_version > 1 && info_p->interlace_type == PNG_INTERLACE_NONE && (png_p->transformations == 0 || png_p->transformations == 0x2000) /* gamma */ + if (pdf->minor_version > 1 && info_p->interlace_type == PNG_INTERLACE_NONE && + (png_p->transformations == 0 || png_p->transformations == 0x2000) /* gamma */ &&!(png_p->color_type == PNG_COLOR_TYPE_GRAY_ALPHA || png_p->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - && (fixed_image_hicolor || (png_p->bit_depth <= 8)) + && ((pdf->image_hicolor != 0) || (png_p->bit_depth <= 8)) && (checked_gamma <= 1.01 && checked_gamma > 0.99) ) { if (img_colorspace(idict) != 0) { - pdf_printf("%i 0 R\n", (int) img_colorspace(idict)); + pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict)); } else { switch (info_p->color_type) { case PNG_COLOR_TYPE_PALETTE: - pdf_create_obj(0, 0); - palette_objnum = obj_ptr; - pdf_printf("[/Indexed /DeviceRGB %i %i 0 R]\n", + pdf_create_obj(pdf, obj_type_others, 0); + palette_objnum = pdf->obj_ptr; + pdf_printf(pdf, "[/Indexed /DeviceRGB %i %i 0 R]\n", (int) (info_p->num_palette - 1), (int) palette_objnum); break; case PNG_COLOR_TYPE_GRAY: - pdf_puts("/DeviceGray\n"); + pdf_puts(pdf, "/DeviceGray\n"); break; default: /* RGB */ - pdf_puts("/DeviceRGB\n"); + pdf_puts(pdf, "/DeviceRGB\n"); }; } if (tracefilenames) tex_printf(" (PNG copy)"); - copy_png(idict); + copy_png(pdf, idict); if (palette_objnum > 0) { - pdf_begin_dict(palette_objnum, 0); - pdf_begin_stream(); + pdf_begin_dict(pdf, palette_objnum, 0); + pdf_begin_stream(pdf); for (i = 0; (unsigned) i < info_p->num_palette; i++) { - pdfroom(3); - pdf_buf[pdf_ptr++] = info_p->palette[i].red; - pdf_buf[pdf_ptr++] = info_p->palette[i].green; - pdf_buf[pdf_ptr++] = info_p->palette[i].blue; + pdf_room(pdf, 3); + pdf_quick_out(pdf, info_p->palette[i].red); + pdf_quick_out(pdf, info_p->palette[i].green); + pdf_quick_out(pdf, info_p->palette[i].blue); } - pdf_end_stream(); + pdf_end_stream(pdf); } } else { if (0) { tex_printf(" PNG copy skipped because: "); - if (fixed_image_apply_gamma && + if ((pdf->image_apply_gamma != 0) && (checked_gamma > 1.01 || checked_gamma < 0.99)) tex_printf("gamma delta=%lf ", checked_gamma); if (png_p->transformations != PNG_TRANSFORM_IDENTITY) @@ -607,8 +616,8 @@ void write_png(image_dict * idict) && (info_p->color_type != PNG_COLOR_TYPE_RGB) && (info_p->color_type != PNG_COLOR_TYPE_PALETTE)) tex_printf("colortype "); - if (fixed_pdf_minor_version <= 1) - tex_printf("version=%d ", (int) fixed_pdf_minor_version); + if (pdf->minor_version <= 1) + tex_printf("version=%d ", pdf->minor_version); if (info_p->interlace_type != PNG_INTERLACE_NONE) tex_printf("interlaced "); if (info_p->bit_depth > 8) @@ -618,56 +627,63 @@ void write_png(image_dict * idict) } switch (info_p->color_type) { case PNG_COLOR_TYPE_PALETTE: - write_png_palette(idict); + write_png_palette(pdf, idict); break; case PNG_COLOR_TYPE_GRAY: - write_png_gray(idict); + write_png_gray(pdf, idict); break; case PNG_COLOR_TYPE_GRAY_ALPHA: - if (fixed_pdf_minor_version >= 4) { - write_png_gray_alpha(idict); + if (pdf->minor_version >= 4) { + write_png_gray_alpha(pdf, idict); last_png_needs_page_group = true; } else - write_png_gray(idict); + write_png_gray(pdf, idict); break; case PNG_COLOR_TYPE_RGB: - write_png_rgb(idict); + write_png_rgb(pdf, idict); break; case PNG_COLOR_TYPE_RGB_ALPHA: - if (fixed_pdf_minor_version >= 4) { - write_png_rgb_alpha(idict); + if (pdf->minor_version >= 4) { + write_png_rgb_alpha(pdf, idict); last_png_needs_page_group = true; } else - write_png_rgb(idict); + write_png_rgb(pdf, idict); break; default: pdftex_fail("unsupported type of color_type <%i>", info_p->color_type); } } - pdf_flush(); + pdf_flush(pdf); close_and_cleanup_png(idict); } +@ @c static boolean transparent_page_group_was_written = false; -/* Called after the xobject generated by write_png has been finished; used to - * write out additional objects */ - -void write_additional_png_objects(void) +@ Called after the xobject generated by |write_png| has been finished; used to +write out additional objects +@c +void write_additional_png_objects(PDF pdf) { - return; /* this interferes with current macro-based usage and cannot be configured */ + (void) pdf; + (void) transparent_page_group; + (void) transparent_page_group_was_written; + return; /* this interferes with current macro-based usage and cannot be configured */ +#if 0 if (last_png_needs_page_group) { if (!transparent_page_group_was_written && transparent_page_group > 1) { /* create new group object */ transparent_page_group_was_written = true; - pdf_begin_obj(transparent_page_group, 2); - if (get_pdf_compress_level() == 0) { - pdf_puts("%PTEX Group needed for transparent pngs\n"); + pdf_begin_obj(pdf, transparent_page_group, 2); + if (pdf->compress_level == 0) { + pdf_puts(pdf, "%PTEX Group needed for transparent pngs\n"); } pdf_puts - ("<</Type/Group /S/Transparency /CS/DeviceRGB /I true /K true>>\n"); - pdf_end_obj(); + (pdf, + "<</Type/Group /S/Transparency /CS/DeviceRGB /I true /K true>>\n"); + pdf_end_obj(pdf); } } +#endif } |