poppler/SplashOutputDev.cc | 9 +++++++-- qt5/src/ArthurOutputDev.cc | 5 ++++- qt5/tests/check_stroke_opacity.cpp | 7 +++++++ splash/Splash.cc | 8 +++++--- splash/Splash.h | 6 +++++- 5 files changed, 28 insertions(+), 7 deletions(-)
New commits: commit 846575911483787a0fe28d76c4e9b51a644d7152 Author: Oliver Sander <[email protected]> Date: Tue Apr 21 16:03:37 2020 +0200 [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: https://gitlab.freedesktop.org/poppler/poppler/-/issues/178 diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc index 346e836d..2bcabc99 100644 --- a/poppler/SplashOutputDev.cc +++ b/poppler/SplashOutputDev.cc @@ -42,6 +42,7 @@ // Copyright (C) 2018, 2019 Stefan Brüns <[email protected]> // Copyright (C) 2018 Adam Reichold <[email protected]> // Copyright (C) 2019 Christian Persch <[email protected]> +// Copyright (C) 2020 Oliver Sander <[email protected]> // // 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); diff --git a/qt5/src/ArthurOutputDev.cc b/qt5/src/ArthurOutputDev.cc index e9ebcc92..3ec8cfab 100644 --- a/qt5/src/ArthurOutputDev.cc +++ b/qt5/src/ArthurOutputDev.cc @@ -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) diff --git a/qt5/tests/check_stroke_opacity.cpp b/qt5/tests/check_stroke_opacity.cpp index 32434adf..b4cff022 100644 --- a/qt5/tests/check_stroke_opacity.cpp +++ b/qt5/tests/check_stroke_opacity.cpp @@ -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) diff --git a/splash/Splash.cc b/splash/Splash.cc index 70584ec4..feb738bb 100644 --- a/splash/Splash.cc +++ b/splash/Splash.cc @@ -21,7 +21,7 @@ // Copyright (C) 2012 Matthias Kramm <[email protected]> // Copyright (C) 2018, 2019 Stefan Brüns <[email protected]> // Copyright (C) 2018 Adam Reichold <[email protected]> -// Copyright (C) 2019 Oliver Sander <[email protected]> +// Copyright (C) 2019, 2020 Oliver Sander <[email protected]> // Copyright (C) 2019 Marek Kasik <[email protected]> // // 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) { diff --git a/splash/Splash.h b/splash/Splash.h index 28ea4e5d..16b41c0a 100644 --- a/splash/Splash.h +++ b/splash/Splash.h @@ -16,6 +16,7 @@ // Copyright (C) 2010-2013, 2015 Thomas Freitag <[email protected]> // Copyright (C) 2010 Christian Feuersänger <[email protected]> // Copyright (C) 2012, 2017 Adrian Johnson <[email protected]> +// Copyright (C) 2020 Oliver Sander <[email protected]> // // 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); _______________________________________________ poppler mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/poppler
