inkscape: revbump for libpoppler, fix pdf crashes

This commit is contained in:
Mateusz Sylwestrzak 2025-02-23 17:33:41 +01:00 committed by Đoàn Trần Công Danh
parent ee18744af9
commit 241ebb296b
7 changed files with 956 additions and 1 deletions

View File

@ -0,0 +1,59 @@
From 0399372ec240d23e0e70548237a541f2b5bf0f34 Mon Sep 17 00:00:00 2001
From: KrIr17 <elendil.krir17@gmail.com>
Date: Tue, 5 Nov 2024 00:40:15 +0100
Subject: [PATCH] Fix building with Poppler 24.11
Poppler 24.11 no longer sets the default value for faceIndex to 0 in
`FoFiTrueType::make()` and `FoFiTrueType::load()` [1], so we do it
on our end instead.
Fixes https://gitlab.com/inkscape/inkscape/-/issues/5370
[1] https://gitlab.freedesktop.org/poppler/poppler/-/commit/94467509a013dd5cf46c942baa598f2b296571f4
---
.../internal/pdfinput/poppler-cairo-font-engine.cpp | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/extension/internal/pdfinput/poppler-cairo-font-engine.cpp b/src/extension/internal/pdfinput/poppler-cairo-font-engine.cpp
index 34a8eed682d..728b1d1aac4 100644
--- a/src/extension/internal/pdfinput/poppler-cairo-font-engine.cpp
+++ b/src/extension/internal/pdfinput/poppler-cairo-font-engine.cpp
@@ -419,9 +419,9 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, FT_Li
FoFiTrueType *ff;
#endif
if (!font_data.empty()) {
- ff = FoFiTrueType::make((fontchar)font_data.data(), font_data.size());
+ ff = FoFiTrueType::make((fontchar)font_data.data(), font_data.size(), 0);
} else {
- ff = FoFiTrueType::load(fileName.c_str());
+ ff = FoFiTrueType::load(fileName.c_str(), 0);
}
if (!ff) {
goto err2;
@@ -444,9 +444,9 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, FT_Li
FoFiTrueType *ff;
#endif
if (!font_data.empty()) {
- ff = FoFiTrueType::make((fontchar)font_data.data(), font_data.size());
+ ff = FoFiTrueType::make((fontchar)font_data.data(), font_data.size(), 0);
} else {
- ff = FoFiTrueType::load(fileName.c_str());
+ ff = FoFiTrueType::load(fileName.c_str(), 0);
}
if (!ff) {
error(errSyntaxError, -1, "failed to load truetype font\n");
@@ -512,9 +512,9 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, FT_Li
FoFiTrueType *ff;
#endif
if (!font_data.empty()) {
- ff = FoFiTrueType::make((fontchar)font_data.data(), font_data.size());
+ ff = FoFiTrueType::make((fontchar)font_data.data(), font_data.size(), 0);
} else {
- ff = FoFiTrueType::load(fileName.c_str());
+ ff = FoFiTrueType::load(fileName.c_str(), 0);
}
if (ff) {
if (ff->isOpenTypeCFF()) {
--
GitLab

View File

@ -0,0 +1,430 @@
From 22304ae8034d067670a9f95022083a75fac92b4c Mon Sep 17 00:00:00 2001
From: PBS <pbs3141@gmail.com>
Date: Tue, 22 Oct 2024 14:48:31 +0100
Subject: [PATCH] Future-proof against poppler 24.10 changes
---
.../internal/pdfinput/pdf-parser.cpp | 120 ++++++++----------
src/extension/internal/pdfinput/pdf-parser.h | 4 +-
.../pdfinput/poppler-transition-api.h | 6 +
3 files changed, 61 insertions(+), 69 deletions(-)
diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp
index 97b2909218a..28000a87b0c 100644
--- a/src/extension/internal/pdfinput/pdf-parser.cpp
+++ b/src/extension/internal/pdfinput/pdf-parser.cpp
@@ -817,11 +817,11 @@ void PdfParser::opSetExtGState(Object args[], int /*numArgs*/)
_POPPLER_FREE(obj3);
if (_POPPLER_CALL_ARGS_DEREF(obj3, obj2.dictLookup, "G").isStream()) {
if (_POPPLER_CALL_ARGS_DEREF(obj4, obj3.streamGetDict()->lookup, "Group").isDict()) {
- GfxColorSpace *blendingColorSpace = nullptr;
+ std::unique_ptr<GfxColorSpace> blendingColorSpace;
GBool isolated = gFalse;
GBool knockout = gFalse;
if (!_POPPLER_CALL_ARGS_DEREF(obj5, obj4.dictLookup, "CS").isNull()) {
- blendingColorSpace = GfxColorSpace::parse(nullptr, &obj5, nullptr, state);
+ blendingColorSpace = std::unique_ptr<GfxColorSpace>(GfxColorSpace::parse(nullptr, &obj5, nullptr, state));
}
_POPPLER_FREE(obj5);
if (_POPPLER_CALL_ARGS_DEREF(obj5, obj4.dictLookup, "I").isBool()) {
@@ -842,7 +842,7 @@ void PdfParser::opSetExtGState(Object args[], int /*numArgs*/)
}
}
}
- doSoftMask(&obj3, alpha, blendingColorSpace, isolated, knockout, funcs[0], &backdropColor);
+ doSoftMask(&obj3, alpha, blendingColorSpace.get(), isolated, knockout, funcs[0], &backdropColor);
if (funcs[0]) {
delete funcs[0];
}
@@ -927,9 +927,6 @@ void PdfParser::doSoftMask(Object *str, GBool alpha,
alpha, transferFunc, backdropColor);
--formDepth;
- if (blendingColorSpace) {
- delete blendingColorSpace;
- }
_POPPLER_FREE(obj1);
}
@@ -946,42 +943,43 @@ void PdfParser::opSetRenderingIntent(Object /*args*/[], int /*numArgs*/)
*
* Maintains a cache for named color spaces to avoid expensive re-parsing.
*/
-GfxColorSpace *PdfParser::lookupColorSpaceCopy(Object &arg)
+std::unique_ptr<GfxColorSpace> PdfParser::lookupColorSpaceCopy(Object &arg)
{
assert(!arg.isNull());
- GfxColorSpace *colorSpace = nullptr;
if (char const *name = arg.isName() ? arg.getName() : nullptr) {
auto const cache_name = std::to_string(formDepth) + "-" + name;
- if ((colorSpace = colorSpacesCache[cache_name].get())) {
- return colorSpace->copy();
+ if (auto cached = colorSpacesCache[cache_name].get()) {
+ return std::unique_ptr<GfxColorSpace>(cached->copy());
}
- Object obj = res->lookupColorSpace(name);
- if (obj.isNull()) {
- colorSpace = GfxColorSpace::parse(res, &arg, nullptr, state);
+ std::unique_ptr<GfxColorSpace> colorSpace;
+ if (auto obj = res->lookupColorSpace(name); !obj.isNull()) {
+ colorSpace = std::unique_ptr<GfxColorSpace>(GfxColorSpace::parse(res, &obj, nullptr, state));
} else {
- colorSpace = GfxColorSpace::parse(res, &obj, nullptr, state);
+ colorSpace = std::unique_ptr<GfxColorSpace>(GfxColorSpace::parse(res, &arg, nullptr, state));
}
if (colorSpace && colorSpace->getMode() != csPattern) {
- colorSpacesCache[cache_name].reset(colorSpace->copy());
+ colorSpacesCache[cache_name] = std::unique_ptr<GfxColorSpace>(colorSpace->copy());
}
+
+ return colorSpace;
} else {
// We were passed in an object directly.
- colorSpace = GfxColorSpace::parse(res, &arg, nullptr, state);
+ return std::unique_ptr<GfxColorSpace>(GfxColorSpace::parse(res, &arg, nullptr, state));
}
- return colorSpace;
}
/**
* Look up pattern/gradients from the GfxResource dictionary
*/
-GfxPattern *PdfParser::lookupPattern(Object *obj, GfxState *state)
+std::unique_ptr<GfxPattern> PdfParser::lookupPattern(Object *obj, GfxState *state)
{
- if (!obj->isName())
- return nullptr;
- return res->lookupPattern(obj->getName(), nullptr, state);
+ if (!obj->isName()) {
+ return {};
+ }
+ return std::unique_ptr<GfxPattern>(res->lookupPattern(obj->getName(), nullptr, state));
}
// TODO not good that numArgs is ignored but args[] is used:
@@ -990,7 +988,7 @@ void PdfParser::opSetFillGray(Object args[], int /*numArgs*/)
GfxColor color;
builder->beforeStateChange(state);
state->setFillPattern(nullptr);
- state->setFillColorSpace(new GfxDeviceGrayColorSpace());
+ state->setFillColorSpace(_POPPLER_CONSUME_UNIQPTR_ARG(std::make_unique<GfxDeviceGrayColorSpace>()));
color.c[0] = dblToCol(args[0].getNum());
state->setFillColor(&color);
builder->updateStyle(state);
@@ -1002,7 +1000,7 @@ void PdfParser::opSetStrokeGray(Object args[], int /*numArgs*/)
GfxColor color;
builder->beforeStateChange(state);
state->setStrokePattern(nullptr);
- state->setStrokeColorSpace(new GfxDeviceGrayColorSpace());
+ state->setStrokeColorSpace(_POPPLER_CONSUME_UNIQPTR_ARG(std::make_unique<GfxDeviceGrayColorSpace>()));
color.c[0] = dblToCol(args[0].getNum());
state->setStrokeColor(&color);
builder->updateStyle(state);
@@ -1015,7 +1013,7 @@ void PdfParser::opSetFillCMYKColor(Object args[], int /*numArgs*/)
int i;
builder->beforeStateChange(state);
state->setFillPattern(nullptr);
- state->setFillColorSpace(new GfxDeviceCMYKColorSpace());
+ state->setFillColorSpace(_POPPLER_CONSUME_UNIQPTR_ARG(std::make_unique<GfxDeviceCMYKColorSpace>()));
for (i = 0; i < 4; ++i) {
color.c[i] = dblToCol(args[i].getNum());
}
@@ -1029,7 +1027,7 @@ void PdfParser::opSetStrokeCMYKColor(Object args[], int /*numArgs*/)
GfxColor color;
builder->beforeStateChange(state);
state->setStrokePattern(nullptr);
- state->setStrokeColorSpace(new GfxDeviceCMYKColorSpace());
+ state->setStrokeColorSpace(_POPPLER_CONSUME_UNIQPTR_ARG(std::make_unique<GfxDeviceCMYKColorSpace>()));
for (int i = 0; i < 4; ++i) {
color.c[i] = dblToCol(args[i].getNum());
}
@@ -1043,7 +1041,7 @@ void PdfParser::opSetFillRGBColor(Object args[], int /*numArgs*/)
GfxColor color;
builder->beforeStateChange(state);
state->setFillPattern(nullptr);
- state->setFillColorSpace(new GfxDeviceRGBColorSpace());
+ state->setFillColorSpace(_POPPLER_CONSUME_UNIQPTR_ARG(std::make_unique<GfxDeviceRGBColorSpace>()));
for (int i = 0; i < 3; ++i) {
color.c[i] = dblToCol(args[i].getNum());
}
@@ -1056,7 +1054,7 @@ void PdfParser::opSetStrokeRGBColor(Object args[], int /*numArgs*/) {
GfxColor color;
builder->beforeStateChange(state);
state->setStrokePattern(nullptr);
- state->setStrokeColorSpace(new GfxDeviceRGBColorSpace());
+ state->setStrokeColorSpace(_POPPLER_CONSUME_UNIQPTR_ARG(std::make_unique<GfxDeviceRGBColorSpace>()));
for (int i = 0; i < 3; ++i) {
color.c[i] = dblToCol(args[i].getNum());
}
@@ -1068,14 +1066,14 @@ void PdfParser::opSetStrokeRGBColor(Object args[], int /*numArgs*/) {
void PdfParser::opSetFillColorSpace(Object args[], int numArgs)
{
assert(numArgs >= 1);
- GfxColorSpace *colorSpace = lookupColorSpaceCopy(args[0]);
+ auto colorSpace = lookupColorSpaceCopy(args[0]);
builder->beforeStateChange(state);
state->setFillPattern(nullptr);
if (colorSpace) {
GfxColor color;
- state->setFillColorSpace(colorSpace);
colorSpace->getDefaultColor(&color);
+ state->setFillColorSpace(_POPPLER_CONSUME_UNIQPTR_ARG(colorSpace));
state->setFillColor(&color);
builder->updateStyle(state);
} else {
@@ -1089,14 +1087,14 @@ void PdfParser::opSetStrokeColorSpace(Object args[], int numArgs)
assert(numArgs >= 1);
builder->beforeStateChange(state);
- GfxColorSpace *colorSpace = lookupColorSpaceCopy(args[0]);
+ auto colorSpace = lookupColorSpaceCopy(args[0]);
state->setStrokePattern(nullptr);
if (colorSpace) {
GfxColor color;
- state->setStrokeColorSpace(colorSpace);
colorSpace->getDefaultColor(&color);
+ state->setStrokeColorSpace(_POPPLER_CONSUME_UNIQPTR_ARG(colorSpace));
state->setStrokeColor(&color);
builder->updateStyle(state);
} else {
@@ -1159,7 +1157,7 @@ void PdfParser::opSetFillColorN(Object args[], int numArgs) {
builder->updateStyle(state);
}
if (auto pattern = lookupPattern(&(args[numArgs - 1]), state)) {
- state->setFillPattern(pattern);
+ state->setFillPattern(_POPPLER_CONSUME_UNIQPTR_ARG(pattern));
builder->updateStyle(state);
}
@@ -1202,7 +1200,7 @@ void PdfParser::opSetStrokeColorN(Object args[], int numArgs) {
builder->updateStyle(state);
}
if (auto pattern = lookupPattern(&(args[numArgs - 1]), state)) {
- state->setStrokePattern(pattern);
+ state->setStrokePattern(_POPPLER_CONSUME_UNIQPTR_ARG(pattern));
builder->updateStyle(state);
}
@@ -1579,11 +1577,11 @@ void PdfParser::doShadingPatternFillFallback(GfxShadingPattern *sPat,
// TODO not good that numArgs is ignored but args[] is used:
void PdfParser::opShFill(Object args[], int /*numArgs*/)
{
- GfxShading *shading = nullptr;
GfxPath *savedPath = nullptr;
bool savedState = false;
- if (!(shading = res->lookupShading(args[0].getName(), nullptr, state))) {
+ auto shading = std::unique_ptr<GfxShading>(res->lookupShading(args[0].getName(), nullptr, state));
+ if (!shading) {
return;
}
@@ -1615,19 +1613,19 @@ void PdfParser::opShFill(Object args[], int /*numArgs*/)
// do shading type-specific operations
switch (shading->getType()) {
case 1: // Function-based shading
- doFunctionShFill(static_cast<GfxFunctionShading *>(shading));
+ doFunctionShFill(static_cast<GfxFunctionShading *>(shading.get()));
break;
case 2: // Axial shading
case 3: // Radial shading
- builder->addClippedFill(shading, stateToAffine(state));
+ builder->addClippedFill(shading.get(), stateToAffine(state));
break;
case 4: // Free-form Gouraud-shaded triangle mesh
case 5: // Lattice-form Gouraud-shaded triangle mesh
- doGouraudTriangleShFill(static_cast<GfxGouraudTriangleShading *>(shading));
+ doGouraudTriangleShFill(static_cast<GfxGouraudTriangleShading *>(shading.get()));
break;
case 6: // Coons patch mesh
case 7: // Tensor-product patch mesh
- doPatchMeshShFill(static_cast<GfxPatchMeshShading *>(shading));
+ doPatchMeshShFill(static_cast<GfxPatchMeshShading *>(shading.get()));
break;
}
@@ -1636,8 +1634,6 @@ void PdfParser::opShFill(Object args[], int /*numArgs*/)
restoreState();
state->setPath(savedPath);
}
-
- delete shading;
}
void PdfParser::doFunctionShFill(GfxFunctionShading *shading) {
@@ -2528,7 +2524,7 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg)
} else {
// get color space and color map
- GfxColorSpace *colorSpace;
+ std::unique_ptr<GfxColorSpace> colorSpace;
_POPPLER_CALL_ARGS(obj1, dict->lookup, "ColorSpace");
if (obj1.isNull()) {
_POPPLER_FREE(obj1);
@@ -2537,13 +2533,11 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg)
if (!obj1.isNull()) {
colorSpace = lookupColorSpaceCopy(obj1);
} else if (csMode == streamCSDeviceGray) {
- colorSpace = new GfxDeviceGrayColorSpace();
+ colorSpace = std::make_unique<GfxDeviceGrayColorSpace>();
} else if (csMode == streamCSDeviceRGB) {
- colorSpace = new GfxDeviceRGBColorSpace();
+ colorSpace = std::make_unique<GfxDeviceRGBColorSpace>();
} else if (csMode == streamCSDeviceCMYK) {
- colorSpace = new GfxDeviceCMYKColorSpace();
- } else {
- colorSpace = nullptr;
+ colorSpace = std::make_unique<GfxDeviceCMYKColorSpace>();
}
_POPPLER_FREE(obj1);
if (!colorSpace) {
@@ -2554,10 +2548,9 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg)
_POPPLER_FREE(obj1);
_POPPLER_CALL_ARGS(obj1, dict->lookup, "D");
}
- GfxImageColorMap *colorMap = new GfxImageColorMap(bits, &obj1, colorSpace);
+ auto colorMap = std::make_unique<GfxImageColorMap>(bits, &obj1, _POPPLER_CONSUME_UNIQPTR_ARG(colorSpace));
_POPPLER_FREE(obj1);
if (!colorMap->isOk()) {
- delete colorMap;
goto err1;
}
@@ -2568,7 +2561,7 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg)
int maskWidth = 0;
int maskHeight = 0;
maskInvert = gFalse;
- GfxImageColorMap *maskColorMap = nullptr;
+ std::unique_ptr<GfxImageColorMap> maskColorMap;
_POPPLER_CALL_ARGS(maskObj, dict->lookup, "Mask");
_POPPLER_CALL_ARGS(smaskObj, dict->lookup, "SMask");
Dict* maskDict;
@@ -2624,7 +2617,7 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg)
_POPPLER_FREE(obj1);
_POPPLER_CALL_ARGS(obj1, maskDict->lookup, "CS");
}
- GfxColorSpace *maskColorSpace = lookupColorSpaceCopy(obj1);
+ auto maskColorSpace = lookupColorSpaceCopy(obj1);
_POPPLER_FREE(obj1);
if (!maskColorSpace || maskColorSpace->getMode() != csDeviceGray) {
goto err1;
@@ -2634,10 +2627,9 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg)
_POPPLER_FREE(obj1);
_POPPLER_CALL_ARGS(obj1, maskDict->lookup, "D");
}
- maskColorMap = new GfxImageColorMap(maskBits, &obj1, maskColorSpace);
+ maskColorMap = std::make_unique<GfxImageColorMap>(maskBits, &obj1, _POPPLER_CONSUME_UNIQPTR_ARG(maskColorSpace));
_POPPLER_FREE(obj1);
if (!maskColorMap->isOk()) {
- delete maskColorMap;
goto err1;
}
//~ handle the Matte entry
@@ -2718,17 +2710,15 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg)
// draw it
if (haveSoftMask) {
- builder->addSoftMaskedImage(state, str, width, height, colorMap, interpolate,
- maskStr, maskWidth, maskHeight, maskColorMap, maskInterpolate);
- delete maskColorMap;
+ builder->addSoftMaskedImage(state, str, width, height, colorMap.get(), interpolate,
+ maskStr, maskWidth, maskHeight, maskColorMap.get(), maskInterpolate);
} else if (haveExplicitMask) {
- builder->addMaskedImage(state, str, width, height, colorMap, interpolate,
+ builder->addMaskedImage(state, str, width, height, colorMap.get(), interpolate,
maskStr, maskWidth, maskHeight, maskInvert, maskInterpolate);
} else {
- builder->addImage(state, str, width, height, colorMap, interpolate,
- haveColorKeyMask ? maskColors : static_cast<int *>(nullptr));
+ builder->addImage(state, str, width, height, colorMap.get(), interpolate,
+ haveColorKeyMask ? maskColors : nullptr);
}
- delete colorMap;
_POPPLER_FREE(maskObj);
_POPPLER_FREE(smaskObj);
@@ -2746,7 +2736,6 @@ void PdfParser::doForm(Object *str, double *offset)
{
Dict *dict;
GBool transpGroup, isolated, knockout;
- GfxColorSpace *blendingColorSpace;
Object matrixObj, bboxObj;
double m[6], bbox[4];
Object resObj;
@@ -2812,12 +2801,12 @@ void PdfParser::doForm(Object *str, double *offset)
// check for a transparency group
transpGroup = isolated = knockout = gFalse;
- blendingColorSpace = nullptr;
+ std::unique_ptr<GfxColorSpace> blendingColorSpace;
if (_POPPLER_CALL_ARGS_DEREF(obj1, dict->lookup, "Group").isDict()) {
if (_POPPLER_CALL_ARGS_DEREF(obj2, obj1.dictLookup, "S").isName("Transparency")) {
transpGroup = gTrue;
if (!_POPPLER_CALL_ARGS_DEREF(obj3, obj1.dictLookup, "CS").isNull()) {
- blendingColorSpace = GfxColorSpace::parse(nullptr, &obj3, nullptr, state);
+ blendingColorSpace = std::unique_ptr<GfxColorSpace>(GfxColorSpace::parse(nullptr, &obj3, nullptr, state));
}
_POPPLER_FREE(obj3);
if (_POPPLER_CALL_ARGS_DEREF(obj3, obj1.dictLookup, "I").isBool()) {
@@ -2835,12 +2824,9 @@ void PdfParser::doForm(Object *str, double *offset)
// draw it
++formDepth;
- doForm1(str, resDict, m, bbox, transpGroup, gFalse, blendingColorSpace, isolated, knockout);
+ doForm1(str, resDict, m, bbox, transpGroup, gFalse, blendingColorSpace.get(), isolated, knockout);
--formDepth;
- if (blendingColorSpace) {
- delete blendingColorSpace;
- }
_POPPLER_FREE(resObj);
}
diff --git a/src/extension/internal/pdfinput/pdf-parser.h b/src/extension/internal/pdfinput/pdf-parser.h
index c7c10caefed..8325ea24364 100644
--- a/src/extension/internal/pdfinput/pdf-parser.h
+++ b/src/extension/internal/pdfinput/pdf-parser.h
@@ -137,7 +137,7 @@ public:
void loadPatternColorProfiles(Dict *resources);
void loadColorProfile();
void loadColorSpaceProfile(GfxColorSpace *space, Object *obj);
- GfxPattern *lookupPattern(Object *obj, GfxState *state);
+ std::unique_ptr<GfxPattern> lookupPattern(Object *obj, GfxState *state);
std::shared_ptr<CairoFontEngine> getFontEngine();
@@ -176,7 +176,7 @@ private:
//! Caches color spaces by name
std::map<std::string, std::unique_ptr<GfxColorSpace>> colorSpacesCache;
- GfxColorSpace *lookupColorSpaceCopy(Object &);
+ std::unique_ptr<GfxColorSpace> lookupColorSpaceCopy(Object &);
void setDefaultApproximationPrecision(); // init color deltas
void pushOperator(const char *name);
diff --git a/src/extension/internal/pdfinput/poppler-transition-api.h b/src/extension/internal/pdfinput/poppler-transition-api.h
index 481aefadf46..8f03aa17779 100644
--- a/src/extension/internal/pdfinput/poppler-transition-api.h
+++ b/src/extension/internal/pdfinput/poppler-transition-api.h
@@ -15,6 +15,12 @@
#include <glib/poppler-features.h>
#include <poppler/UTF.h>
+#if POPPLER_CHECK_VERSION(24, 10, 0)
+#define _POPPLER_CONSUME_UNIQPTR_ARG(value) std::move(value)
+#else
+#define _POPPLER_CONSUME_UNIQPTR_ARG(value) value.release()
+#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()))
--
GitLab

View File

@ -0,0 +1,39 @@
From 874dcfbd303bc7a1bddb6f34aebbb4dba8eda771 Mon Sep 17 00:00:00 2001
From: Rafael Siejakowski <rs@rs-math.net>
Date: Sun, 10 Nov 2024 13:20:48 +0100
Subject: [PATCH] Fix Poppler private includes
In the PDF parser, include the Poppler private headers using
the angular brackets and the poppler/ directory prefix, as is
done in other places in the code which need Poppler's private
headers.
This fixes build against Poppler installed at a custom path.
---
src/extension/internal/pdfinput/pdf-parser.h | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/extension/internal/pdfinput/pdf-parser.h b/src/extension/internal/pdfinput/pdf-parser.h
index 8325ea24364..7d9189dfc0a 100644
--- a/src/extension/internal/pdfinput/pdf-parser.h
+++ b/src/extension/internal/pdfinput/pdf-parser.h
@@ -24,13 +24,12 @@
#pragma interface
#endif
-#include "glib/poppler-features.h"
-#include "Object.h"
-
+#include <2geom/affine.h>
+#include <glib/poppler-features.h>
#include <map>
#include <memory>
+#include <poppler/Object.h>
#include <string>
-#include <2geom/affine.h>
#define Operator Operator_Gfx
#include <poppler/Gfx.h>
--
GitLab

View File

@ -0,0 +1,53 @@
From c9046810d899a408bfbd489aad91872b1203ee6d Mon Sep 17 00:00:00 2001
From: KrIr17 <elendil.krir17@gmail.com>
Date: Thu, 5 Dec 2024 15:03:47 +0100
Subject: [PATCH] Fix building with poppler 24.12.0
Fixes https://gitlab.com/inkscape/inkscape/-/issues/5415
---
src/extension/internal/pdfinput/pdf-parser.cpp | 4 +++-
src/extension/internal/pdfinput/poppler-transition-api.h | 6 ++++++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp
index 28000a87b0c..9ea30b90a48 100644
--- a/src/extension/internal/pdfinput/pdf-parser.cpp
+++ b/src/extension/internal/pdfinput/pdf-parser.cpp
@@ -2403,6 +2403,7 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg)
int bits;
GBool interpolate;
StreamColorSpaceMode csMode;
+ GBool hasAlpha;
GBool mask;
GBool invert;
Object maskObj, smaskObj;
@@ -2414,7 +2415,8 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg)
// get info from the stream
bits = 0;
csMode = streamCSNone;
- str->getImageParams(&bits, &csMode);
+ hasAlpha = false;
+ str->_POPPLER_GET_IMAGE_PARAMS(&bits, &csMode, &hasAlpha);
// get stream dict
dict = str->getDict();
diff --git a/src/extension/internal/pdfinput/poppler-transition-api.h b/src/extension/internal/pdfinput/poppler-transition-api.h
index 8f03aa17779..b7a54828e74 100644
--- a/src/extension/internal/pdfinput/poppler-transition-api.h
+++ b/src/extension/internal/pdfinput/poppler-transition-api.h
@@ -39,6 +39,12 @@
#define _POPPLER_FUNCTION_TYPE_STITCHING 3
#endif
+#if POPPLER_CHECK_VERSION(24,12,0)
+#define _POPPLER_GET_IMAGE_PARAMS(bits, csMode, hasAlpha) getImageParams(bits, csMode, hasAlpha)
+#else
+#define _POPPLER_GET_IMAGE_PARAMS(bits, csMode, hasAlpha) getImageParams(bits, csMode)
+#endif
+
#if POPPLER_CHECK_VERSION(22, 4, 0)
#define _POPPLER_FONTPTR_TO_GFX8(font_ptr) ((Gfx8BitFont *)font_ptr.get())
#else
--
GitLab

View File

@ -0,0 +1,195 @@
From 6c330d56fdf54cb002b8a84b33f73d2a8dd40879 Mon Sep 17 00:00:00 2001
From: Tavmjong Bah <tavmjong@free.fr>
Date: Fri, 8 Nov 2024 15:03:12 +0100
Subject: [PATCH] Fixes two problems related to emojis in PDF import.
1. UTF-8 conversion.
If a "ToUnicode" table is included in an OpenType font in a PDF
file, one can find the Unicode code point that corresponds to a
given glyph (or group of glyphs). This is often the only way one
can reconstruct text from a PDF (which might contain only glyphs
and glyph positions). For Emoji, the code points are outside the
"Basic Plane" (code points that can be encode by four or fewer
hexadecimal digits) and in are located the "Supplementary
Multilingual Plane", a.k.a. "Plane 1". Code points in "Plane 1" are
represented by a hexadecimal number of the form "1xxxx", where 'x'
is any hex digit.
Inkscape's PDF import code takes a Unicode code point and converts
it to its UTF-8 representation. This code assumes that the code
point can be represented by a gunichar2 which is typedef'ed from a
guint16. The glib function g_utf16_to_utf8 is then used for the
conversion. This in incorrect: a single guint16 can only represent
a 4 hex-digit code point and then not all possible values (some
values are used to indicate that a second 16-bit value is being used
to to enable encoding a code point outside the basic plane).
We already use std::wstring_convert<> and std::codecvt<> earlier in
the same function to build up a string to store the original text
in the 'aria-label' attribute. I changed the code to reuse that
result. Note that these are deprecated and will be removed in C++26
so we'll eventually need to find a different solution.
2. Empty paths.
Emoji fonts usually have color. There are four competing methods of
embedding color font data in an OpenType font. Two of these use
bitmaps. If a font has only bitmap glyph data then there is no
vector data to build a path. If there is no path, Inkscape's
current code returns 'nullptr' instead of a pointer to a Path
node. This triggers an assert. Simply removing the assert leads to
other problems down the line. The simplest solution is to return a
Path node with an empty "d" attribute. This also allows one to
store the original text in the "aria-label" attribute of the Path
node.
In the future, we should be able to render bitmaps from fonts in
the same way the same way that we render SVG OpenType fonts (which
caches the glyphs as bitmaps).
Unfixed problems:
If the "Noto-Color-Emoji" font is present, it will be used for
rendering emoji even if "Noto-Emoji" or "Symbola" is specified. It
will also be used as a fallback font for rendering emoji.
"Noto-Color-Emoji" has to "glyf" table and thus lacks vectorized
paths. This leads to empty paths. It would be good to block the use
of "Noto-Color-Emoji" in this case. It's not clear how easy it
would be to do this.
What is even stranger is that the terminal will not show an Emoji
if "Noto-Color-Emoji" is not installed even though the glyph that
is shown is not from "Noto-Color-Emoji"! (It's from "Symbola".)
There appears to be incorrect logic in SvgBuider::_flushTextPath().
If the style changes inside the function, the node existing node is
replaced, effectively orphaning the previous node. Whether this
actually happens in PDF input is unknown.
---
.../internal/pdfinput/svg-builder.cpp | 54 +++++++++----------
1 file changed, 26 insertions(+), 28 deletions(-)
diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp
index 73f57f04952..bb2ce5145e8 100644
--- a/src/extension/internal/pdfinput/svg-builder.cpp
+++ b/src/extension/internal/pdfinput/svg-builder.cpp
@@ -1250,7 +1250,7 @@ void SvgBuilder::updateFont(GfxState *state, std::shared_ptr<CairoFont> cairo_fo
TRACE(("updateFont()\n"));
updateTextMatrix(state, flip); // Ensure that we have a text matrix built
- auto font = state->getFont();
+ auto font = state->getFont(); // GfxFont
auto font_id = font->getID()->num;
auto new_font_size = state->getFontSize();
@@ -1711,6 +1711,10 @@ void SvgBuilder::_setTextStyle(Inkscape::XML::Node *node, GfxState *state, SPCSS
/**
* Renders the text as a path object using cairo and returns the node object.
*
+ * If the path is empty (e.g. due to trying to render a color bitmap font),
+ * return path node with empty "d" attribute. The aria attribute will still
+ * contain the original text.
+ *
* cairo_font - The font that cairo can use to convert text to path.
* font_size - The size of the text when drawing the path.
* transform - The matrix which will place the text on the page, this is critical
@@ -1722,8 +1726,13 @@ Inkscape::XML::Node *SvgBuilder::_renderText(std::shared_ptr<CairoFont> cairo_fo
const Geom::Affine &transform,
cairo_glyph_t *cairo_glyphs, unsigned int count)
{
- if (!cairo_glyphs || !cairo_font || _aria_label.empty())
- return nullptr;
+ Inkscape::XML::Node *path = _addToContainer("svg:path");
+ path->setAttribute("d", "");
+
+ if (!cairo_glyphs || !cairo_font || _aria_label.empty()) {
+ std::cerr << "SvgBuilder::_renderText: Invalid argument!" << std::endl;
+ return path;
+ }
// The surface isn't actually used, no rendering in cairo takes place.
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, _width, _height);
@@ -1738,16 +1747,17 @@ Inkscape::XML::Node *SvgBuilder::_renderText(std::shared_ptr<CairoFont> cairo_fo
// Failing to render text.
if (!pathv) {
- g_warning("Failed to render PDF text!");
- return nullptr;
+ std::cerr << "SvgBuilder::_renderText: Failed to render PDF text! " << _aria_label << std::endl;
+ return path;
}
auto textpath = sp_svg_write_path(*pathv);
- if (textpath.empty())
- return nullptr;
-
- Inkscape::XML::Node *path = _addToContainer("svg:path");
path->setAttribute("d", textpath);
+
+ if (textpath.empty()) {
+ std::cerr << "SvgBuilder::_renderText: Empty path! " << _aria_label << std::endl;
+ }
+
return path;
}
@@ -1785,7 +1795,7 @@ void SvgBuilder::endString(GfxState *state)
* dx, dy: Advance of glyph.
* originX, originY
* code: 8-bit char code, 16 bit CID, or Unicode of glyph.
- * u: Unicode mapping of character.
+ * u: Unicode mapping of character. "Unicode" is an unsigned int.
*/
void SvgBuilder::addChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY,
CharCode code, int /*nBytes*/, Unicode const *u, int uLen)
@@ -1801,9 +1811,13 @@ void SvgBuilder::addChar(GfxState *state, double x, double y, double dx, double
}
_aria_space = false;
+ std::string utf8_code;
static std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv1;
+ // Note std::wstring_convert and std::codecvt_utf are deprecated and will be removed in C++26.
if (u) {
- _aria_label += conv1.to_bytes(*u);
+ // 'u' maybe null if there is not a "ToUnicode" table in the PDF!
+ utf8_code = conv1.to_bytes(*u);
+ _aria_label += utf8_code;
}
// Skip control characters, found in LaTeX generated PDFs
@@ -1835,6 +1849,7 @@ void SvgBuilder::addChar(GfxState *state, double x, double y, double dx, double
}
SvgGlyph new_glyph;
+ new_glyph.code = utf8_code;
new_glyph.is_space = is_space;
new_glyph.delta = delta;
new_glyph.position = Geom::Point( x - originX, y - originY );
@@ -1849,23 +1864,6 @@ void SvgBuilder::addChar(GfxState *state, double x, double y, double dx, double
}
_text_position += delta;
- // Convert the character to UTF-8 since that's our SVG document's encoding
- {
- gunichar2 uu[8] = {0};
-
- for (int i = 0; i < uLen; i++) {
- uu[i] = u[i];
- }
-
- gchar *tmp = g_utf16_to_utf8(uu, uLen, nullptr, nullptr, nullptr);
- if ( tmp && *tmp ) {
- new_glyph.code = tmp;
- } else {
- new_glyph.code.clear();
- }
- g_free(tmp);
- }
-
// Copy current style if it has changed since the previous glyph
if (_invalidated_style || _glyphs.empty()) {
_invalidated_style = false;
--
GitLab

View File

@ -0,0 +1,179 @@
From 5c4c6d116dae5250d75d34a45f0d9220824d2e20 Mon Sep 17 00:00:00 2001
From: KrIr17 <elendil.krir17@gmail.com>
Date: Sun, 9 Feb 2025 22:52:53 +0530
Subject: [PATCH] Fix building with poppler 25.02.0
1. `getCodeToGIDMap`, `getCIDToGID`, `getCIDToGIDMap` are now `std::vector`
2. `pdfDocEncodingToUTF16` returns an `std::string`
---
.../pdfinput/poppler-cairo-font-engine.cpp | 50 +++++++++++++++----
.../pdfinput/poppler-transition-api.h | 20 +++++---
3 files changed, 63 insertions(+), 16 deletions(-)
diff --git a/src/extension/internal/pdfinput/poppler-cairo-font-engine.cpp b/src/extension/internal/pdfinput/poppler-cairo-font-engine.cpp
index 728b1d1aac4..bd1d4e49367 100644
--- a/src/extension/internal/pdfinput/poppler-cairo-font-engine.cpp
+++ b/src/extension/internal/pdfinput/poppler-cairo-font-engine.cpp
@@ -405,14 +405,22 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, FT_Li
break;
case fontCIDType2:
case fontCIDType2OT:
+#if POPPLER_CHECK_VERSION(25,2,0)
+ if (!gfxcid->getCIDToGID().empty()) {
+ const auto src = gfxcid->getCIDToGID();
+ codeToGID = std::move(src);
+ }
+#else
if (gfxcid->getCIDToGID()) {
n = gfxcid->getCIDToGIDLen();
if (n) {
- const int *src = gfxcid->getCIDToGID();
+ const auto src = gfxcid->getCIDToGID();
codeToGID.reserve(n);
codeToGID.insert(codeToGID.begin(), src, src + n);
}
- } else {
+ }
+#endif
+ else {
#if POPPLER_CHECK_VERSION(22, 1, 0)
std::unique_ptr<FoFiTrueType> ff;
#else
@@ -427,13 +435,18 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, FT_Li
goto err2;
}
#if POPPLER_CHECK_VERSION(22, 1, 0)
- int *src = gfxcid->getCodeToGIDMap(ff.get(), &n);
+ auto src = gfxcid->_POPPLER_GET_CODE_TO_GID_MAP(ff.get(), &n);
#else
- int *src = gfxcid->getCodeToGIDMap(ff, &n);
+ auto src = gfxcid->_POPPLER_GET_CODE_TO_GID_MAP(ff, &n);
#endif
+
+#if POPPLER_CHECK_VERSION(25,2,0)
+ codeToGID = std::move(src);
+#else
codeToGID.reserve(n);
codeToGID.insert(codeToGID.begin(), src, src + n);
gfree(src);
+#endif
}
/* Fall through */
case fontTrueType:
@@ -455,13 +468,17 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, FT_Li
/* This might be set already for the CIDType2 case */
if (fontType == fontTrueType || fontType == fontTrueTypeOT) {
#if POPPLER_CHECK_VERSION(22, 1, 0)
- int *src = gfx8bit->getCodeToGIDMap(ff.get());
+ auto src = gfx8bit->getCodeToGIDMap(ff.get());
#else
- int *src = gfx8bit->getCodeToGIDMap(ff);
+ auto src = gfx8bit->getCodeToGIDMap(ff);
#endif
+#if POPPLER_CHECK_VERSION(25,2,0)
+ codeToGID = std::move(src);
+#else
codeToGID.reserve(256);
codeToGID.insert(codeToGID.begin(), src, src + 256);
gfree(src);
+#endif
}
font_face = getFreeTypeFontFace(fontEngine, lib, fileName, std::move(font_data));
if (!font_face) {
@@ -479,10 +496,14 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, FT_Li
ff1c = FoFiType1C::load(fileName.c_str());
}
if (ff1c) {
- int *src = ff1c->getCIDToGIDMap(&n);
+ auto src = ff1c->_POPPLER_GET_CID_TO_GID_MAP(&n);
+#if POPPLER_CHECK_VERSION(25,2,0)
+ codeToGID = std::move(src);
+#else
codeToGID.reserve(n);
codeToGID.insert(codeToGID.begin(), src, src + n);
gfree(src);
+#endif
delete ff1c;
}
}
@@ -495,14 +516,21 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, FT_Li
break;
case fontCIDType0COT:
+#if POPPLER_CHECK_VERSION(25,2,0)
+ if (!gfxcid->getCIDToGID().empty()) {
+ const auto src = gfxcid->getCIDToGID();
+ codeToGID = std::move(src);
+ }
+#else
if (gfxcid->getCIDToGID()) {
n = gfxcid->getCIDToGIDLen();
if (n) {
- const int *src = gfxcid->getCIDToGID();
+ const auto src = gfxcid->getCIDToGID();
codeToGID.reserve(n);
codeToGID.insert(codeToGID.begin(), src, src + n);
}
}
+#endif
if (codeToGID.empty()) {
if (!useCIDs) {
@@ -518,10 +546,14 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, FT_Li
}
if (ff) {
if (ff->isOpenTypeCFF()) {
- int *src = ff->getCIDToGIDMap(&n);
+ auto src = ff1c->_POPPLER_GET_CID_TO_GID_MAP(&n);
+#if POPPLER_CHECK_VERSION(25,2,0)
+ codeToGID = std::move(src);
+#else
codeToGID.reserve(n);
codeToGID.insert(codeToGID.begin(), src, src + n);
gfree(src);
+#endif
}
}
}
diff --git a/src/extension/internal/pdfinput/poppler-transition-api.h b/src/extension/internal/pdfinput/poppler-transition-api.h
index b7a54828e74..a67132ba6bd 100644
--- a/src/extension/internal/pdfinput/poppler-transition-api.h
+++ b/src/extension/internal/pdfinput/poppler-transition-api.h
@@ -15,6 +15,20 @@
#include <glib/poppler-features.h>
#include <poppler/UTF.h>
+#if POPPLER_CHECK_VERSION(25,2,0)
+#define _POPPLER_GET_CODE_TO_GID_MAP(ff, len) getCodeToGIDMap(ff)
+#define _POPPLER_GET_CID_TO_GID_MAP(len) getCIDToGIDMap()
+#else
+#define _POPPLER_GET_CODE_TO_GID_MAP(ff, len) getCodeToGIDMap(ff, len)
+#define _POPPLER_GET_CID_TO_GID_MAP(len) getCIDToGIDMap(len)
+#endif
+
+#if POPPLER_CHECK_VERSION(24,12,0)
+#define _POPPLER_GET_IMAGE_PARAMS(bits, csMode, hasAlpha) getImageParams(bits, csMode, hasAlpha)
+#else
+#define _POPPLER_GET_IMAGE_PARAMS(bits, csMode, hasAlpha) getImageParams(bits, csMode)
+#endif
+
#if POPPLER_CHECK_VERSION(24, 10, 0)
#define _POPPLER_CONSUME_UNIQPTR_ARG(value) std::move(value)
#else
@@ -39,12 +53,6 @@
#define _POPPLER_FUNCTION_TYPE_STITCHING 3
#endif
-#if POPPLER_CHECK_VERSION(24,12,0)
-#define _POPPLER_GET_IMAGE_PARAMS(bits, csMode, hasAlpha) getImageParams(bits, csMode, hasAlpha)
-#else
-#define _POPPLER_GET_IMAGE_PARAMS(bits, csMode, hasAlpha) getImageParams(bits, csMode)
-#endif
-
#if POPPLER_CHECK_VERSION(22, 4, 0)
#define _POPPLER_FONTPTR_TO_GFX8(font_ptr) ((Gfx8BitFont *)font_ptr.get())
#else
--
GitLab

View File

@ -1,7 +1,7 @@
# Template file for 'inkscape'
pkgname=inkscape
version=1.4
revision=2
revision=3
build_style=cmake
make_check_target="check"
hostmakedepends="automake gettext glib-devel intltool libgraphicsmagick-devel