drawinglayer/source/primitive2d/shadowprimitive2d.cxx   |   71 +++------------
 drawinglayer/source/processor2d/vclpixelprocessor2d.cxx |   12 --
 drawinglayer/source/tools/primitive2dxmldump.cxx        |    4 
 include/drawinglayer/primitive2d/baseprimitive2d.hxx    |   12 +-
 include/drawinglayer/primitive2d/shadowprimitive2d.hxx  |    8 -
 svx/qa/unit/table.cxx                                   |   12 +-
 svx/source/sdr/primitive2d/sdrdecompositiontools.cxx    |   72 ++++++++++++----
 svx/source/table/viewcontactoftableobj.cxx              |   15 ++-
 vcl/source/bitmap/bitmapfilter.cxx                      |    5 +
 9 files changed, 106 insertions(+), 105 deletions(-)

New commits:
commit 1f8687d2261082d1a76527c41bc1010ebcf0ddd1
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Sep 23 16:55:19 2021 +0200
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Sep 27 08:27:04 2021 +0200

    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
    
    Change-Id: I63560e3a73473c70157ecee8365ec7154217f269
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122565
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

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 5e50d1ee2f81..5e6c6a73cd60 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 nAlpha = rCandidate.getGlowColor().GetAlpha();
 
     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 da6cb41fea69..1e99ac91ed54 100644
--- a/drawinglayer/source/tools/primitive2dxmldump.cxx
+++ b/drawinglayer/source/tools/primitive2dxmldump.cxx
@@ -601,8 +601,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 c4a9b650308f..f697886c1ac5 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
@@ -240,9 +241,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..b392d8ccb38b 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", "80");
 }
 }
 
diff --git a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx 
b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
index dcff748ea60f..1cd60e75d925 100644
--- a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
+++ b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
@@ -545,7 +545,6 @@ basegfx::B2DRange getTextAnchorRange(const 
attribute::SdrTextAttribute& rText,
         {
             if(!rContent.empty())
             {
-                Primitive2DContainer aRetval(2);
                 basegfx::B2DHomMatrix aShadowOffset;
 
                 {
@@ -576,25 +575,66 @@ basegfx::B2DRange getTextAnchorRange(const 
attribute::SdrTextAttribute& rText,
                 }
 
                 // 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 90f304f33452..41d60d7652f8 100644
--- a/svx/source/table/viewcontactoftableobj.cxx
+++ b/svx/source/table/viewcontactoftableobj.cxx
@@ -39,6 +39,7 @@
 #include <svx/sdooitm.hxx>
 #include <vcl/canvastools.hxx>
 #include <o3tl/unit_conversion.hxx>
+#include <svx/xfltrit.hxx>
 
 #include <cell.hxx>
 #include "tablelayouter.hxx"
@@ -322,14 +323,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);
                                     aRetvalForShadow.append(xCellReference);
@@ -381,8 +389,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 f2020539e04d..9ede4e578b10 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())

Reply via email to