diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2015-10-07 02:16:02 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2015-10-07 02:16:02 +0000 |
commit | a021762e6ccc1101fefbac38abb168b69a11f0ca (patch) | |
tree | baf31827b9c7c7af518a3f4aa58ccba0de18b640 /Build/source/texk/web2c/luatexdir/image | |
parent | 4ca2692153042a0c2f7db8d681e190b867ae2faf (diff) |
web2c/luatexdir: Sync with the upstream trunk.
git-svn-id: svn://tug.org/texlive/trunk@38575 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/image')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/epdf.h | 10 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/image.h | 5 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/pdftoepdf.h | 1 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/pdftoepdf.w | 153 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/writeimg.w | 37 |
5 files changed, 190 insertions, 16 deletions
diff --git a/Build/source/texk/web2c/luatexdir/image/epdf.h b/Build/source/texk/web2c/luatexdir/image/epdf.h index 2c9d5db53e5..1a4cc78c381 100644 --- a/Build/source/texk/web2c/luatexdir/image/epdf.h +++ b/Build/source/texk/web2c/luatexdir/image/epdf.h @@ -124,6 +124,7 @@ extern "C" { extern void read_pdf_info(image_dict *, int, int, img_readtype_e); extern void write_epdf(PDF, image_dict *); extern void unrefPdfDocument(char *); + extern void unrefMemStreamPdfDocument(char *); extern void epdf_free(void); extern void copyReal(PDF pdf, double d); @@ -194,4 +195,13 @@ struct PdfDocument { PdfDocument *refPdfDocument(const char *file_path, file_error_mode fe); +PdfDocument *refMemStreamPdfDocument(char *docstream, unsigned long long streamsize, const char *file_id); + + +#define STREAM_CHECKSUM_SIZE 16 // md5 +#define STRSTREAM_CHECKSUM_SIZE 1+((unsigned int)(log(ULONG_MAX)/log(16))) // djb2 printable digest as hex stream +#define STREAM_FILE_ID_LEN 2048 // 2048 bytes are enough to make a strong almost-unique name +#define STREAM_URI "data:application/pdf," +#define STREAM_URI_LEN 21 // length of "data:application/pdf," without final '\0' + #endif /* EPDF_H */ diff --git a/Build/source/texk/web2c/luatexdir/image/image.h b/Build/source/texk/web2c/luatexdir/image/image.h index 32ead6a0f65..5a9adfdc9bb 100644 --- a/Build/source/texk/web2c/luatexdir/image/image.h +++ b/Build/source/texk/web2c/luatexdir/image/image.h @@ -70,8 +70,9 @@ typedef enum { DICT_NEW, /* fresh dictionary */ DICT_WRITTEN /* image dict written to file */ } dict_state; + typedef enum { IMG_TYPE_NONE, IMG_TYPE_PDF, IMG_TYPE_PNG, IMG_TYPE_JPG, - IMG_TYPE_JP2, IMG_TYPE_JBIG2, IMG_TYPE_PDFSTREAM, IMG_TYPE_SENTINEL + IMG_TYPE_JP2, IMG_TYPE_JBIG2, IMG_TYPE_PDFSTREAM, IMG_TYPE_PDFMEMSTREAM, IMG_TYPE_SENTINEL } imgtype_e; typedef enum { IMG_KEEPOPEN, IMG_CLOSEINBETWEEN } img_readtype_e; @@ -183,7 +184,7 @@ typedef struct { # define epdf_orig_x(a) img_xorig(idict_array[a]) # define epdf_orig_y(a) img_yorig(idict_array[a]) -# define is_pdf_image(a) (img_type(idict_array[a]) == IMG_TYPE_PDF) +# define is_pdf_image(a) ((img_type(idict_array[a]) == IMG_TYPE_PDF) || (img_type(idict_array[a]) == IMG_TYPE_PDFMEMSTREAM)) # define is_png_image(a) (img_type(idict_array[a]) == IMG_TYPE_PNG) # define img_is_refered(N) (img_index(N) != -1) diff --git a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.h b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.h index 4e2dc36717c..203f85c5c31 100644 --- a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.h +++ b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.h @@ -26,6 +26,7 @@ void read_pdf_info(image_dict *, int, int, img_readtype_e); void unrefPdfDocument(char *); +void unrefMemStreamPdfDocument(char *); void write_epdf(PDF, image_dict *); void epdf_check_mem(void); void copyReal(PDF pdf, double d); diff --git a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.w b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.w index b01a10bb8c1..cacaea11389 100644 --- a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.w +++ b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.w @@ -27,7 +27,9 @@ #include "image/epdf.h" // This file is mostly C and not very much C++; it's just used to interface -// the functions of xpdf, which happens to be written in C++. +// the functions of poppler, which happens to be written in C++. + +extern void md5(Guchar *msg, int msgLen, Guchar *digest); static GBool isInit = gFalse; @@ -89,6 +91,27 @@ static char *get_file_checksum(const char *a, file_error_mode fe) 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) + luatex_fail("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. @@ -144,7 +167,7 @@ PdfDocument *refPdfDocument(const char *file_path, file_error_mode fe) if (!doc->isOk() || !doc->okToPrint()) { switch (fe) { case FE_FAIL: - luatex_fail("xpdf: reading PDF image failed"); + luatex_fail("PDF inclusion: reading PDF image failed"); break; case FE_RETURN_NULL: delete doc; @@ -179,6 +202,92 @@ PdfDocument *refPdfDocument(const char *file_path, file_error_mode fe) 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); + assert(checksum != NULL); + 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) { +#ifdef DEBUG + fprintf(stderr, "\nDEBUG: New MemStreamPdfDocument %s\n", file_path); +#endif + /*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 { +#ifdef DEBUG + fprintf(stderr, "\nDEBUG: Found MemStreamPdfDocument %s (%d)\n", + pdf_doc->file_path, pdf_doc->occurences); +#endif + assert(pdf_doc->checksum != NULL); + // As is now, checksum is in file_path, so this check is should be useless. + if (strncmp(pdf_doc->checksum, checksum, STRSTREAM_CHECKSUM_SIZE) != 0) { + luatex_fail("PDF inclusion: stream has changed '%s'", file_path); + } + free(file_path); + free(checksum); + } + assert(pdf_doc != NULL); + if (pdf_doc->doc == NULL) { +#ifdef DEBUG + fprintf(stderr, "\nDEBUG: New PDFDoc %s (%d)\n", + pdf_doc->file_path, pdf_doc->occurences); +#endif + docmemstream = new MemStream( docstream,0,streamsize, obj.initNull() ); + doc = new PDFDoc(docmemstream); // takes ownership of docmemstream + pdf_doc->pc++; + + if (!doc->isOk() || !doc->okToPrint()) { + luatex_fail("poppler: 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) { + void **aa = avl_probe(PdfDocumentTree, pdf_doc); + assert(aa != NULL); + } + pdf_doc->occurences++; +#ifdef DEBUG + fprintf(stderr, "\nDEBUG: Incrementing %s (%d)\n", + pdf_doc->file_path, pdf_doc->occurences); +#endif + return pdf_doc; +} + + + //********************************************************************** // AVL sort ObjMap into ObjMapTree by object number and generation @@ -433,7 +542,7 @@ static void copyObject(PDF pdf, PdfDocument * pdf_doc, Object * obj) obj->getTypeName()); break; default: - assert(0); // xpdf doesn't have any other types + assert(0); // poppler doesn't have any other types } } @@ -507,16 +616,24 @@ read_pdf_info(image_dict * idict, int minor_pdf_version_wanted, int pdf_major_version_found, pdf_minor_version_found; float xsize, ysize, xorig, yorig; assert(idict != NULL); - assert(img_type(idict) == IMG_TYPE_PDF); + assert((img_type(idict) == IMG_TYPE_PDF) || (img_type(idict) == IMG_TYPE_PDFMEMSTREAM)); assert(readtype == IMG_CLOSEINBETWEEN); // only this is implemented // initialize if (isInit == gFalse) { - globalParams = new GlobalParams(); - globalParams->setErrQuiet(gFalse); - isInit = gTrue; + if (!(globalParams)) // globalParams could be already created + globalParams = new GlobalParams(); + globalParams->setErrQuiet(gFalse); + isInit = gTrue; } // open PDF file - pdf_doc = refPdfDocument(img_filepath(idict), FE_FAIL); + 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)) ; + assert(pdf_doc != NULL); + pdf_doc->occurences++; + } else + luatex_fail("PDF inclusion: unknown document (1)"); doc = pdf_doc->doc; catalog = doc->getCatalog(); // check PDF version @@ -638,7 +755,14 @@ void write_epdf(PDF pdf, image_dict * idict) assert(idict != NULL); // open PDF file - pdf_doc = refPdfDocument(img_filepath(idict), FE_FAIL); + 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)) ; + assert(pdf_doc != NULL); + pdf_doc->occurences++; + } else + luatex_fail("PDF inclusion: unknown document (2)"); doc = pdf_doc->doc; catalog = doc->getCatalog(); page = catalog->getPage(img_pagenum(idict)); @@ -855,6 +979,17 @@ void unrefPdfDocument(char *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. // Now deallocate all remaining PdfDocuments. diff --git a/Build/source/texk/web2c/luatexdir/image/writeimg.w b/Build/source/texk/web2c/luatexdir/image/writeimg.w index 3f6da1a4bee..561efd514c0 100644 --- a/Build/source/texk/web2c/luatexdir/image/writeimg.w +++ b/Build/source/texk/web2c/luatexdir/image/writeimg.w @@ -124,18 +124,41 @@ #define HEADER_JP2 "\x6A\x50\x20\x20" #define HEADER_PDF "%PDF-1." #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 */ + static void check_type_by_header(image_dict * idict) { int i; FILE *file = NULL; char header[MAX_HEADER]; + char prefix[LEN_PDF_MEMSTREAM+1]; assert(idict != NULL); if (img_type(idict) != IMG_TYPE_NONE) /* nothing to do */ return; + /* read the header */ - file = xfopen(img_filepath(idict), FOPEN_RBIN_MODE); + /* Like */ + /* file = xfopen(img_filepath(idict), FOPEN_RBIN_MODE);*/ + /* but we also check for a memstream object */ + assert(img_filepath(idict) && FOPEN_RBIN_MODE); + file = fopen(img_filepath(idict), FOPEN_RBIN_MODE); + if (file == NULL) { + /* check the prefix of img_filepath(idict) */ + for (i = 0; (unsigned) i < LEN_PDF_MEMSTREAM; i++) { + prefix[i] = (char) (img_filepath(idict)[i]); + } + prefix[LEN_PDF_MEMSTREAM]='\0'; + if (strncmp(prefix, HEADER_PDF_MEMSTREAM, LEN_PDF_MEMSTREAM) == 0) { + img_type(idict) = IMG_TYPE_PDFMEMSTREAM; + return; + } else { + FATAL_PERROR(img_filepath(idict)); + } + } + /* a valid file, but perhaps unsupported */ for (i = 0; (unsigned) i < MAX_HEADER; i++) { header[i] = (char) xgetc(file); if (feof(file)) @@ -252,6 +275,7 @@ void free_image_dict(image_dict * p) /* called from limglib.c */ assert(img_state(p) < DICT_REFERED); switch (img_type(p)) { + case IMG_TYPE_PDFMEMSTREAM: case IMG_TYPE_PDF: unrefPdfDocument(img_filepath(p)); break; @@ -310,6 +334,7 @@ void read_img(PDF pdf, check_type_by_extension(idict); /* read image */ switch (img_type(idict)) { + case IMG_TYPE_PDFMEMSTREAM: case IMG_TYPE_PDF: assert(pdf != NULL); /* TODO! */ read_pdf_info(idict, minor_version, inclusion_errorlevel, @@ -523,7 +548,7 @@ scaled_whd scale_img(image_dict * idict, scaled_whd alt_rule, int transform) scaled_whd nat; /* natural size corresponding to image resolution */ int default_res; assert(idict != NULL); - if ((img_type(idict) == IMG_TYPE_PDF + 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 */ y = img_ysize(idict) = img_bbox(idict)[3] - img_bbox(idict)[1]; @@ -551,7 +576,7 @@ scaled_whd scale_img(image_dict * idict, scaled_whd alt_rule, int transform) yr = tmp; } nat.dp = 0; /* always for images */ - if (img_type(idict) == IMG_TYPE_PDF + if (img_type(idict) == IMG_TYPE_PDF || img_type(idict) == IMG_TYPE_PDFMEMSTREAM || img_type(idict) == IMG_TYPE_PDFSTREAM) { nat.wd = x; nat.ht = y; @@ -591,6 +616,7 @@ void write_img(PDF pdf, image_dict * idict) case IMG_TYPE_JBIG2: write_jbig2(pdf, idict); break; + case IMG_TYPE_PDFMEMSTREAM: case IMG_TYPE_PDF: write_epdf(pdf, idict); break; @@ -677,7 +703,7 @@ void pdf_dict_add_img_filename(PDF pdf, image_dict * idict) char s[21], *p; assert(idict != NULL); /* for now PTEX.FileName only for PDF, but prepared for JPG, PNG, ... */ - if (img_type(idict) != IMG_TYPE_PDF) + 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) @@ -768,7 +794,7 @@ void dumpimagemeta(void) /* the |image_struct| is not dumped at all, except for a few variables that are needed to restore the contents */ - if (img_type(idict) == IMG_TYPE_PDF) { + if ((img_type(idict) == IMG_TYPE_PDF)|| (img_type(idict) == IMG_TYPE_PDFMEMSTREAM)) { dumpinteger(img_pagebox(idict)); dumpinteger(img_pagenum(idict)); } else if (img_type(idict) == IMG_TYPE_JBIG2) { @@ -808,6 +834,7 @@ void undumpimagemeta(PDF pdf, int pdfversion, int pdfinclusionerrorlevel) undumpinteger(img_colorspace(idict)); switch (img_type(idict)) { + case IMG_TYPE_PDFMEMSTREAM: case IMG_TYPE_PDF: undumpinteger(img_pagebox(idict)); undumpinteger(img_pagenum(idict)); |