drawinglayer/source/attribute/fillgradientattribute.cxx     |   97 +++++++++---
 drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx |    4 
 drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx  |   13 -
 drawinglayer/source/processor2d/vclpixelprocessor2d.cxx     |   18 +-
 drawinglayer/source/processor3d/defaultprocessor3d.cxx      |    4 
 drawinglayer/source/tools/primitive2dxmldump.cxx            |   18 +-
 drawinglayer/source/tools/wmfemfhelper.cxx                  |   15 -
 include/drawinglayer/attribute/fillgradientattribute.hxx    |   89 ++++++++++-
 svx/source/sdr/attribute/sdrallfillattributeshelper.cxx     |   10 -
 svx/source/sdr/primitive2d/sdrattributecreator.cxx          |    1 
 10 files changed, 215 insertions(+), 54 deletions(-)

New commits:
commit 43de98fb59ef3cd1c6eabd3174d57634b7d501a9
Author:     Armin Le Grand (allotropia) <[email protected]>
AuthorDate: Fri Feb 10 11:36:15 2023 +0100
Commit:     Armin Le Grand <[email protected]>
CommitDate: Sun Feb 12 10:54:06 2023 +0000

    MCGR: Add/Provide GradientSteps to FillGradientAttribute
    
    MCGR stands for MultiColorGRadient. This change allows/
    prepares adding multiple color steps to gradient rendering.
    
    This is preparation work to allow rendering MCGRs in the
    future. All places are adapted in a way that currently
    no change of behaviour will happen. It will be the base
    to get MCGR rendering/decompose for Primitives and our
    internal/existing gradients working.
    
    Change-Id: I28bbd7d10b8670042343ada2a66b5909d3d31bbd
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146748
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <[email protected]>

diff --git a/drawinglayer/source/attribute/fillgradientattribute.cxx 
b/drawinglayer/source/attribute/fillgradientattribute.cxx
index b8b06e20bbbf..3d13c4050670 100644
--- a/drawinglayer/source/attribute/fillgradientattribute.cxx
+++ b/drawinglayer/source/attribute/fillgradientattribute.cxx
@@ -18,8 +18,6 @@
  */
 
 #include <drawinglayer/attribute/fillgradientattribute.hxx>
-#include <basegfx/color/bcolor.hxx>
-
 
 namespace drawinglayer::attribute
 {
@@ -31,8 +29,7 @@ namespace drawinglayer::attribute
             double                                  mfOffsetX;
             double                                  mfOffsetY;
             double                                  mfAngle;
-            basegfx::BColor                         maStartColor;
-            basegfx::BColor                         maEndColor;
+            FillGradientAttribute::ColorSteps       maColorSteps;
             GradientStyle                           meStyle;
             sal_uInt16                              mnSteps;
 
@@ -44,16 +41,62 @@ namespace drawinglayer::attribute
                 double fAngle,
                 const basegfx::BColor& rStartColor,
                 const basegfx::BColor& rEndColor,
+                const FillGradientAttribute::ColorSteps* pColorSteps,
                 sal_uInt16 nSteps)
             :   mfBorder(fBorder),
                 mfOffsetX(fOffsetX),
                 mfOffsetY(fOffsetY),
                 mfAngle(fAngle),
-                maStartColor(rStartColor),
-                maEndColor(rEndColor),
+                maColorSteps(),
                 meStyle(eStyle),
                 mnSteps(nSteps)
             {
+                // always add start color to guarentee a color at all. It's 
also just safer
+                // to have one and not an empty vector, that spares many 
checks in the using code
+                maColorSteps.emplace_back(0.0, rStartColor);
+
+                // if we have ColorSteps, integrate these
+                if(nullptr != pColorSteps)
+                {
+                    for(const auto& candidate : *pColorSteps)
+                    {
+                        // only allow ]0.0 .. 1.0[ as offset values, 
*excluding* 0.0 and 1.0
+                        // explicitely - these are reserved for start/end color
+                        if(basegfx::fTools::more(candidate.getOffset(), 0.0) 
&& basegfx::fTools::less(candidate.getOffset(), 1.0))
+                        {
+                            // ignore same offsets, independent from color (so 
1st one wins)
+                            // having two or more same offsets is an error 
(may assert evtl.)
+                            bool bAccept(true);
+
+                            for(const auto& compare : maColorSteps)
+                            {
+                                if(basegfx::fTools::equal(compare.getOffset(), 
candidate.getOffset()))
+                                {
+                                    bAccept = false;
+                                    break;
+                                }
+                            }
+
+                            if(bAccept)
+                            {
+                                maColorSteps.push_back(candidate);
+                            }
+                        }
+                    }
+
+                    // sort by offset when colors were added
+                    if(maColorSteps.size() > 1)
+                    {
+                        std::sort(maColorSteps.begin(), maColorSteps.end());
+                    }
+                }
+
+                // add end color if different from last color - which is the 
start color
+                // when no ColorSteps are given
+                if(rEndColor != maColorSteps.back().getColor())
+                {
+                    maColorSteps.emplace_back(1.0, rEndColor);
+                }
             }
 
             ImpFillGradientAttribute()
@@ -61,9 +104,12 @@ namespace drawinglayer::attribute
                 mfOffsetX(0.0),
                 mfOffsetY(0.0),
                 mfAngle(0.0),
+                maColorSteps(),
                 meStyle(GradientStyle::Linear),
                 mnSteps(0)
             {
+                // always add a fallback color, see above
+                maColorSteps.emplace_back(0.0, basegfx::BColor());
             }
 
             // data read access
@@ -72,10 +118,25 @@ namespace drawinglayer::attribute
             double getOffsetX() const { return mfOffsetX; }
             double getOffsetY() const { return mfOffsetY; }
             double getAngle() const { return mfAngle; }
-            const basegfx::BColor& getStartColor() const { return 
maStartColor; }
-            const basegfx::BColor& getEndColor() const { return maEndColor; }
+            const FillGradientAttribute::ColorSteps& getColorSteps() const { 
return maColorSteps; }
             sal_uInt16 getSteps() const { return mnSteps; }
 
+            bool hasSingleColor() const
+            {
+                // no entries (should not happen, see comments for startColor)
+                if (0 == maColorSteps.size())
+                    return true;
+
+                // check if not all colors are the same
+                const basegfx::BColor& rColor(maColorSteps[0].getColor());
+                for (size_t a(1); a < maColorSteps.size(); a++)
+                    if (maColorSteps[a].getColor() != rColor)
+                        return false;
+
+                // all colors are the same
+                return true;
+            }
+
             bool operator==(const ImpFillGradientAttribute& rCandidate) const
             {
                 return (getStyle() == rCandidate.getStyle()
@@ -83,8 +144,7 @@ namespace drawinglayer::attribute
                     && getOffsetX() == rCandidate.getOffsetX()
                     && getOffsetY() == rCandidate.getOffsetY()
                     && getAngle() == rCandidate.getAngle()
-                    && getStartColor() == rCandidate.getStartColor()
-                    && getEndColor() == rCandidate.getEndColor()
+                    && getColorSteps() == rCandidate.getColorSteps()
                     && getSteps() == rCandidate.getSteps());
             }
         };
@@ -106,9 +166,10 @@ namespace drawinglayer::attribute
             double fAngle,
             const basegfx::BColor& rStartColor,
             const basegfx::BColor& rEndColor,
+            const ColorSteps* pColorSteps,
             sal_uInt16 nSteps)
         :   mpFillGradientAttribute(ImpFillGradientAttribute(
-                eStyle, fBorder, fOffsetX, fOffsetY, fAngle, rStartColor, 
rEndColor, nSteps))
+                eStyle, fBorder, fOffsetX, fOffsetY, fAngle, rStartColor, 
rEndColor, pColorSteps, nSteps))
         {
         }
 
@@ -128,6 +189,11 @@ namespace drawinglayer::attribute
             return mpFillGradientAttribute.same_object(theGlobalDefault());
         }
 
+        bool FillGradientAttribute::hasSingleColor() const
+        {
+            return mpFillGradientAttribute->hasSingleColor();
+        }
+
         FillGradientAttribute& FillGradientAttribute::operator=(const 
FillGradientAttribute&) = default;
 
         FillGradientAttribute& 
FillGradientAttribute::operator=(FillGradientAttribute&&) = default;
@@ -141,14 +207,9 @@ namespace drawinglayer::attribute
             return rCandidate.mpFillGradientAttribute == 
mpFillGradientAttribute;
         }
 
-        const basegfx::BColor& FillGradientAttribute::getStartColor() const
-        {
-            return mpFillGradientAttribute->getStartColor();
-        }
-
-        const basegfx::BColor& FillGradientAttribute::getEndColor() const
+        const FillGradientAttribute::ColorSteps& 
FillGradientAttribute::getColorSteps() const
         {
-            return mpFillGradientAttribute->getEndColor();
+            return mpFillGradientAttribute->getColorSteps();
         }
 
         double FillGradientAttribute::getBorder() const
diff --git a/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx 
b/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx
index 5ca0b5852642..0f6eef0508cb 100644
--- a/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx
@@ -38,8 +38,8 @@ namespace drawinglayer::primitive2d
             rEntries.clear();
 
             // make sure steps is not too high/low
-            const basegfx::BColor aStart(getFillGradient().getStartColor());
-            const basegfx::BColor aEnd(getFillGradient().getEndColor());
+            const basegfx::BColor 
aStart(getFillGradient().getColorSteps().front().getColor());
+            const basegfx::BColor 
aEnd(getFillGradient().getColorSteps().back().getColor());
             const sal_uInt32 
nMaxSteps(sal_uInt32((aStart.getMaximumDistance(aEnd) * 127.5) + 0.5));
             sal_uInt32 nSteps(getFillGradient().getSteps());
 
diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx 
b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
index 33257f48175a..b5989303dd43 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
@@ -258,19 +258,20 @@ void 
VclMetafileProcessor2D::impConvertFillGradientAttributeToVCLGradient(
     Gradient& o_rVCLGradient, const attribute::FillGradientAttribute& rFiGrAtt,
     bool bIsTransparenceGradient) const
 {
+    const basegfx::BColor 
aStartColor(rFiGrAtt.getColorSteps().front().getColor());
+    const basegfx::BColor 
aEndColor(rFiGrAtt.getColorSteps().back().getColor());
+
     if (bIsTransparenceGradient)
     {
         // it's about transparence channel intensities (black/white), do not 
use color modifier
-        o_rVCLGradient.SetStartColor(Color(rFiGrAtt.getStartColor()));
-        o_rVCLGradient.SetEndColor(Color(rFiGrAtt.getEndColor()));
+        o_rVCLGradient.SetStartColor(Color(aStartColor));
+        o_rVCLGradient.SetEndColor(Color(aEndColor));
     }
     else
     {
         // use color modifier to influence start/end color of gradient
-        o_rVCLGradient.SetStartColor(
-            
Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getStartColor())));
-        o_rVCLGradient.SetEndColor(
-            
Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getEndColor())));
+        
o_rVCLGradient.SetStartColor(Color(maBColorModifierStack.getModifiedColor(aStartColor)));
+        
o_rVCLGradient.SetEndColor(Color(maBColorModifierStack.getModifiedColor(aEndColor)));
     }
 
     o_rVCLGradient.SetAngle(
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx 
b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index 7852131ee98f..7a171b915524 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -498,8 +498,10 @@ void 
VclPixelProcessor2D::processPolyPolygonGradientPrimitive2D(
 {
     // direct draw of gradient
     const attribute::FillGradientAttribute& 
rGradient(rPolygonCandidate.getFillGradient());
-    basegfx::BColor 
aStartColor(maBColorModifierStack.getModifiedColor(rGradient.getStartColor()));
-    basegfx::BColor 
aEndColor(maBColorModifierStack.getModifiedColor(rGradient.getEndColor()));
+    basegfx::BColor aStartColor(
+        
maBColorModifierStack.getModifiedColor(rGradient.getColorSteps().front().getColor()));
+    basegfx::BColor aEndColor(
+        
maBColorModifierStack.getModifiedColor(rGradient.getColorSteps().back().getColor()));
     basegfx::B2DPolyPolygon 
aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
 
     if (!aLocalPolyPolygon.count())
@@ -935,6 +937,14 @@ void VclPixelProcessor2D::processFillGradientPrimitive2D(
 {
     const attribute::FillGradientAttribute& rFillGradient = 
rPrimitive.getFillGradient();
 
+    // MCGR: If GradientSteps are used, use decomposition since vcl is not able
+    // to render multi-color gradients
+    if (rFillGradient.getColorSteps().size() > 2)
+    {
+        process(rPrimitive);
+        return;
+    }
+
     // VCL should be able to handle all styles, but for tdf#133477 the VCL 
result
     // is different from processing the gradient manually by drawinglayer
     // (and the Writer unittest for it fails). Keep using the drawinglayer code
@@ -983,8 +993,8 @@ void VclPixelProcessor2D::processFillGradientPrimitive2D(
 
     GradientStyle eGradientStyle = 
convertGradientStyle(rFillGradient.getStyle());
 
-    Gradient aGradient(eGradientStyle, Color(rFillGradient.getStartColor()),
-                       Color(rFillGradient.getEndColor()));
+    Gradient aGradient(eGradientStyle, 
Color(rFillGradient.getColorSteps().front().getColor()),
+                       Color(rFillGradient.getColorSteps().back().getColor()));
 
     
aGradient.SetAngle(Degree10(static_cast<int>(basegfx::rad2deg<10>(rFillGradient.getAngle()))));
     aGradient.SetBorder(rFillGradient.getBorder() * 100);
diff --git a/drawinglayer/source/processor3d/defaultprocessor3d.cxx 
b/drawinglayer/source/processor3d/defaultprocessor3d.cxx
index b9159c46c73f..6be8e78d0d59 100644
--- a/drawinglayer/source/processor3d/defaultprocessor3d.cxx
+++ b/drawinglayer/source/processor3d/defaultprocessor3d.cxx
@@ -61,8 +61,8 @@ namespace drawinglayer::processor3d
             const basegfx::B2DRange aOutlineRange(0.0, 0.0, 
rPrimitive.getTextureSize().getX(), rPrimitive.getTextureSize().getY());
             const attribute::GradientStyle 
aGradientStyle(rFillGradient.getStyle());
             sal_uInt32 nSteps(rFillGradient.getSteps());
-            const basegfx::BColor& aStart(rFillGradient.getStartColor());
-            const basegfx::BColor& aEnd(rFillGradient.getEndColor());
+            const basegfx::BColor 
aStart(rFillGradient.getColorSteps().front().getColor());
+            const basegfx::BColor 
aEnd(rFillGradient.getColorSteps().back().getColor());
             const sal_uInt32 
nMaxSteps(sal_uInt32((aStart.getMaximumDistance(aEnd) * 127.5) + 0.5));
             std::shared_ptr< texture::GeoTexSvx > pNewTex;
 
diff --git a/drawinglayer/source/tools/primitive2dxmldump.cxx 
b/drawinglayer/source/tools/primitive2dxmldump.cxx
index 74e95836fdf9..65967980d110 100644
--- a/drawinglayer/source/tools/primitive2dxmldump.cxx
+++ b/drawinglayer/source/tools/primitive2dxmldump.cxx
@@ -299,8 +299,22 @@ void writeSdrFillAttribute(::tools::XmlWriter& rWriter,
         rWriter.attribute("offsetY", rGradient.getOffsetY());
         rWriter.attribute("angle", rGradient.getAngle());
         rWriter.attribute("steps", rGradient.getSteps());
-        rWriter.attribute("startColor", 
convertColorToString(rGradient.getStartColor()));
-        rWriter.attribute("endColor", 
convertColorToString(rGradient.getEndColor()));
+
+        auto const& rColorSteps(rGradient.getColorSteps());
+        for (size_t a(0); a < rColorSteps.size(); a++)
+        {
+            if (0 == a)
+                rWriter.attribute("startColor", 
convertColorToString(rColorSteps[a].getColor()));
+            else if (rColorSteps.size() == a + 1)
+                rWriter.attribute("endColor", 
convertColorToString(rColorSteps[a].getColor()));
+            else
+            {
+                rWriter.startElement("colorStep");
+                rWriter.attribute("offset", rColorSteps[a].getOffset());
+                rWriter.attribute("color", 
convertColorToString(rColorSteps[a].getColor()));
+                rWriter.endElement();
+            }
+        }
         rWriter.endElement();
     }
 
diff --git a/drawinglayer/source/tools/wmfemfhelper.cxx 
b/drawinglayer/source/tools/wmfemfhelper.cxx
index 3a06f6423665..21a88757c954 100644
--- a/drawinglayer/source/tools/wmfemfhelper.cxx
+++ b/drawinglayer/source/tools/wmfemfhelper.cxx
@@ -718,6 +718,7 @@ namespace wmfemfhelper
             toRadians(rGradient.GetAngle()),
             aStart,
             aEnd,
+            nullptr,
             rGradient.GetSteps());
     }
 
@@ -919,10 +920,10 @@ namespace wmfemfhelper
     {
         drawinglayer::attribute::FillGradientAttribute 
aAttribute(createFillGradientAttribute(rGradient));
 
-        if(aAttribute.getStartColor() == aAttribute.getEndColor())
+        if(aAttribute.hasSingleColor())
         {
             // not really a gradient. Create filled rectangle
-            return CreateColorWallpaper(rRange, aAttribute.getStartColor(), 
rPropertyHolder);
+            return CreateColorWallpaper(rRange, 
aAttribute.getColorSteps().front().getColor(), rPropertyHolder);
         }
         else
         {
@@ -2089,7 +2090,7 @@ namespace wmfemfhelper
                             drawinglayer::attribute::FillGradientAttribute 
aAttribute(createFillGradientAttribute(rGradient));
                             basegfx::B2DPolyPolygon 
aOutline(basegfx::utils::createPolygonFromRect(aRange));
 
-                            if(aAttribute.getStartColor() == 
aAttribute.getEndColor())
+                            if(aAttribute.hasSingleColor())
                             {
                                 // not really a gradient. Create filled 
rectangle
                                 createFillPrimitive(
@@ -2799,13 +2800,13 @@ namespace wmfemfhelper
                                 const Gradient& rGradient = pA->GetGradient();
                                 drawinglayer::attribute::FillGradientAttribute 
aAttribute(createFillGradientAttribute(rGradient));
 
-                                if(aAttribute.getStartColor() == 
aAttribute.getEndColor())
+                                if(aAttribute.hasSingleColor())
                                 {
                                     // not really a gradient; create 
UnifiedTransparencePrimitive2D
                                     rTargetHolders.Current().append(
                                         new 
drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
                                             std::move(xSubContent),
-                                            
aAttribute.getStartColor().luminance()));
+                                            
aAttribute.getColorSteps().front().getColor().luminance()));
                                 }
                                 else
                                 {
@@ -2919,13 +2920,13 @@ namespace wmfemfhelper
                                 const Gradient& rGradient = 
pMetaGradientExAction->GetGradient();
                                 drawinglayer::attribute::FillGradientAttribute 
aAttribute(createFillGradientAttribute(rGradient));
 
-                                if(aAttribute.getStartColor() == 
aAttribute.getEndColor())
+                                if(aAttribute.hasSingleColor())
                                 {
                                     // not really a gradient
                                     rTargetHolders.Current().append(
                                         new 
drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
                                             std::move(aPolyPolygon),
-                                            aAttribute.getStartColor()));
+                                            
aAttribute.getColorSteps().front().getColor()));
                                 }
                                 else
                                 {
diff --git a/include/drawinglayer/attribute/fillgradientattribute.hxx 
b/include/drawinglayer/attribute/fillgradientattribute.hxx
index 50a87a685f1a..11b87f1b3a32 100644
--- a/include/drawinglayer/attribute/fillgradientattribute.hxx
+++ b/include/drawinglayer/attribute/fillgradientattribute.hxx
@@ -21,11 +21,8 @@
 
 #include <drawinglayer/drawinglayerdllapi.h>
 #include <o3tl/cow_wrapper.hxx>
-
-namespace basegfx
-{
-class BColor;
-}
+#include <basegfx/color/bcolor.hxx>
+#include <vector>
 
 namespace drawinglayer::attribute
 {
@@ -46,14 +43,88 @@ class DRAWINGLAYER_DLLPUBLIC FillGradientAttribute
 public:
     typedef o3tl::cow_wrapper<ImpFillGradientAttribute> ImplType;
 
+    /* MCGR: Provide ColorSteps to the FillGradientAttribute
+
+       This is the needed combination of offset and color:
+
+       Offset is defined as:
+       - being in the range of [0.0 .. 1.0] (unit range)
+       - 0.0 being reserved for StartColor
+       - 1.0 being reserved for EndColor
+       - in-between offsets thus being in the range of ]0.0 .. 1.0[
+       - no two equal offsets are allowed
+         - this is an error, but will be ignored (maybe assert?)
+       - missing 1.0 entry (EndColor) is allowed
+       - at least one value (usually 0.0, StartColor) is required
+         - this allows to avoid massive testing in all places where
+           this data has to be accessed
+
+       Color is defined as:
+       - RGB with unit values [0.0 .. 1.0]
+
+       These definitions are packed in a std::vector<ColorStep> ColorSteps,
+       see typedef below. This array is sorted ascending by offsets, from
+       lowest to highest. Since all this primitive data definition is
+       read-only, this can be guaranteed by forcing/checking this in the
+       constructor.
+    */
+    class ColorStep
+    {
+    private:
+        double mfOffset;
+        basegfx::BColor maColor;
+
+    public:
+        ColorStep(double fOffset, const basegfx::BColor& rColor)
+            : mfOffset(fOffset)
+            , maColor(rColor)
+        {
+        }
+
+        double getOffset() const { return mfOffset; }
+        const basegfx::BColor& getColor() const { return maColor; }
+
+        bool operator<(const ColorStep& rCandidate) const
+        {
+            return getOffset() < rCandidate.getOffset();
+        }
+
+        bool operator==(const ColorStep& rCandidate) const
+        {
+            return getOffset() == rCandidate.getOffset() && getColor() == 
rCandidate.getColor();
+        }
+    };
+
+    typedef std::vector<ColorStep> ColorSteps;
+
 private:
     ImplType mpFillGradientAttribute;
 
 public:
+    /* MCGR: Adaptions for MultiColorGradients
+
+       To force providing start/end colors these are still part of the
+       constructor (see rStartColor/rEndColor). To also provide
+       GradientSteps these need to be handed over by ColorSteps data
+       if wanted/needed.
+
+       Start/EndColor will be added to the internal ColorSteps with
+       the according default offsets. A rigid correction/input data
+       testing is done by the construtor, including to sort the
+       ColorSteps by offset.
+
+       To access e.g. the StartColor, use getColorSteps().front(), and
+       getColorSteps().back(), accordingly, for EndColor. The existance
+       of at least one entry is guaranteed, so no need to check before
+       accessing using of front()/back() calls. If only one color entry
+       exists, start == end color is assumed, so not really a gradient
+       but (existing) fallbacks to filled polygon can trigger.
+    */
     /// constructors/assignmentoperator/destructor
     FillGradientAttribute(GradientStyle eStyle, double fBorder, double 
fOffsetX, double fOffsetY,
                           double fAngle, const basegfx::BColor& rStartColor,
-                          const basegfx::BColor& rEndColor, sal_uInt16 nSteps 
= 0);
+                          const basegfx::BColor& rEndColor, const ColorSteps* 
pColorSteps = nullptr,
+                          sal_uInt16 nSteps = 0);
     FillGradientAttribute();
     FillGradientAttribute(const FillGradientAttribute&);
     FillGradientAttribute(FillGradientAttribute&&);
@@ -64,6 +135,9 @@ public:
     // checks if the incarnation is default constructed
     bool isDefault() const;
 
+    // check if it is defined by a single color, then it is no gradient at all
+    bool hasSingleColor() const;
+
     // compare operator
     bool operator==(const FillGradientAttribute& rCandidate) const;
 
@@ -73,8 +147,7 @@ public:
     double getOffsetX() const;
     double getOffsetY() const;
     double getAngle() const;
-    const basegfx::BColor& getStartColor() const;
-    const basegfx::BColor& getEndColor() const;
+    const ColorSteps& getColorSteps() const;
     sal_uInt16 getSteps() const;
 };
 
diff --git a/svx/source/sdr/attribute/sdrallfillattributeshelper.cxx 
b/svx/source/sdr/attribute/sdrallfillattributeshelper.cxx
index 261eef295361..e7bd26ce4f4f 100644
--- a/svx/source/sdr/attribute/sdrallfillattributeshelper.cxx
+++ b/svx/source/sdr/attribute/sdrallfillattributeshelper.cxx
@@ -151,8 +151,8 @@ namespace drawinglayer::attribute
 
                 if(!rFillTransparenceGradientAttribute.isDefault())
                 {
-                    const double fTransA = 
rFillTransparenceGradientAttribute.getStartColor().luminance();
-                    const double fTransB = 
rFillTransparenceGradientAttribute.getEndColor().luminance();
+                    const double 
fTransA(rFillTransparenceGradientAttribute.getColorSteps().front().getColor().luminance());
+                    const double 
fTransB(rFillTransparenceGradientAttribute.getColorSteps().back().getColor().luminance());
 
                     fTransparence = (fTransA + fTransB) * 0.5;
                 }
@@ -160,10 +160,10 @@ namespace drawinglayer::attribute
                 if(!rFillGradientAttribute.isDefault())
                 {
                     // gradient fill
-                    const basegfx::BColor& rStart = 
rFillGradientAttribute.getStartColor();
-                    const basegfx::BColor& rEnd = 
rFillGradientAttribute.getEndColor();
+                    const basegfx::BColor 
aStart(rFillGradientAttribute.getColorSteps().front().getColor());
+                    const basegfx::BColor 
aEnd(rFillGradientAttribute.getColorSteps().back().getColor());
 
-                    aRetval = basegfx::interpolate(rStart, rEnd, 0.5);
+                    aRetval = basegfx::interpolate(aStart, aEnd, 0.5);
                 }
                 else if(!rFillHatchAttribute.isDefault())
                 {
diff --git a/svx/source/sdr/primitive2d/sdrattributecreator.cxx 
b/svx/source/sdr/primitive2d/sdrattributecreator.cxx
index bafa96f95cd8..f79ea50e5a88 100644
--- a/svx/source/sdr/primitive2d/sdrattributecreator.cxx
+++ b/svx/source/sdr/primitive2d/sdrattributecreator.cxx
@@ -500,6 +500,7 @@ namespace drawinglayer::primitive2d
                                 toRadians(aXGradient.GetAngle()),
                                 aStart,
                                 aEnd,
+                                nullptr,
                                 rSet.Get(XATTR_GRADIENTSTEPCOUNT).GetValue());
 
                             break;

Reply via email to