summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/image
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/image')
-rw-r--r--Build/source/texk/web2c/luatexdir/image/pdftoepdf.c1049
-rw-r--r--Build/source/texk/web2c/luatexdir/image/pdftoepdf.w972
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writeimg.c (renamed from Build/source/texk/web2c/luatexdir/image/writeimg.w)415
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writejbig2.c (renamed from Build/source/texk/web2c/luatexdir/image/writejbig2.w)279
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writejp2.c (renamed from Build/source/texk/web2c/luatexdir/image/writejp2.w)85
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writejpg.c (renamed from Build/source/texk/web2c/luatexdir/image/writejpg.w)256
-rw-r--r--Build/source/texk/web2c/luatexdir/image/writepng.c (renamed from Build/source/texk/web2c/luatexdir/image/writepng.w)173
7 files changed, 1656 insertions, 1573 deletions
diff --git a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.c b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.c
new file mode 100644
index 00000000000..b29493b073d
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.c
@@ -0,0 +1,1049 @@
+/*
+pdftoepdf.w
+
+Copyright 1996-2006 Han The Thanh <thanh@pdftex.org>
+Copyright 2006-2015 Taco Hoekwater <taco@luatex.org>
+
+This file is part of LuaTeX.
+
+LuaTeX is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+LuaTeX is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU General Public License along
+with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define __STDC_FORMAT_MACROS /* for PRId64 etc. */
+
+#include "image/epdf.h"
+
+/* Conflict with pdfgen.h */
+
+#ifndef pdf_out
+
+#define pdf_out(pdf, A) do { pdf_room(pdf, 1); *(pdf->buf->p++) = A; } while (0)
+
+#define pdf_check_space(pdf) do { \
+ if (pdf->cave > 0) { \
+ pdf_out(pdf, ' '); \
+ pdf->cave = 0; \
+ } \
+} while (0)
+
+#define pdf_set_space(pdf) \
+ pdf->cave = 1;
+
+#define pdf_reset_space(pdf) \
+ pdf->cave = 0;
+
+#endif
+
+/* Maintain AVL tree of all PDF files for embedding */
+
+static avl_table *PdfDocumentTree = NULL;
+
+/* AVL sort PdfDocument into PdfDocumentTree by file_path */
+
+static int CompPdfDocument(const void *pa, const void *pb, void *p )
+{
+ return strcmp(((const PdfDocument *) pa)->file_path, ((const PdfDocument *) pb)->file_path);
+}
+
+/* Returns pointer to PdfDocument structure for PDF file. */
+
+static PdfDocument *findPdfDocument(char *file_path)
+{
+ PdfDocument *pdf_doc, tmp;
+ if (file_path == NULL) {
+ normal_error("pdf backend","empty filename when loading pdf file");
+ } else if (PdfDocumentTree == NULL) {
+ return NULL;
+ }
+ tmp.file_path = file_path;
+ pdf_doc = (PdfDocument *) avl_find(PdfDocumentTree, &tmp);
+ return pdf_doc;
+}
+
+#define PDF_CHECKSUM_SIZE 32
+
+static char *get_file_checksum(const char *a, file_error_mode fe)
+{
+ struct stat finfo;
+ char *ck = NULL;
+ if (stat(a, &finfo) == 0) {
+ off_t size = finfo.st_size;
+ time_t mtime = finfo.st_mtime;
+ ck = (char *) malloc(PDF_CHECKSUM_SIZE);
+ if (ck == NULL)
+ formatted_error("pdf inclusion","out of memory while processing '%s'", a);
+ snprintf(ck, PDF_CHECKSUM_SIZE, "%" PRIu64 "_%" PRIu64, (uint64_t) size,(uint64_t) mtime);
+ } else {
+ switch (fe) {
+ case FE_FAIL:
+ formatted_error("pdf inclusion","could not stat() file '%s'", a);
+ break;
+ case FE_RETURN_NULL:
+ if (ck != NULL)
+ free(ck);
+ ck = NULL;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ return ck;
+}
+
+static char *get_stream_checksum (const char *str, unsigned long long str_size){
+ /* http://www.cse.yorku.ca/~oz/hash.html */
+ /* djb2 */
+ unsigned long hash ;
+ char *ck = NULL;
+ unsigned int i;
+ hash = 5381;
+ ck = (char *) malloc(STRSTREAM_CHECKSUM_SIZE+1);
+ if (ck == NULL)
+ normal_error("pdf inclusion","out of memory while processing a memstream");
+ for(i=0; i<(unsigned int)(str_size); i++) {
+ hash = ((hash << 5) + hash) + str[i]; /* hash * 33 + str[i] */
+ }
+ snprintf(ck,STRSTREAM_CHECKSUM_SIZE+1,"%lx",hash);
+ ck[STRSTREAM_CHECKSUM_SIZE]='\0';
+ return ck;
+}
+
+/*
+ Returns pointer to PdfDocument structure for PDF file.
+ Creates a new PdfDocument structure if it doesn't exist yet.
+ When fe = FE_RETURN_NULL, the function returns NULL in error case.
+*/
+
+PdfDocument *refPdfDocument(const char *file_path, file_error_mode fe, const char *userpassword, const char *ownerpassword)
+{
+ char *checksum, *path_copy;
+ PdfDocument *pdf_doc;
+ ppdoc *pdfe = NULL;
+ int new_flag = 0;
+ if ((checksum = get_file_checksum(file_path, fe)) == NULL) {
+ return (PdfDocument *) NULL;
+ }
+ path_copy = xstrdup(file_path);
+ if ((pdf_doc = findPdfDocument(path_copy)) == NULL) {
+ new_flag = 1;
+ pdf_doc = (PdfDocument*) xmalloc(sizeof( PdfDocument));
+ pdf_doc->file_path = path_copy;
+ pdf_doc->checksum = checksum;
+ pdf_doc->pdfe = NULL;
+ pdf_doc->inObjList = NULL;
+ pdf_doc->ObjMapTree = NULL;
+ pdf_doc->occurences = 0; /* 0 = unreferenced */
+ pdf_doc->pc = 0;
+ pdf_doc->is_mem = 0;
+ } else {
+ if (strncmp(pdf_doc->checksum, checksum, PDF_CHECKSUM_SIZE) != 0) {
+ formatted_error("pdf inclusion","file has changed '%s'", file_path);
+ }
+ free(checksum);
+ free(path_copy);
+ }
+ if (pdf_doc->pdfe == NULL) {
+ pdfe = ppdoc_load(file_path);
+ pdf_doc->pc++;
+ /* todo: check if we might print the document */
+ if (pdfe == NULL) {
+ switch (fe) {
+ case FE_FAIL:
+ normal_error("pdf inclusion","reading image failed");
+ break;
+ case FE_RETURN_NULL:
+ if (pdf_doc->pdfe != NULL) {
+ ppdoc_free(pdfe);
+ pdf_doc->pdfe = NULL;
+ }
+ /* delete docName */
+ if (new_flag == 1) {
+ if (pdf_doc->file_path != NULL)
+ free(pdf_doc->file_path);
+ if (pdf_doc->checksum != NULL)
+ free(pdf_doc->checksum);
+ free(pdf_doc);
+ }
+ return (PdfDocument *) NULL;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ if (pdfe != NULL) {
+ if (ppdoc_crypt_status(pdfe) < 0) {
+ ppdoc_crypt_pass(pdfe,userpassword,strlen(userpassword),NULL,0);
+ }
+ if (ppdoc_crypt_status(pdfe) < 0) {
+ ppdoc_crypt_pass(pdfe,NULL,0,ownerpassword,strlen(ownerpassword));
+ }
+ if (ppdoc_crypt_status(pdfe) < 0) {
+ formatted_error("pdf inclusion","the pdf file '%s' is encrypted, provide proper passwords",file_path);
+ }
+ }
+ pdf_doc->pdfe = pdfe;
+ }
+ /* PDF file could be opened without problems, checksum ok. */
+ if (PdfDocumentTree == NULL)
+ PdfDocumentTree = avl_create(CompPdfDocument, NULL, &avl_xallocator);
+ if ((PdfDocument *) avl_find(PdfDocumentTree, pdf_doc) == NULL) {
+ avl_probe(PdfDocumentTree, pdf_doc);
+ }
+ pdf_doc->occurences++;
+ return pdf_doc;
+}
+
+/*
+ Returns pointer to PdfDocument structure for a PDF stream in memory of streamsize
+ dimension. As before, creates a new PdfDocument structure if it doesn't exist yet
+ with file_path = file_id
+*/
+
+PdfDocument *refMemStreamPdfDocument(char *docstream, unsigned long long streamsize,const char *file_id)
+{
+ char *checksum;
+ char *file_path;
+ PdfDocument *pdf_doc;
+ ppdoc *pdfe = NULL;
+ size_t cnt = 0;
+ checksum = get_stream_checksum(docstream, streamsize);
+ cnt = strlen(file_id);
+ file_path = (char *) malloc(cnt+STREAM_URI_LEN+STRSTREAM_CHECKSUM_SIZE+1); /* 1 for \0 */
+ strcpy(file_path,STREAM_URI);
+ strcat(file_path,file_id);
+ strcat(file_path,checksum);
+ file_path[cnt+STREAM_URI_LEN+STRSTREAM_CHECKSUM_SIZE]='\0';
+ if ((pdf_doc = findPdfDocument(file_path)) == NULL) {
+ /*new_flag = 1;*/
+ pdf_doc = (PdfDocument*) xmalloc(sizeof( PdfDocument));
+ pdf_doc->file_path = file_path;
+ pdf_doc->checksum = checksum;
+ pdf_doc->pdfe = NULL;
+ pdf_doc->inObjList = NULL;
+ pdf_doc->ObjMapTree = NULL;
+ pdf_doc->occurences = 0; /* 0 = unreferenced */
+ pdf_doc->pc = 0;
+ pdf_doc->is_mem = 1;
+ pdf_doc->memstream = docstream;
+ } else {
+ /* As is now, checksum is in file_path, so this check should be useless. */
+ if (strncmp(pdf_doc->checksum, checksum, STRSTREAM_CHECKSUM_SIZE) != 0) {
+ formatted_error("pdf inclusion","stream has changed '%s'", file_path);
+ }
+ free(file_path);
+ free(checksum);
+ }
+ if (pdf_doc->pdfe == NULL) {
+ pdfe = ppdoc_mem(docstream, streamsize);
+ pdf_doc->pc++;
+ if (pdfe == NULL) {
+ normal_error("pdf inclusion","reading pdf Stream failed");
+ }
+ pdf_doc->pdfe = pdfe;
+ }
+ /* PDF file could be opened without problems, checksum ok. */
+ if (PdfDocumentTree == NULL)
+ PdfDocumentTree = avl_create(CompPdfDocument, NULL, &avl_xallocator);
+ if ((PdfDocument *) avl_find(PdfDocumentTree, pdf_doc) == NULL) {
+ avl_probe(PdfDocumentTree, pdf_doc);
+ }
+ pdf_doc->occurences++;
+ return pdf_doc;
+}
+
+/*
+ AVL sort ObjMap into ObjMapTree by object number and generation keep the ObjMap
+ struct small, as these are accumulated until the end
+*/
+
+typedef struct ObjMap ObjMap ;
+
+struct ObjMap {
+ ppref * in;
+ int out_num;
+};
+
+static int CompObjMap(const void *pa, const void *pb, void *p)
+{
+ const ppref *a = (((const ObjMap *) pa)->in);
+ const ppref *b = (((const ObjMap *) pb)->in);
+ if (a->number > b->number)
+ return 1;
+ else if (a->number < b->number)
+ return -1;
+ else if (a->version == b->version)
+ return 0;
+ else if (a->version < b->version)
+ return -1;
+ return 1;
+}
+
+static ObjMap *findObjMap(PdfDocument * pdf_doc, ppref * in)
+{
+ ObjMap *obj_map, tmp;
+ if (pdf_doc->ObjMapTree == NULL)
+ return NULL;
+ tmp.in = in;
+ obj_map = (ObjMap *) avl_find(pdf_doc->ObjMapTree, &tmp);
+ return obj_map;
+}
+
+static void addObjMap(PdfDocument * pdf_doc, ppref * in, int out_num)
+{
+ ObjMap *obj_map = NULL;
+ if (pdf_doc->ObjMapTree == NULL)
+ pdf_doc->ObjMapTree = avl_create(CompObjMap, NULL, &avl_xallocator);
+ obj_map = (ObjMap*)xmalloc(sizeof(ObjMap));
+ obj_map->in = in;
+ obj_map->out_num = out_num;
+ avl_probe(pdf_doc->ObjMapTree, obj_map);
+}
+
+/*
+ When copying the Resources of the selected page, all objects are
+ copied recursively top-down. The findObjMap() function checks if an
+ object has already been copied; if so, instead of copying just the
+ new object number will be referenced. The ObjMapTree guarantees,
+ that during the entire LuaTeX run any object from any embedded PDF
+ file will end up max. once in the output PDF file. Indirect objects
+ are not fetched during copying, but get a new object number from
+ LuaTeX and then will be appended into a linked list.
+*/
+
+static int addInObj(PDF pdf, PdfDocument * pdf_doc, ppref * ref)
+{
+ ObjMap *obj_map;
+ InObj *p, *q, *n;
+ if (ref->number == 0) {
+ normal_error("pdf inclusion","reference to invalid object (broken pdf)");
+ }
+ if ((obj_map = findObjMap(pdf_doc, ref)) != NULL) {
+ return obj_map->out_num;
+ }
+ n = (InObj*)xmalloc(sizeof(InObj));
+ n->ref = ref;
+ n->next = NULL;
+ n->num = pdf_create_obj(pdf, obj_type_others, 0);
+ addObjMap(pdf_doc, ref, n->num);
+ if (pdf_doc->inObjList == NULL) {
+ pdf_doc->inObjList = n;
+ } else {
+ /*
+ It is important to add new objects at the end of the list,
+ because new objects are being added while the list is being
+ written out by writeRefs().
+ */
+ for (p = pdf_doc->inObjList; p != NULL; p = p->next)
+ q = p;
+ q->next = n;
+ }
+ return n->num;
+}
+
+static void copyObject(PDF, PdfDocument *, ppobj *);
+
+static void copyString(PDF pdf, ppstring str)
+{
+ pdf_check_space(pdf);
+ switch (ppstring_type((void *)(str))) {
+ case PPSTRING_PLAIN:
+ pdf_out(pdf, '(');
+ pdf_out_block(pdf, (const char *) str, ppstring_size((void *)(str)));
+ pdf_out(pdf, ')');
+ break;
+ case PPSTRING_BASE16:
+ pdf_out(pdf, '<');
+ pdf_out_block(pdf, (const char *) str, ppstring_size((void *)(str)));
+ pdf_out(pdf, '>');
+ break;
+ case PPSTRING_BASE85:
+ pdf_out(pdf, '<');
+ pdf_out(pdf, '~');
+ pdf_out_block(pdf, (const char *) str, ppstring_size((void *)(str)));
+ pdf_out(pdf, '~');
+ pdf_out(pdf, '>');
+ break;
+ }
+ pdf_set_space(pdf);
+}
+
+/*
+static void copyName(PDF pdf, ppname *name)
+{
+ pdf_add_name(pdf, (const char *) name);
+}
+*/
+
+static void copyArray(PDF pdf, PdfDocument * pdf_doc, pparray * array)
+{
+ int i;
+ int n = array->size;
+ pdf_begin_array(pdf);
+ for (i=0; i<n; ++i) {
+ copyObject(pdf, pdf_doc, pparray_at(array,i));
+ }
+ pdf_end_array(pdf);
+}
+
+static void copyDict(PDF pdf, PdfDocument * pdf_doc, ppdict *dict)
+{
+ int i;
+ int n = dict->size;
+ pdf_begin_dict(pdf);
+ for (i=0; i<n; ++i) {
+ pdf_add_name(pdf, (const char *) ppdict_key(dict,i));
+ copyObject(pdf, pdf_doc, ppdict_at(dict,i));
+ }
+ pdf_end_dict(pdf);
+}
+
+static void copyStreamStream(PDF pdf, ppstream * stream, int decode)
+{
+ uint8_t *data = NULL;
+ size_t size = 0;
+ if (0) {
+ for (data = ppstream_first(stream, &size, decode); data != NULL; data = ppstream_next(stream, &size)) {
+ pdf_out_block(pdf, (const char *) data, size);
+ }
+ } else {
+ data = ppstream_all(stream,&size,decode);
+ if (data != NULL) {
+ pdf_out_block(pdf, (const char *) data, size);
+ }
+ }
+ ppstream_done(stream);
+}
+
+static void copyStream(PDF pdf, PdfDocument * pdf_doc, ppstream * stream)
+{
+ ppdict *dict = stream->dict; /* bug in: stream_dict(stream) */
+ if (pdf->compress_level == 0 || pdf->recompress) {
+ const char *ignoredkeys[] = {
+ "Filter", "Decode", "Length", "DL", NULL
+ };
+ int i;
+ int n = dict->size;
+ pdf_begin_dict(pdf);
+ for (i=0; i<n; ++i) {
+ const char *key = ppdict_key(dict,i);
+ int okay = 1;
+ int k;
+ for (k = 0; ignoredkeys[k] != NULL; k++) {
+ if (strcmp(key,ignoredkeys[k]) == 0) {
+ okay = 0;
+ break;
+ }
+ }
+ if (okay) {
+ pdf_add_name(pdf, key);
+ copyObject(pdf, pdf_doc, ppdict_at(dict,i));
+ }
+ }
+ pdf_dict_add_streaminfo(pdf);
+ pdf_end_dict(pdf);
+ pdf_begin_stream(pdf);
+ copyStreamStream(pdf, stream, 1);
+ pdf_end_stream(pdf);
+ } else {
+ copyDict(pdf, pdf_doc, dict);
+ pdf_begin_stream(pdf);
+ copyStreamStream(pdf, stream, 0);
+ pdf_end_stream(pdf);
+ }
+}
+
+static void copyObject(PDF pdf, PdfDocument * pdf_doc, ppobj * obj)
+{
+ switch (obj->type) {
+ case PPNULL:
+ pdf_add_null(pdf);
+ break;
+ case PPBOOL:
+ pdf_add_bool(pdf,obj->integer); /* ppobj_get_bool_value(obj) */
+ break;
+ case PPINT:
+ pdf_add_int(pdf,obj->integer); /* ppobj_get_int_value(obj) */
+ break;
+ case PPNUM:
+ pdf_add_real(pdf,obj->number); /* ppobj_get_num_value(obj) */
+ break;
+ case PPNAME:
+ pdf_add_name(pdf, (const char *) obj->name); /* ppobj_get_name(obj) */
+ break;
+ case PPSTRING:
+ copyString(pdf, obj->string); /* ppobj_get_string(obj) */
+ break;
+ case PPARRAY:
+ copyArray(pdf, pdf_doc, obj->array); /* ppobj_get_array(obj) */
+ break;
+ case PPDICT:
+ copyDict(pdf, pdf_doc, obj->dict); /* ppobj_get_dict(obj) */
+ break;
+ case PPSTREAM:
+ copyStream(pdf, pdf_doc, obj->stream); /* ppobj_get_stream(obj) */
+ break;
+ case PPREF:
+ pdf_add_ref(pdf, addInObj(pdf, pdf_doc, obj->ref)); /* ppobj_get_ref(obj) */
+ break;
+ default:
+ break;
+ }
+}
+
+static void writeRefs(PDF pdf, PdfDocument * pdf_doc)
+{
+ InObj *r, *n;
+ ppobj * obj;
+ for (r = pdf_doc->inObjList; r != NULL;) {
+ obj = ppref_obj(r->ref);
+ if (obj->type == PPSTREAM)
+ pdf_begin_obj(pdf, r->num, OBJSTM_NEVER);
+ else
+ pdf_begin_obj(pdf, r->num, 2);
+ copyObject(pdf, pdf_doc, obj);
+ pdf_end_obj(pdf);
+ n = r->next;
+ free(r);
+ r = n;
+ pdf_doc->inObjList = n;
+ }
+}
+
+/* get the pagebox coordinates according to the pagebox_spec */
+
+static void somebox(ppdict *page, const char * key, pprect * box)
+{
+ pprect * r = ppdict_get_box(page, key, box);
+ if (r != NULL) {
+ box->lx = r->lx;
+ box->ly = r->ly;
+ box->rx = r->rx;
+ box->ry = r->ry;
+ }
+}
+
+static void get_pagebox(ppdict * page, int pagebox_spec, pprect * box)
+{
+ box->lx = box->rx = box->ly = box->ry = 0;
+ somebox(page,"MediaBox",box);
+ if (pagebox_spec == PDF_BOX_SPEC_MEDIA) {
+ return;
+ }
+ somebox(page,"CropBox",box);
+ if (pagebox_spec == PDF_BOX_SPEC_CROP) {
+ return;
+ }
+ switch (pagebox_spec) {
+ case PDF_BOX_SPEC_BLEED:
+ somebox(page,"BleedBox",box);
+ break;
+ case PDF_BOX_SPEC_TRIM:
+ somebox(page,"TrimBox",box);
+ break;
+ case PDF_BOX_SPEC_ART:
+ somebox(page,"ArtBox",box);
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ 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.
+*/
+
+static ppdict * get_pdf_page_dict(ppdoc *pdfe, int n)
+{
+ ppref *r;
+ int i;
+ for (r=ppdoc_first_page(pdfe), i=1; r != NULL; r = ppdoc_next_page(pdfe), ++i) {
+ if (i == n) {
+ return ppref_obj(r)->dict;
+ }
+ }
+ return NULL;
+}
+
+// static ppdict * get_pdf_page_dict(ppdoc *pdfe, int n)
+// {
+// return ppref_obj(ppdoc_page(pdfe,n))->dict;
+// }
+
+void read_pdf_info(image_dict * idict)
+{
+ PdfDocument *pdf_doc = NULL;
+ ppdoc * pdfe = NULL;
+ ppdict *pageDict, *groupDict;
+ pprect pagebox;
+ ppint rotate = 0;
+ int pdf_major_version_found = 1;
+ int pdf_minor_version_found = 3;
+ float xsize, ysize, xorig, yorig;
+ if (img_type(idict) == IMG_TYPE_PDF) {
+ pdf_doc = refPdfDocument(img_filepath(idict), FE_FAIL, img_userpassword(idict), img_ownerpassword(idict));
+ } else if (img_type(idict) == IMG_TYPE_PDFMEMSTREAM) {
+ pdf_doc = findPdfDocument(img_filepath(idict)) ;
+ if (pdf_doc == NULL )
+ normal_error("pdf inclusion", "memstream not initialized");
+ if (pdf_doc->pdfe == NULL)
+ normal_error("pdf inclusion", "memstream document is empty");
+ pdf_doc->occurences++;
+ } else {
+ normal_error("pdf inclusion","unknown document");
+ }
+ pdfe = pdf_doc->pdfe;
+ /*
+ 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, we will
+ then have to changed drastically anyway.
+ */
+ pdf_major_version_found = ppdoc_version_number(pdfe,&pdf_minor_version_found);
+ if ((100 * pdf_major_version_found + pdf_major_version_found) > (100 * img_pdfmajorversion(idict) + img_pdfminorversion(idict))) {
+ const char *msg = "PDF inclusion: found PDF version '%d.%d', but at most version '%d.%d' allowed";
+ if (img_errorlevel(idict) > 0) {
+ formatted_error("pdf inclusion",msg, pdf_major_version_found, pdf_minor_version_found, img_pdfmajorversion(idict), img_pdfminorversion(idict));
+ } else {
+ formatted_warning("pdf inclusion",msg, pdf_major_version_found, pdf_minor_version_found, img_pdfmajorversion(idict), img_pdfminorversion(idict));
+ }
+ }
+ img_totalpages(idict) = ppdoc_page_count(pdfe);
+ if (img_pagename(idict)) {
+ /*
+ get page by name is obsolete
+ */
+ normal_error("pdf inclusion","named pages are not supported");
+ } else {
+ /*
+ get page by number
+ */
+ if (img_pagenum(idict) <= 0
+ || img_pagenum(idict) > img_totalpages(idict))
+ formatted_error("pdf inclusion","required page '%i' does not exist",(int) img_pagenum(idict));
+ }
+ /*
+ get the required page
+ */
+ pageDict = get_pdf_page_dict(pdfe,img_pagenum(idict));
+ /*
+ get the pagebox coordinates (media, crop,...) to use
+ */
+ get_pagebox(pageDict, img_pagebox(idict), &pagebox);
+ if (pagebox.rx > pagebox.lx) {
+ xorig = pagebox.lx;
+ xsize = pagebox.rx - pagebox.lx;
+ } else {
+ xorig = pagebox.rx;
+ xsize = pagebox.lx - pagebox.rx;
+ }
+ if (pagebox.ry > pagebox.ly) {
+ yorig = pagebox.ly;
+ ysize = pagebox.ry - pagebox.ly;
+ } else {
+ yorig = pagebox.ry;
+ ysize = pagebox.ly - pagebox.ry;
+ }
+ /*
+ The following 4 parameters are raw. Do _not_ modify by /Rotate!
+ */
+ img_xsize(idict) = bp2sp(xsize);
+ img_ysize(idict) = bp2sp(ysize);
+ img_xorig(idict) = bp2sp(xorig);
+ img_yorig(idict) = bp2sp(yorig);
+ /*
+ Handle /Rotate parameter. Only multiples of 90 deg. are allowed (PDF Ref. v1.3,
+ p. 78). We also accept negative angles. Beware: PDF counts clockwise!
+ */
+ if (ppdict_get_int(pageDict, "Rotate", &rotate)) {
+ switch ((((int)rotate % 360) + 360) % 360) {
+ case 0:
+ img_rotation(idict) = 0;
+ break;
+ case 90:
+ img_rotation(idict) = 3;
+ break;
+ case 180:
+ img_rotation(idict) = 2;
+ break;
+ case 270:
+ img_rotation(idict) = 1;
+ break;
+ default:
+ formatted_warning("pdf inclusion","/Rotate parameter in PDF file not multiple of 90 degrees");
+ }
+ }
+ /*
+ currently unused info whether PDF contains a /Group
+ */
+ groupDict = ppdict_get_dict(pageDict, "Group");
+ if (groupDict != NULL) {
+ img_set_group(idict);
+ }
+ /*
+ LuaTeX pre 0.85 versions did this:
+
+ if (readtype == IMG_CLOSEINBETWEEN) {
+ unrefPdfDocument(img_filepath(idict));
+ }
+
+ and also unref'd in the finalizer so we got an extra unrefs when garbage was
+ collected. However it is more efficient to keep the file open so we do that
+ now. The (slower) alternative is to unref here (which in most cases forcing a
+ close of the file) but then we must not call flush_pdf_info.
+
+ A close (unref) can be forced by nilling the dict object at the lua end and
+ forcing a collectgarbage("collect") after that.
+
+ */
+ if (! img_keepopen(idict)) {
+ unrefPdfDocument(img_filepath(idict));
+ }
+}
+
+void flush_pdf_info(image_dict * idict)
+{
+ if (img_keepopen(idict)) {
+ unrefPdfDocument(img_filepath(idict));
+ }
+}
+
+/*
+ Write 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(PDF pdf, image_dict * idict, int suppress_optional_info)
+{
+ PdfDocument *pdf_doc = NULL;
+ ppdoc *pdfe = NULL;
+ ppdict *pageDict, *infoDict;
+ ppobj *obj, *content, *resources;
+ pprect pagebox;
+ int i;
+ double bbox[4];
+ const char *pagedictkeys[] = {
+ "Group", "LastModified", "Metadata", "PieceInfo", "SeparationInfo", NULL
+ };
+ /*
+ open PDF file
+ */
+ if (img_type(idict) == IMG_TYPE_PDF) {
+ pdf_doc = refPdfDocument(img_filepath(idict), FE_FAIL, img_userpassword(idict), img_ownerpassword(idict));
+ } else if (img_type(idict) == IMG_TYPE_PDFMEMSTREAM) {
+ pdf_doc = findPdfDocument(img_filepath(idict)) ;
+ pdf_doc->occurences++;
+ } else {
+ normal_error("pdf inclusion","unknown document");
+ }
+ pdfe = pdf_doc->pdfe;
+ pageDict = get_pdf_page_dict(pdfe,img_pagenum(idict));
+ /*
+ write the Page header
+ */
+ pdf_begin_obj(pdf, img_objnum(idict), OBJSTM_NEVER);
+ pdf_begin_dict(pdf);
+ pdf_dict_add_name(pdf, "Type", "XObject");
+ pdf_dict_add_name(pdf, "Subtype", "Form");
+ pdf_dict_add_int(pdf, "FormType", 1);
+ /*
+ write additional information
+ */
+ pdf_dict_add_img_filename(pdf, idict);
+ if ((suppress_optional_info & 4) == 0) {
+ pdf_dict_add_int(pdf, "PTEX.PageNumber", (int) img_pagenum(idict));
+ }
+ if ((suppress_optional_info & 8) == 0) {
+ infoDict = ppdoc_info(pdfe);
+ if (infoDict != NULL) {
+ /* todo : check this
+ pdf_dict_add_ref(pdf, "PTEX.InfoDict", addInObj(pdf, pdf_doc, infoDict));
+ */
+ pdf_add_name(pdf, "PTEX.InfoDict");
+ copyDict(pdf, pdf_doc, infoDict);
+ }
+ }
+ if (img_is_bbox(idict)) {
+ bbox[0] = sp2bp(img_bbox(idict)[0]);
+ bbox[1] = sp2bp(img_bbox(idict)[1]);
+ bbox[2] = sp2bp(img_bbox(idict)[2]);
+ bbox[3] = sp2bp(img_bbox(idict)[3]);
+ } else {
+ /*
+ get the pagebox coordinates (media, crop,...) to use.
+ */
+ get_pagebox(pageDict, img_pagebox(idict), &pagebox);
+ bbox[0] = pagebox.lx;
+ bbox[1] = pagebox.ly;
+ bbox[2] = pagebox.rx;
+ bbox[3] = pagebox.ry;
+ }
+ pdf_add_name(pdf, "BBox");
+ pdf_begin_array(pdf);
+ pdf_add_real(pdf, bbox[0]);
+ pdf_add_real(pdf, bbox[1]);
+ pdf_add_real(pdf, bbox[2]);
+ pdf_add_real(pdf, bbox[3]);
+ pdf_end_array(pdf);
+ /*
+ Now all relevant parts of the Page dictionary are copied. Metadata validity
+ check is needed(as a stream it must be indirect).
+ */
+ obj = ppdict_get_obj(pageDict, "Metadata");
+ if (obj != NULL && obj->type != PPREF) {
+ formatted_warning("pdf inclusion","/Metadata must be indirect object");
+ }
+ /*
+ copy selected items in Page dictionary
+ */
+ for (i = 0; pagedictkeys[i] != NULL; i++) {
+ obj = ppdict_rget_obj(pageDict, pagedictkeys[i]);
+ if (obj != NULL) {
+ pdf_add_name(pdf, pagedictkeys[i]);
+ /*
+ preserves indirection
+ */
+ copyObject(pdf, pdf_doc, obj);
+ }
+ }
+ resources = ppdict_rget_obj(pageDict, "Resources");
+ if (resources == NULL) {
+ /*
+ If there are no Resources in the Page dict of the embedded page,
+ try to inherit the Resources from the Pages tree of the embedded
+ PDF file, climbing up the tree until the Resources are found.
+ (This fixes a problem with Scribus 1.3.3.14.)
+ */
+ obj = ppdict_rget_obj(pageDict, "Parent");
+ while (obj != NULL && obj->type == PPDICT) {
+ resources = ppdict_rget_obj(obj->dict, "Resources");
+ if (resources != NULL) {
+ break;
+ }
+ obj = ppdict_get_obj(obj->dict, "Parent");
+ }
+ }
+ if (resources != NULL) {
+ pdf_add_name(pdf, "Resources");
+ copyObject(pdf, pdf_doc, resources);
+ } else {
+ formatted_warning("pdf inclusion","Page /Resources missing");
+ }
+ /*
+ User supplied entries.
+ */
+ if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) {
+ pdf_printf(pdf, "\n%s\n", img_attr(idict));
+ }
+ /*
+ Write the Page contents.
+ */
+ content = ppdict_rget_obj(pageDict, "Contents");
+ if (content->type == PPSTREAM) {
+ if (pdf->compress_level == 0 || pdf->recompress) {
+ pdf_dict_add_streaminfo(pdf);
+ pdf_end_dict(pdf);
+ pdf_begin_stream(pdf);
+ copyStreamStream(pdf, content->stream,1); /* decompress */
+ } else {
+ /* copies compressed stream */
+ ppstream * stream = content->stream;
+ ppdict *streamDict = stream->dict; /* */
+ obj = ppdict_rget_obj(streamDict, "Length");
+ if (obj != NULL) {
+ pdf_add_name(pdf, "Length");
+ copyObject(pdf, pdf_doc, obj);
+ obj = ppdict_rget_obj(streamDict, "Filter");
+ if (obj != NULL) {
+ pdf_add_name(pdf, "Filter");
+ copyObject(pdf, pdf_doc, obj);
+ /* the next one is irrelevant, only for inline images: */
+ /*
+ obj = ppdict_rget_obj(streamDict, "DecodeParms");
+ if (obj != NULL) {
+ pdf_add_name(pdf, "DecodeParms");
+ copyObject(pdf, pdf_doc, obj);
+ }
+ */
+ }
+ pdf_end_dict(pdf);
+ pdf_begin_stream(pdf);
+ copyStreamStream(pdf, stream,0);
+ } else {
+ pdf_dict_add_streaminfo(pdf);
+ pdf_end_dict(pdf);
+ pdf_begin_stream(pdf);
+ copyStreamStream(pdf, stream,1);
+ }
+ }
+ pdf_end_stream(pdf);
+ } else if (content->type == PPARRAY) {
+ /* listens to compresslevel */
+ pdf_dict_add_streaminfo(pdf);
+ pdf_end_dict(pdf);
+ pdf_begin_stream(pdf);
+ {
+ int i;
+ int b = 0;
+ int n = content->array->size;
+ for (i=0; i<n; ++i) {
+ ppobj *o = pparray_at(content->array,i);
+ while (o != NULL && o->type == PPREF) {
+ o = ppref_obj((ppref *) o->ref);
+ }
+ if (o != NULL && o->type == PPSTREAM) {
+ if (b) {
+ /*
+ Put a space between streams to be on the safe side (streams
+ should have a trailing space here, but one never knows)
+ */
+ pdf_out(pdf, ' ');
+ } else {
+ b = 1;
+ }
+ copyStreamStream(pdf, (ppstream *) o->stream,1);
+ }
+ }
+ }
+ pdf_end_stream(pdf);
+ } else {
+ /*
+ the contents are optional, but we need to include an empty stream
+ */
+ pdf_dict_add_streaminfo(pdf);
+ pdf_end_dict(pdf);
+ pdf_begin_stream(pdf);
+ pdf_end_stream(pdf);
+ }
+ pdf_end_obj(pdf);
+ /*
+ write out all indirect objects
+ */
+ writeRefs(pdf, pdf_doc);
+ /*
+ unrefPdfDocument() must come after freeing whatever is used
+
+ */
+ if (! img_keepopen(idict)) {
+ unrefPdfDocument(img_filepath(idict));
+ }
+}
+
+/* a special simple case of inclusion, e.g. an appearance stream */
+
+int write_epdf_object(PDF pdf, image_dict * idict, int n)
+{
+ int num = 0 ;
+ if (img_type(idict) != IMG_TYPE_PDF) {
+ normal_error("pdf inclusion","unknown document");
+ } else {
+ PdfDocument * pdf_doc = refPdfDocument(img_filepath(idict), FE_FAIL, img_userpassword(idict), img_ownerpassword(idict));
+ ppdoc * pdfe = pdf_doc->pdfe;
+ ppref * ref = ppxref_find(ppdoc_xref(pdfe), (ppuint) n);
+ if (ref != NULL) {
+ ppobj *obj;
+ num = pdf->obj_count++;
+ obj = ppref_obj(ref);
+ if (obj->type == PPSTREAM) {
+ pdf_begin_obj(pdf, num, OBJSTM_NEVER);
+ } else {
+ pdf_begin_obj(pdf, num, 2);
+ }
+ copyObject(pdf, pdf_doc, obj);
+ pdf_end_obj(pdf);
+ writeRefs(pdf, pdf_doc);
+ }
+ if (! img_keepopen(idict)) {
+ unrefPdfDocument(img_filepath(idict));
+ }
+ }
+ return num;
+}
+
+/* Deallocate a PdfDocument with all its resources. */
+
+static void deletePdfDocumentPdfDoc(PdfDocument * pdf_doc)
+{
+ InObj *r, *n;
+ /* this may be probably needed for an emergency destroyPdfDocument() */
+ for (r = pdf_doc->inObjList; r != NULL; r = n) {
+ n = r->next;
+ free(r);
+ }
+ if (pdf_doc->pdfe != NULL) {
+ ppdoc_free(pdf_doc->pdfe);
+ pdf_doc->pdfe = NULL;
+ }
+ if (pdf_doc->memstream != NULL) {
+ /* pplib does this: free(pdf_doc->memstream); */
+ pdf_doc->memstream = NULL;
+ }
+ /* pdf_doc->pc++; */
+ pdf_doc->pc = 0;
+}
+
+static void destroyPdfDocument(void *pa, void * p)
+{
+ PdfDocument *pdf_doc = (PdfDocument *) pa;
+ deletePdfDocumentPdfDoc(pdf_doc);
+ /* TODO: delete rest of pdf_doc */
+}
+
+/*
+ Called when an image has been written and its resources in image_tab are
+ freed and it's not referenced anymore.
+*/
+
+void unrefPdfDocument(char *file_path)
+{
+ PdfDocument *pdf_doc = findPdfDocument(file_path);
+ if (pdf_doc == NULL) {
+ /* we're ok */
+ } else if (pdf_doc->occurences > 0) {
+ pdf_doc->occurences--;
+ if (pdf_doc->occurences == 0) {
+ deletePdfDocumentPdfDoc(pdf_doc);
+ }
+ } else {
+ /*
+ We either have a mismatch in ref and unref or we're somehow out of sync
+ which can happen when we mess with the same file in lua and tex.
+ */
+ formatted_warning("pdf inclusion","there can be a mismatch in opening and closing file '%s'",file_path);
+ }
+}
+
+/*
+ For completeness, but it isn't currently used (unreferencing is done by mean
+ of file_path.
+*/
+
+void unrefMemStreamPdfDocument(char *file_id)
+{
+ (void) unrefPdfDocument(file_id);
+
+}
+
+/*
+ Called when PDF embedding system is finalized. We now deallocate all remaining
+ PdfDocuments.
+*/
+
+void epdf_free(void)
+{
+ if (PdfDocumentTree != NULL)
+ avl_destroy(PdfDocumentTree, destroyPdfDocument);
+ PdfDocumentTree = NULL;
+}
diff --git a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.w b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.w
deleted file mode 100644
index d69795926e5..00000000000
--- a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.w
+++ /dev/null
@@ -1,972 +0,0 @@
-% pdftoepdf.w
-%
-% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org>
-% Copyright 2006-2015 Taco Hoekwater <taco@@luatex.org>
-%
-% This file is part of LuaTeX.
-%
-% LuaTeX is free software; you can redistribute it and/or modify it under
-% the terms of the GNU General Public License as published by the Free
-% Software Foundation; either version 2 of the License, or (at your
-% option) any later version.
-%
-% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
-% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
-% License for more details.
-%
-% You should have received a copy of the GNU General Public License along
-% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
-
-@ @c
-
-#define __STDC_FORMAT_MACROS /* for PRId64 etc. */
-
-#include "image/epdf.h"
-
-/*
- This file is mostly C and not very much C++; it's just used to interface
- the functions of poppler, which happens to be written in C++.
- Patches for the new poppler 0.59 from
- https://www.mail-archive.com/arch-commits@archlinux.org/msg357548.html
- with some modifications to comply the poppler API.
-
-*/
-
-extern void md5(Guchar *msg, int msgLen, Guchar *digest);
-
-static GBool isInit = gFalse;
-
-/* Maintain AVL tree of all PDF files for embedding */
-
-static avl_table *PdfDocumentTree = NULL;
-
-/* AVL sort PdfDocument into PdfDocumentTree by file_path */
-
-static int CompPdfDocument(const void *pa, const void *pb, void * /*p */ )
-{
- return strcmp(((const PdfDocument *) pa)->file_path, ((const PdfDocument *) pb)->file_path);
-}
-
-/* Returns pointer to PdfDocument structure for PDF file. */
-
-static PdfDocument *findPdfDocument(char *file_path)
-{
- PdfDocument *pdf_doc, tmp;
- if (file_path == NULL) {
- normal_error("pdf backend","empty filename when loading pdf file");
- } else if (PdfDocumentTree == NULL) {
- return NULL;
- }
- tmp.file_path = file_path;
- pdf_doc = (PdfDocument *) avl_find(PdfDocumentTree, &tmp);
- return pdf_doc;
-}
-
-#define PDF_CHECKSUM_SIZE 32
-
-static char *get_file_checksum(const char *a, file_error_mode fe)
-{
- struct stat finfo;
- char *ck = NULL;
- if (stat(a, &finfo) == 0) {
- off_t size = finfo.st_size;
- time_t mtime = finfo.st_mtime;
- ck = (char *) malloc(PDF_CHECKSUM_SIZE);
- if (ck == NULL)
- formatted_error("pdf inclusion","out of memory while processing '%s'", a);
- snprintf(ck, PDF_CHECKSUM_SIZE, "%"@= @>PRIu64@= @>"_%"@= @>PRIu64, (uint64_t) size,(uint64_t) mtime);
- } else {
- switch (fe) {
- case FE_FAIL:
- formatted_error("pdf inclusion","could not stat() file '%s'", a);
- break;
- case FE_RETURN_NULL:
- if (ck != NULL)
- free(ck);
- ck = NULL;
- break;
- default:
- assert(0);
- }
- }
- return ck;
-}
-
-
-static char *get_stream_checksum (const char *str, unsigned long long str_size){
- /* http://www.cse.yorku.ca/~oz/hash.html */
- /* djb2 */
- unsigned long hash ;
- char *ck = NULL;
- unsigned int i;
- hash = 5381;
- ck = (char *) malloc(STRSTREAM_CHECKSUM_SIZE+1);
- if (ck == NULL)
- normal_error("pdf inclusion","out of memory while processing a memstream");
- for(i=0; i<(unsigned int)(str_size); i++) {
- hash = ((hash << 5) + hash) + str[i]; /* hash * 33 + str[i] */
- }
- snprintf(ck,STRSTREAM_CHECKSUM_SIZE+1,"%lx",hash);
- ck[STRSTREAM_CHECKSUM_SIZE]='\0';
- return ck;
-}
-
-/*
- Returns pointer to PdfDocument structure for PDF file.
- Creates a new PdfDocument structure if it doesn't exist yet.
- When fe = FE_RETURN_NULL, the function returns NULL in error case.
-*/
-
-PdfDocument *refPdfDocument(const char *file_path, file_error_mode fe)
-{
- char *checksum, *path_copy;
- PdfDocument *pdf_doc;
- PDFDoc *doc = NULL;
- GooString *docName = NULL;
- int new_flag = 0;
- if ((checksum = get_file_checksum(file_path, fe)) == NULL) {
- return (PdfDocument *) NULL;
- }
- path_copy = xstrdup(file_path);
- if ((pdf_doc = findPdfDocument(path_copy)) == NULL) {
- new_flag = 1;
- pdf_doc = new PdfDocument;
- pdf_doc->file_path = path_copy;
- pdf_doc->checksum = checksum;
- pdf_doc->doc = NULL;
- pdf_doc->inObjList = NULL;
- pdf_doc->ObjMapTree = NULL;
- pdf_doc->occurences = 0; /* 0 = unreferenced */
- pdf_doc->pc = 0;
- } else {
- if (strncmp(pdf_doc->checksum, checksum, PDF_CHECKSUM_SIZE) != 0) {
- formatted_error("pdf inclusion","file has changed '%s'", file_path);
- }
- free(checksum);
- free(path_copy);
- }
- if (pdf_doc->doc == NULL) {
- docName = new GooString(file_path);
- doc = new PDFDoc(docName); /* takes ownership of docName */
- pdf_doc->pc++;
-
- if (!doc->isOk() || !doc->okToPrint()) {
- switch (fe) {
- case FE_FAIL:
- normal_error("pdf inclusion","reading image failed");
- break;
- case FE_RETURN_NULL:
- delete doc;
- /* delete docName */
- if (new_flag == 1) {
- if (pdf_doc->file_path != NULL)
- free(pdf_doc->file_path);
- if (pdf_doc->checksum != NULL)
- free(pdf_doc->checksum);
- delete pdf_doc;
- }
- return (PdfDocument *) NULL;
- break;
- default:
- assert(0);
- }
- }
- pdf_doc->doc = doc;
- }
- /* PDF file could be opened without problems, checksum ok. */
- if (PdfDocumentTree == NULL)
- PdfDocumentTree = avl_create(CompPdfDocument, NULL, &avl_xallocator);
- if ((PdfDocument *) avl_find(PdfDocumentTree, pdf_doc) == NULL) {
- avl_probe(PdfDocumentTree, pdf_doc);
- }
- pdf_doc->occurences++;
- return pdf_doc;
-}
-
-/*
- Returns pointer to PdfDocument structure for a PDF stream in memory of streamsize
- dimension. As before, creates a new PdfDocument structure if it doesn't exist yet
- with file_path = file_id
-*/
-
-PdfDocument *refMemStreamPdfDocument(char *docstream, unsigned long long streamsize,const char *file_id)
-{
- char *checksum;
- char *file_path;
- PdfDocument *pdf_doc;
- PDFDoc *doc = NULL;
- Object obj;
- MemStream *docmemstream = NULL;
- /*int new_flag = 0;*/
- size_t cnt = 0;
- checksum = get_stream_checksum(docstream, streamsize);
- cnt = strlen(file_id);
- assert(cnt>0 && cnt <STREAM_FILE_ID_LEN);
- file_path = (char *) malloc(cnt+STREAM_URI_LEN+STRSTREAM_CHECKSUM_SIZE+1); /* 1 for \0 */
- assert(file_path != NULL);
- strcpy(file_path,STREAM_URI);
- strcat(file_path,file_id);
- strcat(file_path,checksum);
- file_path[cnt+STREAM_URI_LEN+STRSTREAM_CHECKSUM_SIZE]='\0';
- if ((pdf_doc = findPdfDocument(file_path)) == NULL) {
- /*new_flag = 1;*/
- pdf_doc = new PdfDocument;
- pdf_doc->file_path = file_path;
- pdf_doc->checksum = checksum;
- pdf_doc->doc = NULL;
- pdf_doc->inObjList = NULL;
- pdf_doc->ObjMapTree = NULL;
- pdf_doc->occurences = 0; /* 0 = unreferenced */
- pdf_doc->pc = 0;
- } else {
- /* As is now, checksum is in file_path, so this check should be useless. */
- if (strncmp(pdf_doc->checksum, checksum, STRSTREAM_CHECKSUM_SIZE) != 0) {
- formatted_error("pdf inclusion","stream has changed '%s'", file_path);
- }
- free(file_path);
- free(checksum);
- }
- if (pdf_doc->doc == NULL) {
- docmemstream = new MemStream( docstream,0,streamsize, Object(objNull) );
- doc = new PDFDoc(docmemstream); /* takes ownership of docmemstream */
- pdf_doc->pc++;
- if (!doc->isOk() || !doc->okToPrint()) {
- normal_error("pdf inclusion","reading pdf Stream failed");
- }
- pdf_doc->doc = doc;
- }
- /* PDF file could be opened without problems, checksum ok. */
- if (PdfDocumentTree == NULL)
- PdfDocumentTree = avl_create(CompPdfDocument, NULL, &avl_xallocator);
- if ((PdfDocument *) avl_find(PdfDocumentTree, pdf_doc) == NULL) {
- avl_probe(PdfDocumentTree, pdf_doc);
- }
- pdf_doc->occurences++;
- return pdf_doc;
-}
-
-/*
- AVL sort ObjMap into ObjMapTree by object number and generation keep the ObjMap
- struct small, as these are accumulated until the end
-*/
-
-struct ObjMap {
- Ref in;
- int out_num;
-};
-
-static int CompObjMap(const void *pa, const void *pb, void * /*p */ )
-{
- const Ref *a = &(((const ObjMap *) pa)->in);
- const Ref *b = &(((const ObjMap *) pb)->in);
- if (a->num > b->num)
- return 1;
- else if (a->num < b->num)
- return -1;
- else if (a->gen == b->gen)
- return 0;
- else if (a->gen < b->gen)
- return -1;
- return 1;
-}
-
-static ObjMap *findObjMap(PdfDocument * pdf_doc, Ref in)
-{
- ObjMap *obj_map, tmp;
- if (pdf_doc->ObjMapTree == NULL)
- return NULL;
- tmp.in = in;
- obj_map = (ObjMap *) avl_find(pdf_doc->ObjMapTree, &tmp);
- return obj_map;
-}
-
-static void addObjMap(PdfDocument * pdf_doc, Ref in, int out_num)
-{
- ObjMap *obj_map = NULL;
- if (pdf_doc->ObjMapTree == NULL)
- pdf_doc->ObjMapTree = avl_create(CompObjMap, NULL, &avl_xallocator);
- obj_map = new ObjMap;
- obj_map->in = in;
- obj_map->out_num = out_num;
- avl_probe(pdf_doc->ObjMapTree, obj_map);
-}
-
-/*
- When copying the Resources of the selected page, all objects are
- copied recursively top-down. The findObjMap() function checks if an
- object has already been copied; if so, instead of copying just the
- new object number will be referenced. The ObjMapTree guarantees,
- that during the entire LuaTeX run any object from any embedded PDF
- file will end up max. once in the output PDF file. Indirect objects
- are not fetched during copying, but get a new object number from
- LuaTeX and then will be appended into a linked list.
-*/
-
-static int addInObj(PDF pdf, PdfDocument * pdf_doc, Ref ref)
-{
- ObjMap *obj_map;
- InObj *p, *q, *n;
- if (ref.num == 0) {
- normal_error("pdf inclusion","reference to invalid object (broken pdf)");
- }
- if ((obj_map = findObjMap(pdf_doc, ref)) != NULL)
- return obj_map->out_num;
- n = new InObj;
- n->ref = ref;
- n->next = NULL;
- n->num = pdf_create_obj(pdf, obj_type_others, 0);
- addObjMap(pdf_doc, ref, n->num);
- if (pdf_doc->inObjList == NULL) {
- pdf_doc->inObjList = n;
- } else {
- /*
- It is important to add new objects at the end of the list,
- because new objects are being added while the list is being
- written out by writeRefs().
- */
- for (p = pdf_doc->inObjList; p != NULL; p = p->next)
- q = p;
- q->next = n;
- }
- return n->num;
-}
-
-/*
- Function converts double to pdffloat; very small and very large numbers
- are NOT converted to scientific notation. Here 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 pdffloat conv_double_to_pdffloat(double n)
-{
- pdffloat a;
- a.e = 6;
- a.m = i64round(n * ten_pow[a.e]);
- return a;
-}
-
-static void copyObject(PDF, PdfDocument *, Object *);
-
-void copyReal(PDF pdf, double d)
-{
- if (pdf->cave)
- pdf_out(pdf, ' ');
- print_pdffloat(pdf, conv_double_to_pdffloat(d));
- pdf->cave = true;
-}
-
-static void copyString(PDF pdf, GooString * string)
-{
- char *p;
- unsigned char c;
- size_t i, l;
- p = string->getCString();
- l = (size_t) string->getLength();
- if (pdf->cave)
- pdf_out(pdf, ' ');
- if (strlen(p) == l) {
- pdf_out(pdf, '(');
- for (; *p != 0; p++) {
- c = (unsigned char) *p;
- if (c == '(' || c == ')' || c == '\\')
- pdf_printf(pdf, "\\%c", c);
- else if (c < 0x20 || c > 0x7F)
- pdf_printf(pdf, "\\%03o", (int) c);
- else
- pdf_out(pdf, c);
- }
- pdf_out(pdf, ')');
- } else {
- pdf_out(pdf, '<');
- for (i = 0; i < l; i++) {
- c = (unsigned char) string->getChar(i);
- pdf_printf(pdf, "%.2x", (int) c);
- }
- pdf_out(pdf, '>');
- }
- pdf->cave = true;
-}
-
-static void copyName(PDF pdf, char *s)
-{
- pdf_out(pdf, '/');
- for (; *s != 0; s++) {
- if (isdigit(*s) || isupper(*s) || islower(*s) || *s == '_' ||
- *s == '.' || *s == '-' || *s == '+')
- pdf_out(pdf, *s);
- else
- pdf_printf(pdf, "#%.2X", *s & 0xFF);
- }
- pdf->cave = true;
-}
-
-static void copyArray(PDF pdf, PdfDocument * pdf_doc, Array * array)
-{
- int i, l;
- Object obj1;
- pdf_begin_array(pdf);
- for (i = 0, l = array->getLength(); i < l; ++i) {
- obj1 = array->getNF(i);
- copyObject(pdf, pdf_doc, &obj1);
- }
- pdf_end_array(pdf);
-}
-
-static void copyDict(PDF pdf, PdfDocument * pdf_doc, Dict * dict)
-{
- int i, l;
- Object obj1;
- pdf_begin_dict(pdf);
- for (i = 0, l = dict->getLength(); i < l; ++i) {
- copyName(pdf, dict->getKey(i));
- obj1 = dict->getValNF(i);
- copyObject(pdf, pdf_doc, &obj1);
- }
- pdf_end_dict(pdf);
-}
-
-static void copyStreamStream(PDF pdf, Stream * str)
-{
- int c, i, len = 1024;
- str->reset();
- i = len;
- while ((c = str->getChar()) != EOF) {
- if (i == len) {
- pdf_room(pdf, len);
- i = 0;
- }
- pdf_quick_out(pdf, c);
- i++;
- }
-}
-
-static void copyStream(PDF pdf, PdfDocument * pdf_doc, Stream * stream)
-{
- copyDict(pdf, pdf_doc, stream->getDict());
- pdf_begin_stream(pdf);
- copyStreamStream(pdf, stream->getUndecodedStream());
- pdf_end_stream(pdf);
-}
-
-static void copyObject(PDF pdf, PdfDocument * pdf_doc, Object * obj)
-{
- switch (obj->getType()) {
- case objBool:
- pdf_add_bool(pdf, (int) obj->getBool());
- break;
- case objInt:
- pdf_add_int(pdf, obj->getInt());
- break;
- case objReal:
- copyReal(pdf, obj->getReal());
- break;
- /*
- case objNum:
- GBool isNum() { return type == objInt || type == objReal; }
- break;
- */
- case objString:
- copyString(pdf, (GooString *)obj->getString());
- break;
- case objName:
- copyName(pdf, (char *)obj->getName());
- break;
- case objNull:
- pdf_add_null(pdf);
- break;
- case objArray:
- copyArray(pdf, pdf_doc, obj->getArray());
- break;
- case objDict:
- copyDict(pdf, pdf_doc, obj->getDict());
- break;
- case objStream:
- copyStream(pdf, pdf_doc, obj->getStream());
- break;
- case objRef:
- pdf_add_ref(pdf, addInObj(pdf, pdf_doc, obj->getRef()));
- break;
- case objCmd:
- case objError:
- case objEOF:
- case objNone:
- formatted_error("pdf inclusion","type '%s' cannot be copied", obj->getTypeName());
- break;
- default:
- /* poppler doesn't have any other types */
- assert(0);
- }
-}
-
-static void writeRefs(PDF pdf, PdfDocument * pdf_doc)
-{
- InObj *r, *n;
- Object obj1;
- XRef *xref;
- PDFDoc *doc = pdf_doc->doc;
- xref = doc->getXRef();
- for (r = pdf_doc->inObjList; r != NULL;) {
- obj1 = xref->fetch(r->ref.num, r->ref.gen);
- if (obj1.isStream())
- pdf_begin_obj(pdf, r->num, OBJSTM_NEVER);
- else
- pdf_begin_obj(pdf, r->num, 2);
- copyObject(pdf, pdf_doc, &obj1);
- pdf_end_obj(pdf);
- n = r->next;
- delete r;
- pdf_doc->inObjList = r = n;
- }
-}
-
-/* get the pagebox coordinates according to the pagebox_spec */
-
-static PDFRectangle *get_pagebox(Page * page, int pagebox_spec)
-{
- switch (pagebox_spec) {
- case PDF_BOX_SPEC_MEDIA:
- return page->getMediaBox();
- break;
- case PDF_BOX_SPEC_CROP:
- return page->getCropBox();
- break;
- case PDF_BOX_SPEC_BLEED:
- return page->getBleedBox();
- break;
- case PDF_BOX_SPEC_TRIM:
- return page->getTrimBox();
- break;
- case PDF_BOX_SPEC_ART:
- return page->getArtBox();
- break;
- default:
- return page->getMediaBox();
- break;
- }
-}
-
-/*
- 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 flush_pdf_info(image_dict * idict)
-{
- if (img_keepopen(idict)) {
- unrefPdfDocument(img_filepath(idict));
- }
-}
-
-/*
- void flush_pdfstream_info(image_dict * idict)
- {
- if (img_pdfstream_ptr(idict) != NULL) {
- xfree(img_pdfstream_stream(idict));
- xfree(img_pdfstream_ptr(idict));
- img_pdfstream_stream(idict) = NULL;
- img_pdfstream_ptr(idict) = NULL;
- }
- }
-*/
-
-void read_pdf_info(image_dict * idict)
-{
- PdfDocument *pdf_doc = NULL;
- PDFDoc *doc = NULL;
- Catalog *catalog;
- Page *page;
- int rotate;
- PDFRectangle *pagebox;
- int pdf_major_version_found, pdf_minor_version_found;
- float xsize, ysize, xorig, yorig;
- if (isInit == gFalse) {
- if (!(globalParams))
- globalParams = new GlobalParams();
- globalParams->setErrQuiet(gFalse);
- isInit = gTrue;
- }
- if (img_type(idict) == IMG_TYPE_PDF)
- pdf_doc = refPdfDocument(img_filepath(idict), FE_FAIL);
- else if (img_type(idict) == IMG_TYPE_PDFMEMSTREAM) {
- pdf_doc = findPdfDocument(img_filepath(idict)) ;
- if (pdf_doc == NULL )
- normal_error("pdf inclusion", "memstream not initialized");
- if (pdf_doc->doc == NULL)
- normal_error("pdf inclusion", "memstream document is empty");
- pdf_doc->occurences++;
- } else {
- normal_error("pdf inclusion","unknown document");
- }
- doc = pdf_doc->doc;
- catalog = doc->getCatalog();
- /*
- 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, we will
- then have to changed drastically anyway.
- */
- pdf_major_version_found = doc->getPDFMajorVersion();
- pdf_minor_version_found = doc->getPDFMinorVersion();
- if ((100 * pdf_major_version_found + pdf_major_version_found) > (100 * img_pdfmajorversion(idict) + img_pdfminorversion(idict))) {
- const char *msg = "PDF inclusion: found PDF version '%d.%d', but at most version '%d.%d' allowed";
- if (img_errorlevel(idict) > 0) {
- formatted_error("pdf inclusion",msg, pdf_major_version_found, pdf_minor_version_found, img_pdfmajorversion(idict), img_pdfminorversion(idict));
- } else {
- formatted_warning("pdf inclusion",msg, pdf_major_version_found, pdf_minor_version_found, img_pdfmajorversion(idict), img_pdfminorversion(idict));
- }
- }
- img_totalpages(idict) = catalog->getNumPages();
- if (img_pagename(idict)) {
- /* get page by name */
- GooString name(img_pagename(idict));
- LinkDest *link = doc->findDest(&name);
- if (link == NULL || !link->isOk())
- formatted_error("pdf inclusion","invalid destination '%s'",img_pagename(idict));
- Ref ref = link->getPageRef();
- img_pagenum(idict) = catalog->findPage(ref.num, ref.gen);
- if (img_pagenum(idict) == 0)
- formatted_error("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))
- formatted_error("pdf inclusion","required page '%i' does not exist",(int) img_pagenum(idict));
- }
- /* get the required page */
- page = catalog->getPage(img_pagenum(idict));
- /* get the pagebox coordinates (media, crop,...) to use. */
- pagebox = get_pagebox(page, img_pagebox(idict));
- if (pagebox->x2 > pagebox->x1) {
- xorig = pagebox->x1;
- xsize = pagebox->x2 - pagebox->x1;
- } else {
- xorig = pagebox->x2;
- xsize = pagebox->x1 - pagebox->x2;
- }
- if (pagebox->y2 > pagebox->y1) {
- yorig = pagebox->y1;
- ysize = pagebox->y2 - pagebox->y1;
- } else {
- yorig = pagebox->y2;
- ysize = pagebox->y1 - pagebox->y2;
- }
- /* The following 4 parameters are raw. Do _not_ modify by /Rotate! */
- img_xsize(idict) = bp2sp(xsize);
- img_ysize(idict) = bp2sp(ysize);
- img_xorig(idict) = bp2sp(xorig);
- img_yorig(idict) = bp2sp(yorig);
- /*
- Handle /Rotate parameter. Only multiples of 90 deg. are allowed (PDF Ref. v1.3,
- p. 78). We also accept negative angles. Beware: PDF counts clockwise! */
- rotate = page->getRotate();
- switch (((rotate % 360) + 360) % 360) {
- case 0:
- img_rotation(idict) = 0;
- break;
- case 90:
- img_rotation(idict) = 3;
- break;
- case 180:
- img_rotation(idict) = 2;
- break;
- case 270:
- img_rotation(idict) = 1;
- break;
- default:
- formatted_warning("pdf inclusion","/Rotate parameter in PDF file not multiple of 90 degrees");
- }
- /* currently unused info whether PDF contains a /Group */
- if (page->getGroup() != NULL)
- img_set_group(idict);
- /*
- LuaTeX pre 0.85 versions did this:
-
- if (readtype == IMG_CLOSEINBETWEEN) {
- unrefPdfDocument(img_filepath(idict));
- }
-
- and also unref'd in the finalizer so we got an extra unrefs when garbage was
- collected. However it is more efficient to keep the file open so we do that
- now. The (slower) alternative is to unref here (which in most cases forcing a
- close of the file) but then we must not call flush_pdf_info.
-
- A close (unref) can be forced by nilling the dict object at the lua end and
- forcing a collectgarbage("collect") after that.
-
- */
- if (! img_keepopen(idict)) {
- unrefPdfDocument(img_filepath(idict));
- }
-}
-
-/*
- Write 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(PDF pdf, image_dict * idict, int suppress_optional_info)
-{
- PdfDocument *pdf_doc = NULL;
- PDFDoc *doc = NULL;
- Catalog *catalog;
- Page *page;
- Ref *pageref;
- Dict *pageDict;
- Object obj1, contents, pageobj, pagesobj1, pagesobj2, *op1, *op2, *optmp;
- PDFRectangle *pagebox;
- int i, l;
- double bbox[4];
- /* char s[256]; */
- const char *pagedictkeys[] = {
- "Group", "LastModified", "Metadata", "PieceInfo", "Resources", "SeparationInfo", NULL
- };
- /* open PDF file */
- if (img_type(idict) == IMG_TYPE_PDF) {
- pdf_doc = refPdfDocument(img_filepath(idict), FE_FAIL);
- } else if (img_type(idict) == IMG_TYPE_PDFMEMSTREAM) {
- pdf_doc = findPdfDocument(img_filepath(idict)) ;
- pdf_doc->occurences++;
- } else {
- normal_error("pdf inclusion","unknown document");
- }
- doc = pdf_doc->doc;
- catalog = doc->getCatalog();
- page = catalog->getPage(img_pagenum(idict));
- pageref = catalog->getPageRef(img_pagenum(idict));
- pageobj = doc->getXRef()->fetch(pageref->num, pageref->gen);
- pageDict = pageobj.getDict();
- /* write the Page header */
- pdf_begin_obj(pdf, img_objnum(idict), OBJSTM_NEVER);
- pdf_begin_dict(pdf);
- pdf_dict_add_name(pdf, "Type", "XObject");
- pdf_dict_add_name(pdf, "Subtype", "Form");
- if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) {
- pdf_printf(pdf, "\n%s\n", img_attr(idict));
- }
- pdf_dict_add_int(pdf, "FormType", 1);
- /* write additional information */
- pdf_dict_add_img_filename(pdf, idict);
- if ((suppress_optional_info & 4) == 0) {
- pdf_dict_add_int(pdf, "PTEX.PageNumber", (int) img_pagenum(idict));
- }
- if ((suppress_optional_info & 8) == 0) {
- obj1 = doc->getDocInfoNF();
- if (obj1.isRef()) {
- /* the info dict must be indirect (PDF Ref p. 61) */
- pdf_dict_add_ref(pdf, "PTEX.InfoDict", addInObj(pdf, pdf_doc, obj1.getRef()));
- }
- }
- if (img_is_bbox(idict)) {
- bbox[0] = sp2bp(img_bbox(idict)[0]);
- bbox[1] = sp2bp(img_bbox(idict)[1]);
- bbox[2] = sp2bp(img_bbox(idict)[2]);
- bbox[3] = sp2bp(img_bbox(idict)[3]);
- } else {
- /* get the pagebox coordinates (media, crop,...) to use. */
- pagebox = get_pagebox(page, img_pagebox(idict));
- bbox[0] = pagebox->x1;
- bbox[1] = pagebox->y1;
- bbox[2] = pagebox->x2;
- bbox[3] = pagebox->y2;
- }
- pdf_add_name(pdf, "BBox");
- pdf_begin_array(pdf);
- copyReal(pdf, bbox[0]);
- copyReal(pdf, bbox[1]);
- copyReal(pdf, bbox[2]);
- copyReal(pdf, bbox[3]);
- pdf_end_array(pdf);
- /*
- Now all relevant parts of the Page dictionary are copied. Metadata validity
- check is needed(as a stream it must be indirect).
- */
- obj1 = pageDict->lookupNF("Metadata");
- if (!obj1.isNull() && !obj1.isRef())
- formatted_warning("pdf inclusion","/Metadata must be indirect object");
- /* copy selected items in Page dictionary */
- for (i = 0; pagedictkeys[i] != NULL; i++) {
- obj1 = pageDict->lookupNF(pagedictkeys[i]);
- if (!obj1.isNull()) {
- pdf_add_name(pdf, pagedictkeys[i]);
- /* preserves indirection */
- copyObject(pdf, pdf_doc, &obj1);
- }
- }
- /*
- If there are no Resources in the Page dict of the embedded page,
- try to inherit the Resources from the Pages tree of the embedded
- PDF file, climbing up the tree until the Resources are found.
- (This fixes a problem with Scribus 1.3.3.14.)
- */
- obj1 = pageDict->lookupNF("Resources");
- if (obj1.isNull()) {
- op1 = &pagesobj1;
- op2 = &pagesobj2;
- *op1 = pageDict->lookup("Parent");
- while (op1->isDict()) {
- obj1 = op1->dictLookupNF("Resources");
- if (!obj1.isNull()) {
- pdf_add_name(pdf, "Resources");
- copyObject(pdf, pdf_doc, &obj1);
- break;
- }
- *op2 = op1->dictLookup("Parent");
- optmp = op1;
- op1 = op2;
- op2 = optmp;
- };
- if (!op1->isDict())
- formatted_warning("pdf inclusion","Page /Resources missing");
- }
- /* Write the Page contents. */
- contents = page->getContents();
- if (contents.isStream()) {
- /*
- Variant A: get stream and recompress under control of \pdfcompresslevel
-
- pdf_begin_stream();
- copyStreamStream(contents->getStream());
- pdf_end_stream();
-
- Variant B: copy stream without recompressing
- */
- obj1 = contents.streamGetDict()->lookup("F");
- if (!obj1.isNull()) {
- normal_error("pdf inclusion","unsupported external stream");
- }
- obj1 = contents.streamGetDict()->lookup("Length");
- pdf_add_name(pdf, "Length");
- copyObject(pdf, pdf_doc, &obj1);
- obj1 = contents.streamGetDict()->lookup("Filter");
- if (!obj1.isNull()) {
- pdf_add_name(pdf, "Filter");
- copyObject(pdf, pdf_doc, &obj1);
- obj1 = contents.streamGetDict()->lookup("DecodeParms");
- if (!obj1.isNull()) {
- pdf_add_name(pdf, "DecodeParms");
- copyObject(pdf, pdf_doc, &obj1);
- }
- }
- pdf_end_dict(pdf);
- pdf_begin_stream(pdf);
- copyStreamStream(pdf, contents.getStream()->getUndecodedStream());
- pdf_end_stream(pdf);
- pdf_end_obj(pdf);
- } else if (contents.isArray()) {
- pdf_dict_add_streaminfo(pdf);
- pdf_end_dict(pdf);
- pdf_begin_stream(pdf);
- for (i = 0, l = contents.arrayGetLength(); i < l; ++i) {
- obj1 = contents.arrayGet(i);
- copyStreamStream(pdf, obj1.getStream());
- if (i < (l - 1)) {
- /*
- Put a space between streams to be on the safe side (streams
- should have a trailing space here, but one never knows)
- */
- pdf_out(pdf, ' ');
- }
- }
- pdf_end_stream(pdf);
- pdf_end_obj(pdf);
- } else {
- /* the contents are optional, but we need to include an empty stream */
- pdf_dict_add_streaminfo(pdf);
- pdf_end_dict(pdf);
- pdf_begin_stream(pdf);
- pdf_end_stream(pdf);
- pdf_end_obj(pdf);
- }
- /* write out all indirect objects */
- writeRefs(pdf, pdf_doc);
- /*
- unrefPdfDocument() must come after contents.free() and pageobj.free()!
- TH: The next line makes repeated pdf inclusion unacceptably slow
-
- unrefPdfDocument(img_filepath(idict));
- */
-
-if (! img_keepopen(idict)) {
- unrefPdfDocument(img_filepath(idict));
-}
-
-
-}
-
-/* Deallocate a PdfDocument with all its resources. */
-
-static void deletePdfDocumentPdfDoc(PdfDocument * pdf_doc)
-{
- InObj *r, *n;
- /* this may be probably needed for an emergency destroyPdfDocument() */
- for (r = pdf_doc->inObjList; r != NULL; r = n) {
- n = r->next;
- delete r;
- }
- delete pdf_doc->doc;
- pdf_doc->doc = NULL;
- pdf_doc->pc++;
-}
-
-static void destroyPdfDocument(void *pa, void * /*pb */ )
-{
- PdfDocument *pdf_doc = (PdfDocument *) pa;
- deletePdfDocumentPdfDoc(pdf_doc);
- /* TODO: delete rest of pdf_doc */
-}
-
-/*
- Called when an image has been written and its resources in image_tab are
- freed and it's not referenced anymore.
-*/
-
-void unrefPdfDocument(char *file_path)
-{
- PdfDocument *pdf_doc = findPdfDocument(file_path);
- if (pdf_doc->occurences > 0) {
- pdf_doc->occurences--;
- if (pdf_doc->occurences == 0) {
- deletePdfDocumentPdfDoc(pdf_doc);
- }
- } else {
- /*
- We either have a mismatch in ref and unref or we're somehow out of sync
- which can happen when we mess with the same file in lua and tex.
- */
- formatted_warning("pdf inclusion","there can be a mismatch in opening and closing file '%s'",file_path);
- }
-}
-
-/*
- For completeness, but it isn't currently used (unreferencing is done by mean
- of file_path.
-*/
-
-void unrefMemStreamPdfDocument(char *file_id)
-{
- (void) unrefPdfDocument(file_id);
-
-}
-
-/*
- Called when PDF embedding system is finalized. We now deallocate all remaining
- PdfDocuments.
-*/
-
-void epdf_free()
-{
- if (PdfDocumentTree != NULL)
- avl_destroy(PdfDocumentTree, destroyPdfDocument);
- PdfDocumentTree = NULL;
- if (isInit == gTrue)
- delete globalParams;
- isInit = gFalse;
-}
diff --git a/Build/source/texk/web2c/luatexdir/image/writeimg.w b/Build/source/texk/web2c/luatexdir/image/writeimg.c
index ef414d5d4bb..e3e3f608fea 100644
--- a/Build/source/texk/web2c/luatexdir/image/writeimg.w
+++ b/Build/source/texk/web2c/luatexdir/image/writeimg.c
@@ -1,109 +1,82 @@
-% writeimg.w
-%
-% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org>
-% Copyright 2006-2012 Taco Hoekwater <taco@@luatex.org>
-%
-% This file is part of LuaTeX.
-%
-% LuaTeX is free software; you can redistribute it and/or modify it under
-% the terms of the GNU General Public License as published by the Free
-% Software Foundation; either version 2 of the License, or (at your
-% option) any later version.
-%
-% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
-% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
-% License for more details.
-%
-% You should have received a copy of the GNU General Public License along
-% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
-
-@* Image inclusion.
-
-@ @c
+/*
+
+writeimg.c
+
+Copyright 1996-2006 Han The Thanh <thanh@pdftex.org>
+Copyright 2006-2012 Taco Hoekwater <taco@luatex.org>
+
+This file is part of LuaTeX.
+
+LuaTeX is free software; you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation;
+either version 2 of the License, or (at your option) any later version.
+
+LuaTeX is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+LuaTeX; if not, see <http://www.gnu.org/licenses/>.
+
+*/
+
#include "ptexlib.h"
#include <kpathsea/c-auto.h>
#include <kpathsea/c-memstr.h>
-@ @c
#include "image/image.h"
#include "image/writejpg.h"
#include "image/writejp2.h"
#include "image/writepng.h"
#include "image/writejbig2.h"
-#include "lua.h" /* for |LUA_NOREF| */
+#include "lua.h"
#include "lauxlib.h"
-@* Patch ImageTypeDetection 2003/02/08 by Heiko Oberdiek.
+/*tex
-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
+The 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:
-
- * 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 -- \%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.
+The magic headers are as follows:
+
+\startitemize
+ \startitem
+ \type {png}: 89 50 4E 47 0D 0A 1A 0A or |"\137PNG\013\010\026\010"|
+ \stopitem
+ \startitem
+ \type {jpg}: FF D8 FF or |"\255\216\255"|.
+ \stopitem
+ \startitem
+ \type {jp2}: 00 00 00 0C 6A 50 20 20 0D 0A or |"\000\000\000\012\106\080\032\032\013\010"|
+ \stopitem
+ \startitem
+ \type {pdf}: |"%PDF"| somewhere in the beginning
+ \stopitem
+\stopitemize
Functions |check_type_by_header| and |check_type_by_extension|: |img_type(img)|
is set to |IMG_TYPE_NONE| by |new_image_dict()|. Both functions try to detect a
type and set |img_type(img)|. Thus a value other than |IMG_TYPE_NONE| indicates
that a type has been found.
-@c
-#define HEADER_JPG "\xFF\xD8"
-#define HEADER_PNG "\x89PNG\r\n\x1A\n"
+*/
+
+#define HEADER_JPG "\xFF\xD8"
+#define HEADER_PNG "\x89PNG\r\n\x1A\n"
#define HEADER_JBIG2 "\x97\x4A\x42\x32\x0D\x0A\x1A\x0A"
-#define HEADER_JP2 "\x6A\x50\x20\x20"
-#define HEADER_PDF "%PDF-"
+#define HEADER_JP2 "\x6A\x50\x20\x20"
+#define HEADER_PDF "%PDF-"
+
#define MAX_HEADER (sizeof(HEADER_PNG)-1)
-#define HEADER_PDF_MEMSTREAM "data:application/pdf," /* see epdf.h */
-#define LEN_PDF_MEMSTREAM 21 /* see epdf.h */
+
+#define HEADER_PDF_MEMSTREAM "data:application/pdf,"
+#define LEN_PDF_MEMSTREAM 21
static void check_type_by_header(image_dict * idict)
{
@@ -115,13 +88,13 @@ static void check_type_by_header(image_dict * idict)
return;
if (img_type(idict) != IMG_TYPE_NONE)
return;
- /* here we read the and also check for a memstream object */
+ /*tex Here we read the and also check for a memstream object. */
if (!img_filepath(idict) || !FOPEN_RBIN_MODE) {
normal_error("pdf backend","reading image file failed");
}
file = fopen(img_filepath(idict), FOPEN_RBIN_MODE);
if (file == NULL) {
- /* check the prefix of img_filepath(idict) */
+ /*tex We check the prefix of img_filepath(idict). */
for (i = 0; (unsigned) i < LEN_PDF_MEMSTREAM; i++) {
prefix[i] = (char) (img_filepath(idict)[i]);
}
@@ -133,7 +106,7 @@ static void check_type_by_header(image_dict * idict)
formatted_error("pdf backend","reading image file '%s' failed",img_filepath(idict));
}
}
- /* a valid file, but perhaps unsupported */
+ /*tex Do we have a valid file but perhaps unsupported? */
for (i = 0; (unsigned) i < MAX_HEADER; i++) {
header[i] = (char) xgetc(file);
if (feof(file)) {
@@ -141,7 +114,7 @@ static void check_type_by_header(image_dict * idict)
}
}
xfclose(file, img_filepath(idict));
- /* tests */
+ /*tex Further tests: */
if (strncmp(header, HEADER_JPG, sizeof(HEADER_JPG) - 1) == 0)
img_type(idict) = IMG_TYPE_JPG;
else if (strncmp(header + 4, HEADER_JP2, sizeof(HEADER_JP2) - 1) == 0)
@@ -154,15 +127,13 @@ static void check_type_by_header(image_dict * idict)
img_type(idict) = IMG_TYPE_PDF;
}
-@ @c
static void check_type_by_extension(image_dict * idict)
{
char *image_suffix;
if (idict != NULL)
return;
- if (img_type(idict) != IMG_TYPE_NONE) /* nothing to do */
+ if (img_type(idict) != IMG_TYPE_NONE)
return;
- /* tests */
if ((image_suffix = strrchr(img_filename(idict), '.')) == 0)
img_type(idict) = IMG_TYPE_NONE;
else if (strcasecmp(image_suffix, ".png") == 0)
@@ -179,14 +150,13 @@ static void check_type_by_extension(image_dict * idict)
img_type(idict) = IMG_TYPE_PDF;
}
-@ @c
void new_img_pdfstream_struct(image_dict * p)
{
img_pdfstream_ptr(p) = xtalloc(1, pdf_stream_struct);
img_pdfstream_stream(p) = NULL;
+ img_pdfstream_size(p) = 0;
}
-@ @c
image *new_image(void)
{
image *p = xtalloc(1, image);
@@ -199,7 +169,6 @@ image *new_image(void)
return p;
}
-@ @c
image_dict *new_image_dict(void)
{
image_dict *p = xtalloc(1, image_dict);
@@ -214,7 +183,8 @@ image_dict *new_image_dict(void)
img_unset_bbox(p);
img_unset_group(p);
img_state(p) = DICT_NEW;
- img_index(p) = -1; /* -1 = unused, used count from 0 */
+ /*tex A value of -1 means unused while the used counts from 0 */
+ img_index(p) = -1;
img_luaref(p) = 0;
img_errorlevel(p) = pdf_inclusion_errorlevel;
fix_pdf_version(static_pdf);
@@ -223,7 +193,6 @@ image_dict *new_image_dict(void)
return p;
}
-@ @c
static void free_dict_strings(image_dict * p)
{
xfree(img_filename(p));
@@ -232,12 +201,13 @@ static void free_dict_strings(image_dict * p)
xfree(img_pagename(p));
}
-@ @c
void free_image_dict(image_dict * p)
{
- if (ini_version)
- return; /* The image may be \.{\\dump}ed to a format */
- /* called from limglib.c */
+ if (ini_version) {
+ /*tex The image may be \.{\\dump}ed to a format. */
+ return;
+ }
+ /*tex Called from limglib.c. */
switch (img_type(p)) {
case IMG_TYPE_PDFMEMSTREAM:
case IMG_TYPE_PDF:
@@ -256,7 +226,6 @@ void free_image_dict(image_dict * p)
flush_jbig2_info(p);
break;
case IMG_TYPE_PDFSTREAM:
- /* flush_pdfstream_info(p); */
if (img_pdfstream_ptr(p) != NULL) {
xfree(img_pdfstream_stream(p));
xfree(img_pdfstream_ptr(p));
@@ -271,7 +240,6 @@ void free_image_dict(image_dict * p)
xfree(p);
}
-@ @c
void read_img(image_dict * idict)
{
char *filepath = NULL;
@@ -282,7 +250,7 @@ void read_img(image_dict * idict)
callback_id = callback_defined(find_image_file_callback);
if (img_filepath(idict) == NULL) {
if (callback_id > 0) {
- /* we always callback, also for a mem stream */
+ /*tex We always callback, also for a mem stream. */
if (run_callback(callback_id, "S->S", img_filename(idict),&filepath)) {
if (filepath && (strlen(filepath) > 0)) {
img_filepath(idict) = strdup(filepath);
@@ -290,22 +258,22 @@ void read_img(image_dict * idict)
}
}
if (img_filepath(idict) == NULL && (strstr(img_filename(idict),"data:application/pdf,") != NULL)) {
- /* we need to check here for a pdf memstream */
+ /*tex We need to check here for a pdf memstream. */
img_filepath(idict) = strdup(img_filename(idict));
} else if (callback_id == 0) {
- /* otherwise we use kpse but only when we don't callback */
+ /*tex Otherwise we use kpse but only when we don't callback. */
img_filepath(idict) = kpse_find_file(img_filename(idict), kpse_tex_format, true);
}
if (img_filepath(idict) == NULL) {
- /* in any case we need a name */
+ /*tex In any case we need a name. */
formatted_error("pdf backend","cannot find image file '%s'", img_filename(idict));
}
}
recorder_record_input(img_filepath(idict));
- /* type checks */
+ /*tex A few type checks. */
check_type_by_header(idict);
check_type_by_extension(idict);
- /* read image */
+ /*tex Now we're ready to read the image. */
switch (img_type(idict)) {
case IMG_TYPE_PDFMEMSTREAM:
case IMG_TYPE_PDF:
@@ -340,8 +308,7 @@ void read_img(image_dict * idict)
}
}
-@ @c
-static image_dict *read_image(char *file_name, int page_num, char *page_name, int colorspace, int page_box)
+static image_dict *read_image(char *file_name, int page_num, char *page_name, int colorspace, int page_box, char *user_password, char *owner_password, char *visible_filename)
{
image *a = new_image();
image_dict *idict = img_dict(a) = new_image_dict();
@@ -353,6 +320,9 @@ static image_dict *read_image(char *file_name, int page_num, char *page_name, in
img_colorspace(idict) = colorspace;
img_pagenum(idict) = page_num;
img_pagename(idict) = page_name;
+ img_userpassword(idict) = user_password;
+ img_ownerpassword(idict) = owner_password;
+ img_visiblefilename(idict) = visible_filename;
if (file_name == NULL) {
normal_error("pdf backend","no image filename given");
}
@@ -363,8 +333,12 @@ static image_dict *read_image(char *file_name, int page_num, char *page_name, in
return idict;
}
-@ scans PDF pagebox specification
-@c
+/*tex
+
+ There can be several page boxes. Normally the cropbox is used.
+
+*/
+
static pdfboxspec_e scan_pdf_box_spec(void)
{
if (scan_keyword("mediabox"))
@@ -381,14 +355,13 @@ static pdfboxspec_e scan_pdf_box_spec(void)
return PDF_BOX_SPEC_NONE;
}
-@ @c
-void scan_pdfximage(PDF pdf) /* static_pdf */
+void scan_pdfximage(PDF pdf)
{
scaled_whd alt_rule;
image_dict *idict;
int transform = 0, page = 1, pagebox, colorspace = 0;
- char *named = NULL, *attr = NULL, *file_name = NULL;
- alt_rule = scan_alt_rule(); /* scans |<rule spec>| to |alt_rule| */
+ char *named = NULL, *attr = NULL, *file_name = NULL, *user = NULL, *owner = NULL, *visible = NULL;
+ alt_rule = scan_alt_rule();
if (scan_keyword("attr")) {
scan_toks(false, true);
attr = tokenlist_to_cstring(def_ref, true, NULL);
@@ -396,13 +369,33 @@ void scan_pdfximage(PDF pdf) /* static_pdf */
}
if (scan_keyword("named")) {
scan_toks(false, true);
- named = tokenlist_to_cstring(def_ref, true, NULL);
+ if (0) {
+ named = tokenlist_to_cstring(def_ref, true, NULL);
+ page = 0;
+ } else {
+ normal_warning("pdf backend","named pages are not supported, using page 1");
+ page = 1;
+ }
delete_token_ref(def_ref);
- page = 0;
} else if (scan_keyword("page")) {
scan_int();
page = cur_val;
}
+ if (scan_keyword("userpassword")) {
+ scan_toks(false, true);
+ user = tokenlist_to_cstring(def_ref, true, NULL);
+ delete_token_ref(def_ref);
+ }
+ if (scan_keyword("ownerpassword")) {
+ scan_toks(false, true);
+ owner = tokenlist_to_cstring(def_ref, true, NULL);
+ delete_token_ref(def_ref);
+ }
+ if (scan_keyword("visiblefilename")) {
+ scan_toks(false, true);
+ visible = tokenlist_to_cstring(def_ref, true, NULL);
+ delete_token_ref(def_ref);
+ }
if (scan_keyword("colorspace")) {
scan_int();
colorspace = cur_val;
@@ -419,7 +412,7 @@ void scan_pdfximage(PDF pdf) /* static_pdf */
normal_error("pdf backend","no image filename given");
}
delete_token_ref(def_ref);
- idict = read_image(file_name, page, named, colorspace, pagebox);
+ idict = read_image(file_name, page, named, colorspace, pagebox, user, owner, visible);
img_attr(idict) = attr;
img_dimen(idict) = alt_rule;
img_transform(idict) = transform;
@@ -427,33 +420,32 @@ void scan_pdfximage(PDF pdf) /* static_pdf */
last_saved_image_pages = img_totalpages(idict);
}
-@ @c
void scan_pdfrefximage(PDF pdf)
{
- /* one could scan transform as well */
+ /*tex One could scan transform as well. */
int transform = 0;
- /* begin of experiment */
+ /*tex Begin of experiment. */
int open = 0;
- /* end of experiment */
+ /*tex End of experiment. */
image_dict *idict;
- /* scans |<rule spec>| to |alt_rule| */
+ /*tex This scans |<rule spec>| to |alt_rule|. */
scaled_whd alt_rule, dim;
alt_rule = scan_alt_rule();
- /* begin of experiment */
+ /*tex Begin of experiment. */
if (scan_keyword("keepopen")) {
open = 1;
}
- /* end of experiment */
+ /*tex End of experiment. */
scan_int();
check_obj_type(pdf, obj_type_ximage, cur_val);
tail_append(new_rule(image_rule));
idict = idict_array[obj_data_ptr(pdf, cur_val)];
- /* begin of experiment */
+ /*tex Begin of experiment, */
if (open) {
- /* so we keep the original value when no close is given */
+ /*tex So we keep the original value when no close is given. */
idict->keepopen = 1;
}
- /* end of experiment */
+ /*tex End of experiment. */
if (img_state(idict) == DICT_NEW) {
normal_warning("image","don't rely on the image data to be okay");
width(tail_par) = 0;
@@ -473,38 +465,41 @@ void scan_pdfrefximage(PDF pdf)
}
}
-@ |tex_scale()| sequence of decisions:
-
-{\obeylines\obeyspaces\tt
-wd ht dp : res = tex;
-wd ht --
-wd -- dp
-wd -- --
--- ht dp
--- ht --
--- -- dp
--- -- -- : res = nat;
-}
+/*
+ The |tex_scale| function follows a sequence of decisions:
+
+ \starttyping
+ wd ht dp : res = tex;
+ wd ht --
+ wd -- dp
+ wd -- --
+ -- ht dp
+ -- ht --
+ -- -- dp
+ -- -- -- : res = nat;
+ \stoptyping
+
+*/
-@c
scaled_whd tex_scale(scaled_whd nat, scaled_whd tex)
{
scaled_whd res;
if (!is_running(tex.wd) && !is_running(tex.ht) && !is_running(tex.dp)) {
- /* width, height, and depth specified */
+ /*tex width, height, and depth specified */
res = tex;
- } else /* max. 2 dimensions are specified */ if (!is_running(tex.wd)) {
+ } else if (!is_running(tex.wd)) {
+ /*tex max. 2 dimensions are specified */
res.wd = tex.wd;
if (!is_running(tex.ht)) {
res.ht = tex.ht;
- /* width and height specified */
+ /*tex width and height specified */
res.dp = ext_xn_over_d(tex.ht, nat.dp, nat.ht);
} else if (!is_running(tex.dp)) {
res.dp = tex.dp;
- /* width and depth specified */
+ /*tex width and depth specified */
res.ht = ext_xn_over_d(tex.wd, nat.ht + nat.dp, nat.wd) - tex.dp;
} else {
- /* only width specified */
+ /*tex only width specified */
res.ht = ext_xn_over_d(tex.wd, nat.ht, nat.wd);
res.dp = ext_xn_over_d(tex.wd, nat.dp, nat.wd);
}
@@ -512,44 +507,50 @@ scaled_whd tex_scale(scaled_whd nat, scaled_whd tex)
res.ht = tex.ht;
if (!is_running(tex.dp)) {
res.dp = tex.dp;
- /* height and depth specified */
+ /*tex height and depth specified */
res.wd = ext_xn_over_d(tex.ht + tex.dp, nat.wd, nat.ht + nat.dp);
} else {
- /* only height specified */
+ /*tex only height specified */
res.wd = ext_xn_over_d(tex.ht, nat.wd, nat.ht);
res.dp = ext_xn_over_d(tex.ht, nat.dp, nat.ht);
}
} else if (!is_running(tex.dp)) {
res.dp = tex.dp;
- /* only depth specified */
+ /*tex only depth specified */
res.ht = nat.ht - (tex.dp - nat.dp);
res.wd = nat.wd;
} else {
- /* nothing specified */
+ /*tex nothing specified */
res = nat;
}
return res;
}
-@ Within |scale_img()| only image width and height matter;
-the offsets and positioning are not interesting here.
-But one needs rotation info to swap width and height.
-|img_rotation()| comes from the optional /Rotate key in the PDF file.
+/*tex
+
+Within |scale_img| only image width and height matter; the offsets and
+positioning are not interesting here. But one needs rotation info to swap width
+and height. |img_rotation| comes from the optional |/Rotate| key in the PDF file.
+
+*/
-@c
scaled_whd scale_img(image_dict * idict, scaled_whd alt_rule, int transform)
{
- int x, y, xr, yr, tmp; /* size and resolution of image */
- scaled_whd nat; /* natural size corresponding to image resolution */
+ /*tex size and resolution of image */
+ int x, y, xr, yr, tmp;
+ /*tex natural size corresponding to image resolution */
+ scaled_whd nat;
int default_res;
if ((img_type(idict) == IMG_TYPE_PDF || img_type(idict) == IMG_TYPE_PDFMEMSTREAM
|| img_type(idict) == IMG_TYPE_PDFSTREAM) && img_is_bbox(idict)) {
- x = img_xsize(idict) = img_bbox(idict)[2] - img_bbox(idict)[0]; /* dimensions from image.bbox */
+ /*tex dimensions from image.bbox */
+ x = img_xsize(idict) = img_bbox(idict)[2] - img_bbox(idict)[0];
y = img_ysize(idict) = img_bbox(idict)[3] - img_bbox(idict)[1];
img_xorig(idict) = img_bbox(idict)[0];
img_yorig(idict) = img_bbox(idict)[1];
} else {
- x = img_xsize(idict); /* dimensions, resolutions from image file */
+ /*tex dimensions, resolutions from image file */
+ x = img_xsize(idict);
y = img_ysize(idict);
}
xr = img_xres(idict);
@@ -569,7 +570,8 @@ scaled_whd scale_img(image_dict * idict, scaled_whd alt_rule, int transform)
xr = yr;
yr = tmp;
}
- nat.dp = 0; /* always for images */
+ /*tex always for images */
+ nat.dp = 0;
if (img_type(idict) == IMG_TYPE_PDF || img_type(idict) == IMG_TYPE_PDFMEMSTREAM
|| img_type(idict) == IMG_TYPE_PDFSTREAM) {
nat.wd = x;
@@ -591,7 +593,6 @@ scaled_whd scale_img(image_dict * idict, scaled_whd alt_rule, int transform)
return tex_scale(nat, alt_rule);
}
-@ @c
void write_img(PDF pdf, image_dict * idict)
{
if (img_state(idict) < DICT_WRITTEN) {
@@ -628,15 +629,17 @@ void write_img(PDF pdf, image_dict * idict)
img_state(idict) = DICT_WRITTEN;
}
-@ write an image
-@c
+int write_img_object(PDF pdf, image_dict * idict, int n)
+{
+ return write_epdf_object(pdf, idict, n);
+}
+
void pdf_write_image(PDF pdf, int n)
{
if (pdf->draftmode == 0)
write_img(pdf, idict_array[obj_data_ptr(pdf, n)]);
}
-@ @c
void check_pdfstream_dict(image_dict * idict)
{
if (!img_is_bbox(idict))
@@ -645,40 +648,43 @@ void check_pdfstream_dict(image_dict * idict)
img_state(idict) = DICT_FILESCANNED;
}
-@ @c
void write_pdfstream(PDF pdf, image_dict * idict)
{
pdf_begin_obj(pdf, img_objnum(idict), OBJSTM_NEVER);
pdf_begin_dict(pdf);
pdf_dict_add_name(pdf, "Type", "XObject");
pdf_dict_add_name(pdf, "Subtype", "Form");
- if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
- pdf_printf(pdf, "\n%s\n", img_attr(idict));
pdf_dict_add_int(pdf, "FormType", 1);
pdf_add_name(pdf, "BBox");
pdf_begin_array(pdf);
- copyReal(pdf, sp2bp(img_bbox(idict)[0]));
- copyReal(pdf, sp2bp(img_bbox(idict)[1]));
- copyReal(pdf, sp2bp(img_bbox(idict)[2]));
- copyReal(pdf, sp2bp(img_bbox(idict)[3]));
+ pdf_add_real(pdf, sp2bp(img_bbox(idict)[0]));
+ pdf_add_real(pdf, sp2bp(img_bbox(idict)[1]));
+ pdf_add_real(pdf, sp2bp(img_bbox(idict)[2]));
+ pdf_add_real(pdf, sp2bp(img_bbox(idict)[3]));
pdf_end_array(pdf);
- pdf_dict_add_streaminfo(pdf);
+ if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) {
+ pdf_printf(pdf, "\n%s\n", img_attr(idict));
+ }
+ if (!img_nolength(idict)) {
+ pdf_dict_add_streaminfo(pdf);
+ }
pdf_end_dict(pdf);
pdf_begin_stream(pdf);
- if (img_pdfstream_stream(idict) != NULL)
- pdf_puts(pdf, img_pdfstream_stream(idict));
+ if (img_pdfstream_stream(idict) != NULL) {
+ pdf_out_block(pdf, (const char *) img_pdfstream_stream(idict), img_pdfstream_size(idict));
+ }
pdf_end_stream(pdf);
pdf_end_obj(pdf);
}
-@ @c
idict_entry *idict_ptr, *idict_array = NULL;
size_t idict_limit;
void idict_to_array(image_dict * idict)
{
- if (idict_ptr - idict_array == 0) { /* align to count from 1 */
- alloc_array(idict, 1, SMALL_BUF_SIZE); /* /Im0 unused */
+ if (idict_ptr - idict_array == 0) {
+ /*tex align to count from 1 */
+ alloc_array(idict, 1, SMALL_BUF_SIZE);
idict_ptr++;
}
alloc_array(idict, 1, SMALL_BUF_SIZE);
@@ -690,53 +696,60 @@ void pdf_dict_add_img_filename(PDF pdf, image_dict * idict)
{
char *p;
if ((pdf_image_addfilename > 0) && ((pdf_suppress_optional_info & 2) == 0)) {
- /* for now PTEX.FileName only for PDF, but prepared for JPG, PNG, ... */
+ /*tex
+ For now |PTEX.FileName| is only used for \PDF, but we're prepared
+ for \JPG, \PNG, ...
+ */
if (! ( (img_type(idict) == IMG_TYPE_PDF) || (img_type(idict) == IMG_TYPE_PDFMEMSTREAM) ))
return;
if (img_visiblefilename(idict) != NULL) {
if (strlen(img_visiblefilename(idict)) == 0) {
- return; /* empty string blocks PTEX.FileName output */
+ /*tex empty string blocks PTEX.FileName output */
+ return;
} else {
p = img_visiblefilename(idict);
}
} else {
- /* unset so let's use the default */
+ /*tex unset so let's use the default */
p = img_filepath(idict);
}
- // write additional information
+ /*tex write additional information */
pdf_add_name(pdf, "PTEX.FileName");
pdf_printf(pdf, " (%s)", convertStringToPDFString(p, strlen(p)));
}
}
-/* hh: why store images in the format ... let's get rid of this */
+/*tex
-@ To allow the use of box resources inside saved boxes in -ini mode,
-the information in the array has to be (un)dumped with the format.
-The next two routines take care of that.
+To allow the use of box resources inside saved boxes in -ini mode, the
+information in the array has to be (un)dumped with the format. The next two
+routines take care of that.
-Most of the work involved in setting up the images is simply
-executed again. This solves the many possible errors resulting from
-the split in two separate runs.
+Most of the work involved in setting up the images is simply executed again. This
+solves the many possible errors resulting from the split in two separate runs.
-There was only one problem remaining: The pdfversion and
-pdfinclusionerrorlevel can have changed inbetween the call to
-|readimage()| and dump time.
+There was only one problem remaining: The |pdfversion| and
+|pdfinclusionerrorlevel| can have changed inbetween the call to |readimage| and
+dump time.
-some of the dumped values are really type int, not integer,
-but since the macro falls back to |generic_dump| anyway, that
-does not matter.
+Some of the dumped values are really type int, not integer,but since the macro
+falls back to |generic_dump| anyway, that does not matter.
+
+We might drop this feature as it makes no sense to store images in the format.
+
+*/
-@c
#define dumpinteger generic_dump
#define undumpinteger generic_undump
-@ (un)dumping a string means dumping the allocation size, followed
- by the bytes. The trailing \.{\\0} is dumped as well, because that
- makes the code simpler.
+/*tex
+
+(Un)dumping a string means dumping the allocation size, followed by the bytes.
+The trailing \.{\\0} is dumped as well, because that makes the code simpler. The
+rule specification ends up in |alt_rule|.
+
+*/
-@ scan rule spec to |alt_rule|
-@c
scaled_whd scan_alt_rule(void)
{
boolean loop;
@@ -763,8 +776,12 @@ scaled_whd scan_alt_rule(void)
return alt_rule;
}
-@ copy file of arbitrary size to PDF buffer and flush as needed
-@c
+/*tex
+
+ This copy a file of arbitrary size to the buffer and flushed as needed.
+
+*/
+
size_t read_file_to_buf(PDF pdf, FILE * f, size_t len)
{
size_t i, j, k = 0;
diff --git a/Build/source/texk/web2c/luatexdir/image/writejbig2.w b/Build/source/texk/web2c/luatexdir/image/writejbig2.c
index a58313ce8d8..77a1ddb07ca 100644
--- a/Build/source/texk/web2c/luatexdir/image/writejbig2.w
+++ b/Build/source/texk/web2c/luatexdir/image/writejbig2.c
@@ -1,27 +1,30 @@
-% writejbig2.w
-%
-% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org>
-% Copyright 2006-2013 Taco Hoekwater <taco@@luatex.org>
-% Copyright 2003-2013 Hartmut Henkel <hartmut@@luatex.org>
-%
-% This file is part of LuaTeX.
-%
-% LuaTeX is free software; you can redistribute it and/or modify it under
-% the terms of the GNU General Public License as published by the Free
-% Software Foundation; either version 2 of the License, or (at your
-% option) any later version.
-%
-% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
-% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
-% License for more details.
-%
-% You should have received a copy of the GNU General Public License along
-% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
-
-@
-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.
+/*
+
+writejbig2.c
+
+Copyright 1996-2006 Han The Thanh <thanh@pdftex.org>
+Copyright 2006-2013 Taco Hoekwater <taco@luatex.org>
+Copyright 2003-2013 Hartmut Henkel <hartmut@luatex.org>
+
+This file is part of LuaTeX.
+
+LuaTeX is free software; you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation;
+either version 2 of the License, or (at your option) any later version.
+
+LuaTeX is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+LuaTeX; if not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+/*tex
+
+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
==========
@@ -78,7 +81,8 @@ object exists, reference it. Else create fresh one.
09 Dec. 2002: JBIG2 seg. page numbers > 0 are now set to 1, see PDF Ref.
-@ @c
+*/
+
#undef DEBUG
#include "ptexlib.h"
@@ -87,8 +91,8 @@ object exists, reference it. Else create fresh one.
#include <assert.h>
#include "image/image.h"
-@ @c
-/* 7.3 Segment types */
+/*tex Table 7.3: Segment types */
+
#define M_SymbolDictionary 0
#define M_IntermediateTextRegion 4
#define M_ImmediateTextRegion 6
@@ -111,13 +115,12 @@ object exists, reference it. Else create fresh one.
#define M_Tables 53
#define M_Extension 62
-@ @c
typedef enum { INITIAL, HAVEINFO, WRITEPDF } PHASE;
typedef struct _LITEM {
struct _LITEM *prev;
struct _LITEM *next;
- void *d; /* data */
+ void *d;
} LITEM;
typedef struct _LIST {
@@ -130,26 +133,28 @@ 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() */
+ /*tex Set by |readseghdr|: */
+ unsigned int seghdrflags;
+ boolean pageassocsizeflag;
+ unsigned int reftosegcount;
+ unsigned int countofrefered;
+ unsigned int fieldlen;
+ unsigned int segnumwidth;
+ long segpage;
+ unsigned long segdatalen;
+ unsigned long hdrstart;
+ unsigned long hdrend;
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() */
+ /*tex Set by |checkseghdrflags|: */
+ boolean endofstripeflag;
+ boolean endofpageflag;
+ boolean pageinfoflag;
+ boolean endoffileflag;
} SEGINFO;
typedef struct _PAGEINFO {
- LIST segments; /* segments associated with page */
+ LIST segments;
unsigned long pagenum;
unsigned int width;
unsigned int height;
@@ -164,17 +169,19 @@ typedef struct _FILEINFO {
FILE *file;
char *filepath;
long filesize;
- LIST pages; /* not including page0 */
+ /*tex Not including |page0|: */
+ LIST pages;
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()| */
+ /*tex Set by |readfilehdr| */
+ unsigned int filehdrflags;
+ boolean sequentialaccess;
+ unsigned long numofpages;
+ /*tex Set by |get_jbig2_info| */
+ unsigned long streamstart;
unsigned long pdfpage0objnum;
PHASE phase;
} FILEINFO;
-@ @c
static struct avl_table *file_tree = NULL;
static int comp_file_entry(const void *pa, const void *pb, void *p)
@@ -195,7 +202,6 @@ static int comp_segment_entry(const void *pa, const void *pb, void *p)
return (int) (((const SEGINFO *) pa)->segnum - ((const SEGINFO *) pb)->segnum);
}
-@ @c
static int ygetc(FILE * stream)
{
int c = getc(stream);
@@ -208,7 +214,6 @@ static int ygetc(FILE * stream)
return c;
}
-@ @c
static void initlinkedlist(LIST * lp)
{
lp->first = NULL;
@@ -233,7 +238,6 @@ static LIST *litem_append(LIST * lp)
return lp;
}
-@ @c
static FILEINFO *new_fileinfo(void)
{
FILEINFO *fip;
@@ -252,7 +256,6 @@ static FILEINFO *new_fileinfo(void)
return fip;
}
-@ @c
static PAGEINFO *new_pageinfo(void)
{
PAGEINFO *pip;
@@ -269,7 +272,6 @@ static PAGEINFO *new_pageinfo(void)
return pip;
}
-@ @c
static void init_seginfo(SEGINFO * sip)
{
sip->segnum = 0;
@@ -293,7 +295,6 @@ static void init_seginfo(SEGINFO * sip)
sip->endoffileflag = false;
}
-@ @c
static void pages_maketree(LIST * plp)
{
LITEM *ip;
@@ -307,7 +308,6 @@ static void pages_maketree(LIST * plp)
}
}
-@ @c
static void segments_maketree(LIST * slp)
{
LITEM *ip;
@@ -321,7 +321,6 @@ static void segments_maketree(LIST * slp)
}
}
-@ @c
static PAGEINFO *find_pageinfo(LIST * plp, unsigned long pagenum)
{
PAGEINFO tmp;
@@ -330,7 +329,6 @@ static PAGEINFO *find_pageinfo(LIST * plp, unsigned long pagenum)
return (PAGEINFO *) avl_find(plp->tree, &tmp);
}
-@ @c
static SEGINFO *find_seginfo(LIST * slp, unsigned long segnum)
{
SEGINFO tmp;
@@ -339,21 +337,18 @@ static SEGINFO *find_seginfo(LIST * slp, unsigned long segnum)
return (SEGINFO *) avl_find(slp->tree, &tmp);
}
-@ @c
unsigned int read2bytes(FILE * f)
{
unsigned int c = (unsigned int) ygetc(f);
return (c << 8) + (unsigned int) ygetc(f);
}
-@ @c
unsigned int read4bytes(FILE * f)
{
unsigned int l = read2bytes(f);
return (l << 16) + read2bytes(f);
}
-@ @c
static unsigned long getstreamlen(LITEM * slip, boolean refer)
{
SEGINFO *sip;
@@ -366,39 +361,40 @@ static unsigned long getstreamlen(LITEM * slip, boolean refer)
return len;
}
-@ @c
static void readfilehdr(FILEINFO * fip)
{
unsigned int i;
- /* Annex D.4 File header syntax */
- /* Annex D.4.1 ID string */
+ /*tex Annex D.4: File header syntax */
+ /*tex 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])
normal_error("readjbig2","ID string missing");
- /* Annex D.4.2 File header flags */
+ /*tex Annex D.4.2: File header flags */
fip->filehdrflags = (unsigned int) ygetc(fip->file);
fip->sequentialaccess = (fip->filehdrflags & 0x01) ? true : false;
- if (fip->sequentialaccess) { /* Annex D.1 vs. Annex D.2 */
+ if (fip->sequentialaccess) {
+ /*tex Annex D.1 vs. Annex D.2 */
xfseek(fip->file, 0, SEEK_END, fip->filepath);
fip->filesize = (long) xftello(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 */
+ /*tex Annex D.4.3: Number of pages */
+ if (( !(fip->filehdrflags >> 1)) & 0x01) {
+ /*tex The known number of pages: */
fip->numofpages = read4bytes(fip->file);
- /* --- at end of file header --- */
+ }
+ /*tex End of file header */
}
-@ @c
static void checkseghdrflags(SEGINFO * sip)
{
sip->endofstripeflag = false;
sip->endofpageflag = false;
sip->pageinfoflag = false;
sip->endoffileflag = false;
- /* 7.3 Segment types */
+ /*tex Table 7.3: Segment types */
switch (sip->seghdrflags & 0x3f) {
case M_SymbolDictionary:
case M_IntermediateTextRegion:
@@ -437,24 +433,34 @@ static void checkseghdrflags(SEGINFO * sip)
}
}
-@ for first reading of file; return value tells if header been read
+/*tex
+
+ For first reading of file; return value tells if header been read.
+
+*/
-@c
static boolean readseghdr(FILEINFO * fip, SEGINFO * sip)
{
unsigned int i;
sip->hdrstart = xftell(fip->file, fip->filepath);
- if (fip->sequentialaccess && sip->hdrstart == (unsigned) fip->filesize)
- return false; /* no endoffileflag is ok for sequentialaccess */
- /* 7.2.2 Segment number */
+ if (fip->sequentialaccess && sip->hdrstart == (unsigned) fip->filesize) {
+ /*tex No endoffileflag is ok for sequential access. */
+ return false;
+ }
+ /*tex Table 7.2.2: Segment number */
sip->segnum = read4bytes(fip->file);
- /* 7.2.3 Segment header flags */
+ /*tex Table 7.2.3: Segment header flags */
sip->seghdrflags = (unsigned int) ygetc(fip->file);
checkseghdrflags(sip);
- if (fip->sequentialaccess && sip->endoffileflag) /* accept shorter segment, */
- return true; /* makes it compliant with Example 3.4 of PDFRef. 5th ed. */
+ if (fip->sequentialaccess && sip->endoffileflag) {
+ /*
+ Accept shorter segment, makes it compliant with Example 3.4 of
+ PDFRef. 5th ed.
+ */
+ return true;
+ }
sip->pageassocsizeflag = ((sip->seghdrflags >> 6) & 0x01) ? true : false;
- /* 7.2.4 Referred-to segment count and retention flags */
+ /*tex Table 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)
@@ -463,7 +469,7 @@ static boolean readseghdr(FILEINFO * fip, SEGINFO * sip)
sip->fieldlen = 5 + sip->countofrefered / 8;
xfseek(fip->file, sip->fieldlen - 1, SEEK_CUR, fip->filepath);
}
- /* 7.2.5 Referred-to segment numbers */
+ /*tex Table 7.2.5: Referred-to segment numbers */
if (sip->segnum <= 256)
sip->segnumwidth = 1;
else if (sip->segnum <= 65536)
@@ -483,19 +489,18 @@ static boolean readseghdr(FILEINFO * fip, SEGINFO * sip)
break;
}
}
- /* 7.2.6 Segment page association */
+ /*tex Table 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 */
+ /*tex Table 7.2.7: Segment data length */
sip->segdatalen = read4bytes(fip->file);
sip->hdrend = (unsigned long) xftello(fip->file, fip->filepath);
- /* ---- at end of segment header ---- */
+ /*tex End of segment header. */
return true;
}
-@ @c
static void checkseghdr(FILEINFO * fip, SEGINFO * sip);
static void markpage0seg(FILEINFO * fip, unsigned long referedseg)
@@ -511,19 +516,23 @@ static void markpage0seg(FILEINFO * fip, unsigned long referedseg)
}
}
-@ for writing, marks refered page0 segments, sets segpage > 0 to 1
+/*tex
+
+ For writing, marks refered page0 segments, sets segpage larger than
+ zero to one.
+
+*/
-@c
static void writeseghdr(PDF pdf, 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 */
+ /*tex Table 7.2.2: Segment number */
+ /*tex Table 7.2.3: Segment header flags */
+ /*tex Table 7.2.4: Referred-to segment count and retention flags */
for (i = 0; i < 5 + sip->fieldlen; i++)
pdf_out(pdf, ygetc(fip->file));
- /* 7.2.5 Referred-to segment numbers */
+ /*tex Table 7.2.5: Referred-to segment numbers */
for (i = 0; i < sip->countofrefered; i++) {
switch (sip->segnumwidth) {
case 1:
@@ -548,7 +557,7 @@ static void writeseghdr(PDF pdf, FILEINFO * fip, SEGINFO * sip)
}
if (sip->countofrefered > 0)
sip->refers = true;
- /* 7.2.6 Segment page association */
+ /*tex Table 7.2.6: Segment page association */
if (sip->pageassocsizeflag)
for (i = 0; i < 3; i++) {
(void) ygetc(fip->file);
@@ -556,23 +565,27 @@ static void writeseghdr(PDF pdf, FILEINFO * fip, SEGINFO * sip)
}
(void) ygetc(fip->file);
pdf_out(pdf, (unsigned char) ((sip->segpage > 0) ? 1 : 0));
- /* 7.2.7 Segment data length */
+ /*tex Table 7.2.7: Segment data length */
for (i = 0; i < 4; i++)
pdf_out(pdf, ygetc(fip->file));
- /* ---- at end of segment header ---- */
+ /* End of segment header. */
}
-@ for recursive marking of refered page0 segments
-@c
+/*tex
+
+ For recursive marking of refered page0 segments:
+
+*/
+
static 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 */
+ /*tex Table 7.2.2: Segment number */
+ /*tex Table 7.2.3: Segment header flags */
+ /*tex Table 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 */
+ /*tex Table 7.2.5: Referred-to segment numbers */
for (i = 0; i < sip->countofrefered; i++) {
switch (sip->segnumwidth) {
case 1:
@@ -590,33 +603,34 @@ static void checkseghdr(FILEINFO * fip, SEGINFO * sip)
}
if (sip->countofrefered > 0)
sip->refers = true;
- /* 7.2.6 Segment page association */
- /* 7.2.7 Segment data length */
+ /*tex Table 7.2.6: Segment page association */
+ /*tex Table 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 ---- */
+ /*tex End of segment header. */
}
-@ @c
static unsigned long findstreamstart(FILEINFO * fip)
{
SEGINFO tmp;
- assert(!fip->sequentialaccess); /* D.2 Random-access organisation */
- do /* find random-access stream start */
+ /*tex Table D.2: Random-access organisation */
+ do {
+ /*tex Find random-access stream start. */
(void) readseghdr(fip, &tmp);
- while (!tmp.endoffileflag);
+ } while (!tmp.endoffileflag);
fip->streamstart = tmp.hdrend;
readfilehdr(fip);
return fip->streamstart;
}
-@ @c
static void rd_jbig2_info(FILEINFO * fip)
{
- unsigned long seekdist = 0; /* for sequential-access only */
- unsigned long streampos = 0; /* for random-access only */
+ /*tex For sequential-access only: */
+ unsigned long seekdist = 0;
+ /*tex For random-access only: */
+ unsigned long streampos = 0;
unsigned long currentpage = 0;
boolean sipavail = false;
PAGEINFO *pip;
@@ -624,9 +638,12 @@ static void rd_jbig2_info(FILEINFO * fip)
LIST *plp, *slp;
fip->file = xfopen(fip->filepath, FOPEN_RBIN_MODE);
readfilehdr(fip);
- if (!fip->sequentialaccess) /* D.2 Random-access organisation */
+ if (!fip->sequentialaccess) {
+ /*tex Table D.2: Random-access organisation */
streampos = findstreamstart(fip);
- while (true) { /* loop over segments */
+ }
+ while (true) {
+ /*tex Loop over segments: */
if (!sipavail) {
sip = xtalloc(1, SEGINFO);
sipavail = true;
@@ -658,11 +675,10 @@ static void rd_jbig2_info(FILEINFO * fip)
else
sip->datastart = sip->hdrend;
sip->dataend = sip->datastart + sip->segdatalen;
- if (!fip->sequentialaccess
- && (sip->pageinfoflag || sip->endofstripeflag))
+ if (!fip->sequentialaccess && (sip->pageinfoflag || sip->endofstripeflag))
xfseeko(fip->file, (off_t) sip->datastart, SEEK_SET, fip->filepath);
seekdist = sip->segdatalen;
- /* 7.4.8 Page information segment syntax */
+ /*tex Table 7.4.8: Page information segment syntax */
if (sip->pageinfoflag) {
pip->pagenum = (unsigned long) sip->segpage;
pip->width = read4bytes(fip->file);
@@ -670,7 +686,7 @@ static void rd_jbig2_info(FILEINFO * fip)
pip->xres = read4bytes(fip->file);
pip->yres = read4bytes(fip->file);
pip->pagesegmentflags = (unsigned) ygetc(fip->file);
- /* 7.4.8.6 Page striping information */
+ /*tex Table 7.4.8.6: Page striping information */
pip->stripinginfo = read2bytes(fip->file);
seekdist -= 19;
}
@@ -694,9 +710,7 @@ static void rd_jbig2_info(FILEINFO * fip)
xfclose(fip->file, fip->filepath);
}
-@ @c
-static void wr_jbig2(PDF pdf, image_dict * idict, FILEINFO * fip,
- unsigned long page)
+static void wr_jbig2(PDF pdf, image_dict * idict, FILEINFO * fip, unsigned long page)
{
LITEM *slip;
PAGEINFO *pip;
@@ -743,11 +757,12 @@ static void wr_jbig2(PDF pdf, image_dict * idict, FILEINFO * fip,
}
pdf_begin_stream(pdf);
fip->file = xfopen(fip->filepath, FOPEN_RBIN_MODE);
- for (slip = pip->segments.first; slip != NULL; slip = slip->next) { /* loop over page segments */
+ for (slip = pip->segments.first; slip != NULL; slip = slip->next) {
+ /*tex Loop over page segments. */
sip = slip->d;
if (sip->isrefered || page > 0) {
xfseeko(fip->file, (off_t) sip->hdrstart, SEEK_SET, fip->filepath);
- /* mark refered-to page 0 segments, change segpages > 1 to 1 */
+ /*tex Mark refered-to page 0 segments, change segpages > 1 to 1. */
writeseghdr(pdf, fip, sip);
xfseeko(fip->file, (off_t) sip->datastart, SEEK_SET, fip->filepath);
for (i = sip->datastart; i < sip->dataend; i++)
@@ -759,7 +774,6 @@ static void wr_jbig2(PDF pdf, image_dict * idict, FILEINFO * fip,
xfclose(fip->file, fip->filepath);
}
-@ @c
boolean supported_jbig2(image_dict * idict)
{
if (img_pdfmajorversion(idict) < 2 && img_pdfminorversion(idict) < 4) {
@@ -770,20 +784,19 @@ boolean supported_jbig2(image_dict * idict)
}
}
-@ @c
void flush_jbig2_info(image_dict * idict)
{
- /* todo */
+ /*tex Todo (or not). */
}
-@ @c
void read_jbig2_info(image_dict * idict)
{
FILEINFO *fip, tmp;
PAGEINFO *pip;
- img_type(idict) = IMG_TYPE_JBIG2; /* already set probably, see other read_... */
+ /*tex Already set probably, see other |read_|. */
+ img_type(idict) = IMG_TYPE_JBIG2;
if (! supported_jbig2(idict)) {
- /* already an error done */
+ /*tex Already an error seen? */
}
if (img_pagenum(idict) < 1) {
normal_error("readjbig2","page must be > 0");
@@ -819,24 +832,19 @@ void read_jbig2_info(image_dict * idict)
img_colordepth(idict) = 1;
}
-@ @c
void write_jbig2(PDF pdf, 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 */
+ /*tex Don't write before |rd_jbig2_info()| call. */
pip = find_pageinfo(&(fip->pages), (unsigned long) img_pagenum(idict));
assert(pip != NULL);
wr_jbig2(pdf, idict, fip, pip->pagenum);
img_file(idict) = NULL;
}
-@ @c
void flush_jbig2_page0_objects(PDF pdf)
{
FILEINFO *fip;
@@ -846,7 +854,8 @@ void flush_jbig2_page0_objects(PDF pdf)
for (fip = avl_t_first(&t, file_tree); fip != NULL;
fip = avl_t_next(&t)) {
if (fip->page0.last != NULL)
- wr_jbig2(pdf, NULL, fip, 0); /* NULL: page0 */
+ /*tex |NULL|: page0 */
+ wr_jbig2(pdf, NULL, fip, 0);
}
}
}
diff --git a/Build/source/texk/web2c/luatexdir/image/writejp2.w b/Build/source/texk/web2c/luatexdir/image/writejp2.c
index cb317e11928..0ea0017084a 100644
--- a/Build/source/texk/web2c/luatexdir/image/writejp2.w
+++ b/Build/source/texk/web2c/luatexdir/image/writejp2.c
@@ -1,38 +1,42 @@
-% writejp2.w
-%
-% Copyright 2011-2013 Taco Hoekwater <taco@@luatex.org>
-% Copyright 2011-2013 Hartmut Henkel <hartmut@@luatex.org>
-%
-% This file is part of LuaTeX.
-%
-% LuaTeX is free software; you can redistribute it and/or modify it under
-% the terms of the GNU General Public License as published by the Free
-% Software Foundation; either version 2 of the License, or (at your
-% option) any later version.
-%
-% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
-% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
-% License for more details.
-%
-% You should have received a copy of the GNU General Public License along
-% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
+/*
-@ @c
+writejp2.c
-@ Basic JPEG~2000 image support. Section and Table references below:
-Information technology --- JPEG~2000 image coding system: Core coding system.
-ISO/IEC 15444-1, Second edition, 2004-09-15, file |15444-1annexi.pdf|.
+Copyright 2011-2013 Taco Hoekwater <taco@luatex.org>
+Copyright 2011-2013 Hartmut Henkel <hartmut@luatex.org>
+
+This file is part of LuaTeX.
+
+LuaTeX is free software; you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation;
+either version 2 of the License, or (at your option) any later version.
+
+LuaTeX is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+LuaTeX; if not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+/*tex
+
+ Basic JPEG~2000 image support. Section and Table references below:
+ Information technology --- JPEG~2000 image coding system: Core coding system.
+ ISO/IEC 15444-1, Second edition, 2004-09-15, file |15444-1annexi.pdf|.
+
+*/
-@c
#include "ptexlib.h"
#include <math.h>
#include <assert.h>
#include "image/image.h"
#include "image/writejp2.h"
-#include "image/writejbig2.h" /* read2bytes(), read4bytes() */
+#include "image/writejbig2.h"
+
+/*tex Table 1.2: Defined boxes */
-/* Table 1.2 -- Defined boxes */
#define BOX_JP 0x6A502020
#define BOX_FTYP 0x66747970
#define BOX_JP2H 0x6a703268
@@ -45,7 +49,8 @@ ISO/IEC 15444-1, Second edition, 2004-09-15, file |15444-1annexi.pdf|.
#define BOX_RESD 0x72657364
#define BOX_JP2C 0x6A703263
-/* 1.4 Box definition */
+/*tex Table 1.4: Box definition */
+
typedef struct {
uint64_t lbox;
unsigned int tbox;
@@ -71,7 +76,8 @@ static hdr_struct read_boxhdr(image_dict * idict)
return hdr;
}
-/* 1.5.3.1 Image Header box */
+/*tex Table 1.5.3.1: Image Header box */
+
static void scan_ihdr(image_dict * idict)
{
unsigned int height, width;
@@ -88,8 +94,9 @@ static void scan_ihdr(image_dict * idict)
(void) xgetc(img_file(idict)); /* ipr */
}
-/* 1.5.3.7.1 Capture Resolution box */
-/* 1.5.3.7.2 Default Display Resolution box */
+/*tex Table 1.5.3.7.1: Capture Resolution box */
+
+/*tex Table 1.5.3.7.2: Default Display Resolution box */
static void scan_resc_resd(image_dict * idict)
{
@@ -108,7 +115,7 @@ static void scan_resc_resd(image_dict * idict)
img_yres(idict) = (int) (vr_ + 0.5);
}
-/* 1.5.3.7 Resolution box (superbox) */
+/*tex Table 1.5.3.7: Resolution box (superbox) */
static void scan_res(image_dict * idict, uint64_t epos_s)
{
@@ -121,7 +128,7 @@ static void scan_res(image_dict * idict, uint64_t epos_s)
epos = spos + hdr.lbox;
switch (hdr.tbox) {
case (BOX_RESC):
- /* arbitrarily: let BOX_RESD have precedence */
+ /*tex arbitrary: let BOX_RESD have precedence */
if (img_xres(idict) == 0 && img_yres(idict) == 0) {
scan_resc_resd(idict);
if (xftell(img_file(idict), img_filepath(idict)) != (long)epos)
@@ -143,7 +150,7 @@ static void scan_res(image_dict * idict, uint64_t epos_s)
}
}
-/* 1.5.3 JP2 Header box (superbox) */
+/*tex Table 1.5.3: JP2 Header box (superbox) */
static boolean scan_jp2h(image_dict * idict, uint64_t epos_s)
{
@@ -178,7 +185,7 @@ static boolean scan_jp2h(image_dict * idict, uint64_t epos_s)
static void close_and_cleanup_jp2(image_dict * idict)
{
- /* if one of then is not NULL we already cleaned up */
+ /*tex If one of then is not NULL we already cleaned up. */
if (img_file(idict) != NULL) {
xfclose(img_file(idict), img_filepath(idict));
img_file(idict) = NULL;
@@ -216,11 +223,11 @@ void read_jp2_info(image_dict * idict)
normal_error("readjp2","size problem");
}
spos = epos = 0;
- /* 1.5.1 JPEG 2000 Signature box */
+ /*tex Table 1.5.1: JPEG 2000 Signature box */
hdr = read_boxhdr(idict);
epos = spos + hdr.lbox;
xfseek(img_file(idict), (long) epos, SEEK_SET, img_filepath(idict));
- /* 1.5.2 File Type box */
+ /*tex Table 1.5.2: File Type box */
spos = epos;
hdr = read_boxhdr(idict);
if (hdr.tbox != BOX_FTYP) {
@@ -256,9 +263,7 @@ static void reopen_jp2(image_dict * idict)
height = img_ysize(idict);
xres = img_xres(idict);
yres = img_yres(idict);
- /*
- we need to make sure that the file kept open
- */
+ /*tex We need to make sure that the file kept open. */
img_keepopen(idict) = 1;
read_jp2_info(idict);
if (width != img_xsize(idict) || height != img_ysize(idict)
@@ -292,6 +297,6 @@ void write_jp2(PDF pdf, image_dict * idict)
normal_error("writejp2","fread failed");
pdf_end_stream(pdf);
pdf_end_obj(pdf);
- /* always */
+ /*tex We always:*/
close_and_cleanup_jp2(idict);
}
diff --git a/Build/source/texk/web2c/luatexdir/image/writejpg.w b/Build/source/texk/web2c/luatexdir/image/writejpg.c
index 54ed47f0f92..f58dc2aa642 100644
--- a/Build/source/texk/web2c/luatexdir/image/writejpg.w
+++ b/Build/source/texk/web2c/luatexdir/image/writejpg.c
@@ -1,31 +1,30 @@
-% writejpg.w
-%
-% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org>
-% Copyright 2006-2011 Taco Hoekwater <taco@@luatex.org>
-%
-% This file is part of LuaTeX.
-%
-% LuaTeX is free software; you can redistribute it and/or modify it under
-% the terms of the GNU General Public License as published by the Free
-% Software Foundation; either version 2 of the License, or (at your
-% option) any later version.
-%
-% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
-% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
-% License for more details.
-%
-% You should have received a copy of the GNU General Public License along
-% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
-
-@ @c
+/*
+
+writejpg.w
+
+Copyright 1996-2006 Han The Thanh <thanh@pdftex.org>
+Copyright 2006-2011 Taco Hoekwater <taco@luatex.org>
+
+This file is part of LuaTeX.
+
+LuaTeX is free software; you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation;
+either version 2 of the License, or (at your option) any later version.
+
+LuaTeX is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+LuaTeX; if not, see <http://www.gnu.org/licenses/>.
+
+*/
#include "ptexlib.h"
#include <assert.h>
#include "image/image.h"
#include "image/writejpg.h"
-@ @c
#define JPG_GRAY 1 /* Gray color space, use /DeviceGray */
#define JPG_RGB 3 /* RGB color space, use /DeviceRGB */
#define JPG_CMYK 4 /* CMYK color space, use /DeviceCMYK */
@@ -97,7 +96,6 @@ typedef enum {
M_ERROR = 0x100 /* dummy marker, internal use only */
} JPEG_MARKER;
-@ @c
static unsigned int read_exif_bytes(unsigned char **p, int n, int b)
{
unsigned int rval = 0;
@@ -128,28 +126,31 @@ static unsigned int read_exif_bytes(unsigned char **p, int n, int b)
return rval;
}
-@ The Exif block can contain the data on the resolution in two forms:
-XResolution, YResolution and ResolutionUnit (tag 282, 283 and 296)
-as well as PixelPerUnitX, PixelPerUnitY and PixelUnit (tag 0x5111,
-0x5112 and 0x5110). Tags 282, 293 and 296 have the priority,
-with ResolutionUnit set to inch by default, then
-tag 0x5110, 0x5111 and 0x5112, where the only valid value for PixelUnit is 0.0254,
-and finally the given value xx and yy,
-choosen if the Exif x and y resolution are not strictly positive.
+/*tex
+
+ The Exif block can contain the data on the resolution in two forms:
+ XResolution, YResolution and ResolutionUnit (tag 282, 283 and 296) as well as
+ PixelPerUnitX, PixelPerUnitY and PixelUnit (tag 0x5111, 0x5112 and 0x5110).
+ Tags 282, 293 and 296 have the priority, with ResolutionUnit set to inch by
+ default, then tag 0x5110, 0x5111 and 0x5112, where the only valid value for
+ PixelUnit is 0.0254, and finally the given value xx and yy, choosen if the
+ Exif x and y resolution are not strictly positive.
+ The next one doesn't save the data, just reads the tags we need based on info
+ from \typ {http://www.exif.org/Exif2-2.PDF}.
+
+*/
-@ @c
static void read_APP1_Exif (FILE *fp, unsigned short length, int *xx, int *yy, int *or)
{
- /* this doesn't save the data, just reads the tags we need */
- /* based on info from http://www.exif.org/Exif2-2.PDF */
unsigned char *buffer = (unsigned char *)xmalloc(length);
unsigned char *p, *rp;
unsigned char *tiff_header;
char bigendian;
int i;
int num_fields, tag, type;
- int value = 0;/* silence uninitialized warnings */
+ /*tex silence uninitialized warnings */
+ int value = 0;
unsigned int num = 0;
unsigned int den = 0;
boolean found_x = false;
@@ -165,7 +166,6 @@ static void read_APP1_Exif (FILE *fp, unsigned short length, int *xx, int *yy, i
boolean found_x_ms = false;
boolean found_y_ms = false;
boolean found_res= false;
-
int orientation = 1;
size_t ret_len;
ret_len = fread(buffer, length, 1, fp);
@@ -193,52 +193,65 @@ static void read_APP1_Exif (FILE *fp, unsigned short length, int *xx, int *yy, i
type = read_exif_bytes(&p, 2, bigendian);
read_exif_bytes(&p, 4, bigendian);
switch (type) {
- case 1: /* byte */
+ case 1:
+ /*tex byte */
value = *p++;
p += 3;
break;
- case 3: /* unsigned short */
- case 8: /* signed short */
+ case 3:
+ /*tex unsigned short */
+ case 8:
+ /*tex signed short */
value = read_exif_bytes(&p, 2, bigendian);
p += 2;
break;
- case 4: /* unsigned long */
- case 9: /* signed long */
+ case 4:
+ /*tex unsigned long */
+ case 9:
+ /*tex signed long */
value = read_exif_bytes(&p, 4, bigendian);
break;
- case 5: /* rational */
- case 10: /* srational */
+ case 5:
+ /*tex rational */
+ case 10:
+ /*tex srational */
value = read_exif_bytes(&p, 4, bigendian);
rp = tiff_header + value;
num = read_exif_bytes(&rp, 4, bigendian);
den = read_exif_bytes(&rp, 4, bigendian);
break;
- case 7: /* undefined */
+ case 7:
+ /*tex undefined */
value = *p++;
p += 3;
break;
- case 2: /* ascii */
+ case 2:
+ /*tex ascii */
default:
p += 4;
break;
}
switch (tag) {
- case 274: /* orientation */
+ case 274:
+ /*tex orientation */
orientation = value;
break;
- case 282: /* x res */
+ case 282:
+ /*tex x res */
if (den != 0) {
xres = num / den;
found_x = true;
- }
+ }
break;
- case 283: /* y res */
+ case 283:
+ /*tex y res */
if (den != 0) {
yres = num / den;
found_y = true ;
- }
+ }
break;
- case 296: /* res unit */
+ case 296:
+ /*tex res unit */
switch (value) {
case 2:
res_unit = 1.0;
@@ -250,69 +263,69 @@ static void read_APP1_Exif (FILE *fp, unsigned short length, int *xx, int *yy, i
res_unit = 0;
break;
}
- case 0x5110: /* PixelUnit */
- switch (value) {
+ break;
+ case 0x5110:
+ /*tex PixelUnit */
+ switch (value) {
case 1:
- res_unit_ms = 0.0254; /* Unit is meter */
- break;
- default:
- res_unit_ms = 0;
- }
- case 0x5111: /* PixelPerUnitX */
+ res_unit_ms = 0.0254; /* Unit is meter */
+ break;
+ default:
+ res_unit_ms = 0;
+ }
+ break;
+ case 0x5111:
+ /*tex PixelPerUnitX */
found_x_ms = true ;
- xres_ms = value;
- break;
- case 0x5112: /* PixelPerUnitY */
+ xres_ms = value;
+ break;
+ case 0x5112:
+ /*tex PixelPerUnitY */
found_y_ms = true ;
- yres_ms = value ;
- break;
- }
-
-
+ yres_ms = value ;
+ break;
+ }
}
if (found_x && found_y && res_unit>0) {
- found_res = true;
- tempx = (int)(xres * res_unit+0.5);
- tempy = (int)(yres * res_unit+0.5);
+ found_res = true;
+ tempx = (int)(xres * res_unit+0.5);
+ tempy = (int)(yres * res_unit+0.5);
} else if (found_x_ms && found_y_ms && res_unit_ms==0.0254) {
- found_res = true;
- tempx = (int)(xres_ms * res_unit_ms+0.5);
- tempy = (int)(yres_ms * res_unit_ms+0.5);
+ found_res = true;
+ tempx = (int)(xres_ms * res_unit_ms+0.5);
+ tempy = (int)(yres_ms * res_unit_ms+0.5);
}
if (found_res) {
- if (tempx>0 && tempy>0) {
- if ((tempx!=(*xx) || tempy!=(*yy)) && (*xx!=0 && (*yy!=0) ) ) {
- formatted_warning("readjpg","Exif resolution %ddpi x %ddpi differs from the input resolution %ddpi x %ddpi",tempx,tempy,*xx,*yy);
- }
- if (tempx==1 || tempy==1) {
- formatted_warning("readjpg","Exif resolution %ddpi x %ddpi looks weird", tempx, tempy);
- }
- *xx = tempx;
- *yy = tempy;
- }else {
- formatted_warning("readjpg","Bad Exif resolution %ddpi x %ddpi (zero or negative value of a signed integer)",tempx,tempy);
- }
+ if (tempx>0 && tempy>0) {
+ if ((tempx!=(*xx) || tempy!=(*yy)) && (*xx!=0 && (*yy!=0) ) ) {
+ formatted_warning("readjpg","Exif resolution %ddpi x %ddpi differs from the input resolution %ddpi x %ddpi",tempx,tempy,*xx,*yy);
+ }
+ if (tempx==1 || tempy==1) {
+ formatted_warning("readjpg","Exif resolution %ddpi x %ddpi looks weird", tempx, tempy);
+ }
+ *xx = tempx;
+ *yy = tempy;
+ } else {
+ formatted_warning("readjpg","Bad Exif resolution %ddpi x %ddpi (zero or negative value of a signed integer)",tempx,tempy);
+ }
}
-
*or = orientation;
-
err:
free(buffer);
return;
}
-/*
+/*tex
- Contrary to pdf where several parallel usage can happen (epdf, tex, lua) with
- bitmaps we care less about keeping files open. So, we can keep files open in
- the img lib but then they are closed after inclusion anyway.
+ Contrary to \PDF\ where several parallel usage can happen (\PDF, |TEX, \LUA)
+ with bitmaps we care less about keeping files open. So, we can keep files
+ open in the img lib but then they are closed after inclusion anyway.
*/
-@ @c
static void close_and_cleanup_jpg(image_dict * idict)
{
- /* if one of then is not NULL we already cleaned up */
+ /*tex if one of then is not NULL we already cleaned up */
if (img_file(idict) != NULL) {
xfclose(img_file(idict), img_filepath(idict));
img_file(idict) = NULL;
@@ -322,19 +335,21 @@ static void close_and_cleanup_jpg(image_dict * idict)
}
}
-@ @c
void flush_jpg_info(image_dict * idict)
{
close_and_cleanup_jpg(idict);
}
-@ The jpeg images are scanned for resolution, colorspace, depth, dimensions and
-orientation. We need to look at the exif blob for that. The original version did
-a quick test for jfif and exif but there can be more blobs later on. The current
-approach is to run over the linked list of blobs which is somewhat less efficient
-but not noticeable.
+/*tex
+
+ The jpeg images are scanned for resolution, colorspace, depth, dimensions and
+ orientation. We need to look at the exif blob for that. The original version
+ did a quick test for jfif and exif but there can be more blobs later on. The
+ current approach is to run over the linked list of blobs which is somewhat
+ less efficient but not noticeable.
+
+*/
-@ @c
void read_jpg_info(image_dict * idict)
{
int i, position, units = 0;
@@ -381,16 +396,20 @@ void read_jpg_info(image_dict * idict)
position = ftell(fp);
length = 0 ;
switch (i) {
- case M_SOF3: /* lossless */
+ case M_SOF3:
+ /*tex lossless */
case M_SOF5:
case M_SOF6:
- case M_SOF7: /* lossless */
+ case M_SOF7:
+ /*tex lossless */
case M_SOF9:
case M_SOF10:
- case M_SOF11: /* lossless */
+ case M_SOF11:
+ /*tex lossless */
case M_SOF13:
case M_SOF14:
- case M_SOF15: /* lossless */
+ case M_SOF15:
+ /*tex lossless */
formatted_error("readjpg","unsupported compression SOF_%d", i - M_SOF0);
break;
case M_SOF2:
@@ -399,7 +418,8 @@ void read_jpg_info(image_dict * idict)
}
case M_SOF0:
case M_SOF1:
- length = (int) read2bytes(fp); /* read segment length */
+ /*tex read segment length */
+ length = (int) read2bytes(fp);
img_colordepth(idict) = xgetc(fp);
img_ysize(idict) = (int) read2bytes(fp);
img_xsize(idict) = (int) read2bytes(fp);
@@ -427,19 +447,20 @@ void read_jpg_info(image_dict * idict)
if (fread(app_sig, sizeof(char), 5, fp) != 5)
return;
if (!memcmp(app_sig, "JFIF\000", 5)) {
- units = (int) read2bytes(fp); /*skip two bytes, compiler is also happy*/
+ /*tex skip two bytes, compiler is also happy*/
+ units = (int) read2bytes(fp);
units = xgetc(fp);
img_xres(idict) = (int) read2bytes(fp);
img_yres(idict) = (int) read2bytes(fp);
switch (units) {
case 1:
- /* pixels per inch */
+ /*tex pixels per inch */
if ((img_xres(idict) == 1) || (img_yres(idict) == 1)) {
formatted_warning("readjpg","unusual resolution of %ddpi by %ddpi", img_xres(idict), img_yres(idict));
}
break;
case 2:
- /* pixels per cm */
+ /*tex pixels per cm */
img_xres(idict) = (int) ((double) img_xres(idict) * 2.54);
img_yres(idict) = (int) ((double) img_yres(idict) * 2.54);
break;
@@ -448,7 +469,10 @@ void read_jpg_info(image_dict * idict)
break;
}
}
- /* if either xres or yres is 0 but the other isn't, set it to the value of the other */
+ /*tex
+ If either xres or yres is 0 but the other isn't, set
+ it to the value of the other.
+ */
}
}
break;
@@ -471,7 +495,7 @@ void read_jpg_info(image_dict * idict)
}
}
break;
- /* ignore markers without parameters */
+ /*tex ignore markers without parameters */
case M_SOI:
case M_EOI:
case M_TEM:
@@ -485,23 +509,18 @@ void read_jpg_info(image_dict * idict)
case M_RST7:
break;
default:
- /* skip variable length markers */
+ /*tex skip variable length markers */
length = (int) read2bytes(fp);
break;
}
- /*
- printf("marker %X : %i %i\n",i,position,length);
- */
if (length > 0) {
xfseek(fp, position + length, SEEK_SET, img_filepath(idict));
}
}
- /* moved */
xfseek(fp, 0, SEEK_SET, img_filepath(idict));
if (! img_keepopen(idict)) {
close_and_cleanup_jpg(idict);
}
- /* */
if (okay){
if ((img_xres(idict) == 0) && (img_yres(idict) != 0)) {
img_xres(idict) = img_yres(idict);
@@ -514,14 +533,13 @@ void read_jpg_info(image_dict * idict)
}
}
-@ @c
static void reopen_jpg(image_dict * idict)
{
int width = img_xsize(idict);
int height = img_ysize(idict);
int xres = img_xres(idict);
int yres = img_yres(idict);
- /*
+ /*tex
we need to make sure that the file kept open
*/
img_keepopen(idict) = 1;
@@ -531,7 +549,6 @@ static void reopen_jpg(image_dict * idict)
}
}
-@ @c
void write_jpg(PDF pdf, image_dict * idict)
{
size_t l;
@@ -588,6 +605,5 @@ void write_jpg(PDF pdf, image_dict * idict)
}
pdf_end_stream(pdf);
pdf_end_obj(pdf);
- /* always */
close_and_cleanup_jpg(idict);
}
diff --git a/Build/source/texk/web2c/luatexdir/image/writepng.w b/Build/source/texk/web2c/luatexdir/image/writepng.c
index 412000c427f..165e202f4e3 100644
--- a/Build/source/texk/web2c/luatexdir/image/writepng.w
+++ b/Build/source/texk/web2c/luatexdir/image/writepng.c
@@ -1,36 +1,32 @@
-% writepng.w
-%
-% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org>
-% Copyright 2006-2013 Taco Hoekwater <taco@@luatex.org>
-%
-% This file is part of LuaTeX.
-%
-% LuaTeX is free software; you can redistribute it and/or modify it under
-% the terms of the GNU General Public License as published by the Free
-% Software Foundation; either version 2 of the License, or (at your
-% option) any later version.
-%
-% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
-% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
-% License for more details.
-%
-% You should have received a copy of the GNU General Public License along
-% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
-
-@ @c
+/*
+
+writepng.c
+
+Copyright 1996-2006 Han The Thanh <thanh@pdftex.org>
+Copyright 2006-2013 Taco Hoekwater <taco@luatex.org>
+
+This file is part of LuaTeX.
+
+LuaTeX is free software; you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation;
+either version 2 of the License, or (at your option) any later version.
+
+LuaTeX is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+LuaTeX; if not, see <http://www.gnu.org/licenses/>.
+
+*/
#include "ptexlib.h"
#include <assert.h>
#include "image/image.h"
#include "image/writepng.h"
-@ @c
-static int transparent_page_group = -1;
-
static void close_and_cleanup_png(image_dict * idict)
{
- /* if one of then is not NULL we already cleaned up */
if (img_file(idict) != NULL) {
xfclose(img_file(idict), img_filepath(idict));
img_file(idict) = NULL;
@@ -41,16 +37,16 @@ static void close_and_cleanup_png(image_dict * idict)
}
}
-@ @c
void flush_png_info(image_dict * idict)
{
close_and_cleanup_png(idict);
}
-@ @c
+/*tex A dummy function: */
+
static void warn(png_structp png_ptr, png_const_charp msg)
{
- (void)png_ptr; (void)msg; /* Make compiler happy */
+ (void)png_ptr; (void)msg;
}
void read_png_info(image_dict * idict)
@@ -80,12 +76,12 @@ void read_png_info(image_dict * idict)
normal_error("readpng","internal error");
}
#if PNG_LIBPNG_VER >= 10603
- /* ignore possibly incorrect CMF bytes */
+ /*tex ignore possibly incorrect CMF bytes */
png_set_option(png_p, PNG_MAXIMUM_INFLATE_WINDOW, PNG_OPTION_ON);
#endif
png_init_io(png_p, img_file(idict));
png_read_info(png_p, info_p);
- /* resolution support */
+ /*tex resolution support */
img_xsize(idict) = (int) png_get_image_width(png_p, info_p);
img_ysize(idict) = (int) png_get_image_height(png_p, info_p);
if (png_get_valid(png_p, info_p, PNG_INFO_pHYs)) {
@@ -108,15 +104,12 @@ void read_png_info(image_dict * idict)
formatted_error("readpng","unsupported type of color_type '%i'",(int) png_get_color_type(png_p, info_p));
}
img_colordepth(idict) = png_get_bit_depth(png_p, info_p);
- /*
- So we can optionally keep open a file in img.
- */
+ /*tex So we can optionally keep open a file in |img|. */
if (! img_keepopen(idict)) {
close_and_cleanup_png(idict);
}
}
-@ @c
#define write_gray_pixel_16(r) \
if (j % 4 == 0 || j % 4 == 1) \
pdf_quick_out(pdf, *r++); \
@@ -173,7 +166,6 @@ void read_png_info(image_dict * idict)
xfree(rows[i]); \
}
-@ @c
static void write_palette_streamobj(PDF pdf, int palette_objnum, png_colorp palette, int num_palette)
{
int i;
@@ -195,7 +187,6 @@ static void write_palette_streamobj(PDF pdf, int palette_objnum, png_colorp pale
pdf_end_obj(pdf);
}
-@ @c
static void write_smask_streamobj(PDF pdf, image_dict * idict, int smask_objnum, png_bytep smask, int smask_size)
{
int i;
@@ -227,7 +218,6 @@ static void write_smask_streamobj(PDF pdf, image_dict * idict, int smask_objnum,
pdf_end_obj(pdf);
}
-@ @c
static void write_png_gray(PDF pdf, image_dict * idict)
{
int i;
@@ -258,7 +248,6 @@ static void write_png_gray(PDF pdf, image_dict * idict)
pdf_end_obj(pdf);
}
-@ @c
static void write_png_gray_alpha(PDF pdf, image_dict * idict)
{
int i;
@@ -307,7 +296,6 @@ static void write_png_gray_alpha(PDF pdf, image_dict * idict)
xfree(smask);
}
-@ @c
static void write_png_rgb_alpha(PDF pdf, image_dict * idict)
{
int i;
@@ -356,20 +344,21 @@ static void write_png_rgb_alpha(PDF pdf, image_dict * idict)
xfree(smask);
}
-@ The |copy_png| code is cheerfully gleaned from Thomas Merz' PDFlib,
-file |p_png.c| ``SPNG - Simple PNG''.
-The goal is to use pdf's native FlateDecode support, if that is possible.
-Only a subset of the png files allows this, but for these it greatly
-improves inclusion speed.
+/*tex
-In the ``PNG Copy'' mode only the IDAT chunks are copied;
-all other chunks from the PNG file are discarded.
-If there are any other chunks in the PNG file,
-which might influence the visual appearance of the image,
-or if image processing like gamma change is requested,
-the ``PNG Copy'' function must be skipped; therefore the lengthy tests.
+The |copy_png| code is cheerfully gleaned from Thomas Merz' PDFlib, file
+|p_png.c| ``SPNG - Simple PNG''. The goal is to use pdf's native FlateDecode
+support, if that is possible. Only a subset of the png files allows this, but for
+these it greatly improves inclusion speed.
+
+In the ``PNG Copy'' mode only the IDAT chunks are copied; all other chunks from
+the PNG file are discarded. If there are any other chunks in the PNG file, which
+might influence the visual appearance of the image, or if image processing like
+gamma change is requested, the ``PNG Copy'' function must be skipped; therefore
+the lengthy tests.
+
+*/
-@c
static int spng_getint(FILE * f)
{
unsigned char buf[4];
@@ -394,7 +383,7 @@ static void copy_png(PDF pdf, image_dict * idict)
png_p = img_png_png_ptr(idict);
info_p = img_png_info_ptr(idict);
f = (FILE *) png_get_io_ptr(png_p);
- /* 1st pass to find overall stream /Length */
+ /*tex 1st pass to find overall stream /Length */
if (fseek(f, 8, SEEK_SET) != 0)
normal_error("writepng", "fseek in file failed");
do {
@@ -423,8 +412,7 @@ static void copy_png(PDF pdf, image_dict * idict)
pdf_end_dict(pdf);
pdf_end_dict(pdf);
pdf_begin_stream(pdf);
- assert(pdf->zip_write_state == NO_ZIP); /* the PNG stream is already compressed */
- /* 2nd pass to copy data */
+ /*tex 2nd pass to copy data */
endflag = false;
if (fseek(f, 8, SEEK_SET) != 0)
normal_error("writepng", "fseek in file failed");
@@ -433,7 +421,7 @@ static void copy_png(PDF pdf, image_dict * idict)
type = spng_getint(f);
switch (type) {
case SPNG_CHUNK_IDAT:
- /* do copy */
+ /*tex do copy */
if (idat == 2) {
normal_error("writepng", "IDAT chunk sequence broken");
}
@@ -445,7 +433,7 @@ static void copy_png(PDF pdf, image_dict * idict)
}
break;
case SPNG_CHUNK_IEND:
- /* done */
+ /*tex done */
endflag = true;
break;
default:
@@ -459,17 +447,15 @@ static void copy_png(PDF pdf, image_dict * idict)
pdf_end_obj(pdf);
}
-@ @c
static void reopen_png(image_dict * idict)
{
int width, height, xres, yres;
- width = img_xsize(idict); /* do consistency check */
+ /*tex A consistency check: */
+ width = img_xsize(idict);
height = img_ysize(idict);
xres = img_xres(idict);
yres = img_yres(idict);
- /*
- we need to ake sure that the file kept open
- */
+ /*tex We need to ake sure that the file kept open. */
img_keepopen(idict) = 1;
read_png_info(idict);
if (width != img_xsize(idict) || height != img_ysize(idict) || xres != img_xres(idict) || yres != img_yres(idict)) {
@@ -477,13 +463,10 @@ static void reopen_png(image_dict * idict)
}
}
-@ @c
-static boolean last_png_needs_page_group;
-
void write_png(PDF pdf, image_dict * idict)
{
#ifndef PNG_FP_1
- /* for libpng < 1.5.0 */
+ /*tex for libpng < 1.5.0 */
# define PNG_FP_1 100000
#endif
int num_palette, palette_objnum = 0;
@@ -494,31 +477,30 @@ void write_png(PDF pdf, image_dict * idict)
png_infop info_p;
png_colorp palette;
assert(idict != NULL);
- last_png_needs_page_group = false;
if (img_file(idict) == NULL)
reopen_png(idict);
assert(img_png_ptr(idict) != NULL);
png_p = img_png_png_ptr(idict);
info_p = img_png_info_ptr(idict);
- /* simple transparency support */
+ /*tex simple transparency support */
if (png_get_valid(png_p, info_p, PNG_INFO_tRNS)) {
png_set_tRNS_to_alpha(png_p);
png_copy = false;
}
- /* alpha channel support */
+ /*tex alpha channel support */
if (pdf->minor_version < 4
&& png_get_color_type(png_p, info_p) | PNG_COLOR_MASK_ALPHA) {
png_set_strip_alpha(png_p);
png_copy = false;
}
- /* 16 bit depth support */
+ /*tex 16 bit depth support */
if (pdf->minor_version < 5)
pdf->image_hicolor = 0;
if ((png_get_bit_depth(png_p, info_p) == 16) && (pdf->image_hicolor == 0)) {
png_set_strip_16(png_p);
png_copy = false;
}
- /* gamma support */
+ /*tex gamma support */
if (png_get_valid(png_p, info_p, PNG_INFO_gAMA)) {
png_get_gAMA(png_p, info_p, &gamma);
png_get_gAMA_fixed(png_p, info_p, &int_file_gamma);
@@ -527,11 +509,10 @@ void write_png(PDF pdf, image_dict * idict)
if (png_get_valid(png_p, info_p, PNG_INFO_gAMA))
png_set_gamma(png_p, (pdf->gamma / 1000.0), gamma);
else
- png_set_gamma(png_p, (pdf->gamma / 1000.0),
- (1000.0 / pdf->image_gamma));
+ png_set_gamma(png_p, (pdf->gamma / 1000.0), (1000.0 / pdf->image_gamma));
png_copy = false;
}
- /* reset structure */
+ /*tex reset structure */
(void) png_set_interlace_handling(png_p);
png_read_update_info(png_p, info_p);
pdf_begin_obj(pdf, img_objnum(idict), OBJSTM_NEVER);
@@ -555,9 +536,11 @@ void write_png(PDF pdf, image_dict * idict)
pdf_add_name(pdf, "ColorSpace");
pdf_begin_array(pdf);
pdf_add_name(pdf, "Indexed");
- pdf_add_name(pdf, "DeviceRGB"); /* base; PDFRef. 4.5.5 */
- pdf_add_int(pdf, (int) (num_palette - 1)); /* hival */
- pdf_add_ref(pdf, (int) palette_objnum); /* lookup */
+ pdf_add_name(pdf, "DeviceRGB");
+ /*tex hival */
+ pdf_add_int(pdf, (int) (num_palette - 1));
+ /*tex lookup */
+ pdf_add_ref(pdf, (int) palette_objnum);
pdf_end_array(pdf);
break;
case PNG_COLOR_TYPE_GRAY:
@@ -629,14 +612,12 @@ void write_png(PDF pdf, image_dict * idict)
case PNG_COLOR_TYPE_GRAY_ALPHA:
if (pdf->minor_version >= 4) {
write_png_gray_alpha(pdf, idict);
- last_png_needs_page_group = true;
} else
write_png_gray(pdf, idict);
break;
case PNG_COLOR_TYPE_RGB_ALPHA:
if (pdf->minor_version >= 4) {
write_png_rgb_alpha(pdf, idict);
- last_png_needs_page_group = true;
} else
write_png_gray(pdf, idict);
break;
@@ -645,42 +626,20 @@ void write_png(PDF pdf, image_dict * idict)
}
}
write_palette_streamobj(pdf, palette_objnum, palette, num_palette);
- /* always */
+ /*tex always */
close_and_cleanup_png(idict);
}
-@ @c
-static boolean transparent_page_group_was_written = false;
-@ Called after the xobject generated by |write_png| has been finished; used to
-write out additional objects
+/*tex
+
+ Called after the xobject generated by |write_png| has been finished; used to
+ write out additional objects.
+
+*/
-@c
void write_additional_png_objects(PDF pdf)
{
(void) pdf;
- (void) transparent_page_group;
- (void) transparent_page_group_was_written;
return;
- /* this interferes with current macro-based usage and cannot be configured */
-#if 0
- if (last_png_needs_page_group) {
- if (!transparent_page_group_was_written && transparent_page_group > 1) {
- /* create new group object */
- transparent_page_group_was_written = true;
- pdf_begin_obj(pdf, transparent_page_group, 2);
- if (pdf->compress_level == 0) {
- pdf_puts(pdf, "%PTEX Group needed for transparent pngs\n");
- }
- pdf_begin_dict(pdf);
- pdf_dict_add_name(pdf, "Type", "Group");
- pdf_dict_add_name(pdf, "S", "Transparency");
- pdf_dict_add_name(pdf, "CS", "DeviceRGB");
- pdf_dict_add_bool(pdf, "I", 1);
- pdf_dict_add_bool(pdf, "K", 1);
- pdf_end_dict(pdf);
- pdf_end_obj(pdf);
- }
- }
-#endif
}