Dear Werner, > See attachment for figure_fsteps.pdf ... Please test attached pdftoepdf.cc and pdftosrc.cc on SUSE. They are working fine on windows for your example with the poppler 0.60.1. Simply replace pdftoepdf.cc and pdftosrc.cc in web2c/pdftexdir by the attached files. Thanks, Akira --- texk/web2c/pdftexdir/pdftoepdf.cc | 113 +++++++++++++++++++++++--------------- texk/web2c/pdftexdir/pdftosrc.cc | 19 ++++-- 2 files changed, 83 insertions(+), 49 deletions(-) --- texk/web2c/pdftexdir/pdftoepdf.cc +++ texk/web2c/pdftexdir/pdftoepdf.cc 2017-11-07 15:57:03.960327000 +0000 @@ -1,5 +1,5 @@ /* -Copyright 1996-2016 Han The Thanh, +Copyright 1996-2017 Han The Thanh, This file is part of pdfTeX. @@ -17,6 +17,15 @@ You should have received a copy of the G with this program. If not, see . */ +/* +This is based on the patch texlive-poppler-0.59.patch <2017-09-19> at +https://git.archlinux.org/svntogit/packages.git/plain/texlive-bin/trunk +by Arch Linux. A little modifications are made to avoid a crash for +some kind of pdf images, such as figure_missing.pdf in gnuplot. +The poppler should be 0.59.0 or newer versions. +POPPLER_VERSION should be defined. +*/ + /* Do this early in order to avoid a conflict between MINGW32 defining 'boolean' as 'unsigned char' and defining Pascal's boolean as 'int'. @@ -39,10 +48,7 @@ with this program. If not, see #define GString GooString #else -#include -#include -#include -#include +#error POPPLER_VERSION should be defined. #endif #include @@ -357,10 +363,29 @@ static void copyProcSet(Object * obj) #define REPLACE_TYPE1C true +static bool embeddableFont(Object * fontdesc) +{ + Object fontfile, ffsubtype; + + if (!fontdesc->isDict()) + return false; + fontfile = fontdesc->dictLookup("FontFile"); + if (fontfile.isStream()) + return true; + if (REPLACE_TYPE1C) { + fontfile = fontdesc->dictLookup("FontFile3"); + if (!fontfile.isStream()) + return false; + ffsubtype = fontfile.streamGetDict()->lookup("Subtype"); + return ffsubtype.isName() && !strcmp(ffsubtype.getName(), "Type1C"); + } + return false; +} + static void copyFont(char *tag, Object * fontRef) { Object fontdict, subtype, basefont, fontdescRef, fontdesc, charset, - fontfile, ffsubtype, stemV; + stemV; GfxFont *gfont; fd_entry *fd; fm_entry *fontmap; @@ -377,23 +402,13 @@ static void copyFont(char *tag, Object * // Only handle included Type1 (and Type1C) fonts; anything else will be copied. // Type1C fonts are replaced by Type1 fonts, if REPLACE_TYPE1C is true. fontdict = fontRef->fetch(xref); + fontdesc = Object(objNull); if (fontdict.isDict()) { subtype = fontdict.dictLookup("Subtype"); basefont = fontdict.dictLookup("BaseFont"); fontdescRef = fontdict.dictLookupNF("FontDescriptor"); if (fontdescRef.isRef()) { fontdesc = fontdescRef.fetch(xref); - if (fontdesc.isDict()) { - fontfile = fontdesc.dictLookup("FontFile"); - if (!fontfile.isStream() && REPLACE_TYPE1C) { - fontfile = fontdesc.dictLookup("FontFile3"); - ffsubtype = fontfile.streamGetDict()->lookup("Subtype"); - if (!(ffsubtype.isName() && !strcmp(ffsubtype.getName(), "Type1C"))) { - // not a Type1-C font. - fontfile = Object(objNull); - } - } - } } } if (!fixedinclusioncopyfont && fontdict.isDict() @@ -402,7 +417,7 @@ static void copyFont(char *tag, Object * && basefont.isName() && fontdescRef.isRef() && fontdesc.isDict() - && fontfile.isStream() + && embeddableFont(&fontdesc) && (fontmap = lookup_fontmap(basefont.getName())) != NULL) { // round /StemV value, since the PDF input is a float // (see Font Descriptors in PDF reference), but we only store an @@ -591,9 +606,8 @@ static void copyObject(Object * obj) copyDict(obj); pdf_puts(">>"); } else if (obj->isStream()) { - obj1 = Object(obj->streamGetDict()); pdf_puts("<<\n"); - copyDict(&obj1); + copyDict(obj->getStream()->getDictObject()); pdf_puts(">>\n"); pdf_puts("stream\n"); copyStream(obj->getStream()->getUndecodedStream()); @@ -662,7 +676,7 @@ static void writeEncodings() #ifdef POPPLER_VERSION r->font->decRefCnt(); #else - delete r->font; +#error POPPLER_VERSION should be defined. #endif delete r; } @@ -705,7 +719,7 @@ read_pdf_info(char *image_name, char *pa #ifdef POPPLER_VERSION int pdf_major_version_found, pdf_minor_version_found; #else - float pdf_version_found, pdf_version_wanted; +#error POPPLER_VERSION should be defined. #endif // initialize if (!isInit) { @@ -737,19 +751,7 @@ read_pdf_info(char *image_name, char *pa } } #else - pdf_version_found = pdf_doc->doc->getPDFVersion(); - pdf_version_wanted = 1 + (minor_pdf_version_wanted * 0.1); - if (pdf_version_found > pdf_version_wanted + 0.01) { - char msg[] = - "PDF inclusion: found PDF version <%.1f>, but at most version <%.1f> allowed"; - if (pdf_inclusion_errorlevel > 0) { - pdftex_fail(msg, pdf_version_found, pdf_version_wanted); - } else if (pdf_inclusion_errorlevel < 0) { - ; /* do nothing */ - } else { /* = 0, give warning */ - pdftex_warn(msg, pdf_version_found, pdf_version_wanted); - } - } +#error POPPLER_VERSION should be defined. #endif epdf_num_pages = pdf_doc->doc->getCatalog()->getNumPages(); if (page_name) { @@ -931,12 +933,12 @@ void write_epdf(void) pdf_printf("/%s ", pageDictKeys[i]); copyObject(&dictObj); // preserves indirection } - } + } // handle page group dictObj = pageDict->lookupNF("Group"); if (!dictObj.isNull()) { - if (pdfpagegroupval == 0) { + if (pdfpagegroupval == 0) { // another pdf with page group was included earlier on the // same page; copy the Group entry as is. See manual for // info on why this is a warning. @@ -953,7 +955,32 @@ void write_epdf(void) if (!dictObj.isDict()) pdftex_fail("PDF inclusion: /Group dict missing"); writeSepGroup = true; +/* +This part is only a single line groupDict = Object(page->getGroup()); +in the original patch. In this case, however, pdftex crashes at +"delete pdf_doc->doc" in "delete_document()" for inclusion of some +kind of pdf images, for example, figure_missing.pdf in gnuplot. +A change + groupDict = Object(page->getGroup()).copy(); +does not improve the situation. +The changes below seem to work fine. +*/ +// begin modification + groupDict = pageDict->lookup("Group"); + Dict dic1 = page->getGroup(); + Dict dic2 = groupDict.getDict(); + // replace dic2 in groupDict with dic1 + l = dic2.getLength(); + for (i = 0; i < l; i++) { + groupDict.dictRemove(dic2.getKey(i)); + } + l = dic1.getLength(); + for (i = 0; i < l; i++) { + groupDict.dictAdd(copyString(dic1.getKey(i)), + dic1.getValNF(i)); + } +// end modification pdf_printf("/Group %ld 0 R\n", (long)pdfpagegroupval); } } @@ -966,15 +993,15 @@ void write_epdf(void) pdftex_warn ("PDF inclusion: /Resources missing. 'This practice is not recommended' (PDF Ref)"); } else { - obj1 = Object(page->getResourceDict()); - if (!obj1.isDict()) + Object *obj1 = page->getResourceDictObject(); + if (!obj1->isDict()) pdftex_fail("PDF inclusion: invalid resources dict type <%s>", - obj1.getTypeName()); + obj1->getTypeName()); pdf_newline(); pdf_puts("/Resources <<\n"); - for (i = 0, l = obj1.dictGetLength(); i < l; ++i) { - obj2 = obj1.dictGetVal(i); - key = obj1.dictGetKey(i); + for (i = 0, l = obj1->dictGetLength(); i < l; ++i) { + obj2 = obj1->dictGetVal(i); + key = obj1->dictGetKey(i); if (strcmp("Font", key) == 0) copyFontResources(&obj2); else if (strcmp("ProcSet", key) == 0) --- texk/web2c/pdftexdir/pdftosrc.cc +++ texk/web2c/pdftexdir/pdftosrc.cc 2017-11-07 15:57:11.068340000 +0000 @@ -1,5 +1,5 @@ /* -Copyright 1996-2014 Han The Thanh, +Copyright 1996-2017 Han The Thanh, This file is part of pdfTeX. @@ -16,6 +16,14 @@ GNU General Public License for more deta You should have received a copy of the GNU General Public License along with this program. If not, see . */ + +/* +This is based on the patch texlive-poppler-0.59.patch <2017-09-19> at +https://git.archlinux.org/svntogit/packages.git/plain/texlive-bin/trunk +by Arch Linux. The poppler should be 0.59.0 or newer versions. +POPPLER_VERSION should be defined. +*/ + #include #include @@ -32,10 +40,7 @@ with this program. If not, see #include #else -#include -#include -#include -#include +#error POPPLER_VERSION should be defined. #endif #include @@ -151,6 +156,7 @@ int main(int argc, char *argv[]) (e->type == xrefEntryFree ? "f" : "n")); else { // e->offset is the object number of the object stream Stream *str; + Lexer *lexer; Parser *parser; Object objStr, obj1, obj2; int nObjects, first, n; @@ -168,7 +174,8 @@ int main(int argc, char *argv[]) // parse the header: object numbers and offsets objStr.streamReset(); str = new EmbedStream(objStr.getStream(), Object(objNull), gTrue, first); - parser = new Parser(xref, new Lexer(xref, str), gFalse); + lexer = new Lexer(xref, str); + parser = new Parser(xref, lexer, gFalse); for (n = 0; n < nObjects; ++n) { obj1 = parser->getObj(); obj2 = parser->getObj();