diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/image/pdftoepdf.w')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/pdftoepdf.w | 669 |
1 files changed, 315 insertions, 354 deletions
diff --git a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.w b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.w index 1ece3a2dd48..b9d496ac9f0 100644 --- a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.w +++ b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.w @@ -20,40 +20,40 @@ @ @c - -// define DEBUG #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++. +/* + 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++. +*/ extern void md5(Guchar *msg, int msgLen, Guchar *digest); static GBool isInit = gFalse; -//********************************************************************** -// Maintain AVL tree of all PDF files for embedding +/* Maintain AVL tree of all PDF files for embedding */ static avl_table *PdfDocumentTree = NULL; -// AVL sort PdfDocument into PdfDocumentTree by file_path +/* AVL sort PdfDocument into PdfDocumentTree by file_path */ static int CompPdfDocument(const void *pa, const void *pb, void * /*p */ ) { - return strcmp(((const PdfDocument *) pa)->file_path, - ((const PdfDocument *) pb)->file_path); + return strcmp(((const PdfDocument *) pa)->file_path, ((const PdfDocument *) pb)->file_path); } -// Returns pointer to PdfDocument structure for PDF file. +/* Returns pointer to PdfDocument structure for PDF file. */ static PdfDocument *findPdfDocument(char *file_path) { PdfDocument *pdf_doc, tmp; - assert(file_path != NULL); - if (PdfDocumentTree == NULL) + 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; @@ -70,22 +70,20 @@ static char *get_file_checksum(const char *a, file_error_mode fe) time_t mtime = finfo.st_mtime; ck = (char *) malloc(PDF_CHECKSUM_SIZE); if (ck == NULL) - luatex_fail("PDF inclusion: out of memory while processing '%s'", - a); - snprintf(ck, PDF_CHECKSUM_SIZE, "%" PRIu64 "_%" PRIu64, (uint64_t) size, - (uint64_t) mtime); + 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: - luatex_fail("PDF inclusion: could not stat() file '%s'", a); - break; - case FE_RETURN_NULL: - if (ck != NULL) - free(ck); - ck = NULL; - break; - default: - assert(0); + 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; @@ -93,28 +91,28 @@ static char *get_file_checksum(const char *a, file_error_mode fe) 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; + /* 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. +/* + 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) { @@ -124,15 +122,10 @@ PdfDocument *refPdfDocument(const char *file_path, file_error_mode fe) GooString *docName = NULL; int new_flag = 0; if ((checksum = get_file_checksum(file_path, fe)) == NULL) { - assert(fe == FE_RETURN_NULL); return (PdfDocument *) NULL; } - assert(checksum != NULL); path_copy = xstrdup(file_path); if ((pdf_doc = findPdfDocument(path_copy)) == NULL) { -#ifdef DEBUG - fprintf(stderr, "\nDEBUG: New PdfDocument %s\n", file_path); -#endif new_flag = 1; pdf_doc = new PdfDocument; pdf_doc->file_path = path_copy; @@ -140,38 +133,28 @@ PdfDocument *refPdfDocument(const char *file_path, file_error_mode fe) pdf_doc->doc = NULL; pdf_doc->inObjList = NULL; pdf_doc->ObjMapTree = NULL; - pdf_doc->occurences = 0; // 0 = unreferenced + pdf_doc->occurences = 0; /* 0 = unreferenced */ pdf_doc->pc = 0; } else { -#ifdef DEBUG - fprintf(stderr, "\nDEBUG: Found PdfDocument %s (%d)\n", - pdf_doc->file_path, pdf_doc->occurences); -#endif - assert(pdf_doc->checksum != NULL); if (strncmp(pdf_doc->checksum, checksum, PDF_CHECKSUM_SIZE) != 0) { - luatex_fail("PDF inclusion: file has changed '%s'", file_path); + formatted_error("pdf inclusion","file has changed '%s'", file_path); } free(checksum); free(path_copy); } - 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 docName = new GooString(file_path); - doc = new PDFDoc(docName); // takes ownership of docName + doc = new PDFDoc(docName); /* takes ownership of docName */ pdf_doc->pc++; if (!doc->isOk() || !doc->okToPrint()) { switch (fe) { case FE_FAIL: - luatex_fail("PDF inclusion: reading PDF image failed"); + normal_error("pdf inclusion","reading image failed"); break; case FE_RETURN_NULL: delete doc; - // delete docName; + /* delete docName */ if (new_flag == 1) { if (pdf_doc->file_path != NULL) free(pdf_doc->file_path); @@ -187,27 +170,21 @@ PdfDocument *refPdfDocument(const char *file_path, file_error_mode fe) } pdf_doc->doc = doc; } - // PDF file could be opened without problems, checksum ok. + /* 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); + avl_probe(PdfDocumentTree, pdf_doc); } pdf_doc->occurences++; -#ifdef DEBUG - fprintf(stderr, "\nDEBUG: Incrementing %s (%d)\n", - pdf_doc->file_path, pdf_doc->occurences); -#endif 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 +/* + 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) { @@ -219,21 +196,16 @@ PdfDocument *refMemStreamPdfDocument(char *docstream, unsigned long long streams 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(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; @@ -241,61 +213,43 @@ PdfDocument *refMemStreamPdfDocument(char *docstream, unsigned long long streams pdf_doc->doc = NULL; pdf_doc->inObjList = NULL; pdf_doc->ObjMapTree = NULL; - pdf_doc->occurences = 0; // 0 = unreferenced + 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 should be useless. + /* As is now, checksum is in file_path, so this check should be useless. */ if (strncmp(pdf_doc->checksum, checksum, STRSTREAM_CHECKSUM_SIZE) != 0) { - luatex_fail("PDF inclusion: stream has changed '%s'", file_path); + formatted_error("pdf inclusion","stream has changed '%s'", file_path); } - free(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 + 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"); - } + normal_error("pdf inclusion","reading pdf Stream failed"); + } pdf_doc->doc = doc; } - // PDF file could be opened without problems, checksum ok. + /* 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); + avl_probe(PdfDocumentTree, pdf_doc); } 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 - -// keep the ObjMap struct small, as these are accumulated until the end +/* + 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; // object num/gen in orig. PDF file - int out_num; // object num after embedding (gen == 0) + Ref in; + int out_num; }; static int CompObjMap(const void *pa, const void *pb, void * /*p */ ) @@ -304,11 +258,11 @@ static int CompObjMap(const void *pa, const void *pb, void * /*p */ ) const Ref *b = &(((const ObjMap *) pb)->in); if (a->num > b->num) return 1; - if (a->num < b->num) + else if (a->num < b->num) return -1; - if (a->gen == b->gen) // most likely gen == 0 anyway + else if (a->gen == b->gen) return 0; - if (a->gen < b->gen) + else if (a->gen < b->gen) return -1; return 1; } @@ -316,7 +270,6 @@ static int CompObjMap(const void *pa, const void *pb, void * /*p */ ) static ObjMap *findObjMap(PdfDocument * pdf_doc, Ref in) { ObjMap *obj_map, tmp; - assert(pdf_doc != NULL); if (pdf_doc->ObjMapTree == NULL) return NULL; tmp.in = in; @@ -327,32 +280,31 @@ static ObjMap *findObjMap(PdfDocument * pdf_doc, Ref in) static void addObjMap(PdfDocument * pdf_doc, Ref in, int out_num) { ObjMap *obj_map = NULL; - assert(findObjMap(pdf_doc, in) == NULL); if (pdf_doc->ObjMapTree == NULL) pdf_doc->ObjMapTree = avl_create(CompObjMap, NULL, &avl_xallocator); obj_map = new ObjMap; obj_map->in = in; obj_map->out_num = out_num; - void **aa = avl_probe(pdf_doc->ObjMapTree, obj_map); - assert(aa != NULL); + 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. +/* + 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) { - luatex_fail("PDF inclusion: reference to invalid object" - " (is the included pdf broken?)"); + normal_error("pdf inclusion","reference to invalid object (broken pdf)"); } if ((obj_map = findObjMap(pdf_doc, ref)) != NULL) return obj_map->out_num; @@ -361,12 +313,14 @@ static int addInObj(PDF pdf, PdfDocument * pdf_doc, 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) + 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(). + } 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; @@ -374,15 +328,16 @@ static int addInObj(PDF pdf, PdfDocument * pdf_doc, Ref ref) return n->num; } -//********************************************************************** -// Function converts double to pdffloat; very small and very large numbers -// are NOT converted to scientific notation. -// n must be a number or real conforming to the implementation limits -// of PDF as specified in appendix C.1 of the PDF Ref. -// These are: -// maximum value of ints is +2^32 -// maximum value of reals is +2^15 -// smalles values of reals is 1/(2^16) +/* + 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) { @@ -493,7 +448,6 @@ static void copyStream(PDF pdf, PdfDocument * pdf_doc, Stream * stream) { copyDict(pdf, pdf_doc, stream->getDict()); pdf_begin_stream(pdf); - assert(pdf->zip_write_state == NO_ZIP); copyStreamStream(pdf, stream->getUndecodedStream()); pdf_end_stream(pdf); } @@ -510,9 +464,11 @@ static void copyObject(PDF pdf, PdfDocument * pdf_doc, Object * obj) case objReal: copyReal(pdf, obj->getReal()); break; - // not needed: - // case objNum: - // GBool isNum() { return type == objInt || type == objReal; } + /* + case objNum: + GBool isNum() { return type == objInt || type == objReal; } + break; + */ case objString: copyString(pdf, obj->getString()); break; @@ -538,16 +494,14 @@ static void copyObject(PDF pdf, PdfDocument * pdf_doc, Object * obj) case objError: case objEOF: case objNone: - luatex_fail("PDF inclusion: type <%s> cannot be copied", - obj->getTypeName()); + formatted_error("pdf inclusion","type '%s' cannot be copied", obj->getTypeName()); break; default: - assert(0); // poppler doesn't have any other types + /* poppler doesn't have any other types */ + assert(0); } } -//********************************************************************** - static void writeRefs(PDF pdf, PdfDocument * pdf_doc) { InObj *r, *n; @@ -560,7 +514,7 @@ static void writeRefs(PDF pdf, PdfDocument * pdf_doc) if (obj1.isStream()) pdf_begin_obj(pdf, r->num, OBJSTM_NEVER); else - pdf_begin_obj(pdf, r->num, 2); // \pdfobjcompresslevel = 2 is for this + pdf_begin_obj(pdf, r->num, 2); copyObject(pdf, pdf_doc, &obj1); obj1.free(); pdf_end_obj(pdf); @@ -570,115 +524,120 @@ static void writeRefs(PDF pdf, PdfDocument * pdf_doc) } } -// get the pagebox coordinates according to the pagebox_spec +/* 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: - luatex_fail("PDF inclusion: unknown value of pagebox spec (%i)", - (int) 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; } - return page->getMediaBox(); // to make the compiler happy } -// Reads various information about the PDF and sets it up for later inclusion. -// This will fail if the PDF version of the PDF is higher than -// minor_pdf_version_wanted or page_name is given and can not be found. -// It makes no sense to give page_name _and_ page_num. -// Returns the page number. +/* + Reads various information about the PDF and sets it up for later inclusion. + This will fail if the PDF version of the PDF is higher than minor_pdf_version_wanted + or page_name is given and can not be found. It makes no sense to give page_name and + page_num. Returns the page number. +*/ -void -read_pdf_info(image_dict * idict, int minor_pdf_version_wanted, - int pdf_inclusion_errorlevel, img_readtype_e readtype) +void flush_pdf_info(image_dict * idict) { - PdfDocument *pdf_doc; - PDFDoc *doc; + 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; - assert(idict != NULL); - 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) { - if (!(globalParams)) // globalParams could be already created - globalParams = new GlobalParams(); - globalParams->setErrQuiet(gFalse); - isInit = gTrue; - } - // open PDF file - if (img_type(idict) == IMG_TYPE_PDF) - pdf_doc = refPdfDocument(img_filepath(idict), FE_FAIL); + 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)) ; - assert(pdf_doc != NULL); - pdf_doc->occurences++; - } else - luatex_fail("PDF inclusion: unknown document (1)"); + pdf_doc = findPdfDocument(img_filepath(idict)) ; + 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, pdfTeX will - // then have to changed drastically anyway. + /* + 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 ((pdf_major_version_found > 1) - || (pdf_minor_version_found > minor_pdf_version_wanted)) { - const char *msg = - "PDF inclusion: found PDF version <%d.%d>, but at most version <1.%d> allowed"; - if (pdf_inclusion_errorlevel > 0) { - luatex_fail(msg, pdf_major_version_found, pdf_minor_version_found, - minor_pdf_version_wanted); + if ((pdf_major_version_found > 1) || (pdf_minor_version_found > img_pdfminorversion(idict))) { + const char *msg = "PDF inclusion: found PDF version '%d.%d', but at most version '1.%d' allowed"; + if (img_errorlevel(idict) > 0) { + formatted_error("pdf inclusion",msg, pdf_major_version_found, pdf_minor_version_found, img_pdfminorversion(idict)); } else { - luatex_warn(msg, pdf_major_version_found, pdf_minor_version_found, - minor_pdf_version_wanted); + formatted_warning("pdf inclusion",msg, pdf_major_version_found, pdf_minor_version_found, img_pdfminorversion(idict)); } } img_totalpages(idict) = catalog->getNumPages(); if (img_pagename(idict)) { - // get page by name + /* get page by name */ GooString name(img_pagename(idict)); LinkDest *link = doc->findDest(&name); if (link == NULL || !link->isOk()) - luatex_fail("PDF inclusion: invalid destination <%s>", - img_pagename(idict)); + 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) - luatex_fail("PDF inclusion: destination is not a page <%s>", - img_pagename(idict)); + formatted_error("pdf inclusion","destination is not a page '%s'",img_pagename(idict)); delete link; } else { - // get page by number + /* get page by number */ if (img_pagenum(idict) <= 0 || img_pagenum(idict) > img_totalpages(idict)) - luatex_fail("PDF inclusion: required page <%i> does not exist", - (int) img_pagenum(idict)); + formatted_error("pdf inclusion","required page '%i' does not exist",(int) img_pagenum(idict)); } - // get the required page + /* get the required page */ page = catalog->getPage(img_pagenum(idict)); - - // get the pagebox coordinates (media, crop,...) to use. + /* get the pagebox coordinates (media, crop,...) to use. */ pagebox = get_pagebox(page, img_pagebox(idict)); if (pagebox->x2 > pagebox->x1) { xorig = pagebox->x1; @@ -694,51 +653,64 @@ read_pdf_info(image_dict * idict, int minor_pdf_version_wanted, yorig = pagebox->y2; ysize = pagebox->y1 - pagebox->y2; } - // The following 4 parameters are raw. Do _not_ modify by /Rotate! + /* 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). + /* + 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) { // handles also neg. angles - case 0: - img_rotation(idict) = 0; - break; - case 90: - img_rotation(idict) = 3; // PDF counts clockwise! - break; - case 180: - img_rotation(idict) = 2; - break; - case 270: - img_rotation(idict) = 1; - break; - default: - luatex_warn - ("PDF inclusion: " - "/Rotate parameter in PDF file not multiple of 90 degrees."); + 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 + /* 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) + if (readtype == IMG_CLOSEINBETWEEN) { + unrefPdfDocument(img_filepath(idict)); + } + + and also unref'd in the finalizer zo 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)); + } } -//********************************************************************** -// Writes the current epf_doc. -// Here the included PDF is copied, so most errors that can happen -// during PDF inclusion will arise here. +/* + 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) { - PdfDocument *pdf_doc; - PDFDoc *doc; + PdfDocument *pdf_doc = NULL; + PDFDoc *doc = NULL; Catalog *catalog; Page *page; Ref *pageref; @@ -748,46 +720,39 @@ void write_epdf(PDF pdf, image_dict * idict) int i, l; double bbox[4]; char s[256]; - const char *pagedictkeys[] = - { "Group", "LastModified", "Metadata", "PieceInfo", "Resources", - "SeparationInfo", NULL + const char *pagedictkeys[] = { + "Group", "LastModified", "Metadata", "PieceInfo", "Resources", "SeparationInfo", NULL }; - assert(idict != 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)) ; - assert(pdf_doc != NULL); - pdf_doc->occurences++; - } else - luatex_fail("PDF inclusion: unknown document (2)"); + /* 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)); - assert(pageref != NULL); // was checked already in read_pdf_info() doc->getXRef()->fetch(pageref->num, pageref->gen, &pageobj); pageDict = pageobj.getDict(); - - // write the Page header + /* 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 + /* write additional information */ pdf_dict_add_img_filename(pdf, idict); snprintf(s, 30, "%s.PageNumber", pdfkeyprefix); pdf_dict_add_int(pdf, s, (int) img_pagenum(idict)); doc->getDocInfoNF(&obj1); if (obj1.isRef()) { - // the info dict must be indirect (PDF Ref p. 61) + /* the info dict must be indirect (PDF Ref p. 61) */ snprintf(s, 30, "%s.InfoDict", pdfkeyprefix); pdf_dict_add_ref(pdf, s, addInObj(pdf, pdf_doc, obj1.getRef())); } @@ -798,7 +763,7 @@ void write_epdf(PDF pdf, image_dict * idict) bbox[2] = sp2bp(img_bbox(idict)[2]); bbox[3] = sp2bp(img_bbox(idict)[3]); } else { - // get the pagebox coordinates (media, crop,...) to use. + /* get the pagebox coordinates (media, crop,...) to use. */ pagebox = get_pagebox(page, img_pagebox(idict)); bbox[0] = pagebox->x1; bbox[1] = pagebox->y1; @@ -812,30 +777,30 @@ void write_epdf(PDF pdf, image_dict * idict) copyReal(pdf, bbox[2]); copyReal(pdf, bbox[3]); pdf_end_array(pdf); - // The /Matrix calculation is replaced by transforms in out_img(). - - // Now all relevant parts of the Page dictionary are copied: - - // Metadata validity check (as a stream it must be indirect) + /* + Now all relevant parts of the Page dictionary are copied. Metadata validity + check is needed(as a stream it must be indirect). + */ pageDict->lookupNF("Metadata", &obj1); if (!obj1.isNull() && !obj1.isRef()) - luatex_warn("PDF inclusion: /Metadata must be indirect object"); + formatted_warning("pdf inclusion","/Metadata must be indirect object"); obj1.free(); - - // copy selected items in Page dictionary + /* copy selected items in Page dictionary */ for (i = 0; pagedictkeys[i] != NULL; i++) { pageDict->lookupNF(pagedictkeys[i], &obj1); if (!obj1.isNull()) { pdf_add_name(pdf, pagedictkeys[i]); - copyObject(pdf, pdf_doc, &obj1); // preserves indirection + /* preserves indirection */ + copyObject(pdf, pdf_doc, &obj1); } obj1.free(); } - - // 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.) + /* + 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.) + */ pageDict->lookupNF("Resources", &obj1); if (obj1.isNull()) { op1 = &pagesobj1; @@ -856,30 +821,28 @@ void write_epdf(PDF pdf, image_dict * idict) op2->free(); }; if (!op1->isDict()) - luatex_warn("PDF inclusion: Page /Resources missing."); + formatted_warning("pdf inclusion","Page /Resources missing"); op1->free(); } obj1.free(); - - // write the Page contents + /* Write the Page contents. */ page->getContents(&contents); 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 - // + /* + 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 + */ contents.streamGetDict()->lookup("F", &obj1); if (!obj1.isNull()) { - luatex_fail("PDF inclusion: Unsupported external stream"); + normal_error("pdf inclusion","unsupported external stream"); } obj1.free(); contents.streamGetDict()->lookup("Length", &obj1); - assert(!obj1.isNull()); pdf_add_name(pdf, "Length"); copyObject(pdf, pdf_doc, &obj1); obj1.free(); @@ -908,46 +871,45 @@ void write_epdf(PDF pdf, image_dict * idict) copyStreamStream(pdf, (contents.arrayGet(i, &obj1))->getStream()); obj1.free(); 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) + /* + 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 + } 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 + /* write out all indirect objects */ writeRefs(pdf, pdf_doc); contents.free(); pageobj.free(); - // unrefPdfDocument() must come after contents.free() and pageobj.free()! - // TH: The next line makes repeated pdf inclusion unacceptably slow -#if 0 - unrefPdfDocument(img_filepath(idict)); -#endif + /* + unrefPdfDocument() must come after contents.free() and pageobj.free()! + TH: The next line makes repeated pdf inclusion unacceptably slow + + unrefPdfDocument(img_filepath(idict)); + */ } -//********************************************************************** -// Deallocate a PdfDocument with all its resources +/* Deallocate a PdfDocument with all its resources. */ static void deletePdfDocumentPdfDoc(PdfDocument * pdf_doc) { InObj *r, *n; - assert(pdf_doc != NULL); - // this may be probably needed for an emergency destroyPdfDocument() + /* this may be probably needed for an emergency destroyPdfDocument() */ for (r = pdf_doc->inObjList; r != NULL; r = n) { n = r->next; delete r; } -#ifdef DEBUG - fprintf(stderr, "\nDEBUG: Deleting PDFDoc %s\n", pdf_doc->file_path); -#endif delete pdf_doc->doc; pdf_doc->doc = NULL; pdf_doc->pc++; @@ -957,47 +919,46 @@ static void destroyPdfDocument(void *pa, void * /*pb */ ) { PdfDocument *pdf_doc = (PdfDocument *) pa; deletePdfDocumentPdfDoc(pdf_doc); - // TODO: delete rest of 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. +/* + 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) /* Does the caller break the contract ? */ -return; - if (pdf_doc->occurences == 0) /* Again, does the caller breaks the contract ? */ -return; - /* for the moment we keep these assert here as remind that the code */ - /* should be revisited */ - //assert(pdf_doc != NULL); - //assert(pdf_doc->occurences != 0); // aim for point landing - pdf_doc->occurences--; -#ifdef DEBUG - fprintf(stderr, "\nDEBUG: Decrementing %s (%d)\n", - pdf_doc->file_path, pdf_doc->occurences); -#endif - if (pdf_doc->occurences == 0) { - assert(pdf_doc->inObjList == NULL); // should be eaten up already - deletePdfDocumentPdfDoc(pdf_doc); + 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) +/* + 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. +/* + Called when PDF embedding system is finalized. We now deallocate all remaining + PdfDocuments. +*/ void epdf_free() { |