drawinglayer/Library_drawinglayer.mk                                     |    
1 
 drawinglayer/source/primitive2d/PolyPolygonAlphaGradientPrimitive2D.cxx  |  
106 ++++++++++
 drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D.cxx           |    
6 
 drawinglayer/source/primitive2d/Tools.cxx                                |    
2 
 drawinglayer/source/processor2d/cairopixelprocessor2d.cxx                |   
81 +++++++
 drawinglayer/source/tools/primitive2dxmldump.cxx                         |   
13 +
 include/drawinglayer/primitive2d/PolyPolygonAlphaGradientPrimitive2D.hxx |   
87 ++++++++
 include/drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx          |    
4 
 include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx       |    
1 
 include/drawinglayer/processor2d/cairopixelprocessor2d.hxx               |    
4 
 svx/source/sdr/primitive2d/sdrdecompositiontools.cxx                     |   
32 ++-
 11 files changed, 322 insertions(+), 15 deletions(-)

New commits:
commit ebe1543250b9729a6560545e58f50ea68e62be11
Author:     Armin Le Grand (Collabora) <armin.le.gr...@me.com>
AuthorDate: Thu Aug 8 14:08:22 2024 +0200
Commit:     Armin Le Grand <armin.le.gr...@me.com>
CommitDate: Thu Aug 8 18:27:16 2024 +0200

    CairoSDPR: Support ColorPolygon with AlphaGradient
    
    Cairo can render RGBA gradients directly and the
    CairoSDPR supports that. If we have a PolyPolygon
    filled with single color combined with a gradient
    alpha the renderer could map RGB to that color
    and combine with the real alpha gradient steps.
    
    To support that I added another Primitive called
    PolyPolygonAlphaGradientPrimitive2D. It decomposes
    as needed (TransparencePrimitive2D if needed), so
    no other renderers have to be touched.
    
    The Cairo renderer supports it directly, though,
    what makes it much faster.
    
    Change-Id: Ie90c8bd84d6458d12443db815ced55bdea93c15c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171628
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <armin.le.gr...@me.com>

diff --git a/drawinglayer/Library_drawinglayer.mk 
b/drawinglayer/Library_drawinglayer.mk
index 7529c34a43b7..e8e3dde7c952 100644
--- a/drawinglayer/Library_drawinglayer.mk
+++ b/drawinglayer/Library_drawinglayer.mk
@@ -144,6 +144,7 @@ $(eval $(call 
gb_Library_add_exception_objects,drawinglayer,\
     drawinglayer/source/primitive2d/PolyPolygonStrokePrimitive2D \
     drawinglayer/source/primitive2d/PolyPolygonColorPrimitive2D \
     drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D \
+    drawinglayer/source/primitive2d/PolyPolygonAlphaGradientPrimitive2D \
     drawinglayer/source/primitive2d/PolyPolygonGradientPrimitive2D \
     drawinglayer/source/primitive2d/PolyPolygonHatchPrimitive2D \
     drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D \
diff --git 
a/drawinglayer/source/primitive2d/PolyPolygonAlphaGradientPrimitive2D.cxx 
b/drawinglayer/source/primitive2d/PolyPolygonAlphaGradientPrimitive2D.cxx
new file mode 100644
index 000000000000..c65785e78bb8
--- /dev/null
+++ b/drawinglayer/source/primitive2d/PolyPolygonAlphaGradientPrimitive2D.cxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <drawinglayer/primitive2d/PolyPolygonAlphaGradientPrimitive2D.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <basegfx/utils/bgradient.hxx>
+
+using namespace com::sun::star;
+
+namespace drawinglayer::primitive2d
+{
+Primitive2DReference 
PolyPolygonAlphaGradientPrimitive2D::create2DDecomposition(
+    const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+    if (0 == getB2DPolyPolygon().count())
+    {
+        // no geometry, done
+        return nullptr;
+    }
+
+    if (getAlphaGradient().isDefault())
+    {
+        // default is a single ColorStop at 0.0 with black (0, 0, 0). The
+        // luminance is then 0.0, too -> not transparent at all
+        return new PolyPolygonColorPrimitive2D(getB2DPolyPolygon(), 
getBColor());
+    }
+
+    basegfx::BColor aSingleColor;
+    if (getAlphaGradient().getColorStops().isSingleColor(aSingleColor))
+    {
+        // no real taransparence gradient, only unified alpha,
+        // we can use PolyPolygonRGBAPrimitive2D
+        return new PolyPolygonRGBAPrimitive2D(getB2DPolyPolygon(), getBColor(),
+                                              aSingleColor.luminance());
+    }
+
+    // transparency gradient is a real gradient, create TransparencePrimitive2D
+    Primitive2DContainer aContent{ new 
PolyPolygonColorPrimitive2D(getB2DPolyPolygon(),
+                                                                   
getBColor()) };
+
+    Primitive2DContainer aAlpha{ new FillGradientPrimitive2D(
+        basegfx::utils::getRange(getB2DPolyPolygon()), getAlphaGradient()) };
+
+    return new TransparencePrimitive2D(std::move(aContent), std::move(aAlpha));
+}
+
+PolyPolygonAlphaGradientPrimitive2D::PolyPolygonAlphaGradientPrimitive2D(
+    const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::BColor& 
rBColor,
+    const attribute::FillGradientAttribute& rAlphaGradient)
+    : maPolyPolygon(rPolyPolygon)
+    , maBColor(rBColor)
+    , maAlphaGradient(rAlphaGradient)
+{
+}
+
+bool PolyPolygonAlphaGradientPrimitive2D::operator==(const BasePrimitive2D& 
rPrimitive) const
+{
+    if (BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+    {
+        const PolyPolygonAlphaGradientPrimitive2D& rCompare
+            = static_cast<const 
PolyPolygonAlphaGradientPrimitive2D&>(rPrimitive);
+
+        return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
+                && getBColor() == rCompare.getBColor()
+                && getAlphaGradient() == rCompare.getAlphaGradient());
+    }
+
+    return false;
+}
+
+basegfx::B2DRange PolyPolygonAlphaGradientPrimitive2D::getB2DRange(
+    const geometry::ViewInformation2D& /*rViewInformation*/) const
+{
+    // return range - without decompose
+    return basegfx::utils::getRange(getB2DPolyPolygon());
+}
+
+// provide unique ID
+sal_uInt32 PolyPolygonAlphaGradientPrimitive2D::getPrimitive2DID() const
+{
+    return PRIMITIVE2D_ID_POLYPOLYGONALPHAGRADIENTPRIMITIVE2D;
+}
+} // end of namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D.cxx 
b/drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D.cxx
index eb453116c97c..fb230af8712e 100644
--- a/drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D.cxx
+++ b/drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D.cxx
@@ -58,10 +58,10 @@ Primitive2DReference 
PolyPolygonRGBAPrimitive2D::create2DDecomposition(
                                                                     
getTransparency()) };
 }
 
-PolyPolygonRGBAPrimitive2D::PolyPolygonRGBAPrimitive2D(basegfx::B2DPolyPolygon 
aPolyPolygon,
+PolyPolygonRGBAPrimitive2D::PolyPolygonRGBAPrimitive2D(const 
basegfx::B2DPolyPolygon& rPolyPolygon,
                                                        const basegfx::BColor& 
rBColor,
                                                        double fTransparency)
-    : maPolyPolygon(std::move(aPolyPolygon))
+    : maPolyPolygon(rPolyPolygon)
     , maBColor(rBColor)
     , mfTransparency(std::max(0.0, std::min(1.0, fTransparency)))
 {
@@ -85,7 +85,7 @@ bool PolyPolygonRGBAPrimitive2D::operator==(const 
BasePrimitive2D& rPrimitive) c
 basegfx::B2DRange PolyPolygonRGBAPrimitive2D::getB2DRange(
     const geometry::ViewInformation2D& /*rViewInformation*/) const
 {
-    // return range
+    // return range - without decompose
     return basegfx::utils::getRange(getB2DPolyPolygon());
 }
 
diff --git a/drawinglayer/source/primitive2d/Tools.cxx 
b/drawinglayer/source/primitive2d/Tools.cxx
index 2a4314c70ec4..52545212b8cc 100644
--- a/drawinglayer/source/primitive2d/Tools.cxx
+++ b/drawinglayer/source/primitive2d/Tools.cxx
@@ -239,6 +239,8 @@ OUString idToString(sal_uInt32 nId)
             return u"POLYPOLYGONRGBAPRIMITIVE2D"_ustr;
         case PRIMITIVE2D_ID_BITMAPALPHAPRIMITIVE2D:
             return u"BITMAPALPHAPRIMITIVE2D"_ustr;
+        case PRIMITIVE2D_ID_POLYPOLYGONALPHAGRADIENTPRIMITIVE2D:
+            return u"POLYPOLYGONALPHAGRADIENTPRIMITIVE2D"_ustr;
         default:
             return OUString::number((nId >> 16) & 0xFF) + "|" + 
OUString::number(nId & 0xFF);
     }
diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx 
b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
index 62e009e62bc9..31387125c259 100644
--- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
@@ -38,6 +38,7 @@
 #include <drawinglayer/primitive2d/invertprimitive2d.hxx>
 #include <drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx>
 #include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonAlphaGradientPrimitive2D.hxx>
 #include <drawinglayer/primitive2d/BitmapAlphaPrimitive2D.hxx>
 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
 #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
@@ -2786,6 +2787,80 @@ void 
CairoPixelProcessor2D::processPolyPolygonRGBAPrimitive2D(
                          rPolyPolygonRGBAPrimitive2D.getTransparency());
 }
 
+void CairoPixelProcessor2D::processPolyPolygonAlphaGradientPrimitive2D(
+    const primitive2d::PolyPolygonAlphaGradientPrimitive2D& 
rPolyPolygonAlphaGradientPrimitive2D)
+{
+    const basegfx::B2DPolyPolygon& rPolyPolygon(
+        rPolyPolygonAlphaGradientPrimitive2D.getB2DPolyPolygon());
+    if (0 == rPolyPolygon.count())
+    {
+        // no geometry, done
+        return;
+    }
+
+    const basegfx::BColor& 
rColor(rPolyPolygonAlphaGradientPrimitive2D.getBColor());
+    const attribute::FillGradientAttribute& rAlphaGradient(
+        rPolyPolygonAlphaGradientPrimitive2D.getAlphaGradient());
+    if (rAlphaGradient.isDefault())
+    {
+        // default is a single ColorStop at 0.0 with black (0, 0, 0). The
+        // luminance is then 0.0, too -> not transparent at all
+        paintPolyPoylgonRGBA(rPolyPolygon, rColor);
+        return;
+    }
+
+    basegfx::BColor aSingleColor;
+    const basegfx::BColorStops& rAlphaStops(rAlphaGradient.getColorStops());
+    if (rAlphaStops.isSingleColor(aSingleColor))
+    {
+        // draw with alpha directly
+        paintPolyPoylgonRGBA(rPolyPolygon, rColor, aSingleColor.luminance());
+        return;
+    }
+
+    const css::awt::GradientStyle aStyle(rAlphaGradient.getStyle());
+    if (css::awt::GradientStyle_SQUARE == aStyle || 
css::awt::GradientStyle_RECT == aStyle)
+    {
+        // direct paint cannot be used for thse styles since they get 
'stitched'
+        // by multiple parts, so *need* singhle alpha for multiple pieces, go
+        // with decompose/recursion
+        process(rPolyPolygonAlphaGradientPrimitive2D);
+        return;
+    }
+
+    // render as FillGradientPrimitive2D. The idea is to create BColorStops
+    // with the same number of entries, but all the same color, using the
+    // polygon's traget fill color, so we can directly paint gradients as
+    // RGBA in Cairo
+    basegfx::BColorStops aColorStops;
+
+    // create ColorStops at same stops but single color
+    aColorStops.reserve(rAlphaStops.size());
+    for (const auto& entry : rAlphaStops)
+        aColorStops.emplace_back(entry.getStopOffset(), rColor);
+
+    // create FillGradient using that single-color ColorStops
+    const attribute::FillGradientAttribute aFillGradient(
+        rAlphaGradient.getStyle(), rAlphaGradient.getBorder(), 
rAlphaGradient.getOffsetX(),
+        rAlphaGradient.getOffsetY(), rAlphaGradient.getAngle(), aColorStops,
+        rAlphaGradient.getSteps());
+
+    // create temporary FillGradientPrimitive2D, but do not forget
+    // to embed to MaskPrimitive2D to get the PolyPolygon form
+    const basegfx::B2DRange aRange(basegfx::utils::getRange(rPolyPolygon));
+    const primitive2d::Primitive2DContainer aContainerMaskedFillGradient{
+        rtl::Reference<primitive2d::MaskPrimitive2D>(new 
primitive2d::MaskPrimitive2D(
+            rPolyPolygon,
+            primitive2d::Primitive2DContainer{ 
rtl::Reference<primitive2d::FillGradientPrimitive2D>(
+                new primitive2d::FillGradientPrimitive2D(aRange, // OutputRange
+                                                         aRange, // 
DefinitionRange
+                                                         aFillGradient, 
&rAlphaGradient)) }))
+    };
+
+    // render this
+    process(aContainerMaskedFillGradient);
+}
+
 void CairoPixelProcessor2D::processBitmapAlphaPrimitive2D(
     const primitive2d::BitmapAlphaPrimitive2D& rBitmapAlphaPrimitive2D)
 {
@@ -3070,6 +3145,12 @@ void CairoPixelProcessor2D::processBasePrimitive2D(const 
primitive2d::BasePrimit
                 static_cast<const 
primitive2d::BitmapAlphaPrimitive2D&>(rCandidate));
             break;
         }
+        case PRIMITIVE2D_ID_POLYPOLYGONALPHAGRADIENTPRIMITIVE2D:
+        {
+            processPolyPolygonAlphaGradientPrimitive2D(
+                static_cast<const 
primitive2d::PolyPolygonAlphaGradientPrimitive2D&>(rCandidate));
+            break;
+        }
         case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D:
         {
             processTextSimplePortionPrimitive2D(
diff --git a/drawinglayer/source/tools/primitive2dxmldump.cxx 
b/drawinglayer/source/tools/primitive2dxmldump.cxx
index 55c581dab510..527889cd7399 100644
--- a/drawinglayer/source/tools/primitive2dxmldump.cxx
+++ b/drawinglayer/source/tools/primitive2dxmldump.cxx
@@ -43,6 +43,7 @@
 #include <drawinglayer/primitive2d/sceneprimitive2d.hxx>
 #include <drawinglayer/primitive2d/shadowprimitive2d.hxx>
 #include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonAlphaGradientPrimitive2D.hxx>
 #include <drawinglayer/geometry/viewinformation2d.hxx>
 #include <drawinglayer/attribute/lineattribute.hxx>
 #include <drawinglayer/attribute/fontattribute.hxx>
@@ -1229,6 +1230,18 @@ void Primitive2dXmlDump::decomposeAndWrite(
                 break;
             }
 
+            case PRIMITIVE2D_ID_POLYPOLYGONALPHAGRADIENTPRIMITIVE2D:
+            {
+                const PolyPolygonAlphaGradientPrimitive2D& 
rPolyPolygonAlphaGradientPrimitive2D
+                    = dynamic_cast<const 
PolyPolygonAlphaGradientPrimitive2D&>(*pBasePrimitive);
+                rWriter.startElement("polypolygonalphagradient");
+                rWriter.attribute("color", convertColorToString(
+                                               
rPolyPolygonAlphaGradientPrimitive2D.getBColor()));
+                writePolyPolygon(rWriter, 
rPolyPolygonAlphaGradientPrimitive2D.getB2DPolyPolygon());
+                rWriter.endElement();
+                break;
+            }
+
             default:
             {
                 rWriter.startElement("unhandled");
diff --git 
a/include/drawinglayer/primitive2d/PolyPolygonAlphaGradientPrimitive2D.hxx 
b/include/drawinglayer/primitive2d/PolyPolygonAlphaGradientPrimitive2D.hxx
new file mode 100644
index 000000000000..34f8c4dfb253
--- /dev/null
+++ b/include/drawinglayer/primitive2d/PolyPolygonAlphaGradientPrimitive2D.hxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <drawinglayer/drawinglayerdllapi.h>
+
+#include <drawinglayer/primitive2d/BufferedDecompositionPrimitive2D.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/color/bcolor.hxx>
+#include <drawinglayer/attribute/fillgradientattribute.hxx>
+// #include <basegfx/numeric/ftools.hxx>
+
+namespace drawinglayer::primitive2d
+{
+/** PolyPolygonAlphaGradientPrimitive2D class
+
+    This is a simple extension to PolyPolygonColorPrimitive2D
+    that allows to directly define an alpha gradient for the PolyPolygon
+    to be represented, additionally to the color.
+
+    It will be decomposed simply to PolyPolygonColorPrimitive2D,
+    maybe embedded to a FillGradientPrimitive2D if
+    needed, so no changes have to be done to any primitive processor.
+
+    OTOH e.g. SDPR implementations *may* use this directly if they
+    are capable to draw a filled PolyPolygon with transparency gradient
+    directly (e.g. CairoPixelProcessor2D)
+ */
+class DRAWINGLAYER_DLLPUBLIC PolyPolygonAlphaGradientPrimitive2D final
+    : public BufferedDecompositionPrimitive2D
+{
+private:
+    /// the tools::PolyPolygon geometry
+    basegfx::B2DPolyPolygon maPolyPolygon;
+
+    /// the polygon fill color
+    basegfx::BColor maBColor;
+
+    /// alphaGradient definition
+    attribute::FillGradientAttribute maAlphaGradient;
+
+    /// create local decomposition
+    virtual Primitive2DReference
+    create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) 
const override;
+
+public:
+    /// constructor
+    PolyPolygonAlphaGradientPrimitive2D(const basegfx::B2DPolyPolygon& 
rPolyPolygon,
+                                        const basegfx::BColor& rBColor,
+                                        const 
attribute::FillGradientAttribute& rAlphaGradient);
+
+    /// data read access
+    const basegfx::B2DPolyPolygon& getB2DPolyPolygon() const { return 
maPolyPolygon; }
+    const basegfx::BColor& getBColor() const { return maBColor; }
+    const attribute::FillGradientAttribute& getAlphaGradient() const { return 
maAlphaGradient; }
+
+    /// compare operator
+    virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
+
+    /// get B2Drange
+    virtual basegfx::B2DRange
+    getB2DRange(const geometry::ViewInformation2D& rViewInformation) const 
override;
+
+    /// provide unique ID
+    virtual sal_uInt32 getPrimitive2DID() const override;
+};
+
+} // end of namespace drawinglayer::primitive2d
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx 
b/include/drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx
index 74ac76e4e3d1..f5502dee0fef 100644
--- a/include/drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx
+++ b/include/drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx
@@ -61,8 +61,8 @@ private:
 
 public:
     /// constructor
-    PolyPolygonRGBAPrimitive2D(basegfx::B2DPolyPolygon aPolyPolygon, const 
basegfx::BColor& rBColor,
-                               double fTransparency = 0.0);
+    PolyPolygonRGBAPrimitive2D(const basegfx::B2DPolyPolygon& rPolyPolygon,
+                               const basegfx::BColor& rBColor, double 
fTransparency = 0.0);
 
     /// data read access
     const basegfx::B2DPolyPolygon& getB2DPolyPolygon() const { return 
maPolyPolygon; }
diff --git a/include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx 
b/include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx
index 8f86167dc5f7..015d0befe32f 100644
--- a/include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx
+++ b/include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx
@@ -111,6 +111,7 @@
 #define PRIMITIVE2D_ID_ANIMATEDGRAPHICPRIMITIVE2D           
(PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 77)
 #define PRIMITIVE2D_ID_POLYPOLYGONRGBAPRIMITIVE2D           
(PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 78)
 #define PRIMITIVE2D_ID_BITMAPALPHAPRIMITIVE2D               
(PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 79)
+#define PRIMITIVE2D_ID_POLYPOLYGONALPHAGRADIENTPRIMITIVE2D  
(PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 80)
 // When you add a new primitive, please update the 
drawinglayer::primitive2d::idToString() function
 // in drawinglayer/source/primitive2d/Tools.cxx.
 
diff --git a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx 
b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx
index 21cffda24e7c..76b35d3530a0 100644
--- a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx
+++ b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx
@@ -38,6 +38,7 @@ class FillGradientPrimitive2D;
 class PolyPolygonRGBAGradientPrimitive2D;
 class FillGraphicPrimitive2D;
 class PolyPolygonRGBAPrimitive2D;
+class PolyPolygonAlphaGradientPrimitive2D;
 class BitmapAlphaPrimitive2D;
 class TextSimplePortionPrimitive2D;
 }
@@ -100,6 +101,9 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) 
CairoPixelProcessor2D final : pub
         const primitive2d::FillGraphicPrimitive2D& rFillGraphicPrimitive2D);
     void processPolyPolygonRGBAPrimitive2D(
         const primitive2d::PolyPolygonRGBAPrimitive2D& 
rPolyPolygonRGBAPrimitive2D);
+    void processPolyPolygonAlphaGradientPrimitive2D(
+        const primitive2d::PolyPolygonAlphaGradientPrimitive2D&
+            rPolyPolygonAlphaGradientPrimitive2D);
     void paintBitmapAlpha(const BitmapEx& rBitmapEx, const 
basegfx::B2DHomMatrix& rTransform,
                           double fTransparency = 0.0);
     void processBitmapAlphaPrimitive2D(
diff --git a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx 
b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
index b518dbf8ede1..c04aef0a9604 100644
--- a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
+++ b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
@@ -29,6 +29,7 @@
 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
 #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
 #include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonAlphaGradientPrimitive2D.hxx>
 #include <basegfx/polygon/b2dpolypolygontools.hxx>
 #include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
 #include <drawinglayer/attribute/strokeattribute.hxx>
@@ -410,11 +411,11 @@ sal_uInt32 
SlideBackgroundFillPrimitive2D::getPrimitive2DID() const
                 // gets priority over gradient transparency (and none). Thus 
here only one
                 // option is used. Note that the implementation of 
FillGradientPrimitive2D
                 // and PolyPolygonGradientPrimitive2D do support both alphas 
being used
-                const bool bHasAlphaGradient(!bHasTransparency
+                const bool bHasCompatibleAlphaGradient(!bHasTransparency
                     && !rAlphaGradient.isDefault()
                     && rFillGradient.sameDefinitionThanAlpha(rAlphaGradient));
 
-                if(bHasTransparency || bHasAlphaGradient)
+                if(bHasTransparency || bHasCompatibleAlphaGradient)
                 {
                     // SDPR: check early if we have a gradient and an alpha
                     // gradient that 'fits' in its geometric definition
@@ -424,7 +425,7 @@ sal_uInt32 
SlideBackgroundFillPrimitive2D::getPrimitive2DID() const
                         rPolyPolygon,
                         rDefinitionRange,
                         rFillGradient,
-                        bHasAlphaGradient ? &rAlphaGradient : nullptr,
+                        bHasCompatibleAlphaGradient ? &rAlphaGradient : 
nullptr,
                         bHasTransparency ? rFill.getTransparence() : 0.0);
                 }
 
@@ -476,7 +477,19 @@ sal_uInt32 
SlideBackgroundFillPrimitive2D::getPrimitive2DID() const
                         rFill.getTransparence());
                 }
 
-                pNewFillPrimitive = new PolyPolygonColorPrimitive2D(
+                // SDPR: check early if we have alpha gradient and add directly
+                // This may be useful for some SDPRs like Cairo: It can render 
RGBA
+                // gradients quick and direct, so it can use polygon color as 
RGB
+                // (no real gradient steps) combined with the existing alpha 
steps
+                if (!rAlphaGradient.isDefault())
+                {
+                    return new PolyPolygonAlphaGradientPrimitive2D(
+                        rPolyPolygon,
+                        rFill.getColor(),
+                        rAlphaGradient);
+                }
+
+                return new PolyPolygonColorPrimitive2D(
                     rPolyPolygon,
                     rFill.getColor());
             }
@@ -487,7 +500,8 @@ sal_uInt32 
SlideBackgroundFillPrimitive2D::getPrimitive2DID() const
                 Primitive2DContainer aContent { pNewFillPrimitive };
                 return new UnifiedTransparencePrimitive2D(std::move(aContent), 
rFill.getTransparence());
             }
-            else if(!rAlphaGradient.isDefault())
+
+            if(!rAlphaGradient.isDefault())
             {
                 // create sequence with created fill primitive
                 Primitive2DContainer aContent { pNewFillPrimitive };
@@ -504,11 +518,9 @@ sal_uInt32 
SlideBackgroundFillPrimitive2D::getPrimitive2DID() const
                 // create TransparencePrimitive2D using alpha and content
                 return new TransparencePrimitive2D(std::move(aContent), 
std::move(aAlpha));
             }
-            else
-            {
-                // add to decomposition
-                return pNewFillPrimitive;
-            }
+
+            // add to decomposition
+            return pNewFillPrimitive;
         }
 
         Primitive2DReference createPolygonLinePrimitive(

Reply via email to