diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2021-09-23 16:55:19 +0200 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2021-09-27 16:15:13 +0200 |
commit | 0f99f237be9ee4135a548e255c6c8dcceba8648d (patch) | |
tree | b2b584561195c9864b6fe7f0d1e73678fd34b0a9 | |
parent | 92adaab00003beb7314354018909e26272a245a9 (diff) |
Related: tdf#144091 svx: fix interaction of transp cell fill and transp shadow
This is a follow-up to commit 37a52d30bbfcf1d073779b50139c4dafa507be4b
(tdf#144091 svx: fix unwanted blur of shadow from table cell fill,
2021-09-20), where it turned out that the original bugdoc was just a
special case of almost full transparency (80%), that's why avoiding the
blur fixed the problem.
A more general approach instead is to multiply the alpha or the cell
fill of table shapes and the alpha of the shadow itself. The end result
is the same (80% transparency) for the first bugdoc, but this gives back
the blur on the second bugdoc.
(cherry picked from commit 00fa364a2403dc23a786d3f91fde06e10b3a4a9a)
Conflicts:
drawinglayer/source/primitive2d/shadowprimitive2d.cxx
drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
include/drawinglayer/primitive2d/BufferedDecompositionPrimitive2D.hxx
svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
svx/source/table/viewcontactoftableobj.cxx
Change-Id: I63560e3a73473c70157ecee8365ec7154217f269
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122680
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
-rw-r--r-- | drawinglayer/source/primitive2d/shadowprimitive2d.cxx | 71 | ||||
-rw-r--r-- | drawinglayer/source/processor2d/vclpixelprocessor2d.cxx | 12 | ||||
-rw-r--r-- | drawinglayer/source/tools/primitive2dxmldump.cxx | 4 | ||||
-rw-r--r-- | include/drawinglayer/primitive2d/baseprimitive2d.hxx | 12 | ||||
-rw-r--r-- | include/drawinglayer/primitive2d/shadowprimitive2d.hxx | 8 | ||||
-rw-r--r-- | svx/qa/unit/table.cxx | 12 | ||||
-rw-r--r-- | svx/source/sdr/primitive2d/sdrdecompositiontools.cxx | 72 | ||||
-rw-r--r-- | svx/source/table/viewcontactoftableobj.cxx | 15 | ||||
-rw-r--r-- | vcl/source/bitmap/bitmapfilter.cxx | 5 |
9 files changed, 106 insertions, 105 deletions
diff --git a/drawinglayer/source/primitive2d/shadowprimitive2d.cxx b/drawinglayer/source/primitive2d/shadowprimitive2d.cxx index 516cc0c0bd4a..f0efd64c7bdc 100644 --- a/drawinglayer/source/primitive2d/shadowprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/shadowprimitive2d.cxx @@ -30,27 +30,6 @@ using namespace com::sun::star; namespace drawinglayer::primitive2d { -namespace -{ -void get2DDecompositionOfChildren(const ShadowPrimitive2D& rPrimitive, - Primitive2DDecompositionVisitor& rVisitor, - const Primitive2DContainer& rChildren) -{ - if (rChildren.empty()) - return; - - // create a modifiedColorPrimitive containing the shadow color and the content - const basegfx::BColorModifierSharedPtr aBColorModifier - = std::make_shared<basegfx::BColorModifier_replace>(rPrimitive.getShadowColor()); - const Primitive2DReference xRefA(new ModifiedColorPrimitive2D(rChildren, aBColorModifier)); - Primitive2DContainer aSequenceB{ xRefA }; - - // build transformed primitiveVector with shadow offset and add to target - rVisitor.append( - new TransformPrimitive2D(rPrimitive.getShadowTransform(), std::move(aSequenceB))); -} -} - ShadowPrimitive2D::ShadowPrimitive2D( const basegfx::B2DHomMatrix& rShadowTransform, const basegfx::BColor& rShadowColor, @@ -87,41 +66,21 @@ void get2DDecompositionOfChildren(const ShadowPrimitive2D& rPrimitive, void ShadowPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& /*rViewInformation*/) const { - get2DDecompositionOfChildren(*this, rVisitor, getChildren()); - } - - void ShadowPrimitive2D::get2DDecompositionWithoutBlur( - Primitive2DDecompositionVisitor& rVisitor, - const geometry::ViewInformation2D& /*rViewInformation*/) const - { - Primitive2DContainer aChildren; - // Only decompose children which are not blurred (they opted in for this). - std::copy_if(getChildren().begin(), getChildren().end(), std::back_inserter(aChildren), - [](const Primitive2DReference& xChild) { - auto pChild - = dynamic_cast<primitive2d::BufferedDecompositionPrimitive2D*>( - xChild.get()); - return pChild && pChild->getExcludeFromBlur(); - }); - - get2DDecompositionOfChildren(*this, rVisitor, aChildren); - } - - void ShadowPrimitive2D::get2DDecompositionWithBlur( - Primitive2DDecompositionVisitor& rVisitor, - const geometry::ViewInformation2D& /*rViewInformation*/) const - { - // Only decompose children which are blurred (which is the default). - Primitive2DContainer aChildren; - std::copy_if(getChildren().begin(), getChildren().end(), std::back_inserter(aChildren), - [](const Primitive2DReference& xChild) { - auto pChild - = dynamic_cast<primitive2d::BufferedDecompositionPrimitive2D*>( - xChild.get()); - return !pChild || !pChild->getExcludeFromBlur(); - }); - - get2DDecompositionOfChildren(*this, rVisitor, aChildren); + if(getChildren().empty()) + return; + + // create a modifiedColorPrimitive containing the shadow color and the content + const basegfx::BColorModifierSharedPtr aBColorModifier = + std::make_shared<basegfx::BColorModifier_replace>( + getShadowColor()); + const Primitive2DReference xRefA( + new ModifiedColorPrimitive2D( + getChildren(), + aBColorModifier)); + const Primitive2DContainer aSequenceB { xRefA }; + + // build transformed primitiveVector with shadow offset and add to target + rVisitor.append(new TransformPrimitive2D(getShadowTransform(), aSequenceB)); } // provide unique ID diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index 393c40c90842..10845409b9ec 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -1037,7 +1037,7 @@ void VclPixelProcessor2D::processGlowPrimitive2D(const primitive2d::GlowPrimitiv const sal_uInt8 nTransparency = rCandidate.getGlowColor().GetTransparency(); impBufferDevice aBufferDevice(*mpOutputDevice, aRange); - if (aBufferDevice.isVisible()) + if (aBufferDevice.isVisible() && !aRange.isEmpty()) { // remember last OutDev and set to content OutputDevice* pLastOutputDevice = mpOutputDevice; @@ -1160,18 +1160,10 @@ void VclPixelProcessor2D::processShadowPrimitive2D(const primitive2d::ShadowPrim impBufferDevice aBufferDevice(*mpOutputDevice, aRange); if (aBufferDevice.isVisible()) { - // Process children which don't want blur. - primitive2d::Primitive2DContainer aContainer; - rCandidate.get2DDecompositionWithoutBlur(aContainer, getViewInformation2D()); - process(aContainer); - - // Process children which want blur. OutputDevice* pLastOutputDevice = mpOutputDevice; mpOutputDevice = &aBufferDevice.getContent(); - aContainer.clear(); - rCandidate.get2DDecompositionWithBlur(aContainer, getViewInformation2D()); - process(aContainer); + process(rCandidate); const tools::Rectangle aRect(static_cast<tools::Long>(std::floor(aRange.getMinX())), static_cast<tools::Long>(std::floor(aRange.getMinY())), diff --git a/drawinglayer/source/tools/primitive2dxmldump.cxx b/drawinglayer/source/tools/primitive2dxmldump.cxx index 1342fd39354f..5fe1eb41fead 100644 --- a/drawinglayer/source/tools/primitive2dxmldump.cxx +++ b/drawinglayer/source/tools/primitive2dxmldump.cxx @@ -549,8 +549,8 @@ void Primitive2dXmlDump::decomposeAndWrite( if (pBufferedDecomposition) { rWriter.attribute( - "excludeFromBlur", - OString::boolean(pBufferedDecomposition->getExcludeFromBlur())); + "transparenceForShadow", + OString::number(pBufferedDecomposition->getTransparenceForShadow())); } drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer; diff --git a/include/drawinglayer/primitive2d/baseprimitive2d.hxx b/include/drawinglayer/primitive2d/baseprimitive2d.hxx index b94218b07111..c5d947c8b1de 100644 --- a/include/drawinglayer/primitive2d/baseprimitive2d.hxx +++ b/include/drawinglayer/primitive2d/baseprimitive2d.hxx @@ -204,8 +204,9 @@ private: /// a sequence used for buffering the last create2DDecomposition() result Primitive2DContainer maBuffered2DDecomposition; - /// When blur is invoked on a list of primitives, exclude this primitive from the blur effect. - bool mbExcludeFromBlur = false; + /// When a shadow wraps a list of primitives, this primitive wants to influence the transparency + /// of the shadow. + sal_uInt16 mnTransparenceForShadow = 0; protected: /** access methods to maBuffered2DDecomposition. The usage of this methods may allow @@ -241,9 +242,12 @@ public: get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const override; - void setExcludeFromBlur(bool bExcludeFromBlur) { mbExcludeFromBlur = bExcludeFromBlur; } + void setTransparenceForShadow(sal_uInt16 nTransparenceForShadow) + { + mnTransparenceForShadow = nTransparenceForShadow; + } - bool getExcludeFromBlur() const { return mbExcludeFromBlur; } + sal_uInt16 getTransparenceForShadow() const { return mnTransparenceForShadow; } }; } // end of namespace drawinglayer::primitive2d diff --git a/include/drawinglayer/primitive2d/shadowprimitive2d.hxx b/include/drawinglayer/primitive2d/shadowprimitive2d.hxx index 7bd223847f8d..37258d8f34ed 100644 --- a/include/drawinglayer/primitive2d/shadowprimitive2d.hxx +++ b/include/drawinglayer/primitive2d/shadowprimitive2d.hxx @@ -76,14 +76,6 @@ namespace drawinglayer::primitive2d /// create decomposition virtual void get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const override; - void get2DDecompositionWithoutBlur( - Primitive2DDecompositionVisitor& rVisitor, - const geometry::ViewInformation2D& rViewInformation) const; - - void - get2DDecompositionWithBlur(Primitive2DDecompositionVisitor& rVisitor, - const geometry::ViewInformation2D& rViewInformation) const; - /// provide unique ID virtual sal_uInt32 getPrimitive2DID() const override; }; diff --git a/svx/qa/unit/table.cxx b/svx/qa/unit/table.cxx index 4419892a42ba..f65118e536c6 100644 --- a/svx/qa/unit/table.cxx +++ b/svx/qa/unit/table.cxx @@ -89,11 +89,13 @@ CPPUNIT_TEST_FIXTURE(Test, testTableShadowBlur) drawinglayer::Primitive2dXmlDump aDumper; xmlDocUniquePtr pDocument = aDumper.dumpAndParse(xPrimitiveSequence); // Without the accompanying fix in place, this test would have failed with: - // - Expected: true - // - Actual : false - // i.e. blur was applied on both the cell fill and the cell border. - assertXPath(pDocument, "//shadow/transform/modifiedColor/sdrCell[1]", "excludeFromBlur", - "true"); + // - number of nodes is incorrect + // - Expected: 1 + // - Actual : 0 + // i.e. the shadow itself was not transparent and that resulted in a non-transparent rendering + // as well, while the rendering transparency should be based on the transparency of the shadow + // itself and the transparency of the cell fill. + assertXPath(pDocument, "//objectinfo/unifiedtransparence[1]", "transparence", "0.8"); } } diff --git a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx index 504862a64229..aef53062a492 100644 --- a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx +++ b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx @@ -514,7 +514,6 @@ namespace drawinglayer::primitive2d { if(!rContent.empty()) { - Primitive2DContainer aRetval(2); basegfx::B2DHomMatrix aShadowOffset; { @@ -545,25 +544,66 @@ namespace drawinglayer::primitive2d } // create shadow primitive and add content - aRetval[0] = Primitive2DReference( - new ShadowPrimitive2D( - aShadowOffset, - rShadow.getColor(), - rShadow.getBlur(), - (pContentForShadow ? *pContentForShadow : rContent))); - - if(0.0 != rShadow.getTransparence()) + const Primitive2DContainer& rContentForShadow + = pContentForShadow ? *pContentForShadow : rContent; + int nContentWithTransparence = std::count_if( + rContentForShadow.begin(), rContentForShadow.end(), + [](const Primitive2DReference& xChild) { + auto pChild = dynamic_cast<BufferedDecompositionPrimitive2D*>(xChild.get()); + return pChild && pChild->getTransparenceForShadow() != 0; + }); + if (nContentWithTransparence == 0) { - // create SimpleTransparencePrimitive2D - const Primitive2DContainer aTempContent { aRetval[0] }; - + Primitive2DContainer aRetval(2); aRetval[0] = Primitive2DReference( - new UnifiedTransparencePrimitive2D( - aTempContent, - rShadow.getTransparence())); + new ShadowPrimitive2D( + aShadowOffset, + rShadow.getColor(), + rShadow.getBlur(), + (pContentForShadow ? *pContentForShadow : rContent))); + + if(0.0 != rShadow.getTransparence()) + { + // create SimpleTransparencePrimitive2D + const Primitive2DContainer aTempContent { aRetval[0] }; + + aRetval[0] = Primitive2DReference( + new UnifiedTransparencePrimitive2D( + aTempContent, + rShadow.getTransparence())); + } + + aRetval[1] = Primitive2DReference(new GroupPrimitive2D(rContent)); + return aRetval; + } + + Primitive2DContainer aRetval; + for (const auto& xChild : rContentForShadow) + { + double fChildTransparence = 0.0; + auto pChild = dynamic_cast<BufferedDecompositionPrimitive2D*>(xChild.get()); + if (pChild) + { + fChildTransparence = pChild->getTransparenceForShadow(); + fChildTransparence /= 100; + } + aRetval.push_back(Primitive2DReference( + new ShadowPrimitive2D(aShadowOffset, rShadow.getColor(), rShadow.getBlur(), + { xChild }))); + if (rShadow.getTransparence() != 0.0 || fChildTransparence != 0.0) + { + Primitive2DContainer aTempContent{ aRetval.back() }; + + double fChildAlpha = 1.0 - fChildTransparence; + double fShadowAlpha = 1.0 - rShadow.getTransparence(); + double fTransparence = 1.0 - fChildAlpha * fShadowAlpha; + aRetval.back() = Primitive2DReference(new UnifiedTransparencePrimitive2D( + std::move(aTempContent), fTransparence)); + } } - aRetval[1] = Primitive2DReference(new GroupPrimitive2D(rContent)); + aRetval.push_back( + Primitive2DReference(new GroupPrimitive2D(rContent))); return aRetval; } else diff --git a/svx/source/table/viewcontactoftableobj.cxx b/svx/source/table/viewcontactoftableobj.cxx index 409e099ae3e5..6262c7a54d1c 100644 --- a/svx/source/table/viewcontactoftableobj.cxx +++ b/svx/source/table/viewcontactoftableobj.cxx @@ -38,6 +38,7 @@ #include <svx/framelinkarray.hxx> #include <svx/sdooitm.hxx> #include <vcl/canvastools.hxx> +#include <svx/xfltrit.hxx> #include <cell.hxx> #include "tablelayouter.hxx" @@ -320,14 +321,21 @@ namespace sdr::contact aRetval.append(xCellReference); } - // Create cell primitive without text and blur. + // Create cell primitive without text. aAttribute = drawinglayer::primitive2d::createNewSdrFillTextAttribute( rCellItemSet, nullptr); rtl::Reference pCellReference = new drawinglayer::primitive2d::SdrCellPrimitive2D( aCellMatrix, aAttribute); - pCellReference->setExcludeFromBlur(true); + + sal_uInt16 nTransparence( + rCellItemSet.Get(XATTR_FILLTRANSPARENCE).GetValue()); + if (nTransparence != 0) + { + pCellReference->setTransparenceForShadow(nTransparence); + } + const drawinglayer::primitive2d::Primitive2DReference xCellReference(pCellReference.get()); aRetvalForShadow.append(xCellReference); @@ -379,8 +387,7 @@ namespace sdr::contact aTransform, aCellBorderPrimitives)); - // Borders are always the same for shadow as well, and implicitly included - // in blur. + // Borders are always the same for shadow as well. aRetvalForShadow.append(new drawinglayer::primitive2d::TransformPrimitive2D( aTransform, aCellBorderPrimitives)); } diff --git a/vcl/source/bitmap/bitmapfilter.cxx b/vcl/source/bitmap/bitmapfilter.cxx index 70d9cdd62dc1..67744e71aa05 100644 --- a/vcl/source/bitmap/bitmapfilter.cxx +++ b/vcl/source/bitmap/bitmapfilter.cxx @@ -19,6 +19,11 @@ BitmapFilter::~BitmapFilter() {} bool BitmapFilter::Filter(BitmapEx& rBmpEx, BitmapFilter const& rFilter) { + if (rBmpEx.IsEmpty()) + { + return true; + } + BitmapEx aTmpBmpEx(rFilter.execute(rBmpEx)); if (aTmpBmpEx.IsEmpty()) |