Commit 84657591 authored by Oliver Sander's avatar Oliver Sander

[splash, arthur] Use stroking opacity when clipping to a stroke path

When filling a region that is clipped to a stroke path, then the
stroking opacity shall be used rather than the fill opacity.
I couldn't find this in the spec, but it seems to be what
Acrobat does.

BUG: poppler/poppler#178
parent 9e302b6b
Pipeline #135618 passed with stage
in 4 minutes and 28 seconds
......@@ -42,6 +42,7 @@
// Copyright (C) 2018, 2019 Stefan Brüns <stefan.bruens@rwth-aachen.de>
// Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
// Copyright (C) 2019 Christian Persch <chpe@src.gnome.org>
// Copyright (C) 2020 Oliver Sander <oliver.sander@tu-dresden.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
......@@ -4609,7 +4610,9 @@ bool SplashOutputDev::univariateShadedFill(GfxState *state, SplashUnivariatePatt
pattern->getShading()->getColorSpace()->createMapping(bitmap->getSeparationList(), SPOT_NCOMPS);
setOverprintMask(pattern->getShading()->getColorSpace(), state->getFillOverprint(),
state->getOverprintMode(), nullptr);
retVal = (splash->shadedFill(&path, pattern->getShading()->getHasBBox(), pattern) == splashOk);
// If state->getStrokePattern() is set, then the current clipping region
// is a stroke path.
retVal = (splash->shadedFill(&path, pattern->getShading()->getHasBBox(), pattern, (state->getStrokePattern()!=nullptr)) == splashOk);
state->clearPath();
setVectorAntialias(vaa);
......@@ -4670,7 +4673,9 @@ bool SplashOutputDev::functionShadedFill(GfxState *state, GfxFunctionShading *sh
pattern->getShading()->getColorSpace()->createMapping(bitmap->getSeparationList(), SPOT_NCOMPS);
setOverprintMask(pattern->getShading()->getColorSpace(), state->getFillOverprint(),
state->getOverprintMode(), nullptr);
retVal = (splash->shadedFill(&path, pattern->getShading()->getHasBBox(), pattern) == splashOk);
// If state->getStrokePattern() is set, then the current clipping region
// is a stroke path.
retVal = (splash->shadedFill(&path, pattern->getShading()->getHasBBox(), pattern, (state->getStrokePattern()!=nullptr)) == splashOk);
state->clearPath();
setVectorAntialias(vaa);
......
......@@ -767,7 +767,10 @@ bool ArthurOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading,
// Number of color space components
auto nComps = shading->getColorSpace()->getNComps();
auto opacity = state->getFillOpacity();
// If the clipping region is a stroke, then the current operation counts as a stroke
// rather than as a fill, and the opacity has to be set accordingly.
// See https://gitlab.freedesktop.org/poppler/poppler/-/issues/178
auto opacity = (state->getStrokePattern()) ? state->getStrokeOpacity() : state->getFillOpacity();
// Helper function to test two color objects for 'almost-equality'
auto isSameGfxColor = [&nComps,&colorDelta](const GfxColor &colorA, const GfxColor &colorB)
......
......@@ -75,6 +75,13 @@ void TestStrokeOpacity::checkStrokeOpacity()
tolerance = 0;
QVERIFY(approximatelyEqual(pixelUpperLeftInterior, Qt::white));
// Now check whether that stroke is semi-transparent.
// Bug https://gitlab.freedesktop.org/poppler/poppler/-/issues/178
auto pixelUpperLeftOnStroke = image.pixel(70,20);
tolerance = 2;
QVERIFY(approximatelyEqual(pixelUpperLeftOnStroke, QColor(253,233,196,255)));
}
QTEST_GUILESS_MAIN(TestStrokeOpacity)
......
......@@ -21,7 +21,7 @@
// Copyright (C) 2012 Matthias Kramm <kramm@quiss.org>
// Copyright (C) 2018, 2019 Stefan Brüns <stefan.bruens@rwth-aachen.de>
// Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
// Copyright (C) 2019 Oliver Sander <oliver.sander@tu-dresden.de>
// Copyright (C) 2019, 2020 Oliver Sander <oliver.sander@tu-dresden.de>
// Copyright (C) 2019 Marek Kasik <mkasik@redhat.com>
//
// To see a description of the changes please see the Changelog file that
......@@ -6356,7 +6356,8 @@ void Splash::dumpXPath(SplashXPath *path) {
}
SplashError Splash::shadedFill(SplashPath *path, bool hasBBox,
SplashPattern *pattern) {
SplashPattern *pattern,
bool clipToStrokePath) {
SplashPipe pipe;
int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y;
SplashClipResult clipRes;
......@@ -6397,7 +6398,8 @@ SplashError Splash::shadedFill(SplashPath *path, bool hasBBox,
yMaxI = state->clip->getYMaxI();
}
pipeInit(&pipe, 0, yMinI, pattern, nullptr, (unsigned char)splashRound(state->fillAlpha * 255), vectorAntialias && !hasBBox, false);
unsigned char alpha = splashRound((clipToStrokePath) ? state->strokeAlpha * 255 : state->fillAlpha * 255);
pipeInit(&pipe, 0, yMinI, pattern, nullptr, alpha, vectorAntialias && !hasBBox, false);
// draw the spans
if (vectorAntialias) {
......
......@@ -16,6 +16,7 @@
// Copyright (C) 2010-2013, 2015 Thomas Freitag <Thomas.Freitag@alfa.de>
// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com>
// Copyright (C) 2012, 2017 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2020 Oliver Sander <oliver.sander@tu-dresden.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
......@@ -264,8 +265,11 @@ public:
#endif
// Do shaded fills with dynamic patterns
//
// clipToStrokePath: Whether the current clip region is a stroke path.
// In that case, strokeAlpha is used rather than fillAlpha.
SplashError shadedFill(SplashPath *path, bool hasBBox,
SplashPattern *pattern);
SplashPattern *pattern, bool clipToStrokePath);
// Draw a gouraud triangle shading.
bool gouraudTriangleShadedFill(SplashGouraudColor *shading);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment