Source: inkscape Version: 1.4.3-1 Severity: normal Tags: ftbfs -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512
Dear Maintainer, poppler 26.07 is currently in experimental. Once it migrates to unstable, inkscape 1.4.3-1 will fail to build from source as the PDF import extension (src/extension/internal/pdfinput/) does not compile against it poppler 26.02-26.07 reshaped much of the internal C++ API it uses. GfxColor*/PDFRectangle* parameters became const references, Object::getString() returns const std::string&, Gfx8BitFont::getEncoding() returns a std::array, GfxFont::getWMode() returns a scoped enum, and GfxState::setPath(), Object::streamGetDict()/arrayGetNF()/dictGetKey()/ dictGetValNF() and the Object(Dict*) constructor were removed, while Catalog::indexToLabel() now takes a std::string* All of these have already been fixed upstream. You may prefer to package a newer upstream release (1.4.4+, which contains them natively) rather than carry a patch. If a backport is more convenient, the attached patch combines the relevant upstream merge requests -- !7780, !7839, !7919, !7968, !8034 and !8037 -- rebased onto 1.4.3. Every change is guarded on POPPLER_CHECK_VERSION, so it is a no-op with the poppler currently in unstable and can be applied now, ahead of the transition Thanks, Nadzeya -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEuVOE/FJ0HcdfWSw//lAdKwFeZPsFAmprT7gACgkQ/lAdKwFe ZPskrg/+KPi8GT3siGW/atvAaPQkE8PZyJfDwEZHBGDS4CK9OfMpkwph38c5yOlB kShnMqVWqOHXPsX+V2c773CyQsu9wZrubYhT03DcGXmjHZrFUMSUhjS2zqUkjNHq ImK/uMo8KUDVtlRS7DdoZ8gJ8/bDGxvgu2NQwjZ1Jv2CbqNgKQxEAtaanvEJBvUZ rVLkl+bkkJHeKBNhUaa77E+1nw5SOlBBFFKAb4fPs/UPahyvHRwH0QaiLL/vvnem 2+rpRAp+rvGKtBA0PVHkwAOeP7Zxlkwx4CBHy4GXw5PCpFko8yZh7zIXfLOu3tzc rPR902qZDT1t5hXaD6i6rklujY8Dw/Sqho5sCCNCNrWY2cAHAVP3pIuWNjHcAb+G vR9lPcfAZSP4mtXKCVqkIISLm9YwIjNfhsGZ+cwPBQyG9Ji+u2IQ6CtvBcMsbNbq jX4hOddb3BRNUpsWZ6kPlcDctL1TYTzqt6eP+eVzB3RushozsJ1ejJq9JBgFkAb6 f0+s8GNfsIsFROCKsOVs3ti9dWUSuSgrL67/9U/zCbc81wDG4Cy/ESqhVZ0UxnSD Qv26Iqq1kkf2wJDd2iUbdh0gzMkSsfs+miyucQ0jIWKV3AZp/2L0rVSntpi5v9hA 8VAlOM35yNsuHaxuSIIpA9nEvogJu+USPj26uPjQGs8WyI1soXs= =lqz7 -----END PGP SIGNATURE-----
Description: Fix FTBFS with poppler 26.07 poppler 26.02 through 26.07 reshaped large parts of the internal C++ API used by Inkscape's PDF import extension: many GfxColor*/PDFRectangle* parameters and getters became const references, Object::getString() now returns a const std::string&, Gfx8BitFont::getEncoding() returns a std::array, GfxFont::getWMode() returns a scoped enum, and GfxState::setPath(), Object::streamGetDict()/arrayGetNF()/dictGetKey()/dictGetValNF() and the Object(Dict*) constructor were removed, while Catalog::indexToLabel() now takes a std::string*. . This backports Inkscape's own upstream poppler 26.02-26.07 port, rebased onto 1.4.3, combining these upstream merge requests: * !7780 - Fix building with Poppler 26.02 (47e20c05) * !7839 - Fix building with Poppler 26.04 (9fcd1ec7) * !7919 - Support for poppler >= 26.05 font encoding change * !7968 - Fix building with Poppler 26.06 (1ad89c94) * !8034 - Fix building with Poppler 26.07 (fc52525f) * !8037 - Fix incorrect Poppler version check (09cbe3cf) . Every change is guarded on POPPLER_CHECK_VERSION, so it is a no-op with the poppler currently in the archive and can be applied ahead of the transition. Author: Nadzeya Hutsko <[email protected]> Bug-Ubuntu: https://bugs.launchpad.net/bugs/2162141 Origin: backport, https://gitlab.com/inkscape/inkscape/-/commit/09cbe3cf Forwarded: not-needed Last-Update: 2026-07-30 --- a/src/extension/internal/pdfinput/pdf-input.cpp +++ b/src/extension/internal/pdfinput/pdf-input.cpp @@ -59,6 +59,8 @@ #include "document.h" #include "extension/input.h" #include "extension/system.h" +#include <optional> + #include "inkscape.h" #include "object/sp-root.h" #include "pdf-parser.h" @@ -808,7 +810,11 @@ } // Apply crop settings +#if POPPLER_CHECK_VERSION(26, 6, 0) + std::optional<PDFRectangle> clipToBox; +#else _POPPLER_CONST PDFRectangle *clipToBox = nullptr; +#endif if (crop_to == "media-box") { clipToBox = page->getMediaBox(); @@ -822,8 +828,16 @@ clipToBox = page->getArtBox(); } + std::optional<PDFRectangle> cropBox; +#if POPPLER_CHECK_VERSION(26, 6, 0) + cropBox = clipToBox; +#else + if (clipToBox) { + cropBox = *clipToBox; + } +#endif // Create parser (extension/internal/pdfinput/pdf-parser.h) - auto pdf_parser = PdfParser(pdf_doc, builder, page, clipToBox); + auto pdf_parser = PdfParser(pdf_doc, builder, page, cropBox); // Set up approximation precision for parser. Used for converting Mesh Gradients into tiles. if ( color_delta <= 0.0 ) { --- a/src/extension/internal/pdfinput/pdf-parser.cpp +++ b/src/extension/internal/pdfinput/pdf-parser.cpp @@ -43,6 +43,7 @@ #include <poppler/GlobalParams.h> #include <poppler/Lexer.h> #include <poppler/Object.h> +#include <poppler/OptionalContent.h> #include <poppler/OutputDev.h> #include <poppler/PDFDoc.h> #include <poppler/Page.h> @@ -266,7 +267,7 @@ //------------------------------------------------------------------------ PdfParser::PdfParser(std::shared_ptr<PDFDoc> pdf_doc, Inkscape::Extension::Internal::SvgBuilder *builderA, Page *page, - _POPPLER_CONST PDFRectangle *cropBox) + const std::optional<PDFRectangle> &cropBox) : _pdf_doc(pdf_doc) , xref(pdf_doc->getXRef()) , builder(builderA) @@ -292,8 +293,8 @@ if (page) { // Increment the page building here and set page label Catalog *catalog = pdf_doc->getCatalog(); - GooString *label = new GooString(""); - catalog->indexToLabel(page->getNum() - 1, label); + _POPPLER_STRING_26_7 label; + catalog->indexToLabel(page->getNum() - 1, &label); builder->pushPage(getString(label), state); } @@ -307,8 +308,8 @@ builder->setMargins(getRect(page->getTrimBox()) * scale, getRect(page->getArtBox()) * scale, getRect(page->getBleedBox()) * scale); - if (cropBox && getRect(cropBox) != page_box) { - builder->cropPage(getRect(cropBox) * scale); + if (cropBox && getRect(*cropBox) != page_box) { + builder->cropPage(getRect(*cropBox) * scale); } saveState(); @@ -325,7 +326,7 @@ , printCommands(false) , res(new GfxResources(xref, resDict, nullptr)) , // start the resource stack - state(new GfxState(72, 72, box, 0, false)) + state(new _POPPLER_GFX_STATE(72, 72, *box, 0, false)) , fontChanged(gFalse) , clip(clipNone) , ignoreUndef(0) @@ -653,7 +654,11 @@ void PdfParser::opSetLineJoin(Object args[], int /*numArgs*/) { builder->beforeStateChange(state); +#if POPPLER_CHECK_VERSION(26,2,0) + state->setLineJoin((GfxState::LineJoinStyle) args[0].getInt()); +#else state->setLineJoin(args[0].getInt()); +#endif builder->updateStyle(state); } @@ -661,7 +666,11 @@ void PdfParser::opSetLineCap(Object args[], int /*numArgs*/) { builder->beforeStateChange(state); +#if POPPLER_CHECK_VERSION(26,2,0) + state->setLineCap((GfxState::LineCapStyle) args[0].getInt()); +#else state->setLineCap(args[0].getInt()); +#endif builder->updateStyle(state); } @@ -809,7 +818,7 @@ } _POPPLER_FREE(obj3); if (_POPPLER_CALL_ARGS_DEREF(obj3, obj2.dictLookup, "G").isStream()) { - if (_POPPLER_CALL_ARGS_DEREF(obj4, obj3.streamGetDict()->lookup, "Group").isDict()) { + if (_POPPLER_CALL_ARGS_DEREF(obj4, obj3.getStream()->getDict()->lookup, "Group").isDict()) { std::unique_ptr<GfxColorSpace> blendingColorSpace; GBool isolated = gFalse; GBool knockout = gFalse; @@ -872,7 +881,7 @@ } // get stream dict - dict = str->streamGetDict(); + dict = str->getStream()->getDict(); // check form type _POPPLER_CALL_ARGS(obj1, dict->lookup, "FormType"); @@ -984,7 +993,7 @@ state->setFillPattern(nullptr); state->setFillColorSpace(_POPPLER_CONSUME_UNIQPTR_ARG(std::make_unique<GfxDeviceGrayColorSpace>())); color.c[0] = dblToCol(args[0].getNum()); - state->setFillColor(&color); + state->_POPPLER_SET_FILL_COLOR(color); builder->updateStyle(state); } @@ -996,7 +1005,7 @@ state->setStrokePattern(nullptr); state->setStrokeColorSpace(_POPPLER_CONSUME_UNIQPTR_ARG(std::make_unique<GfxDeviceGrayColorSpace>())); color.c[0] = dblToCol(args[0].getNum()); - state->setStrokeColor(&color); + state->_POPPLER_SET_STROKE_COLOR(color); builder->updateStyle(state); } @@ -1011,7 +1020,7 @@ for (i = 0; i < 4; ++i) { color.c[i] = dblToCol(args[i].getNum()); } - state->setFillColor(&color); + state->_POPPLER_SET_FILL_COLOR(color); builder->updateStyle(state); } @@ -1025,7 +1034,7 @@ for (int i = 0; i < 4; ++i) { color.c[i] = dblToCol(args[i].getNum()); } - state->setStrokeColor(&color); + state->_POPPLER_SET_STROKE_COLOR(color); builder->updateStyle(state); } @@ -1039,7 +1048,7 @@ for (int i = 0; i < 3; ++i) { color.c[i] = dblToCol(args[i].getNum()); } - state->setFillColor(&color); + state->_POPPLER_SET_FILL_COLOR(color); builder->updateStyle(state); } @@ -1052,7 +1061,7 @@ for (int i = 0; i < 3; ++i) { color.c[i] = dblToCol(args[i].getNum()); } - state->setStrokeColor(&color); + state->_POPPLER_SET_STROKE_COLOR(color); builder->updateStyle(state); } @@ -1068,7 +1077,7 @@ GfxColor color; colorSpace->getDefaultColor(&color); state->setFillColorSpace(_POPPLER_CONSUME_UNIQPTR_ARG(colorSpace)); - state->setFillColor(&color); + state->_POPPLER_SET_FILL_COLOR(color); builder->updateStyle(state); } else { error(errSyntaxError, getPos(), "Bad color space (fill)"); @@ -1089,7 +1098,7 @@ GfxColor color; colorSpace->getDefaultColor(&color); state->setStrokeColorSpace(_POPPLER_CONSUME_UNIQPTR_ARG(colorSpace)); - state->setStrokeColor(&color); + state->_POPPLER_SET_STROKE_COLOR(color); builder->updateStyle(state); } else { error(errSyntaxError, getPos(), "Bad color space (stroke)"); @@ -1109,7 +1118,7 @@ for (i = 0; i < numArgs; ++i) { color.c[i] = dblToCol(args[i].getNum()); } - state->setFillColor(&color); + state->_POPPLER_SET_FILL_COLOR(color); builder->updateStyle(state); } @@ -1126,7 +1135,7 @@ for (i = 0; i < numArgs; ++i) { color.c[i] = dblToCol(args[i].getNum()); } - state->setStrokeColor(&color); + state->_POPPLER_SET_STROKE_COLOR(color); builder->updateStyle(state); } @@ -1147,7 +1156,7 @@ color.c[i] = dblToCol(args[i].getNum()); } } - state->setFillColor(&color); + state->_POPPLER_SET_FILL_COLOR(color); builder->updateStyle(state); } if (auto pattern = lookupPattern(&(args[numArgs - 1]), state)) { @@ -1166,7 +1175,7 @@ color.c[i] = dblToCol(args[i].getNum()); } } - state->setFillColor(&color); + state->_POPPLER_SET_FILL_COLOR(color); builder->updateStyle(state); } } @@ -1190,7 +1199,7 @@ color.c[i] = dblToCol(args[i].getNum()); } } - state->setStrokeColor(&color); + state->_POPPLER_SET_STROKE_COLOR(color); builder->updateStyle(state); } if (auto pattern = lookupPattern(&(args[numArgs - 1]), state)) { @@ -1209,7 +1218,7 @@ color.c[i] = dblToCol(args[i].getNum()); } } - state->setStrokeColor(&color); + state->_POPPLER_SET_STROKE_COLOR(color); builder->updateStyle(state); } } @@ -1565,7 +1574,13 @@ // restore graphics state restoreState(); +#if POPPLER_CHECK_VERSION(26, 2, 0) + state->clearPath(); + GfxPath *currPath = const_cast<GfxPath*>(state->getPath()); + currPath->append(savedPath); +#else state->setPath(savedPath); +#endif } // TODO not good that numArgs is ignored but args[] is used: @@ -1626,7 +1641,13 @@ // restore graphics state if (savedState) { restoreState(); +#if POPPLER_CHECK_VERSION(26, 2, 0) + state->clearPath(); + GfxPath *currPath = const_cast<GfxPath*>(state->getPath()); + currPath->append(savedPath); +#else state->setPath(savedPath); +#endif } } @@ -1680,7 +1701,7 @@ // use the center color shading->getColor(xM, yM, &fillColor); - state->setFillColor(&fillColor); + state->_POPPLER_SET_FILL_COLOR(fillColor); // fill the rectangle state->moveTo(x0 * matrix[0] + y0 * matrix[2] + matrix[4], @@ -1779,7 +1800,7 @@ } } if (i == nComps || depth == maxDepths[pdfGouraudTriangleShading-1]) { - state->setFillColor(color0); + state->_POPPLER_SET_FILL_COLOR(*color0); state->moveTo(x0, y0); state->lineTo(x1, y1); state->lineTo(x2, y2); @@ -1857,7 +1878,7 @@ color.c[i] = GfxColorComp(patch->color[0][0].c[i]); } if (i == nComps || depth == maxDepths[pdfPatchMeshShading-1]) { - state->setFillColor(&color); + state->_POPPLER_SET_FILL_COLOR(color); state->moveTo(patch->x[0][0], patch->y[0][0]); state->curveTo(patch->x[0][1], patch->y[0][1], patch->x[0][2], patch->y[0][2], @@ -2213,7 +2234,7 @@ { Array *a = nullptr; Object obj; - int wMode = 0; // Writing mode (horizontal/vertical). + _POPPLER_WMODE wMode = _POPPLER_WMODE_HORIZONTAL; // Writing mode (horizontal/vertical). if (!state->getFont()) { error(errSyntaxError, getPos(), "No font in show/space"); @@ -2227,7 +2248,7 @@ if (obj.isNum()) { // this uses the absolute value of the font size to match // Acrobat's behavior - if (wMode) { + if (wMode != _POPPLER_WMODE_HORIZONTAL) { state->textShift(0, -obj.getNum() * 0.001 * fabs(state->getFontSize())); } else { @@ -2248,15 +2269,11 @@ * This adds a string from a PDF file that is contained in one command ('Tj', ''', '"') * or is one string in ShowSpacetext ('TJ'). */ -#if POPPLER_CHECK_VERSION(0,64,0) -void PdfParser::doShowText(const GooString *s) { -#else -void PdfParser::doShowText(GooString *s) { -#endif +void PdfParser::doShowText(const std::string &s) { auto font = state->getFont(); - int wMode = font->getWMode(); // Vertical/Horizontal/Invalid + _POPPLER_WMODE wMode = font->getWMode(); // Vertical/Horizontal/Invalid - builder->beginString(state, get_goostring_length(*s)); + builder->beginString(state, s.size()); // handle a Type 3 char if (font->getType() == fontType3) { @@ -2266,8 +2283,8 @@ double riseX, riseY; state->textTransformDelta(0, state->getRise(), &riseX, &riseY); - auto p = s->getCString(); // char* or const char* - int len = get_goostring_length(*s); + auto p = s.c_str(); // char* or const char* + int len = s.size(); while (len > 0) { @@ -2289,7 +2306,7 @@ auto ax = dx; auto ay = dy; - if (wMode != 0) { + if (wMode != _POPPLER_WMODE_HORIZONTAL) { // Vertical text (or invalid value). dy += state->getCharSpace(); if (n == 1 && *p == ' ') { @@ -2324,6 +2341,15 @@ builder->endString(state); } +#if POPPLER_CHECK_VERSION(0,64,0) +void PdfParser::doShowText(const GooString *s) { +#else +void PdfParser::doShowText(GooString *s) { +#endif + const std::string str = s->toStr(); + doShowText(str); +} + //------------------------------------------------------------------------ // XObject operators @@ -2352,7 +2378,7 @@ } //add layer at root if xObject has type OCG - _POPPLER_CALL_ARGS(obj2, obj1.streamGetDict()->lookup, "OC"); + _POPPLER_CALL_ARGS(obj2, obj1.getStream()->getDict()->lookup, "OC"); if(obj2.isDict()){ auto type_dict = obj2.getDict(); if (type_dict->lookup("Type").isName("OCG")) { @@ -2370,7 +2396,7 @@ } } - _POPPLER_CALL_ARGS(obj2, obj1.streamGetDict()->lookup, "Subtype"); + _POPPLER_CALL_ARGS(obj2, obj1.getStream()->getDict()->lookup, "Subtype"); if (obj2.isName(const_cast<char*>("Image"))) { _POPPLER_CALL_ARGS(refObj, res->lookupXObjectNF, name); doImage(&refObj, obj1.getStream(), gFalse); @@ -2378,7 +2404,7 @@ } else if (obj2.isName(const_cast<char*>("Form"))) { doForm(&obj1); } else if (obj2.isName(const_cast<char*>("PS"))) { - _POPPLER_CALL_ARGS(obj3, obj1.streamGetDict()->lookup, "Level1"); + _POPPLER_CALL_ARGS(obj3, obj1.getStream()->getDict()->lookup, "Level1"); } else if (obj2.isName()) { error(errSyntaxError, getPos(), "Unknown XObject subtype '{0:s}'", obj2.getName()); } else { @@ -2571,7 +2597,7 @@ goto err1; } maskStr = smaskObj.getStream(); - maskDict = smaskObj.streamGetDict(); + maskDict = smaskObj.getStream()->getDict(); _POPPLER_CALL_ARGS(obj1, maskDict->lookup, "Width"); if (obj1.isNull()) { _POPPLER_FREE(obj1); @@ -2649,7 +2675,7 @@ goto err1; } maskStr = maskObj.getStream(); - maskDict = maskObj.streamGetDict(); + maskDict = maskObj.getStream()->getDict(); _POPPLER_CALL_ARGS(obj1, maskDict->lookup, "Width"); if (obj1.isNull()) { _POPPLER_FREE(obj1); @@ -2749,7 +2775,7 @@ } // get stream dict - dict = str->streamGetDict(); + dict = str->getStream()->getDict(); // check form type _POPPLER_CALL_ARGS(obj1, dict->lookup, "FormType"); @@ -2931,7 +2957,12 @@ // build dictionary #if defined(POPPLER_NEW_OBJECT_API) +#if POPPLER_CHECK_VERSION(26, 6, 0) + // poppler 26.06 removed the Object(Dict *) constructor + dict = Object(std::make_unique<Dict>(xref)); +#else dict = Object(new Dict(xref)); +#endif #else dict.initDict(xref); #endif @@ -2964,7 +2995,11 @@ // make stream #if defined(POPPLER_NEW_OBJECT_API) str = new EmbedStream(parser->getStream(), dict.copy(), gFalse, 0); +#if POPPLER_CHECK_VERSION(26, 2, 0) + str = str->addFilters(std::unique_ptr<Stream>(str), dict.getDict()).release(); +#else str = str->addFilters(dict.getDict()); +#endif #else str = new EmbedStream(parser->getStream(), &dict, gFalse, 0); str = str->addFilters(&dict); @@ -3137,10 +3172,17 @@ auto visible = true; // Normally we'd use poppler optContentIsVisible, but these dict // objects don't retain their references so can't be used directly. +#if POPPLER_CHECK_VERSION(26, 2, 0) + for (auto &[ref, ocg] : ocgs->getOCGs()) { + if (ocg->getName()->toStr() == label) + visible = ocg->getState() == OptionalContentGroup::On; + } +#else for (auto &[ref, ocg] : ocgs->getOCGs()) { if (ocg->getName()->cmp(label) == 0) visible = ocg->getState() == OptionalContentGroup::On; } +#endif builder->addOptionalGroup(dict->getKey(j), label, visible); } } --- a/src/extension/internal/pdfinput/pdf-parser.h +++ b/src/extension/internal/pdfinput/pdf-parser.h @@ -29,6 +29,7 @@ #include <glib/poppler-features.h> #include <map> #include <memory> +#include <optional> #include <poppler/Object.h> #include <string> @@ -113,7 +114,7 @@ public: // Constructor for regular output. - PdfParser(std::shared_ptr<PDFDoc> pdf_doc, SvgBuilder *builderA, Page *page, _POPPLER_CONST PDFRectangle *cropBox); + PdfParser(std::shared_ptr<PDFDoc> pdf_doc, SvgBuilder *builderA, Page *page, const std::optional<PDFRectangle> &cropBox); // Constructor for a sub-page object. PdfParser(XRef *xrefA, SvgBuilder *builderA, Dict *resDict, _POPPLER_CONST PDFRectangle *box); @@ -283,10 +284,11 @@ void opMoveShowText(Object args[], int numArgs); void opMoveSetShowText(Object args[], int numArgs); void opShowSpaceText(Object args[], int numArgs); + void doShowText(const std::string &s); #if POPPLER_CHECK_VERSION(0,64,0) - void doShowText(const GooString *s); + void doShowText(const GooString *s); #else - void doShowText(GooString *s); + void doShowText(GooString *s); #endif --- a/src/extension/internal/pdfinput/pdf-utils.cpp +++ b/src/extension/internal/pdfinput/pdf-utils.cpp @@ -133,6 +133,11 @@ return Geom::Rect(box->x1, box->y1, box->x2, box->y2); } +Geom::Rect getRect(_POPPLER_CONST PDFRectangle &box) +{ + return Geom::Rect(box.x1, box.y1, box.x2, box.y2); +} + Geom::PathVector getPathV(GfxPath *path) { if (!path) { --- a/src/extension/internal/pdfinput/pdf-utils.h +++ b/src/extension/internal/pdfinput/pdf-utils.h @@ -59,6 +59,7 @@ }; Geom::Rect getRect(_POPPLER_CONST PDFRectangle *box); +Geom::Rect getRect(_POPPLER_CONST PDFRectangle &box); Geom::PathVector getPathV(GfxPath *gPath); #endif /* PDF_UTILS_H */ --- a/src/extension/internal/pdfinput/poppler-transition-api.h +++ b/src/extension/internal/pdfinput/poppler-transition-api.h @@ -15,6 +15,38 @@ #include <glib/poppler-features.h> #include <poppler/UTF.h> +#if POPPLER_CHECK_VERSION(26, 7, 0) +#define _POPPLER_STRING_26_7 std::string +#else +#define _POPPLER_STRING_26_7 GooString +#endif + +#if POPPLER_CHECK_VERSION(26, 6, 0) +#define _POPPLER_GET_GRAY(color, gray) getGray(color, gray) +#define _POPPLER_GET_RGB(color, rgb) getRGB(color, rgb) +#define _POPPLER_GET_CMYK(color, cmyk) getCMYK(color, cmyk) +#define _POPPLER_SET_FILL_COLOR(color) setFillColor(color) +#define _POPPLER_SET_STROKE_COLOR(color) setStrokeColor(color) +#define _POPPLER_GFX_STATE(h, v, Rect, rotateA, upsideDown) GfxState(h, v, Rect, rotateA, upsideDown) +#else +#define _POPPLER_GET_GRAY(color, gray) getGray(&color, gray) +#define _POPPLER_GET_RGB(color, rgb) getRGB(&color, rgb) +#define _POPPLER_GET_CMYK(color, cmyk) getCMYK(&color, cmyk) +#define _POPPLER_SET_FILL_COLOR(color) setFillColor(&color) +#define _POPPLER_SET_STROKE_COLOR(color) setStrokeColor(&color) +#define _POPPLER_GFX_STATE(h, v, Rect, rotateA, upsideDown) GfxState(h, v, &Rect, rotateA, upsideDown) +#endif + +#if POPPLER_CHECK_VERSION(26, 2, 0) +#define _POPPLER_WMODE GfxFont::WritingMode +#define _POPPLER_WMODE_HORIZONTAL GfxFont::WritingMode::Horizontal +#define _POPPLER_WMODE_VERTICAL GfxFont::WritingMode::Vertical +#else +#define _POPPLER_WMODE int +#define _POPPLER_WMODE_HORIZONTAL 0 +#define _POPPLER_WMODE_VERTICAL 1 +#endif + #if POPPLER_CHECK_VERSION(25, 7, 0) #define _POPPLER_TEXT_SHIFT_WITH_USER_COORDS(dx, dy) textShiftWithUserCoords(dx, dy) #define _POPPLER_FOFI_TRUETYPE_MAKE(font_data, faceIndex) FoFiTrueType::make(std::span(font_data), faceIndex) @@ -62,11 +94,11 @@ #endif #if POPPLER_CHECK_VERSION(24, 5, 0) -#define _POPPLER_HAS_UNICODE_BOM(value) (hasUnicodeByteOrderMark(value->toStr())) -#define _POPPLER_HAS_UNICODE_BOMLE(value) (hasUnicodeByteOrderMarkLE(value->toStr())) +#define _POPPLER_HAS_UNICODE_BOM(value) (hasUnicodeByteOrderMark(value)) +#define _POPPLER_HAS_UNICODE_BOMLE(value) (hasUnicodeByteOrderMarkLE(value)) #else -#define _POPPLER_HAS_UNICODE_BOM(value) (value->hasUnicodeMarker()) -#define _POPPLER_HAS_UNICODE_BOMLE(value) (value->hasUnicodeMarkerLE()) +#define _POPPLER_HAS_UNICODE_BOM(value) (GooString(value).hasUnicodeMarker()) +#define _POPPLER_HAS_UNICODE_BOMLE(value) (GooString(value).hasUnicodeMarkerLE()) #endif #if POPPLER_CHECK_VERSION(24, 3, 0) --- a/src/extension/internal/pdfinput/poppler-utils.cpp +++ b/src/extension/internal/pdfinput/poppler-utils.cpp @@ -88,7 +88,12 @@ r.num = hashFontObject(&obj2); } // Newer poppler will require some reworking as it gives a shared ptr. +#if POPPLER_CHECK_VERSION(26, 3, 0) + // poppler 26.03 made GfxFont::makeFont() take a const Dict& fontDict + fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i), r, *obj2.getDict()); +#else fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i), r, obj2.getDict()); +#endif if (fonts[i] && !fonts[i]->isOk()) { fonts[i] = nullptr; } @@ -145,7 +150,6 @@ void InkFontDict::hashFontObject1(const Object *obj, FNVHash *h) { - const GooString *s; const char *p; double r; int n, i; @@ -165,11 +169,16 @@ r = obj->getReal(); h->hash((char *)&r, sizeof(double)); break; - case objString: + case objString: { h->hash('s'); - s = obj->getString(); +#if POPPLER_CHECK_VERSION(26, 4, 0) + const auto &s = obj->getString(); + h->hash(s.c_str(), s.size()); +#else + const GooString* s = obj->getString(); h->hash(s->c_str(), get_goostring_length(*s)); - break; +#endif + } break; case objName: h->hash('n'); p = obj->getName(); @@ -178,26 +187,28 @@ case objNull: h->hash('z'); break; - case objArray: - h->hash('a'); - n = obj->arrayGetLength(); - h->hash((char *)&n, sizeof(int)); - for (i = 0; i < n; ++i) { - const Object &obj2 = obj->arrayGetNF(i); - hashFontObject1(&obj2, h); - } - break; - case objDict: - h->hash('d'); - n = obj->dictGetLength(); - h->hash((char *)&n, sizeof(int)); - for (i = 0; i < n; ++i) { - p = obj->dictGetKey(i); - h->hash(p, (int)strlen(p)); - const Object &obj2 = obj->dictGetValNF(i); - hashFontObject1(&obj2, h); - } - break; + case objArray: { + h->hash('a'); + Array * objArray = obj->getArray(); + n = objArray->getLength(); + h->hash((char *)&n, sizeof(int)); + for (i = 0; i < n; ++i) { + const Object &obj2 = objArray->getNF(i); + hashFontObject1(&obj2, h); + } + } break; + case objDict: { + h->hash('d'); + auto objdict = obj->getDict(); + n = objdict->getLength(); + h->hash((char *)&n, sizeof(int)); + for (i = 0; i < n; ++i) { + auto p = std::string(objdict->getKey(i)); + h->hash(p.c_str(), p.length()); + const Object &obj2 = objdict->getValNF(i); + hashFontObject1(&obj2, h); + } + } break; case objStream: // this should never happen - streams must be indirect refs break; @@ -535,7 +546,7 @@ continue; Ref resourcesRef; - const Object resObj = obj2.streamGetDict()->lookup("Resources", &resourcesRef); + const Object resObj = obj2.getStream()->getDict()->lookup("Resources", &resourcesRef); if (resourcesRef != Ref::INVALID() && !visitedObjects.insert(resourcesRef.num).second) continue; @@ -590,16 +601,29 @@ * Convert PDF strings, which can be formatted as UTF8, UTF16BE or UTF16LE into * a predictable UTF8 string consistant with svg requirements. */ -std::string getString(const GooString *value) +std::string getString(const std::string &value) { if (_POPPLER_HAS_UNICODE_BOM(value)) { - return g_convert(value->getCString () + 2, get_goostring_length(*value) - 2, + return g_convert(value.c_str() + 2, value.size() - 2, "UTF-8", "UTF-16BE", NULL, NULL, NULL); } else if (_POPPLER_HAS_UNICODE_BOMLE(value)) { - return g_convert(value->getCString () + 2, get_goostring_length(*value) - 2, + return g_convert(value.c_str() + 2, value.size() - 2, "UTF-8", "UTF-16LE", NULL, NULL, NULL); } - return value->toStr(); + return value; +} + +std::string getString(const GooString *value) +{ + if (value) { + return getString(value->toStr()); + } + return ""; +} + +std::string getString(const GooString &value) +{ + return getString(value.toStr()); } void pdf_debug_array(const Array *array, int depth, XRef *xref) @@ -656,7 +680,11 @@ } else if (obj->isArray()) { pdf_debug_array(obj->getArray(), depth, xref); } else if (obj->isString()) { +#if POPPLER_CHECK_VERSION(26, 4, 0) + std::cout << " STR '" << obj->getString().c_str() << "'"; +#else std::cout << " STR '" << obj->getString()->getCString() << "'"; +#endif } else if (obj->isName()) { std::cout << " NAME '" << obj->getName() << "'"; } else if (obj->isBool()) { --- a/src/extension/internal/pdfinput/poppler-utils.h +++ b/src/extension/internal/pdfinput/poppler-utils.h @@ -83,7 +83,9 @@ FontList getPdfFonts(std::shared_ptr<PDFDoc> pdf_doc); std::string getNameWithoutSubsetTag(std::string name); std::string getDictString(Dict *dict, const char *key); +std::string getString(const std::string &value); std::string getString(const GooString *value); +std::string getString(const GooString &value); std::string validateString(std::string const &in); // Replacate poppler FontDict --- a/src/extension/internal/pdfinput/svg-builder.cpp +++ b/src/extension/internal/pdfinput/svg-builder.cpp @@ -392,7 +392,15 @@ return svgConvertRGBToText(r, g, b); } -std::string SvgBuilder::convertGfxColor(const GfxColor *color, GfxColorSpace *space) +// for poppler < 26.06.0 +std::string SvgBuilder::convertGfxColor(const GfxColor *color, GfxColorSpace *space) { + if (!color) { + return ""; + } + return convertGfxColor(*color, space); +} + +std::string SvgBuilder::convertGfxColor(const GfxColor &color, GfxColorSpace *space) { std::string icc = ""; switch (space->getMode()) { @@ -412,14 +420,14 @@ } GfxRGB rgb; - space->getRGB(color, &rgb); + space->_POPPLER_GET_RGB(color, &rgb); auto rgb_color = svgConvertGfxRGB(&rgb); if (!icc.empty()) { Inkscape::CSSOStringStream icc_color; icc_color << rgb_color << " icc-color(" << icc; for (int i = 0; i < space->getNComps(); ++i) { - icc_color << ", " << colToDbl((*color).c[i]); + icc_color << ", " << colToDbl((color).c[i]); } icc_color << ");"; return icc_color.str(); @@ -1204,7 +1212,7 @@ /** * \brief Adds a stop with the given properties to the gradient's representation */ -void SvgBuilder::_addStopToGradient(Inkscape::XML::Node *gradient, double offset, GfxColor *color, GfxColorSpace *space, +void SvgBuilder::_addStopToGradient(Inkscape::XML::Node *gradient, double offset, GfxColor &color, GfxColorSpace *space, double opacity) { Inkscape::XML::Node *stop = _xml_doc->createElement("svg:stop"); @@ -1214,7 +1222,7 @@ if (space->getMode() == csDeviceGray) { // This is a transparency mask. GfxRGB rgb; - space->getRGB(color, &rgb); + space->_POPPLER_GET_RGB(color, &rgb); double gray = (double)rgb.r / 65535.0; gray = CLAMP(gray, 0.0, 1.0); os_opacity << gray; @@ -1255,8 +1263,8 @@ if (!svgGetShadingColor(shading, 0.0, &stop1) || !svgGetShadingColor(shading, 1.0, &stop2)) { return false; } else { - _addStopToGradient(gradient, 0.0, &stop1, space, 1.0); - _addStopToGradient(gradient, 1.0, &stop2, space, 1.0); + _addStopToGradient(gradient, 0.0, stop1, space, 1.0); + _addStopToGradient(gradient, 1.0, stop2, space, 1.0); } } else if (type == _POPPLER_FUNCTION_TYPE_STITCHING) { auto stitchingFunc = static_cast<_POPPLER_CONST StitchingFunction*>(func); @@ -1269,7 +1277,7 @@ // Add stops from all the stitched functions GfxColor prev_color, color; svgGetShadingColor(shading, bounds[0], &prev_color); - _addStopToGradient(gradient, bounds[0], &prev_color, space, 1.0); + _addStopToGradient(gradient, bounds[0], prev_color, space, 1.0); for ( int i = 0 ; i < num_funcs ; i++ ) { svgGetShadingColor(shading, bounds[i + 1], &color); // Add stops @@ -1279,14 +1287,14 @@ expE = (bounds[i + 1] - bounds[i])/expE; // approximate exponential as a single straight line at x=1 if (encode[2*i] == 0) { // normal sequence auto offset = (bounds[i + 1] - expE) / max_bound; - _addStopToGradient(gradient, offset, &prev_color, space, 1.0); + _addStopToGradient(gradient, offset, prev_color, space, 1.0); } else { // reflected sequence auto offset = (bounds[i] + expE) / max_bound; - _addStopToGradient(gradient, offset, &color, space, 1.0); + _addStopToGradient(gradient, offset, color, space, 1.0); } } } - _addStopToGradient(gradient, bounds[i + 1] / max_bound, &color, space, 1.0); + _addStopToGradient(gradient, bounds[i + 1] / max_bound, color, space, 1.0); prev_color = color; } } else { // Unsupported function type @@ -1386,7 +1394,7 @@ sp_repr_css_set_property(_css_font, "font-variant", "normal"); // Writing mode - if ( font->getWMode() == 0 ) { + if ( font->getWMode() == _POPPLER_WMODE_HORIZONTAL ) { sp_repr_css_set_property(_css_font, "writing-mode", "lr"); } else { sp_repr_css_set_property(_css_font, "writing-mode", "tb"); @@ -1398,7 +1406,7 @@ */ void SvgBuilder::updateTextShift(GfxState *state, double shift) { double shift_value = -shift * 0.001 * fabs(state->getFontSize()); - if (state->getFont()->getWMode()) { + if (state->getFont()->getWMode() != _POPPLER_WMODE_HORIZONTAL) { _text_position[1] += shift_value; } else { _text_position[0] += shift_value; @@ -1452,7 +1460,7 @@ // Text direction is a property of the <text> element. auto font = state->getFont(); - if (font->getWMode() == 1) { + if (font->getWMode() == _POPPLER_WMODE_VERTICAL) { // Only set if vertical. auto css_text = sp_repr_css_attr_new(); sp_repr_css_set_property(css_text, "writing-mode", "tb"); @@ -1546,8 +1554,8 @@ bool output_tspan = next_it == _glyphs.end() || next_it->style_changed || - (writing_mode == 0 && std::abs(glyph.text_position[1] - next_it->text_position[1]) > 0.1) || - (writing_mode == 1 && std::abs(glyph.text_position[0] - next_it->text_position[0]) > 0.1); + (writing_mode == _POPPLER_WMODE_HORIZONTAL && std::abs(glyph.text_position[1] - next_it->text_position[1]) > 0.1) || + (writing_mode == _POPPLER_WMODE_VERTICAL && std::abs(glyph.text_position[0] - next_it->text_position[0]) > 0.1); if (output_tspan) { --- a/src/extension/internal/pdfinput/svg-builder.h +++ b/src/extension/internal/pdfinput/svg-builder.h @@ -186,7 +186,7 @@ // Pattern creation gchar *_createPattern(GfxPattern *pattern, GfxState *state, bool is_stroke=false); gchar *_createGradient(GfxShading *shading, const Geom::Affine pat_matrix, bool for_shading = false); - void _addStopToGradient(Inkscape::XML::Node *gradient, double offset, GfxColor *color, GfxColorSpace *space, + void _addStopToGradient(Inkscape::XML::Node *gradient, double offset, GfxColor &color, GfxColorSpace *space, double opacity); bool _addGradientStops(Inkscape::XML::Node *gradient, GfxShading *shading, _POPPLER_CONST Function *func); @@ -239,6 +239,7 @@ static bool _attrEqual(Inkscape::XML::Node *a, Inkscape::XML::Node *b, char const *attr); // Colors + std::string convertGfxColor(const GfxColor &color, GfxColorSpace *space); std::string convertGfxColor(const GfxColor *color, GfxColorSpace *space); std::string _getColorProfile(cmsHPROFILE hp); --- a/src/extension/internal/pdfinput/poppler-cairo-font-engine.cpp +++ b/src/extension/internal/pdfinput/poppler-cairo-font-engine.cpp @@ -313,7 +313,11 @@ #else GfxFontLoc *fontLoc; #endif +#if POPPLER_CHECK_VERSION(26, 5, 0) + const char * const *enc; +#else char **enc; +#endif const char *name; #if POPPLER_CHECK_VERSION(25, 7, 0) std::unique_ptr<FoFiType1C> ff1c; @@ -385,7 +389,11 @@ goto err2; } +#if POPPLER_CHECK_VERSION(26, 5, 0) + enc = gfx8bit->getEncoding().data(); +#else enc = gfx8bit->getEncoding(); +#endif codeToGID.resize(256); for (i = 0; i < 256; ++i) { @@ -677,7 +685,7 @@ #endif std::vector<int> codeToGID; - char *name; + const char *name; Dict *charProcs = gfx8bit->getCharProcs(); Ref ref = *gfxFont->getID(); @@ -694,13 +702,17 @@ cairo_font_face_set_user_data(font_face, &type3_font_key, (void *)info, _free_type3_font_info); +#if POPPLER_CHECK_VERSION(26, 5, 0) + const char * const *enc = gfx8bit->getEncoding().data(); +#else char **enc = gfx8bit->getEncoding(); +#endif codeToGID.resize(256); for (int i = 0; i < 256; ++i) { codeToGID[i] = 0; if (charProcs && (name = enc[i])) { for (int j = 0; j < charProcs->getLength(); j++) { - if (strcmp(name, charProcs->getKey(j)) == 0) { + if (std::string(charProcs->getKey(j)).compare(name) == 0) { codeToGID[i] = j; } }

