summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/image
diff options
context:
space:
mode:
authorMartin Schröder <martin@oneiros.de>2008-03-24 15:47:15 +0000
committerMartin Schröder <martin@oneiros.de>2008-03-24 15:47:15 +0000
commit0b5550c241229764120d133af80a0cbab5937ddd (patch)
tree81309c18d6f0deba7407813cf15b9add2db375d1 /Build/source/texk/web2c/luatexdir/image
parent51f55df6a36ce376952a1f2b30bdb4dd0e06548d (diff)
First step of importing luatex (up to r1121)
git-svn-id: svn://tug.org/texlive/trunk@7124 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/image')
-rw-r--r--Build/source/texk/web2c/luatexdir/image/.indent.pro12
-rw-r--r--Build/source/texk/web2c/luatexdir/image/epdf.c107
-rw-r--r--Build/source/texk/web2c/luatexdir/image/epdf.h125
-rw-r--r--Build/source/texk/web2c/luatexdir/image/image.h223
-rw-r--r--Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc1008
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writeimg.c677
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writejbig2.c749
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writejbig2.h151
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writejpg.c277
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writepng.c635
10 files changed, 3964 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/image/.indent.pro b/Build/source/texk/web2c/luatexdir/image/.indent.pro
new file mode 100644
index 00000000000..e9e690f1ba8
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/.indent.pro
@@ -0,0 +1,12 @@
+/* $Id$ */
+--k-and-r-style
+--blank-lines-after-procedures
+--line-length 80
+--procnames-start-lines
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--space-after-cast
+/* this does not work in indent 2.2.6 :-( */
+--no-tabs
+/* this is new in indent 2.2.9 */
+--preprocessor-indentation 2
diff --git a/Build/source/texk/web2c/luatexdir/image/epdf.c b/Build/source/texk/web2c/luatexdir/image/epdf.c
new file mode 100644
index 00000000000..071181f17bd
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/epdf.c
@@ -0,0 +1,107 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: epdf.c 1012 2008-02-14 00:00:57Z oneiros $
+*/
+
+#include "ptexlib.h"
+
+
+#include <kpathsea/c-vararg.h>
+#include <kpathsea/c-proto.h>
+#include <string.h>
+
+extern void epdf_check_mem(void);
+extern void register_fd_entry(fd_entry *);
+
+
+int is_subsetable(fm_entry * fm)
+{
+ assert(is_included(fm));
+ return is_subsetted(fm);
+}
+
+fd_entry *epdf_create_fontdescriptor(fm_entry * fm)
+{
+ 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 */
+ /* preset_fontmetrics (fo->fd, f); */
+ fd->gl_tree = avl_create(comp_string_entry, NULL, &avl_xallocator);
+ assert(fd->gl_tree != NULL);
+ }
+ return fd;
+}
+
+integer get_fd_objnum(fd_entry * fd)
+{
+ assert(fd->fd_objnum != 0);
+ return fd->fd_objnum;
+}
+
+integer get_fn_objnum(fd_entry * fd)
+{
+ if (fd->fn_objnum == 0)
+ fd->fn_objnum = pdf_new_objnum();
+ return fd->fn_objnum;
+}
+
+/***********************************************************************
+ * 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 embed_whole_font(fd_entry * fd)
+{
+ fd->all_glyphs = true;
+}
+
+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
new file mode 100644
index 00000000000..2359d53d3db
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/epdf.h
@@ -0,0 +1,125 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: epdf.h 1031 2008-02-14 23:03:20Z hhenkel $
+*/
+
+extern "C" {
+
+#include <kpathsea/c-auto.h>
+
+ extern char *xstrdup(const char *);
+
+/* the following code is extremly ugly but needed for including web2c/config.h */
+
+#include <kpathsea/c-proto.h> /* define P?H macros */
+
+ 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 */
+ /* from web2c/config.h */
+
+#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/luatexdir/ptexmac.h>
+#include "openbsd-compat.h"
+#include "image.h"
+
+/* #-define pdfbufsize pdfbufmax */
+
+ extern integer epdf_page_box;
+ extern void *epdf_xref;
+
+ 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 integer pdf_stream_length;
+ extern integer 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 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);
+ extern void epdf_delete(image_dict *);
+ extern void epdf_free(void);
+ __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);
+ __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 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 void epdf_mark_glyphs(struct fd_entry *, char *);
+ extern struct fd_entry *epdf_create_fontdescriptor(struct fm_entry *);
+ extern int get_fd_objnum(struct fd_entry *);
+ extern int get_fn_objnum(struct fd_entry *);
+
+/* write_enc.c */
+ extern void epdf_write_enc(char **, integer);
+
+/* write_enc.c */
+ extern pdf_img_struct *new_pdf_img_struct(void);
+
+/* 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);
+}
diff --git a/Build/source/texk/web2c/luatexdir/image/image.h b/Build/source/texk/web2c/luatexdir/image/image.h
new file mode 100644
index 00000000000..cf7d4f0dd88
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/image.h
@@ -0,0 +1,223 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+pdfTeX 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.
+
+pdfTeX 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: image.h 1100 2008-03-09 13:40:48Z hhenkel $
+*/
+
+#ifndef IMAGE_H
+# define IMAGE_H
+
+# include <../libpng/png.h>
+
+# 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))
+
+# define TYPE_IMG "image"
+# define TYPE_IMG_DICT "image-dict"
+
+# define scaled integer
+
+/**********************************************************************/
+
+typedef struct {
+ float width;
+ float height;
+ float orig_x;
+ float orig_y;
+ void *doc;
+} pdf_img_struct;
+
+typedef struct {
+ png_structp png_ptr;
+ png_infop info_ptr;
+} png_img_struct;
+
+typedef struct {
+ int color_space; /* used color space. See JPG_ constants */
+ JPG_UINT32 length; /* length of file/data */
+} jpg_img_struct;
+
+typedef struct { /* currently unused */
+} jb2_img_struct;
+
+typedef enum { DICT_NEW, /* fresh dictionary */
+ DICT_FILESCANNED, /* image file scanned */
+ DICT_REFERED, /* pdf_refximage_node in node list --> read-only dict */
+ DICT_OUTIMG, /* /Im* appears in pagestream */
+ DICT_SCHEDULED, /* image dict scheduled for writing */
+ DICT_WRITTEN /* image dict written to file */
+} dict_state;
+
+typedef enum { IMAGE_TYPE_NONE, IMAGE_TYPE_PDF, IMAGE_TYPE_PNG, IMAGE_TYPE_JPG,
+ IMAGE_TYPE_JBIG2, IMAGE_TYPE_SENTINEL
+} imgtype_e;
+
+typedef enum { IMG_KEEPOPEN, IMG_CLOSEINBETWEEN } img_readtype_e;
+
+typedef enum { PDF_BOX_SPEC_NONE, PDF_BOX_SPEC_MEDIA, PDF_BOX_SPEC_CROP,
+ PDF_BOX_SPEC_BLEED, PDF_BOX_SPEC_TRIM, PDF_BOX_SPEC_ART,
+ PDF_BOX_SPEC_SENTINEL
+} pdfboxspec_e;
+
+/**********************************************************************/
+
+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_res; /* pixel resolution as in JPG/PNG/JBIG2 file */
+ integer y_res;
+ integer colorspace; /* number of /ColorSpace object */
+ integer total_pages;
+ integer 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 color_depth; /* color depth */
+ pdfboxspec_e page_box_spec; /* PDF page box spec.: media/crop/bleed/trim/art */
+ dict_state state;
+ union {
+ pdf_img_struct *pdf;
+ png_img_struct *png;
+ jpg_img_struct *jpg;
+ jb2_img_struct *jb2;
+ } img_struct;
+} image_dict;
+
+# define img_objnum(N) ((N)->objnum)
+# define img_index(N) ((N)->index)
+# define img_xsize(N) ((N)->x_size)
+# define img_ysize(N) ((N)->y_size)
+# define img_xres(N) ((N)->x_res)
+# define img_yres(N) ((N)->y_res)
+# define img_colorspace(N) ((N)->colorspace)
+# define img_totalpages(N) ((N)->total_pages)
+# define img_pagenum(N) ((N)->page_num)
+# define img_pagename(N) ((N)->pagename)
+# define img_filename(N) ((N)->filename)
+# define img_filepath(N) ((N)->filepath)
+# 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_colordepth(N) ((N)->color_depth)
+# define img_pagebox(N) ((N)->page_box_spec)
+# define img_state(N) ((N)->state)
+
+# define img_pdf_ptr(N) ((N)->img_struct.pdf)
+# define img_pdf_width(N) ((N)->img_struct.pdf->width)
+# define img_pdf_height(N) ((N)->img_struct.pdf->height)
+# define img_pdf_orig_x(N) ((N)->img_struct.pdf->orig_x)
+# define img_pdf_orig_y(N) ((N)->img_struct.pdf->orig_y)
+# define img_pdf_doc(N) ((N)->img_struct.pdf->doc)
+
+# define img_png_ptr(N) ((N)->img_struct.png)
+# define img_png_png_ptr(N) ((N)->img_struct.png->png_ptr)
+# define img_png_info_ptr(N) ((N)->img_struct.png->info_ptr)
+
+# define img_jpg_ptr(N) ((N)->img_struct.jpg)
+# define img_jpg_color(N) ((N)->img_struct.jpg->color_space)
+
+# define img_jb2_ptr(N) ((N)->img_struct.jb2)
+
+/**********************************************************************/
+
+typedef struct {
+ integer width; /* requested/actual TeX dimensions */
+ integer height;
+ integer depth;
+ integer transform;
+ integer flags;
+ image_dict *dict;
+ 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_dictref(N) ((N)->dict_ref)
+
+# define F_FLAG_SCALED 0x01
+# define F_FLAG_REFERED 0x02
+
+# define img_flags(N) ((N)->flags)
+# define img_set_scaled(N) (img_flags(N) |= F_FLAG_SCALED)
+# define img_set_refered(N) (img_flags(N) |= F_FLAG_REFERED)
+# define img_unset_scaled(N) (img_flags(N) &= ~F_FLAG_SCALED)
+# define img_unset_refered(N) (img_flags(N) &= ~F_FLAG_REFERED)
+# define img_is_scaled(N) ((img_flags(N) & F_FLAG_SCALED) != 0)
+# define img_is_refered(N) ((img_flags(N) & F_FLAG_REFERED) != 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)
+# define is_wd_running(N) (img_width(N) == null_flag)
+# define is_ht_running(N) (img_height(N) == null_flag)
+# define is_dp_running(N) (img_depth(N) == null_flag)
+
+/**********************************************************************/
+
+/* writeimg.c */
+
+image *new_image();
+image_dict *new_image_dict();
+void init_image(image *);
+void init_image_dict(image_dict *);
+void scale_img(image *);
+integer img_to_array(image *);
+void delete_image(image *);
+void free_image_dict(image_dict * p);
+void read_img(image_dict *, integer, integer);
+
+/* writepng.c */
+
+# ifndef boolean /* TODO: from where to get the original definition? */
+# define boolean int
+# endif
+
+void read_png_info(image_dict *, img_readtype_e);
+void read_jpg_info(image_dict *, img_readtype_e);
+void read_jbig2_info(image_dict *);
+void read_pdf_info(image_dict *, integer, integer);
+void write_img(image_dict *);
+void write_png(image_dict *);
+void write_jpg(image_dict *);
+void write_jbig2(image_dict *);
+void write_epdf(image_dict *);
+
+/* pdftoepdf.cc */
+
+void epdf_delete(image_dict * idict);
+
+#endif
diff --git a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc
new file mode 100644
index 00000000000..c5270eb58bd
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc
@@ -0,0 +1,1008 @@
+/*
+Copyright 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: pdftoepdf.cc 1058 2008-02-19 21:13:58Z hhenkel $
+*/
+
+#include <stdlib.h>
+#include <math.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <aconf.h>
+#include <GString.h>
+#include <gmem.h>
+#include <gfile.h>
+#include <config.h>
+#include <assert.h>
+#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"
+
+#include "epdf.h"
+
+#define one_hundred_bp 6578176 /* 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++.
+
+// Used flags below:
+// PDFTEX_COPY_PAGEGROUP
+// If pdfTeX should copy a page group (a new feature in PDF 1.4 for
+// transparency) of an included file. The current support for this is
+// most likely broken. pdfTeX will at least give a warning if this flag
+// is not set. Surprisingly Acrobat and Jaws display files without a
+// page group correctly, so it might be safe to not set the flag.
+// See also PDFTEX_COPY_PAGEGROUP_NOFAIL.
+// PDFTEX_COPY_PAGEGROUP_NOFAIL
+// If set to false, pdfTeX will treat a page group in an included file
+// as an error and abort gracefully. This is only evaluated if
+// PDFTEX_COPY_PAGEGROUP is set.
+
+// The prefix "PTEX" for the PDF keys is special to pdfTeX;
+// this has been registered with Adobe by Hans Hagen.
+
+#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.
+
+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;
+};
+
+// 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
+ InObj *next; // next entry in list of indirect objects
+ 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?
+};
+
+struct UsedEncoding {
+ integer enc_objnum;
+ GfxFont *font;
+ UsedEncoding *next;
+};
+
+static InObj *inObjList;
+static UsedEncoding *encodingList;
+static GBool isInit = gFalse;
+
+// --------------------------------------------------------------------
+// Maintain list of open embedded PDF files
+// --------------------------------------------------------------------
+
+struct PdfDocument {
+ char *file_name;
+ PDFDoc *doc;
+ XRef *xref;
+ InObj *inObjList;
+ int occurences; // number of references to the document; the doc can be
+ // deleted when this is negative
+ PdfDocument *next;
+};
+
+static PdfDocument *pdfDocuments = 0;
+
+static XRef *xref = 0;
+
+// Returns pointer to PdfDocument record for PDF file.
+// Creates a new record if it doesn't exist yet.
+// xref is made current for the document.
+
+static PdfDocument *find_add_document(char *file_name)
+{
+ PdfDocument *p = pdfDocuments;
+ while (p && strcmp(p->file_name, file_name) != 0)
+ p = p->next;
+ if (p) {
+ xref = p->xref;
+ (p->occurences)++;
+#ifdef DEBUG
+ fprintf(stderr, "\npdfTeX Debug: Incrementing %s (%d)\n", p->file_name,
+ p->occurences);
+#endif
+ return p;
+ }
+ p = new PdfDocument;
+ p->file_name = xstrdup(file_name);
+ p->xref = xref = 0;
+ p->occurences = 0;
+#ifdef DEBUG
+ fprintf(stderr, "\npdfTeX Debug: Creating %s (%d)\n", p->file_name,
+ p->occurences);
+#endif
+ GString *docName = new GString(p->file_name);
+ p->doc = new PDFDoc(docName); // takes ownership of docName
+ if (!p->doc->isOk() || !p->doc->okToPrint()) {
+ pdftex_fail("xpdf: reading PDF image failed");
+ }
+ p->inObjList = 0;
+ p->next = pdfDocuments;
+ pdfDocuments = p;
+ return p;
+}
+
+// Deallocate a PdfDocument with all its resources
+
+static void delete_document(PdfDocument * pdf_doc)
+{
+ PdfDocument **p = &pdfDocuments;
+ while (*p && *p != pdf_doc)
+ p = &((*p)->next);
+ // should not happen:
+ if (!*p)
+ return;
+ // unlink from list
+ *p = pdf_doc->next;
+ // free pdf_doc's resources
+ InObj *r, *n;
+ for (r = pdf_doc->inObjList; r != 0; r = n) {
+ n = r->next;
+ delete r;
+ }
+ xref = pdf_doc->xref;
+ delete pdf_doc->doc;
+ xfree(pdf_doc->file_name);
+ delete pdf_doc;
+}
+
+// Replacement for
+// Object *initDict(Dict *dict1){ initObj(objDict); dict = dict1; return this; }
+
+static void initDictFromDict(PdfObject & obj, Dict * dict)
+{
+ 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));
+ }
+}
+
+// --------------------------------------------------------------------
+
+static int addEncoding(GfxFont * gfont)
+{
+ UsedEncoding *n;
+ n = new UsedEncoding;
+ n->next = encodingList;
+ encodingList = n;
+ n->font = gfont;
+ n->enc_objnum = pdf_new_objnum();
+ return n->enc_objnum;
+}
+
+#define addFont(ref, fd, enc_objnum) \
+ addInObj(objFont, ref, fd, enc_objnum)
+
+// 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, 0, 0)
+
+static int addInObj(InObjType type, Ref ref, fd_entry * fd, integer e)
+{
+ InObj *p, *q, *n = new InObj;
+ if (ref.num == 0)
+ pdftex_fail("PDF inclusion: invalid reference");
+ n->ref = ref;
+ n->type = type;
+ n->next = 0;
+ n->fd = fd;
+ n->enc_objnum = e;
+ n->written = 0;
+ if (inObjList == 0)
+ inObjList = n;
+ else {
+ for (p = inObjList; p != 0; 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.
+ q->next = n;
+ }
+ if (type == objFontDesc)
+ n->num = get_fd_objnum(fd);
+ else
+ n->num = pdf_new_objnum();
+ return n->num;
+}
+
+static void copyObject(Object *);
+
+static void copyName(char *s)
+{
+ pdf_puts("/");
+ for (; *s != 0; s++) {
+ if (isdigit(*s) || isupper(*s) || islower(*s) || *s == '_' ||
+ *s == '.' || *s == '-')
+ pdfout(*s);
+ else
+ pdf_printf("#%.2X", *s & 0xFF);
+ }
+}
+
+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 = pdf_buf[pdf_ptr - 1];
+}
+
+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;
+ 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_replace_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) {
+ fd = epdf_create_fontdescriptor(fontmap);
+ 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
+// 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.
+// These are:
+// maximum value of ints is +2^32
+// maximum value of reals is +2^15
+// smalles values of reals is 1/(2^16)
+
+static char *convertNumToPDF(double n)
+{
+ static const int precision = 6;
+ static const int fact = (int) 1E6; // must be 10^precision
+ static const double epsilon = 0.5E-6; // 2epsilon must be 10^-precision
+ static char buf[64];
+ // handle very small values: return 0
+ if (fabs(n) < epsilon) {
+ buf[0] = '0';
+ buf[1] = '\0';
+ } else {
+ char ints[64];
+ int bindex = 0, sindex = 0;
+ int ival, fval;
+ // handle the sign part if n is negative
+ if (n < 0) {
+ buf[bindex++] = '-';
+ n = -n;
+ }
+ n += epsilon; // for rounding
+ // handle the integer part, simply with sprintf
+ ival = (int) floor(n);
+ n -= ival;
+ sprintf(ints, "%d", ival);
+ while (ints[sindex] != 0)
+ buf[bindex++] = ints[sindex++];
+ // handle the fractional part up to 'precision' digits
+ fval = (int) floor(n * fact);
+ if (fval) {
+ // set a dot
+ buf[bindex++] = '.';
+ sindex = bindex + precision;
+ buf[sindex--] = '\0';
+ // fill up trailing zeros with the string terminator NULL
+ while (((fval % 10) == 0) && (sindex >= bindex)) {
+ buf[sindex--] = '\0';
+ fval /= 10;
+ }
+ // fill up the fractional part back to front
+ while (sindex >= bindex) {
+ buf[sindex--] = (fval % 10) + '0';
+ fval /= 10;
+ }
+ } else
+ buf[bindex++] = 0;
+ }
+ return (char *) buf;
+}
+
+static void copyObject(Object * obj)
+{
+ 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);
+ }
+ 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()->getBaseStream());
+ 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_warn
+ ("PDF inclusion: reference to invalid object was replaced by <null>");
+ pdf_puts("null");
+ } else
+ pdf_printf("%d 0 R", addOther(ref));
+ } else {
+ pdftex_fail("PDF inclusion: type <%s> cannot be copied",
+ obj->getTypeName());
+ }
+}
+
+static void writeRefs()
+{
+ InObj *r;
+ for (r = inObjList; r != 0; 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();
+ }
+ }
+}
+
+static void writeEncodings()
+{
+ UsedEncoding *r, *n;
+ char *glyphNames[256], *s;
+ int i;
+ for (r = encodingList; r != 0; r = r->next) {
+ for (i = 0; i < 256; i++) {
+ if (r->font->isCIDFont()) {
+ pdftex_warn
+ ("PDF inclusion: CID font included, encoding maybe wrong");
+ }
+ if ((s = ((Gfx8BitFont *) r->font)->getCharName(i)) != 0)
+ glyphNames[i] = s;
+ else
+ glyphNames[i] = notdef;
+ }
+ epdf_write_enc(glyphNames, r->enc_objnum);
+ }
+ for (r = encodingList; r != 0; r = n) {
+ n = r->next;
+ delete r->font;
+ delete r;
+ }
+}
+
+// get the pagebox according to the pagebox_spec
+
+static PDFRectangle *get_pagebox(Page * page, integer pagebox_spec)
+{
+ if (pagebox_spec == pdf_box_spec_media)
+ return page->getMediaBox();
+ else if (pagebox_spec == pdf_box_spec_crop)
+ return page->getCropBox();
+ else if (pagebox_spec == pdf_box_spec_bleed)
+ return page->getBleedBox();
+ else if (pagebox_spec == pdf_box_spec_trim)
+ return page->getTrimBox();
+ else if (pagebox_spec == pdf_box_spec_art)
+ return page->getArtBox();
+ else
+ pdftex_fail("PDF inclusion: unknown value of pagebox spec (%i)",
+ (int) pagebox_spec);
+ return page->getMediaBox(); // to make the compiler happy
+}
+
+
+// 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.
+// It makes no sense to give page_name _and_ page_num.
+// Returns the page number.
+
+void
+read_pdf_info(image_dict * idict, integer minor_pdf_version_wanted,
+ integer pdf_inclusion_errorlevel)
+{
+ PdfDocument *pdf_doc;
+ Page *page;
+ int rotate;
+ PDFRectangle *pagebox;
+ float pdf_version_found, pdf_version_wanted;
+ assert(idict != NULL);
+ assert(img_type(idict) == IMAGE_TYPE_PDF);
+ assert(img_pdf_ptr(idict) == NULL);
+ img_pdf_ptr(idict) = new_pdf_img_struct();
+ // initialize
+ if (!isInit) {
+ globalParams = new GlobalParams();
+ globalParams->setErrQuiet(gFalse);
+ isInit = gTrue;
+ }
+ // open PDF file
+ pdf_doc = find_add_document(img_filepath(idict));
+ img_pdf_doc(idict) = pdf_doc;
+
+ // 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.
+ pdf_version_found = pdf_doc->doc->getPDFVersion();
+ pdf_version_wanted = 1 + (minor_pdf_version_wanted * 0.1);
+ if (pdf_version_found > pdf_version_wanted) {
+ char msg[] =
+ "PDF inclusion: found PDF version <%.1f>, but at most version <%.1f> allowed";
+ if (pdf_inclusion_errorlevel > 0) {
+ pdftex_fail(msg, pdf_version_found, pdf_version_wanted);
+ } else {
+ pdftex_warn(msg, pdf_version_found, pdf_version_wanted);
+ }
+ }
+ img_totalpages(idict) = pdf_doc->doc->getCatalog()->getNumPages();
+ if (img_pagename(idict)) {
+ // get page by name
+ GString name(img_pagename(idict));
+ LinkDest *link = pdf_doc->doc->findDest(&name);
+ if (link == 0 || !link->isOk())
+ pdftex_fail("PDF inclusion: invalid destination <%s>",
+ img_pagename(idict));
+ Ref ref = link->getPageRef();
+ img_pagenum(idict) =
+ pdf_doc->doc->getCatalog()->findPage(ref.num, ref.gen);
+ if (img_pagenum(idict) == 0)
+ pdftex_fail("PDF inclusion: destination is not a page <%s>",
+ img_pagename(idict));
+ delete link;
+ } else {
+ // get page by number
+ if (img_pagenum(idict) <= 0
+ || img_pagenum(idict) > img_totalpages(idict))
+ pdftex_fail("PDF inclusion: required page <%i> does not exist",
+ (int) img_pagenum(idict));
+ }
+ // get the required page
+ page = pdf_doc->doc->getCatalog()->getPage(img_pagenum(idict));
+
+ // get the pagebox (media, crop...) to use.
+ pagebox = get_pagebox(page, img_pagebox(idict));
+ if (pagebox->x2 > pagebox->x1) {
+ img_pdf_orig_x(idict) = pagebox->x1;
+ img_pdf_width(idict) = pagebox->x2 - pagebox->x1;
+ } else {
+ img_pdf_orig_x(idict) = pagebox->x2;
+ img_pdf_width(idict) = pagebox->x1 - pagebox->x2;
+ }
+ if (pagebox->y2 > pagebox->y1) {
+ img_pdf_orig_y(idict) = pagebox->y1;
+ img_pdf_height(idict) = pagebox->y2 - pagebox->y1;
+ } else {
+ img_pdf_orig_y(idict) = pagebox->y2;
+ img_pdf_height(idict) = pagebox->y1 - pagebox->y2;
+ }
+
+ rotate = page->getRotate();
+ // handle page rotation and adjust dimens as needed
+ if (rotate != 0) {
+ if (rotate % 90 == 0) {
+ // handle only the simple case: multiple of 90s.
+ // these are the only values allowed according to the
+ // reference (v1.3, p. 78).
+ // 180 needs no special treatment here
+ register float f;
+ switch (rotate) {
+ case 90:
+ f = img_pdf_height(idict);
+ img_pdf_height(idict) = img_pdf_width(idict);
+ img_pdf_width(idict) = f;
+ break;
+ case 270:
+ f = img_pdf_height(idict);
+ img_pdf_height(idict) = img_pdf_width(idict);
+ img_pdf_width(idict) = f;
+ break;
+ }
+ }
+ }
+ pdf_doc->xref = pdf_doc->doc->getXRef();
+ img_xsize(idict) = bp2int(img_pdf_width(idict));
+ img_ysize(idict) = bp2int(img_pdf_height(idict));
+}
+
+// writes the current epf_doc.
+// Here the included PDF is copied, so most errors that can happen during PDF
+// inclusion will arise here.
+
+void write_epdf(image_dict * idict)
+{
+ Page *page;
+ PdfObject contents, obj1, obj2;
+ PdfObject group, metadata, pieceinfo, separationInfo;
+ Object info;
+ char *key;
+ char s[256];
+ int i, l;
+ int rotate;
+ double scale[6] = { 0, 0, 0, 0, 0, 0 };
+ bool writematrix = false;
+ PdfDocument *pdf_doc = (PdfDocument *) img_pdf_doc(idict);
+ (pdf_doc->occurences)--;
+#ifdef DEBUG
+ fprintf(stderr, "\npdfTeX Debug: Decrementing %s (%d)\n",
+ pdf_doc->file_name, pdf_doc->occurences);
+#endif
+ xref = pdf_doc->xref;
+ inObjList = pdf_doc->inObjList;
+ encodingList = 0;
+ page = pdf_doc->doc->getCatalog()->getPage(img_pagenum(idict));
+ rotate = page->getRotate();
+ PDFRectangle *pagebox;
+ // write the Page header
+ 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");
+
+ // write additional information
+ pdf_printf("/%s.FileName (%s)\n", pdfkeyprefix,
+ convertStringToPDFString(pdf_doc->file_name,
+ strlen(pdf_doc->file_name)));
+ pdf_printf("/%s.PageNumber %i\n", pdfkeyprefix, (int) img_pagenum(idict));
+ pdf_doc->doc->getDocInfoNF(&info);
+ 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()));
+ }
+ // get the pagebox (media, crop...) to use.
+ pagebox = get_pagebox(page, img_pagebox(idict));
+
+ // handle page rotation
+ if (rotate != 0) {
+ if (rotate % 90 == 0) {
+ // this handles only the simple case: multiple of 90s but these
+ // are the only values allowed according to the reference
+ // (v1.3, p. 78).
+ // the image is rotated around its center.
+ // the /Rotate key is clockwise while the matrix is
+ // counterclockwise :-%
+ tex_printf(", page is rotated %d degrees", rotate);
+ switch (rotate) {
+ case 90:
+ scale[1] = -1;
+ scale[2] = 1;
+ scale[4] = pagebox->x1 - pagebox->y1;
+ scale[5] = pagebox->y1 + pagebox->x2;
+ writematrix = true;
+ break;
+ case 180:
+ scale[0] = scale[3] = -1;
+ scale[4] = pagebox->x1 + pagebox->x2;
+ scale[5] = pagebox->y1 + pagebox->y2;
+ writematrix = true;
+ break; // width and height are exchanged
+ case 270:
+ scale[1] = 1;
+ scale[2] = -1;
+ scale[4] = pagebox->x1 + pagebox->y2;
+ scale[5] = pagebox->y1 - pagebox->x1;
+ writematrix = true;
+ break;
+ }
+ if (writematrix) { // The matrix is only written if the image is rotated.
+ sprintf(s, "/Matrix [%.8f %.8f %.8f %.8f %.8f %.8f]\n",
+ scale[0],
+ scale[1], scale[2], scale[3], scale[4], scale[5]);
+ pdf_printf(stripzeros(s));
+ }
+ }
+ }
+
+ sprintf(s, "/BBox [%.8f %.8f %.8f %.8f]\n",
+ pagebox->x1, pagebox->y1, pagebox->x2, pagebox->y2);
+ pdf_printf(stripzeros(s));
+
+ // write the page Group if it's there
+ if (page->getGroup() != NULL) {
+#if PDFTEX_COPY_PAGEGROUP
+# if PDFTEX_COPY_PAGEGROUP_NOFAIL
+ // FIXME: This will most likely produce incorrect PDFs :-(
+ initDictFromDict(group, page->getGroup());
+ if (group->dictGetLength() > 0) {
+ pdf_puts("/Group ");
+ copyObject(&group);
+ pdf_puts("\n");
+ }
+# else
+ // FIXME: currently we don't know how to handle Page Groups so we abort gracefully :-(
+ pdftex_fail
+ ("PDF inclusion: Page Group detected which pdfTeX can't handle. Sorry.");
+# endif
+#else
+ // FIXME: currently we don't know how to handle Page Groups so we at least give a warning :-(
+ pdftex_warn
+ ("PDF inclusion: Page Group detected which pdfTeX can't handle. Ignoring it.");
+#endif
+ }
+ // write the page Metadata if it's there
+ if (page->getMetadata() != NULL) {
+ metadata->initStream(page->getMetadata());
+ pdf_puts("/Metadata ");
+ copyObject(&metadata);
+ pdf_puts("\n");
+ }
+ // 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");
+ }
+ }
+ // 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). This violates the PDF Ref., which claims they are
+ // required, but all RIPs accept them.
+ // We "replace" them with empty /Resources, although in form xobjects
+ // /Resources are not required.
+ pdftex_warn
+ ("PDF inclusion: no /Resources detected. Replacing with empty /Resources.");
+ pdf_puts("/Resources <<>>\n");
+ } 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()) {
+ initDictFromDict(obj1, contents->streamGetDict());
+ contents->streamGetDict()->incRef();
+ copyDict(&obj1);
+ pdf_puts(">>\nstream\n");
+ copyStream(contents->getStream()->getBaseStream());
+ pdf_end_stream();
+ } else if (contents->isArray()) {
+ pdf_begin_stream();
+ for (i = 0, l = contents->arrayGetLength(); i < l; ++i) {
+ Object contentsobj;
+ copyStream((contents->arrayGet(i, &contentsobj))->getStream());
+ contentsobj.free();
+ }
+ pdf_end_stream();
+ } else { // the contents are optional, but we need to include an empty stream
+ pdf_begin_stream();
+ pdf_end_stream();
+ }
+ // write out all indirect objects
+ writeRefs();
+ // write out all used encodings (and delete list)
+ writeEncodings();
+ // save object list, xref
+ pdf_doc->inObjList = inObjList;
+ pdf_doc->xref = xref;
+}
+
+// Called when an image has been written and it's resources in image_tab are
+// freed and it's not referenced anymore.
+
+void epdf_delete(image_dict * idict)
+{
+ PdfDocument *pdf_doc = (PdfDocument *) img_pdf_doc(idict);
+ xref = pdf_doc->xref;
+ if (pdf_doc->occurences < 0) {
+#ifdef DEBUG
+ fprintf(stderr, "\npdfTeX Debug: Deleting %s\n", pdf_doc->file_name);
+#endif
+ delete_document(pdf_doc);
+ }
+ img_pdf_doc(idict) = NULL;
+}
+
+// Called when PDF embedding system is finalized.
+// Now deallocate all remaining PdfDocuments.
+
+void epdf_check_mem()
+{
+ if (isInit) {
+ PdfDocument *p, *n;
+ for (p = pdfDocuments; p; p = n) {
+ n = p->next;
+ delete_document(p);
+ }
+ // see above for globalParams
+ delete globalParams;
+ }
+}
diff --git a/Build/source/texk/web2c/luatexdir/image/writeimg.c b/Build/source/texk/web2c/luatexdir/image/writeimg.c
new file mode 100644
index 00000000000..66eb459bc0c
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/writeimg.c
@@ -0,0 +1,677 @@
+/*
+Copyright (c) 1996-2002, 2005 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+pdfTeX 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.
+
+pdfTeX 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writeimg.c 1119 2008-03-22 11:27:02Z hhenkel $
+*/
+
+#include <assert.h>
+#include "ptexlib.h"
+#include <kpathsea/c-auto.h>
+#include <kpathsea/c-memstr.h>
+
+#include "image.h"
+
+#include <../lua51/lua.h>
+#include <../lua51/lauxlib.h>
+
+extern void pdf_print_real(integer m, integer d);
+
+#define obj_aux(A) obj_tab[(A)].int4
+
+/**********************************************************************/
+/*
+ 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 IMAGE_TYPE_NONE by new_image_dict().
+ Both functions try to detect a type and set img_type(img).
+ Thus a value other than IMAGE_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)
+
+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) != IMAGE_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) = IMAGE_TYPE_JPG;
+ else if (strncmp(header, HEADER_PNG, sizeof(HEADER_PNG) - 1) == 0)
+ img_type(idict) = IMAGE_TYPE_PNG;
+ else if (strncmp(header, HEADER_JBIG2, sizeof(HEADER_JBIG2) - 1) == 0)
+ img_type(idict) = IMAGE_TYPE_JBIG2;
+ else if (strncmp(header, HEADER_PDF, sizeof(HEADER_PDF) - 1) == 0)
+ img_type(idict) = IMAGE_TYPE_PDF;
+}
+
+static void check_type_by_extension(image_dict * idict)
+{
+ char *image_suffix;
+
+ assert(idict != NULL);
+ if (img_type(idict) != IMAGE_TYPE_NONE) /* nothing to do */
+ return;
+ /* tests */
+ if ((image_suffix = strrchr(img_filename(idict), '.')) == 0)
+ img_type(idict) = IMAGE_TYPE_NONE;
+ else if (strcasecmp(image_suffix, ".png") == 0)
+ img_type(idict) = IMAGE_TYPE_PNG;
+ else if (strcasecmp(image_suffix, ".jpg") == 0 ||
+ strcasecmp(image_suffix, ".jpeg") == 0)
+ img_type(idict) = IMAGE_TYPE_JPG;
+ else if (strcasecmp(image_suffix, ".jbig2") == 0 ||
+ strcasecmp(image_suffix, ".jb2") == 0)
+ img_type(idict) = IMAGE_TYPE_JBIG2;
+ else if (strcasecmp(image_suffix, ".pdf") == 0)
+ img_type(idict) = IMAGE_TYPE_PDF;
+}
+
+/**********************************************************************/
+
+pdf_img_struct *new_pdf_img_struct()
+{
+ pdf_img_struct *p;
+ p = xtalloc(1, pdf_img_struct);
+ p->width = 0;
+ p->height = 0;
+ p->orig_x = 0;
+ p->orig_y = 0;
+ p->doc = NULL;
+ return p;
+}
+
+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_refered(p); /* wd/ht/dp may be modified */
+ img_unset_scaled(p);
+ img_dict(p) = NULL;
+ img_dictref(p) = LUA_NOREF;
+}
+
+image *new_image()
+{
+ 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_xres(p) = 0;
+ img_yres(p) = 0;
+ img_colorspace(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) = IMAGE_TYPE_NONE;
+ img_color(p) = 0;
+ img_colordepth(p) = 0;
+ img_pagebox(p) = PDF_BOX_SPEC_MEDIA;
+ img_state(p) = DICT_NEW;
+ img_pdf_ptr(p) = NULL; /* union */
+}
+
+image_dict *new_image_dict()
+{
+ image_dict *p = xtalloc(1, image_dict);
+ init_image_dict(p);
+ return p;
+}
+
+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)
+{
+ free_dict_strings(p);
+ if (img_type(p) == IMAGE_TYPE_PDF)
+ epdf_delete(p);
+ assert(img_file(p) == NULL);
+ xfree(p);
+}
+
+/**********************************************************************/
+
+void pdf_print_resname_prefix()
+{
+ 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");
+ /* type checks */
+ check_type_by_header(idict);
+ check_type_by_extension(idict);
+ /* read image */
+ switch (img_type(idict)) {
+ case IMAGE_TYPE_PDF:
+ read_pdf_info(idict, pdf_minor_version, pdf_inclusion_errorlevel);
+ break;
+ case IMAGE_TYPE_PNG:
+ read_png_info(idict, IMG_CLOSEINBETWEEN);
+ break;
+ case IMAGE_TYPE_JPG:
+ read_jpg_info(idict, IMG_CLOSEINBETWEEN);
+ break;
+ case IMAGE_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");
+ }
+ cur_file_name = NULL;
+ if (img_state(idict) < DICT_FILESCANNED)
+ img_state(idict) = DICT_FILESCANNED;
+}
+
+void scale_img(image * img)
+{
+ integer x, y, xr, yr; /* size and resolution of image */
+ scaled w, h; /* indeed size corresponds to image resolution */
+ integer default_res;
+ assert(img != NULL);
+ image_dict *idict = img_dict(img);
+ assert(idict != NULL);
+ x = img_xsize(idict); /* dimensions, resolutions from image file */
+ y = img_ysize(idict);
+ xr = img_xres(idict);
+ yr = img_yres(idict);
+ if ((img_transform(img) & 1) == 1) {
+ int tmp = x;
+ x = y;
+ y = tmp;
+ tmp = xr;
+ xr = yr;
+ yr = tmp;
+ }
+ if (xr > 65535 || yr > 65535) {
+ xr = 0;
+ yr = 0;
+ pdftex_warn("ext1: too large image resolution ignored");
+ }
+ if (x <= 0 || y <= 0 || xr < 0 || yr < 0)
+ pdftex_fail("ext1: invalid image dimensions");
+ if (img_type(idict) == IMAGE_TYPE_PDF) {
+ 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);
+}
+
+void out_img(image * img, scaled hpos, scaled vpos)
+{
+ float a[7]; /* transformation matrix (todo: indices should be reduced!) */
+ int r; /* number of digits after the decimal point */
+ assert(img != 0);
+ image_dict *idict = img_dict(img);
+ assert(idict != 0);
+ scaled wd = img_width(img);
+ scaled ht = img_height(img);
+ scaled dp = img_depth(img);
+ if (img_type(idict) == IMAGE_TYPE_PDF) {
+ a[1] = wd * 1.0e6 / img_xsize(idict);
+ a[2] = 0;
+ a[3] = 0;
+ a[4] = (ht + dp) * 1.0e6 / img_ysize(idict);
+ a[5] = hpos -
+ (float) wd *bp2int(img_pdf_orig_x(idict)) / img_xsize(idict);
+ a[6] = vpos -
+ (float) ht *bp2int(img_pdf_orig_y(idict)) / img_ysize(idict);
+ r = 6;
+ } else {
+ a[1] = wd * 1.0e6 / one_hundred_bp;
+ a[2] = 0;
+ a[3] = 0;
+ a[4] = (ht + dp) * 1.0e6 / one_hundred_bp;
+ a[5] = hpos;
+ a[6] = vpos;
+ r = 4;
+ }
+ if ((img_transform(img) & 1) == 1) {
+ if (ht == -dp)
+ pdftex_fail("image transform: division by zero (height == -depth)");
+ if (wd == 0)
+ pdftex_fail("image transform: division by zero (width == 0)");
+ }
+ switch (img_transform(img) & 7) {
+ case 0: /* unrotated */
+ break;
+ case 1: /* rot. 90 deg. (counterclockwise) */
+ a[2] = a[1] * (ht + dp) / wd;
+ a[1] = 0;
+ a[3] = -a[4] * wd / (ht + dp);
+ a[4] = 0;
+ a[5] += wd;
+ break;
+ case 2: /* rot. 180 deg. */
+ a[1] = -a[1];
+ a[4] = -a[4];
+ a[5] += wd;
+ a[6] += ht + dp;
+ break;
+ case 3: /* rot. 270 deg. */
+ a[2] = -a[1] * (ht + dp) / wd;
+ a[1] = 0;
+ a[3] = a[4] * wd / (ht + dp);
+ a[4] = 0;
+ a[6] += ht + dp;
+ break;
+ case 4: /* mirrored, unrotated */
+ a[1] = -a[1];
+ a[5] += wd;
+ break;
+ case 5: /* mirrored, then rot. 90 deg. */
+ a[2] = -a[1] * (ht + dp) / wd;
+ a[1] = 0;
+ a[3] = -a[4] * wd / (ht + dp);
+ a[4] = 0;
+ a[5] += wd;
+ a[6] += ht + dp;
+ break;
+ case 6: /* mirrored, then rot. 180 deg. */
+ a[4] = -a[4];
+ a[6] += ht + dp;
+ break;
+ case 7: /* mirrored, then rot. 270 deg. */
+ a[2] = a[1] * (ht + dp) / wd;
+ a[1] = 0;
+ a[3] = a[4] * wd / (ht + dp);
+ a[4] = 0;
+ break;
+ default:
+ assert(0);
+ }
+ pdf_end_text();
+ pdf_printf("q\n");
+ pdf_print_real((integer) a[1], r);
+ pdfout(' ');
+ pdf_print_real((integer) a[2], r);
+ pdfout(' ');
+ pdf_print_real((integer) a[3], r);
+ pdfout(' ');
+ pdf_print_real((integer) a[4], r);
+ pdfout(' ');
+ pdf_print_bp((integer) a[5]);
+ pdfout(' ');
+ pdf_print_bp((integer) a[6]);
+ pdf_printf(" cm\n/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 IMAGE_TYPE_PNG:
+ write_png(idict);
+ break;
+ case IMAGE_TYPE_JPG:
+ write_jpg(idict);
+ break;
+ case IMAGE_TYPE_JBIG2:
+ write_jbig2(idict);
+ break;
+ case IMAGE_TYPE_PDF:
+ write_epdf(idict);
+ break;
+ default:
+ pdftex_fail("internal error: unknown image type");
+ }
+ if (tracefilenames)
+ tex_printf(">");
+ }
+ if (img_state(idict) < DICT_WRITTEN)
+ img_state(idict) = DICT_WRITTEN;
+}
+
+/**********************************************************************/
+
+typedef image *img_entry;
+/* define img_ptr, img_array, & img_limit */
+define_array(img); /* array of pointers to image structures */
+
+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 */
+}
+
+/**********************************************************************/
+/* stuff to be accessible from TeX */
+
+integer read_image(integer objnum, integer index, strnumber filename,
+ integer page_num,
+ strnumber attr,
+ strnumber page_name,
+ integer colorspace, integer page_box,
+ integer pdf_minor_version, integer pdf_inclusion_errorlevel)
+{
+ integer ref;
+ image *a = new_image();
+ ref = img_to_array(a);
+ image_dict *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);
+ img_set_refered(a);
+ return ref;
+}
+
+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];
+ out_img(a, hpos, vpos);
+}
+
+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]));
+}
+
+integer epdf_orig_x(integer ref)
+{
+ return bp2int(img_pdf_orig_x(img_dict(img_array[ref])));
+}
+
+integer epdf_orig_y(integer ref)
+{
+ return bp2int(img_pdf_orig_y(img_dict(img_array[ref])));
+}
+
+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/writejbig2.c b/Build/source/texk/web2c/luatexdir/image/writejbig2.c
new file mode 100644
index 00000000000..d50ed88c485
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/writejbig2.c
@@ -0,0 +1,749 @@
+/***********************************************************************
+Copyright (c) 2002-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX 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 General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with pdfTeX; if not, write to the Free Software Foundation, Inc., 59
+Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+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.
+
+References
+==========
+
+* 14492 FCD: Information technology -- coded representation of picture
+and audio information -- lossy/lossless coding of bi-level images /
+JBIG committee, 1999 July 16. This JBIG2 Working Draft is available from
+http://www.jpeg.org/public/fcd14492.pdf. The references in the C-code
+correspond to the sections of this document.
+
+* PDF Reference, 5th edition, version 1.6, 1985--2005 Adobe Systems
+Incorporated. Available online:
+
+http://partners.adobe.com/public/developer/en/pdf/PDFReference16.pdf
+
+News
+====
+
+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
+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,
+some cleaning up.
+
+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
+of the pdfTeX run all pending page0 objects are written out.
+
+08 Jan. 2003: Release on private webpage.
+
+04 Jan. 2003: Completely rewritten. Now with some data structures.
+Rudimentary local file and image bookkeeping. Multiple image inclusion
+from one JBIG2 file. Only required page0 segments are marked for
+inclusion.
+
+13 Nov. 2002: pdfcrypting removed.
+
+08 Dec. 2002: bug in page 0 stream writing repaired.
+Strategy for multiple page inclusion from same JBIG2 file: When writing
+1st image, create fresh PDF object for page 0, and include any page
+0 segments from complete file (even if these segments are not needed
+for image). When writing next image, check by filename comparison if
+PDF object for page 0 of this JBIG2 file has already been written. This
+can only remember the file name for the direct predecessor JBIG2 image
+(but images of other types might come inbetween). If such page 0 PDF
+object exists, reference it. Else create fresh one.
+
+09 Dec. 2002: JBIG2 seg. page numbers > 0 are now set to 1, see PDF Ref.
+
+$Id: writejbig2.c 1027 2008-02-14 21:01:03Z hhenkel $
+***********************************************************************/
+
+#include "writejbig2.h"
+#undef DEBUG
+
+/**********************************************************************/
+
+struct avl_table *file_tree = NULL;
+
+static int comp_file_entry(const void *pa, const void *pb, void *p)
+{
+ return strcmp(((const FILEINFO *) pa)->filepath,
+ ((const FILEINFO *) pb)->filepath);
+}
+
+static int comp_page_entry(const void *pa, const void *pb, void *p)
+{
+ return ((const PAGEINFO *) pa)->pagenum - ((const PAGEINFO *) pb)->pagenum;
+}
+
+static int comp_segment_entry(const void *pa, const void *pb, void *p)
+{
+ return ((const SEGINFO *) pa)->segnum - ((const SEGINFO *) pb)->segnum;
+}
+
+/**********************************************************************/
+
+int ygetc(FILE * stream)
+{
+ int c = getc(stream);
+ if (c < 0) {
+ if (c == EOF)
+ pdftex_fail("getc() failed; premature end of JBIG2 image file");
+ else
+ pdftex_fail("getc() failed (can't happen)");
+ }
+ return c;
+}
+
+/**********************************************************************/
+
+FILEINFO *new_fileinfo()
+{
+ FILEINFO *fip;
+ fip = xtalloc(1, FILEINFO);
+ fip->file = NULL;
+ fip->filepath = NULL;
+ fip->filesize = 0;
+ initlinkedlist(&(fip->pages));
+ initlinkedlist(&(fip->page0));
+ fip->filehdrflags = 0;
+ fip->sequentialaccess = false;
+ fip->numofpages = 0;
+ fip->streamstart = 0;
+ fip->pdfpage0objnum = 0;
+ fip->phase = INITIAL;
+ return fip;
+}
+
+PAGEINFO *new_pageinfo()
+{
+ PAGEINFO *pip;
+ pip = xtalloc(1, PAGEINFO);
+ initlinkedlist(&(pip->segments));
+ pip->pagenum = 0;
+ pip->width = 0;
+ pip->height = 0;
+ pip->xres = 0;
+ pip->yres = 0;
+ pip->pagesegmentflags = 0;
+ pip->stripinginfo = 0;
+ pip->stripedheight = 0;
+ return pip;
+}
+
+void init_seginfo(SEGINFO * sip)
+{
+ sip->segnum = 0;
+ sip->isrefered = false;
+ sip->refers = false;
+ sip->seghdrflags = 0;
+ sip->pageassocsizeflag = false;
+ sip->reftosegcount = 0;
+ sip->countofrefered = 0;
+ sip->fieldlen = 0;
+ sip->segnumwidth = 0;
+ sip->segpage = 0;
+ sip->segdatalen = 0;
+ sip->hdrstart = 0;
+ sip->hdrend = 0;
+ sip->datastart = 0;
+ sip->dataend = 0;
+ sip->endofstripeflag = false;
+ sip->endofpageflag = false;
+ sip->pageinfoflag = false;
+ sip->endoffileflag = false;
+}
+
+/**********************************************************************/
+
+void initlinkedlist(LIST * lp)
+{
+ lp->first = NULL;
+ lp->last = NULL;
+ lp->tree = NULL;
+}
+
+LIST *litem_append(LIST * lp)
+{
+ LITEM *ip;
+ ip = xtalloc(1, LITEM);
+ if (lp->first == NULL) {
+ lp->first = ip;
+ ip->prev = NULL;
+ } else {
+ lp->last->next = ip;
+ ip->prev = lp->last;
+ }
+ lp->last = ip;
+ ip->next = NULL;
+ ip->d = NULL;
+ return lp;
+}
+
+/**********************************************************************/
+
+void pages_maketree(LIST * plp)
+{
+ LITEM *ip;
+ void **aa;
+ assert(plp->tree == NULL);
+ plp->tree = avl_create(comp_page_entry, NULL, &avl_xallocator);
+ assert(plp->tree != NULL);
+ for (ip = plp->first; ip != NULL; ip = ip->next) {
+ aa = avl_probe(plp->tree, (PAGEINFO *) ip->d);
+ assert(aa != NULL);
+ }
+}
+
+void segments_maketree(LIST * slp)
+{
+ LITEM *ip;
+ void **aa;
+ assert(slp->tree == NULL);
+ slp->tree = avl_create(comp_segment_entry, NULL, &avl_xallocator);
+ assert(slp->tree != NULL);
+ for (ip = slp->first; ip != NULL; ip = ip->next) {
+ aa = avl_probe(slp->tree, (SEGINFO *) ip->d);
+ assert(aa != NULL);
+ }
+}
+
+/**********************************************************************/
+
+PAGEINFO *find_pageinfo(LIST * plp, unsigned long pagenum)
+{
+ PAGEINFO tmp;
+ tmp.pagenum = pagenum;
+ assert(plp->tree != NULL);
+ return (PAGEINFO *) avl_find(plp->tree, &tmp);
+}
+
+SEGINFO *find_seginfo(LIST * slp, unsigned long segnum)
+{
+ SEGINFO tmp;
+ tmp.segnum = segnum;
+ assert(slp->tree != NULL);
+ return (SEGINFO *) avl_find(slp->tree, &tmp);
+}
+
+/**********************************************************************/
+
+unsigned int read2bytes(FILE * f)
+{
+ unsigned int c = ygetc(f);
+ return (c << 8) + ygetc(f);
+}
+
+unsigned long read4bytes(FILE * f)
+{
+ unsigned int l = read2bytes(f);
+ return (l << 16) + read2bytes(f);
+}
+
+/**********************************************************************/
+
+unsigned long getstreamlen(LITEM * slip, boolean refer)
+{
+ SEGINFO *sip;
+ unsigned long len = 0;
+ for (; slip != NULL; slip = slip->next) {
+ sip = slip->d;
+ if (refer || sip->isrefered)
+ len += sip->hdrend - sip->hdrstart + sip->dataend - sip->datastart;
+ }
+ return len;
+}
+
+/**********************************************************************/
+
+void readfilehdr(FILEINFO * fip)
+{
+ unsigned int i;
+ /* Annex D.4 File header syntax */
+ /* Annex D.4.1 ID string */
+ unsigned char jbig2_id[] = { 0x97, 'J', 'B', '2', 0x0d, 0x0a, 0x1a, 0x0a };
+ xfseek(fip->file, 0, SEEK_SET, fip->filepath);
+ for (i = 0; i < 8; i++)
+ if (ygetc(fip->file) != jbig2_id[i])
+ pdftex_fail
+ ("readfilehdr(): reading JBIG2 image file failed: ID string missing");
+ /* Annex D.4.2 File header flags */
+ fip->filehdrflags = 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);
+ fip->filesize = xftell(fip->file, fip->filepath);
+ xfseek(fip->file, 9, SEEK_SET, fip->filepath);
+ }
+ /* Annex D.4.3 Number of pages */
+ if (!(fip->filehdrflags >> 1) & 0x01) /* known number of pages */
+ fip->numofpages = read4bytes(fip->file);
+ /* --- at end of file header --- */
+}
+
+/**********************************************************************/
+/* for first reading of file; return value tells if header been read */
+
+boolean readseghdr(FILEINFO * fip, SEGINFO * sip)
+{
+ unsigned int i;
+ sip->hdrstart = xftell(fip->file, fip->filepath);
+ if (fip->sequentialaccess && sip->hdrstart == fip->filesize)
+ return false; /* no endoffileflag is ok for sequentialaccess */
+#ifdef DEBUG
+ printf("\nhdrstart %d\n", sip->hdrstart);
+#endif
+ /* 7.2.2 Segment number */
+ sip->segnum = read4bytes(fip->file);
+#ifdef DEBUG
+ printf(" segnum %d\n", sip->segnum);
+#endif
+ /* 7.2.3 Segment header flags */
+ sip->seghdrflags = ygetc(fip->file);
+#ifdef DEBUG
+ printf(" hdrflags %d\n", sip->seghdrflags & 0x3f);
+#endif
+ checkseghdrflags(sip);
+ if (fip->sequentialaccess && sip->endoffileflag) /* accept shorter segment, */
+ return true; /* makes it compliant with Example 3.4 of PDFRef. 5th ed. */
+ sip->pageassocsizeflag = ((sip->seghdrflags >> 6) & 0x01) ? true : false;
+ /* 7.2.4 Referred-to segment count and retention flags */
+ sip->reftosegcount = (unsigned int) ygetc(fip->file);
+ sip->countofrefered = sip->reftosegcount >> 5;
+ if (sip->countofrefered < 5)
+ sip->fieldlen = 1;
+ else {
+ sip->fieldlen = 5 + sip->countofrefered / 8;
+ xfseek(fip->file, sip->fieldlen - 1, SEEK_CUR, fip->filepath);
+ }
+ /* 7.2.5 Referred-to segment numbers */
+ if (sip->segnum <= 256)
+ sip->segnumwidth = 1;
+ else if (sip->segnum <= 65536)
+ sip->segnumwidth = 2;
+ else
+ sip->segnumwidth = 4;
+ for (i = 0; i < sip->countofrefered; i++) {
+ switch (sip->segnumwidth) {
+ case 1:
+ (void) ygetc(fip->file);
+ break;
+ case 2:
+ (void) read2bytes(fip->file);
+ break;
+ case 4:
+ (void) read4bytes(fip->file);
+ break;
+ }
+ }
+ /* 7.2.6 Segment page association */
+ if (sip->pageassocsizeflag)
+ sip->segpage = read4bytes(fip->file);
+ else
+ sip->segpage = ygetc(fip->file);
+ /* 7.2.7 Segment data length */
+ sip->segdatalen = read4bytes(fip->file);
+ sip->hdrend = xftell(fip->file, fip->filepath);
+ /* ---- at end of segment header ---- */
+ return true;
+}
+
+/**********************************************************************/
+/* for writing, marks refered page0 segments, sets segpage > 0 to 1 */
+
+void writeseghdr(FILEINFO * fip, SEGINFO * sip)
+{
+ unsigned int i;
+ unsigned long referedseg = 0;
+ /* 7.2.2 Segment number */
+ /* 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));
+ /* 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);
+ break;
+ case 2:
+ referedseg = read2bytes(fip->file);
+ pdfout((referedseg >> 8) & 0xff);
+ pdfout(referedseg & 0xff);
+ break;
+ case 4:
+ referedseg = read4bytes(fip->file);
+ pdfout((referedseg >> 24) & 0xff);
+ pdfout((referedseg >> 16) & 0xff);
+ pdfout((referedseg >> 8) & 0xff);
+ pdfout(referedseg & 0xff);
+ break;
+ }
+ if (fip->page0.last != NULL && !sip->refers)
+ markpage0seg(fip, referedseg);
+ }
+ if (sip->countofrefered > 0)
+ sip->refers = true;
+ /* 7.2.6 Segment page association */
+ if (sip->pageassocsizeflag)
+ for (i = 0; i < 3; i++) {
+ (void) ygetc(fip->file);
+ pdfout(0);
+ }
+ (void) ygetc(fip->file);
+ pdfout((sip->segpage > 0) ? 1 : 0);
+ /* 7.2.7 Segment data length */
+ for (i = 0; i < 4; i++)
+ pdfout(ygetc(fip->file));
+ /* ---- at end of segment header ---- */
+}
+
+/**********************************************************************/
+/* for recursive marking of refered page0 segments */
+
+void checkseghdr(FILEINFO * fip, SEGINFO * sip)
+{
+ unsigned int i;
+ unsigned long referedseg = 0;
+ /* 7.2.2 Segment number */
+ /* 7.2.3 Segment header flags */
+ /* 7.2.4 Referred-to segment count and retention flags */
+ xfseek(fip->file, 5 + sip->fieldlen, SEEK_CUR, fip->filepath);
+ /* 7.2.5 Referred-to segment numbers */
+ for (i = 0; i < sip->countofrefered; i++) {
+ switch (sip->segnumwidth) {
+ case 1:
+ referedseg = ygetc(fip->file);
+ break;
+ case 2:
+ referedseg = read2bytes(fip->file);
+ break;
+ case 4:
+ referedseg = read4bytes(fip->file);
+ break;
+ }
+ if (!sip->refers)
+ markpage0seg(fip, referedseg);
+ }
+ if (sip->countofrefered > 0)
+ sip->refers = true;
+ /* 7.2.6 Segment page association */
+ /* 7.2.7 Segment data length */
+ if (sip->pageassocsizeflag)
+ xfseek(fip->file, 8, SEEK_CUR, fip->filepath);
+ else
+ xfseek(fip->file, 5, SEEK_CUR, fip->filepath);
+ /* ---- at end of segment header ---- */
+}
+
+/**********************************************************************/
+
+void checkseghdrflags(SEGINFO * sip)
+{
+ sip->endofstripeflag = false;
+ sip->endofpageflag = false;
+ sip->pageinfoflag = false;
+ sip->endoffileflag = false;
+ /* 7.3 Segment types */
+ switch (sip->seghdrflags & 0x3f) {
+ case M_SymbolDictionary:
+ case M_IntermediateTextRegion:
+ case M_ImmediateTextRegion:
+ case M_ImmediateLosslessTextRegion:
+ case M_PatternDictionary:
+ case M_IntermediateHalftoneRegion:
+ case M_ImmediateHalftoneRegion:
+ case M_ImmediateLosslessHalftoneRegion:
+ case M_IntermediateGenericRegion:
+ case M_ImmediateGenericRegion:
+ case M_ImmediateLosslessGenericRegion:
+ case M_IntermediateGenericRefinementRegion:
+ case M_ImmediateGenericRefinementRegion:
+ case M_ImmediateLosslessGenericRefinementRegion:
+ break;
+ case M_PageInformation:
+ sip->pageinfoflag = true;
+ break;
+ case M_EndOfPage:
+ sip->endofpageflag = true;
+ break;
+ case M_EndOfStripe:
+ sip->endofstripeflag = true;
+ break;
+ case M_EndOfFile:
+ sip->endoffileflag = true;
+ break;
+ case M_Profiles:
+ case M_Tables:
+ case M_Extension:
+ break;
+ default:
+ pdftex_fail
+ ("checkseghdrflags(): unknown segment type in JBIG2 image file");
+ break;
+ }
+}
+
+/**********************************************************************/
+
+void markpage0seg(FILEINFO * fip, unsigned long referedseg)
+{
+ PAGEINFO *pip;
+ SEGINFO *sip;
+ pip = fip->page0.first->d;
+ sip = find_seginfo(&(pip->segments), referedseg);
+ if (sip != NULL) {
+ if (!sip->refers && sip->countofrefered > 0)
+ checkseghdr(fip, sip);
+ sip->isrefered = true;
+ }
+}
+
+/**********************************************************************/
+
+unsigned long findstreamstart(FILEINFO * fip)
+{
+ SEGINFO tmp;
+ assert(!fip->sequentialaccess); /* D.2 Random-access organisation */
+ do /* find random-access stream start */
+ (void) readseghdr(fip, &tmp);
+ while (!tmp.endoffileflag);
+ fip->streamstart = tmp.hdrend;
+ readfilehdr(fip);
+ return fip->streamstart;
+}
+
+/**********************************************************************/
+
+void rd_jbig2_info(FILEINFO * fip)
+{
+ unsigned long seekdist = 0; /* for sequential-access only */
+ unsigned long streampos = 0; /* for random-access only */
+ unsigned long currentpage = 0;
+ boolean sipavail = false;
+ PAGEINFO *pip;
+ SEGINFO *sip = NULL;
+ LIST *plp, *slp;
+ fip->file = xfopen(fip->filepath, FOPEN_RBIN_MODE);
+ readfilehdr(fip);
+ if (!fip->sequentialaccess) /* D.2 Random-access organisation */
+ streampos = findstreamstart(fip);
+ while (true) { /* loop over segments */
+ if (!sipavail) {
+ sip = xtalloc(1, SEGINFO);
+ sipavail = true;
+ }
+ init_seginfo(sip);
+ if (!readseghdr(fip, sip) || sip->endoffileflag)
+ break;
+ if (sip->segpage > 0) {
+ if (sip->segpage > currentpage) {
+ plp = litem_append(&(fip->pages));
+ plp->last->d = new_pageinfo();
+ currentpage = sip->segpage;
+ }
+ pip = fip->pages.last->d;
+ } else {
+ if (fip->page0.last == NULL) {
+ plp = litem_append(&(fip->page0));
+ plp->last->d = new_pageinfo();
+ }
+ pip = fip->page0.last->d;
+ }
+ if (!sip->endofpageflag) {
+ slp = litem_append(&(pip->segments));
+ slp->last->d = sip;
+ sipavail = false;
+ }
+ if (!fip->sequentialaccess)
+ sip->datastart = streampos;
+ else
+ sip->datastart = sip->hdrend;
+ sip->dataend = sip->datastart + sip->segdatalen;
+ if (!fip->sequentialaccess
+ && (sip->pageinfoflag || sip->endofstripeflag))
+ xfseek(fip->file, 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);
+ /* 7.4.8.6 Page striping information */
+ pip->stripinginfo = read2bytes(fip->file);
+ seekdist -= 19;
+ }
+ if (sip->endofstripeflag) {
+ pip->stripedheight = read4bytes(fip->file);
+ seekdist -= 4;
+ }
+ if (!fip->sequentialaccess
+ && (sip->pageinfoflag || sip->endofstripeflag))
+ xfseek(fip->file, sip->hdrend, SEEK_SET, fip->filepath);
+ if (!fip->sequentialaccess)
+ streampos += sip->segdatalen;
+ if (fip->sequentialaccess)
+ xfseek(fip->file, seekdist, SEEK_CUR, fip->filepath);
+ if (sip->endofpageflag && currentpage && (pip->stripinginfo >> 15))
+ pip->height = pip->stripedheight;
+ }
+ fip->phase = HAVEINFO;
+ if (sipavail)
+ xfree(sip);
+ xfclose(fip->file, fip->filepath);
+}
+
+/**********************************************************************/
+
+void wr_jbig2(FILEINFO * fip, unsigned long page)
+{
+ LITEM *slip;
+ PAGEINFO *pip;
+ SEGINFO *sip;
+ unsigned long i;
+ 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");
+ if (fip->page0.last != NULL) {
+ if (fip->pdfpage0objnum == 0) {
+ pdf_create_obj(0, 0);
+ fip->pdfpage0objnum = obj_ptr;
+ }
+ pdf_printf("/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_puts(">>\n");
+ pdf_puts("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) {
+ xfseek(fip->file, sip->hdrstart, SEEK_SET, fip->filepath);
+ /* mark refered-to page 0 segments, change segpages > 1 to 1 */
+ writeseghdr(fip, sip);
+ xfseek(fip->file, sip->datastart, SEEK_SET, fip->filepath);
+ for (i = sip->datastart; i < sip->dataend; i++)
+ pdfout(ygetc(fip->file));
+ }
+ }
+ pdf_end_stream();
+ xfclose(fip->file, fip->filepath);
+}
+
+/**********************************************************************/
+
+void read_jbig2_info(image_dict * idict)
+{
+ FILEINFO *fip, tmp;
+ PAGEINFO *pip;
+ void **aa;
+ assert(idict != NULL);
+ img_type(idict) = IMAGE_TYPE_JBIG2;
+ if (img_pagenum(idict) < 1)
+ pdftex_fail
+ ("read_jbig2_info(): page %d not in JBIG2 image file; page must be > 0",
+ (int) img_pagenum(idict));
+ if (file_tree == NULL) {
+ file_tree = avl_create(comp_file_entry, NULL, &avl_xallocator);
+ assert(file_tree != NULL);
+ }
+ tmp.filepath = img_filepath(idict);
+ fip = (FILEINFO *) avl_find(file_tree, &tmp);
+ if (fip == NULL) {
+ fip = new_fileinfo();
+ fip->filepath = xstrdup(img_filepath(idict));
+ aa = avl_probe(file_tree, fip);
+ assert(aa != NULL);
+ }
+ if (fip->phase == INITIAL) {
+ rd_jbig2_info(fip);
+ pages_maketree(&(fip->pages));
+ if (fip->page0.last != NULL) {
+ pages_maketree(&(fip->page0));
+ pip = fip->page0.first->d;
+ segments_maketree(&(pip->segments));
+ }
+ }
+ pip = find_pageinfo(&(fip->pages), img_pagenum(idict));
+ if (pip == NULL)
+ pdftex_fail("read_jbig2_info(): page %d not found in JBIG2 image file",
+ (int) img_pagenum(idict));
+ img_xsize(idict) = pip->width;
+ img_ysize(idict) = 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)
+{
+ FILEINFO *fip, tmp;
+ PAGEINFO *pip;
+ assert(idict != NULL);
+ assert(file_tree != NULL);
+ 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(pip != NULL);
+ wr_jbig2(fip, pip->pagenum);
+ img_file(idict) = NULL;
+}
+
+/**********************************************************************/
+
+void flush_jbig2_page0_objects()
+{
+ FILEINFO *fip;
+ struct avl_traverser t;
+ if (file_tree != NULL) {
+ avl_t_init(&t, file_tree);
+ for (fip = avl_t_first(&t, file_tree); fip != NULL;
+ fip = avl_t_next(&t)) {
+ if (fip->page0.last != NULL)
+ wr_jbig2(fip, 0);
+ }
+ }
+}
+
+/**********************************************************************/
diff --git a/Build/source/texk/web2c/luatexdir/image/writejbig2.h b/Build/source/texk/web2c/luatexdir/image/writejbig2.h
new file mode 100644
index 00000000000..c1bec32d859
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/writejbig2.h
@@ -0,0 +1,151 @@
+/***********************************************************************
+Copyright (c) 2002-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX 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 General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with pdfTeX; if not, write to the Free Software Foundation, Inc., 59
+Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+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.
+
+$Id: writejbig2.h 1012 2008-02-14 00:00:57Z oneiros $
+***********************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include "ptexlib.h"
+#include "ptexmac.h"
+#include "image.h"
+
+/* 7.3 Segment types */
+#define M_SymbolDictionary 0
+#define M_IntermediateTextRegion 4
+#define M_ImmediateTextRegion 6
+#define M_ImmediateLosslessTextRegion 7
+#define M_PatternDictionary 16
+#define M_IntermediateHalftoneRegion 20
+#define M_ImmediateHalftoneRegion 22
+#define M_ImmediateLosslessHalftoneRegion 23
+#define M_IntermediateGenericRegion 36
+#define M_ImmediateGenericRegion 38
+#define M_ImmediateLosslessGenericRegion 39
+#define M_IntermediateGenericRefinementRegion 40
+#define M_ImmediateGenericRefinementRegion 42
+#define M_ImmediateLosslessGenericRefinementRegion 43
+#define M_PageInformation 48
+#define M_EndOfPage 49
+#define M_EndOfStripe 50
+#define M_EndOfFile 51
+#define M_Profiles 52
+#define M_Tables 53
+#define M_Extension 62
+
+/**********************************************************************/
+
+typedef enum { INITIAL, HAVEINFO, WRITEPDF } PHASE;
+
+typedef struct _LITEM {
+ struct _LITEM *prev;
+ struct _LITEM *next;
+ void *d; /* data */
+} LITEM;
+
+typedef struct _LIST {
+ LITEM *first;
+ LITEM *last;
+ struct avl_table *tree;
+} LIST;
+
+typedef struct _SEGINFO {
+ unsigned long segnum;
+ boolean isrefered;
+ boolean refers;
+ unsigned int seghdrflags; /* set by readseghdr() */
+ boolean pageassocsizeflag; /* set by readseghdr() */
+ unsigned int reftosegcount; /* set by readseghdr() */
+ unsigned int countofrefered; /* set by readseghdr() */
+ unsigned int fieldlen; /* set by readseghdr() */
+ unsigned int segnumwidth; /* set by readseghdr() */
+ long segpage; /* set by readseghdr() */
+ unsigned long segdatalen; /* set by readseghdr() */
+ unsigned long hdrstart; /* set by readseghdr() */
+ unsigned long hdrend; /* set by readseghdr() */
+ unsigned long datastart;
+ unsigned long dataend;
+ boolean endofstripeflag; /* set by checkseghdrflags() */
+ boolean endofpageflag; /* set by checkseghdrflags() */
+ boolean pageinfoflag; /* set by checkseghdrflags() */
+ boolean endoffileflag; /* set by checkseghdrflags() */
+} SEGINFO;
+
+typedef struct _PAGEINFO {
+ LIST segments; /* segments associated with page */
+ unsigned long pagenum;
+ unsigned int width;
+ unsigned int height;
+ unsigned int xres;
+ unsigned int yres;
+ unsigned int pagesegmentflags;
+ unsigned int stripinginfo;
+ unsigned int stripedheight;
+} PAGEINFO;
+
+typedef struct _FILEINFO {
+ FILE *file;
+ char *filepath;
+ long filesize;
+ LIST pages; /* not including page0 */
+ LIST page0;
+ 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 pdfpage0objnum;
+ PHASE phase;
+} FILEINFO;
+
+/**********************************************************************/
+
+static int comp_file_entry(const void *, const void *, void *);
+static int comp_page_entry(const void *, const void *, void *);
+static int comp_segment_entry(const void *, const void *, void *);
+int ygetc(FILE *);
+FILEINFO *new_fileinfo();
+PAGEINFO *new_pageinfo();
+void initseginfo(SEGINFO *);
+void initlinkedlist(LIST *);
+LIST *litem_append(LIST *);
+void pages_maketree(LIST *);
+void segments_maketree(LIST *);
+PAGEINFO *find_pageinfo(LIST *, unsigned long);
+SEGINFO *find_seginfo(LIST *, unsigned long);
+unsigned int read2bytes(FILE *);
+unsigned long read4bytes(FILE *);
+unsigned long getstreamlen(LITEM *, boolean);
+void readfilehdr(FILEINFO *);
+boolean readseghdr(FILEINFO *, SEGINFO *);
+void writeseghdr(FILEINFO *, SEGINFO *);
+void checkseghdr(FILEINFO *, SEGINFO *);
+void checkseghdrflags(SEGINFO * sip);
+void markpage0seg(FILEINFO *, unsigned long);
+unsigned long findstreamstart(FILEINFO *);
+void rd_jbig2_info(FILEINFO *);
+void wr_jbig2(FILEINFO *, unsigned long);
+void read_jbig2_info(image_dict *);
+void write_jbig2(image_dict *);
+void flushjbig2page0objects();
+
+/**********************************************************************/
diff --git a/Build/source/texk/web2c/luatexdir/image/writejpg.c b/Build/source/texk/web2c/luatexdir/image/writejpg.c
new file mode 100644
index 00000000000..422c29470fb
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/writejpg.c
@@ -0,0 +1,277 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+pdfTeX 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.
+
+pdfTeX 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writejpg.c 1100 2008-03-09 13:40:48Z hhenkel $
+*/
+
+#include <assert.h>
+#include "ptexlib.h"
+#include "image.h"
+
+#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 */
+
+typedef enum { /* JPEG marker codes */
+ M_SOF0 = 0xc0, /* baseline DCT */
+ M_SOF1 = 0xc1, /* extended sequential DCT */
+ M_SOF2 = 0xc2, /* progressive DCT */
+ M_SOF3 = 0xc3, /* lossless (sequential) */
+
+ M_SOF5 = 0xc5, /* differential sequential DCT */
+ M_SOF6 = 0xc6, /* differential progressive DCT */
+ M_SOF7 = 0xc7, /* differential lossless */
+
+ M_JPG = 0xc8, /* JPEG extensions */
+ M_SOF9 = 0xc9, /* extended sequential DCT */
+ M_SOF10 = 0xca, /* progressive DCT */
+ M_SOF11 = 0xcb, /* lossless (sequential) */
+
+ M_SOF13 = 0xcd, /* differential sequential DCT */
+ M_SOF14 = 0xce, /* differential progressive DCT */
+ M_SOF15 = 0xcf, /* differential lossless */
+
+ M_DHT = 0xc4, /* define Huffman tables */
+
+ M_DAC = 0xcc, /* define arithmetic conditioning table */
+
+ M_RST0 = 0xd0, /* restart */
+ M_RST1 = 0xd1, /* restart */
+ M_RST2 = 0xd2, /* restart */
+ M_RST3 = 0xd3, /* restart */
+ M_RST4 = 0xd4, /* restart */
+ M_RST5 = 0xd5, /* restart */
+ M_RST6 = 0xd6, /* restart */
+ M_RST7 = 0xd7, /* restart */
+
+ M_SOI = 0xd8, /* start of image */
+ M_EOI = 0xd9, /* end of image */
+ M_SOS = 0xda, /* start of scan */
+ M_DQT = 0xdb, /* define quantization tables */
+ M_DNL = 0xdc, /* define number of lines */
+ M_DRI = 0xdd, /* define restart interval */
+ M_DHP = 0xde, /* define hierarchical progression */
+ M_EXP = 0xdf, /* expand reference image(s) */
+
+ M_APP0 = 0xe0, /* application marker, used for JFIF */
+ M_APP1 = 0xe1, /* application marker */
+ M_APP2 = 0xe2, /* application marker */
+ M_APP3 = 0xe3, /* application marker */
+ M_APP4 = 0xe4, /* application marker */
+ M_APP5 = 0xe5, /* application marker */
+ M_APP6 = 0xe6, /* application marker */
+ M_APP7 = 0xe7, /* application marker */
+ M_APP8 = 0xe8, /* application marker */
+ M_APP9 = 0xe9, /* application marker */
+ M_APP10 = 0xea, /* application marker */
+ M_APP11 = 0xeb, /* application marker */
+ M_APP12 = 0xec, /* application marker */
+ M_APP13 = 0xed, /* application marker */
+ M_APP14 = 0xee, /* application marker, used by Adobe */
+ M_APP15 = 0xef, /* application marker */
+
+ M_JPG0 = 0xf0, /* reserved for JPEG extensions */
+ M_JPG13 = 0xfd, /* reserved for JPEG extensions */
+ M_COM = 0xfe, /* comment */
+
+ M_TEM = 0x01, /* temporary use */
+
+ M_ERROR = 0x100 /* dummy marker, internal use only */
+} JPEG_MARKER;
+
+static JPG_UINT16 read2bytes(FILE * f)
+{
+ int c = xgetc(f);
+ return (c << 8) + xgetc(f);
+}
+
+void close_and_cleanup_jpg(image_dict * idict)
+{
+ assert(idict != NULL);
+ assert(img_file(idict) != NULL);
+ assert(img_filepath(idict) != NULL);
+ xfclose(img_file(idict), img_filepath(idict));
+ img_file(idict) = NULL;
+ assert(img_jpg_ptr(idict) != NULL);
+ xfree(img_jpg_ptr(idict));
+ img_jpg_ptr(idict) = NULL;
+}
+
+void read_jpg_info(image_dict * idict, img_readtype_e readtype)
+{
+ int i, units = 0;
+ unsigned char jpg_id[] = "JFIF";
+ assert(idict != NULL);
+ assert(img_type(idict) == IMAGE_TYPE_JPG);
+ img_totalpages(idict) = 1;
+ img_pagenum(idict) = 1;
+ img_xres(idict) = img_yres(idict) = 0;
+ assert(img_file(idict) == NULL);
+ img_file(idict) = xfopen(img_filepath(idict), FOPEN_RBIN_MODE);
+ assert(img_jpg_ptr(idict) == NULL);
+ img_jpg_ptr(idict) = xtalloc(1, jpg_img_struct);
+ xfseek(img_file(idict), 0, SEEK_END, img_filepath(idict));
+ img_jpg_ptr(idict)->length = xftell(img_file(idict), img_filepath(idict));
+ 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 */
+ if (read2bytes(img_file(idict)) == 0xFFE0) { /* check for JFIF */
+ (void) read2bytes(img_file(idict));
+ for (i = 0; i < 5; i++) {
+ if (xgetc(img_file(idict)) != jpg_id[i])
+ break;
+ }
+ 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));
+ switch (units) {
+ case 1:
+ break; /* pixels per inch */
+ case 2:
+ img_xres(idict) *= 2.54;
+ img_yres(idict) *= 2.54;
+ break; /* pixels per cm */
+ default:
+ img_xres(idict) = img_yres(idict) = 0;
+ break;
+ }
+ }
+ }
+ xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict));
+ while (1) {
+ if (feof(img_file(idict)))
+ pdftex_fail("reading JPEG image failed (premature file end)");
+ if (fgetc(img_file(idict)) != 0xFF)
+ pdftex_fail("reading JPEG image failed (no marker found)");
+ switch (xgetc(img_file(idict))) {
+ case M_SOF5:
+ case M_SOF6:
+ case M_SOF7:
+ case M_SOF9:
+ case M_SOF10:
+ case M_SOF11:
+ case M_SOF13:
+ case M_SOF14:
+ case M_SOF15:
+ pdftex_fail("unsupported type of compression");
+ case M_SOF2:
+ if (fixed_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_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;
+ break;
+ case JPG_RGB:
+ img_color(idict) = IMAGE_COLOR_C;
+ break;
+ case JPG_CMYK:
+ img_color(idict) = IMAGE_COLOR_C;
+ break;
+ default:
+ pdftex_fail("Unsupported color space %i",
+ (int) img_jpg_color(idict));
+ }
+ if (readtype == IMG_CLOSEINBETWEEN)
+ close_and_cleanup_jpg(idict);
+ return;
+ case M_SOI: /* ignore markers without parameters */
+ case M_EOI:
+ case M_TEM:
+ case M_RST0:
+ case M_RST1:
+ case M_RST2:
+ case M_RST3:
+ case M_RST4:
+ case M_RST5:
+ case M_RST6:
+ case M_RST7:
+ break;
+ default: /* skip variable length markers */
+ xfseek(img_file(idict), read2bytes(img_file(idict)) - 2,
+ SEEK_CUR, img_filepath(idict));
+ break;
+ }
+ }
+ assert(0);
+}
+
+static void reopen_jpg(image_dict * idict)
+{
+ integer 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);
+ 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)
+{
+ long unsigned l;
+ FILE *f;
+ assert(idict != NULL);
+ if (img_file(idict) == NULL)
+ reopen_jpg(idict);
+ assert(img_jpg_ptr(idict) != NULL);
+ pdf_puts("/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",
+ (int) img_xsize(idict),
+ (int) img_ysize(idict),
+ (int) img_colordepth(idict), (int) img_jpg_ptr(idict)->length);
+ pdf_puts("/ColorSpace ");
+ if (img_colorspace(idict) != 0) {
+ pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
+ } else {
+ switch (img_jpg_color(idict)) {
+ case JPG_GRAY:
+ pdf_puts("/DeviceGray\n");
+ break;
+ case JPG_RGB:
+ pdf_puts("/DeviceRGB\n");
+ break;
+ case JPG_CMYK:
+ pdf_puts("/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");
+ for (l = img_jpg_ptr(idict)->length, f = img_file(idict); l > 0; l--)
+ pdfout(xgetc(f));
+ pdf_end_stream();
+ close_and_cleanup_jpg(idict);
+}
diff --git a/Build/source/texk/web2c/luatexdir/image/writepng.c b/Build/source/texk/web2c/luatexdir/image/writepng.c
new file mode 100644
index 00000000000..7f1269d9943
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/writepng.c
@@ -0,0 +1,635 @@
+/*
+Copyright (c) 1996-2004 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX 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.
+
+pdfTeX 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writepng.c 1101 2008-03-09 16:12:15Z hhenkel $
+*/
+
+#include <assert.h>
+#include "ptexlib.h"
+#include "image.h"
+
+void close_and_cleanup_png(image_dict * idict)
+{
+ assert(idict != NULL);
+ assert(img_file(idict) != NULL);
+ assert(img_filepath(idict) != NULL);
+ xfclose(img_file(idict), img_filepath(idict));
+ img_file(idict) = NULL;
+ assert(img_png_ptr(idict) != NULL);
+ png_destroy_read_struct(&(img_png_png_ptr(idict)),
+ &(img_png_info_ptr(idict)), NULL);
+ xfree(img_png_ptr(idict));
+ img_png_ptr(idict) = NULL;
+}
+
+void read_png_info(image_dict * idict, img_readtype_e readtype)
+{
+ double gamma;
+ png_structp png_p;
+ png_infop info_p;
+ assert(idict != NULL);
+ assert(img_type(idict) == IMAGE_TYPE_PNG);
+ img_totalpages(idict) = 1;
+ img_pagenum(idict) = 1;
+ img_xres(idict) = img_yres(idict) = 0;
+ assert(img_file(idict) == NULL);
+ img_file(idict) = xfopen(img_filepath(idict), FOPEN_RBIN_MODE);
+ assert(img_png_ptr(idict) == NULL);
+ img_png_ptr(idict) = xtalloc(1, png_img_struct);
+ if ((png_p = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL)) == NULL)
+ pdftex_fail("libpng: png_create_read_struct() failed");
+ img_png_png_ptr(idict) = png_p;
+ if ((info_p = png_create_info_struct(png_p)) == NULL)
+ pdftex_fail("libpng: png_create_info_struct() failed");
+ img_png_info_ptr(idict) = info_p;
+ if (setjmp(png_p->jmpbuf))
+ pdftex_fail("libpng: internal error");
+ png_init_io(png_p, img_file(idict));
+ png_read_info(png_p, info_p);
+ /* simple transparency support */
+ if (png_get_valid(png_p, info_p, PNG_INFO_tRNS)) {
+ png_set_tRNS_to_alpha(png_p);
+ }
+ /* alpha channel support */
+ if (fixed_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)
+ png_set_strip_16(png_p);
+ /* gamma support */
+ if (fixed_image_apply_gamma) {
+ if (png_get_gAMA(png_p, info_p, &gamma))
+ png_set_gamma(png_p, (fixed_gamma / 1000.0), gamma);
+ else
+ png_set_gamma(png_p, (fixed_gamma / 1000.0),
+ (1000.0 / fixed_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;
+ if (info_p->valid & PNG_INFO_pHYs) {
+ img_xres(idict) =
+ round(0.0254 * 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));
+ }
+ switch (info_p->color_type) {
+ case PNG_COLOR_TYPE_PALETTE:
+ img_color(idict) = IMAGE_COLOR_C | IMAGE_COLOR_I;
+ break;
+ case PNG_COLOR_TYPE_GRAY:
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ img_color(idict) = IMAGE_COLOR_B;
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ img_color(idict) = IMAGE_COLOR_C;
+ break;
+ default:
+ pdftex_fail("unsupported type of color_type <%i>", info_p->color_type);
+ }
+ img_colordepth(idict) = info_p->bit_depth;
+ if (readtype == IMG_CLOSEINBETWEEN)
+ close_and_cleanup_png(idict);
+}
+
+#define write_gray_pixel_16(r) \
+ if (j % 4 == 0||j % 4 == 1) pdf_buf[pdf_ptr++] = *r++; \
+ else smask[smask_ptr++] = *r++
+
+#define write_gray_pixel_8(r) \
+ if (j % 2 == 0) pdf_buf[pdf_ptr++] = *r++; \
+ else smask[smask_ptr++] = *r++
+
+
+#define write_rgb_pixel_16(r) \
+ if (!(j % 8 == 6||j % 8 == 7)) pdf_buf[pdf_ptr++] = *r++; \
+ else smask[smask_ptr++] = *r++
+
+#define write_rgb_pixel_8(r) \
+ if (j % 4 != 3) pdf_buf[pdf_ptr++] = *r++; \
+ else smask[smask_ptr++] = *r++
+
+#define write_simple_pixel(r) pdf_buf[pdf_ptr++] = *r++
+
+#define write_noninterlaced(outmac) \
+ for (i = 0; (unsigned) i < (int)info_p->height; i++) { \
+ png_read_row(png_p, row, NULL); \
+ r = row; \
+ k = info_p->rowbytes; \
+ while(k > 0) { \
+ l = (k > pdf_buf_size)? pdf_buf_size : k; \
+ pdfroom(l); \
+ for (j = 0; j < l; j++) { \
+ outmac; \
+ } \
+ k -= l; \
+ } \
+ }
+
+#define write_interlaced(outmac) \
+ for (i = 0; (unsigned) i < (int)info_p->height; i++) { \
+ row = rows[i]; \
+ k = info_p->rowbytes; \
+ while(k > 0) { \
+ l = (k > pdf_buf_size)? pdf_buf_size : k;\
+ pdfroom(l); \
+ for (j = 0; j < l; j++) { \
+ outmac; \
+ } \
+ k -= l; \
+ } \
+ xfree(rows[i]); \
+ }
+
+void write_png_palette(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;
+ if (img_colorspace(idict) != 0) {
+ pdf_printf("%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",
+ (int) (info_p->num_palette - 1), (int) palette_objnum);
+ }
+ pdf_begin_stream();
+ if (info_p->interlace_type == PNG_INTERLACE_NONE) {
+ row = xtalloc(info_p->rowbytes, png_byte);
+ write_noninterlaced(write_simple_pixel(r));
+ xfree(row);
+ } else {
+ if (info_p->height * info_p->rowbytes >= 10240000L)
+ pdftex_warn
+ ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
+ rows = xtalloc(info_p->height, png_bytep);
+ for (i = 0; (unsigned) i < info_p->height; i++)
+ rows[i] = xtalloc(info_p->rowbytes, png_byte);
+ png_read_image(png_p, rows);
+ write_interlaced(write_simple_pixel(row));
+ xfree(rows);
+ }
+ pdf_end_stream();
+ if (palette_objnum > 0) {
+ pdf_begin_dict(palette_objnum, 0);
+ pdf_begin_stream();
+ 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_end_stream();
+ }
+}
+
+void write_png_gray(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));
+ } else {
+ pdf_puts("/DeviceGray\n");
+ }
+ pdf_begin_stream();
+ if (info_p->interlace_type == PNG_INTERLACE_NONE) {
+ row = xtalloc(info_p->rowbytes, png_byte);
+ write_noninterlaced(write_simple_pixel(r));
+ xfree(row);
+ } else {
+ if (info_p->height * info_p->rowbytes >= 10240000L)
+ pdftex_warn
+ ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
+ rows = xtalloc(info_p->height, png_bytep);
+ for (i = 0; (unsigned) i < info_p->height; i++)
+ rows[i] = xtalloc(info_p->rowbytes, png_byte);
+ png_read_image(png_p, rows);
+ write_interlaced(write_simple_pixel(row));
+ xfree(rows);
+ }
+ pdf_end_stream();
+}
+
+void write_png_gray_alpha(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;
+ png_bytep smask;
+ integer smask_ptr = 0;
+ integer smask_size = 0;
+ int bitdepth;
+ if (img_colorspace(idict) != 0) {
+ pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
+ } else {
+ pdf_puts("/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();
+ if (info_p->interlace_type == PNG_INTERLACE_NONE) {
+ row = xtalloc(info_p->rowbytes, png_byte);
+ if ((info_p->bit_depth == 16) && fixed_image_hicolor) {
+ write_noninterlaced(write_gray_pixel_16(r));
+ } else {
+ write_noninterlaced(write_gray_pixel_8(r));
+ }
+ xfree(row);
+ } else {
+ if (info_p->height * info_p->rowbytes >= 10240000L)
+ pdftex_warn
+ ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
+ rows = xtalloc(info_p->height, png_bytep);
+ 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) {
+ write_interlaced(write_gray_pixel_16(row));
+ } else {
+ write_interlaced(write_gray_pixel_8(row));
+ }
+ xfree(rows);
+ }
+ pdf_end_stream();
+ pdf_flush();
+ /* 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");
+ 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",
+ (int) info_p->width,
+ (int) info_p->height, (bitdepth == 16 ? 8 : bitdepth));
+ pdf_puts("/ColorSpace /DeviceGray\n");
+ pdf_begin_stream();
+ for (i = 0; i < smask_size; i++) {
+ if (i % 8 == 0)
+ pdfroom(8);
+ pdf_buf[pdf_ptr++] = smask[i];
+ if (bitdepth == 16)
+ i++;
+ }
+ pdf_end_stream();
+ xfree(smask);
+}
+
+void write_png_rgb(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));
+ } else {
+ pdf_puts("/DeviceRGB\n");
+ }
+ pdf_begin_stream();
+ if (info_p->interlace_type == PNG_INTERLACE_NONE) {
+ row = xtalloc(info_p->rowbytes, png_byte);
+ write_noninterlaced(write_simple_pixel(r));
+ xfree(row);
+ } else {
+ if (info_p->height * info_p->rowbytes >= 10240000L)
+ pdftex_warn
+ ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
+ rows = xtalloc(info_p->height, png_bytep);
+ for (i = 0; (unsigned) i < info_p->height; i++)
+ rows[i] = xtalloc(info_p->rowbytes, png_byte);
+ png_read_image(png_p, rows);
+ write_interlaced(write_simple_pixel(row));
+ xfree(rows);
+ }
+ pdf_end_stream();
+}
+
+void write_png_rgb_alpha(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;
+ png_bytep smask;
+ integer smask_ptr = 0;
+ integer smask_size = 0;
+ int bitdepth;
+ if (img_colorspace(idict) != 0) {
+ pdf_printf("%i 0 R\n", (int) img_colorspace(idict));
+ } else {
+ pdf_puts("/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();
+ if (info_p->interlace_type == PNG_INTERLACE_NONE) {
+ row = xtalloc(info_p->rowbytes, png_byte);
+ if ((info_p->bit_depth == 16) && fixed_image_hicolor) {
+ write_noninterlaced(write_rgb_pixel_16(r));
+ } else {
+ write_noninterlaced(write_rgb_pixel_8(r));
+ }
+ xfree(row);
+ } else {
+ if (info_p->height * info_p->rowbytes >= 10240000L)
+ pdftex_warn
+ ("large interlaced PNG might cause out of memory (use non-interlaced PNG to fix this)");
+ rows = xtalloc(info_p->height, png_bytep);
+ 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) {
+ write_interlaced(write_rgb_pixel_16(row));
+ } else {
+ write_interlaced(write_rgb_pixel_8(row));
+ }
+ xfree(rows);
+ }
+ pdf_end_stream();
+ pdf_flush();
+ /* 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");
+ if (img_attr(idict) != NULL)
+ pdf_printf("%s\n", img_attr(idict));
+ pdf_printf("/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();
+ for (i = 0; i < smask_size; i++) {
+ if (i % 8 == 0)
+ pdfroom(8);
+ pdf_buf[pdf_ptr++] = smask[i];
+ if (bitdepth == 16)
+ i++;
+ }
+ xfree(smask);
+ pdf_end_stream();
+ }
+}
+
+/**********************************************************************/
+/*
+ * 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"
+ */
+
+static int spng_getint(FILE * fp)
+{
+ unsigned char buf[4];
+ if (fread(buf, 1, 4, fp) != 4)
+ pdftex_fail("writepng: reading chunk type failed");
+ return ((((((int) buf[0] << 8) + buf[1]) << 8) + buf[2]) << 8) + buf[3];
+}
+
+#define SPNG_CHUNK_IDAT 0x49444154
+#define SPNG_CHUNK_IEND 0x49454E44
+
+void copy_png(image_dict * idict)
+{
+ assert(idict != NULL);
+ png_structp png_p = img_png_png_ptr(idict);
+ png_infop info_p = img_png_info_ptr(idict);
+ FILE *fp = (FILE *) png_p->io_ptr;
+ int i, len, type, streamlength = 0;
+ boolean endflag = false;
+ int idat = 0; /* flag to check continuous IDAT chunks sequence */
+ /* 1st pass to find overall stream /Length */
+ if (fseek(fp, 8, SEEK_SET) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed");
+ do {
+ len = spng_getint(fp);
+ type = spng_getint(fp);
+ switch (type) {
+ case SPNG_CHUNK_IEND:
+ endflag = true;
+ break;
+ case SPNG_CHUNK_IDAT:
+ streamlength += len;
+ default:
+ if (fseek(fp, len + 4, SEEK_CUR) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed");
+ }
+ } while (endflag == false);
+ pdf_printf("/Length %d\n", streamlength);
+ pdf_printf("/Filter /FlateDecode\n");
+ pdf_printf("/DecodeParms << ");
+ pdf_printf("/Colors %d ", info_p->color_type == 2 ? 3 : 1);
+ pdf_printf("/Columns %d ", (int) info_p->width);
+ pdf_printf("/BitsPerComponent %i ", (int) info_p->bit_depth);
+ pdf_printf("/Predictor %d ", 10); /* actual predictor defined on line basis */
+ pdf_printf(">>\n>>\nstream\n");
+ /* 2nd pass to copy data */
+ endflag = false;
+ if (fseek(fp, 8, SEEK_SET) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed");
+ do {
+ len = spng_getint(fp);
+ type = spng_getint(fp);
+ switch (type) {
+ case SPNG_CHUNK_IDAT: /* do copy */
+ if (idat == 2)
+ 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;
+ 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();
+ endflag = true;
+ break;
+ default:
+ if (idat == 1)
+ idat = 2;
+ if (fseek(fp, len + 4, SEEK_CUR) != 0)
+ pdftex_fail("writepng: fseek in PNG file failed");
+ }
+ } while (endflag == false);
+}
+
+void reopen_png(image_dict * idict)
+{
+ integer 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);
+ if (width != img_xsize(idict) || height != img_ysize(idict)
+ || xres != img_xres(idict) || yres != img_yres(idict))
+ pdftex_fail("writepng: image dimensions have changed");
+}
+
+void write_png(image_dict * idict)
+{
+ double gamma, checked_gamma;
+ int i;
+ integer palette_objnum = 0;
+ assert(idict != NULL);
+ if (img_file(idict) == NULL)
+ reopen_png(idict);
+ assert(img_png_ptr(idict) != NULL);
+ png_structp png_p = img_png_png_ptr(idict);
+ png_infop 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 (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",
+ (int) info_p->width,
+ (int) info_p->height, (int) info_p->bit_depth);
+ pdf_puts("/ColorSpace ");
+ checked_gamma = 1.0;
+ if (fixed_image_apply_gamma) {
+ if (png_get_gAMA(png_p, info_p, &gamma)) {
+ checked_gamma = (fixed_gamma / 1000.0) * gamma;
+ } else {
+ checked_gamma =
+ (fixed_gamma / 1000.0) * (1000.0 / fixed_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 */
+ &&!(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))
+ && (checked_gamma <= 1.01 && checked_gamma > 0.99)
+ ) {
+ if (img_colorspace(idict) != 0) {
+ pdf_printf("%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",
+ (int) (info_p->num_palette - 1),
+ (int) palette_objnum);
+ break;
+ case PNG_COLOR_TYPE_GRAY:
+ pdf_puts("/DeviceGray\n");
+ break;
+ default: /* RGB */
+ pdf_puts("/DeviceRGB\n");
+ };
+ }
+ if (tracefilenames)
+ tex_printf(" (PNG copy)");
+ copy_png(idict);
+ if (palette_objnum > 0) {
+ pdf_begin_dict(palette_objnum, 0);
+ pdf_begin_stream();
+ 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_end_stream();
+ }
+ } else {
+ if (0) {
+ tex_printf(" PNG copy skipped because: ");
+ if (fixed_image_apply_gamma &&
+ (checked_gamma > 1.01 || checked_gamma < 0.99))
+ tex_printf("gamma delta=%lf ", checked_gamma);
+ if (png_p->transformations != PNG_TRANSFORM_IDENTITY)
+ tex_printf("transform=%lu", (long) png_p->transformations);
+ if ((info_p->color_type != PNG_COLOR_TYPE_GRAY)
+ && (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 (info_p->interlace_type != PNG_INTERLACE_NONE)
+ tex_printf("interlaced ");
+ if (info_p->bit_depth > 8)
+ tex_printf("bitdepth=%d ", info_p->bit_depth);
+ if (png_get_valid(png_p, info_p, PNG_INFO_tRNS))
+ tex_printf("simple transparancy ");
+ }
+ switch (info_p->color_type) {
+ case PNG_COLOR_TYPE_PALETTE:
+ write_png_palette(idict);
+ break;
+ case PNG_COLOR_TYPE_GRAY:
+ write_png_gray(idict);
+ break;
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ if (fixed_pdf_minor_version >= 4)
+ write_png_gray_alpha(idict);
+ else
+ write_png_gray(idict);
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ write_png_rgb(idict);
+ break;
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ if (fixed_pdf_minor_version >= 4)
+ write_png_rgb_alpha(idict);
+ else
+ write_png_rgb(idict);
+ break;
+ default:
+ pdftex_fail("unsupported type of color_type <%i>",
+ info_p->color_type);
+ }
+ }
+ pdf_flush();
+ close_and_cleanup_png(idict);
+}