basctl/inc/pch/precompiled_basctl.hxx                     |    1 
 basegfx/Library_basegfx.mk                                |    1 
 basegfx/source/tools/bgradient.cxx                        |  774 ++++++++++++++
 basegfx/source/tools/gradienttools.cxx                    |  602 ----------
 chart2/inc/pch/precompiled_chartcontroller.hxx            |    1 
 chart2/qa/extras/chart2import.cxx                         |    8 
 chart2/source/controller/main/ChartController_Tools.cxx   |   11 
 cui/source/inc/cuitabarea.hxx                             |    8 
 cui/source/tabpages/tpgradnt.cxx                          |   41 
 cui/source/tabpages/tptrans.cxx                           |   18 
 drawinglayer/inc/texture/texture.hxx                      |   21 
 drawinglayer/qa/unit/vclpixelprocessor2d.cxx              |   61 -
 drawinglayer/source/attribute/fillgradientattribute.cxx   |   26 
 drawinglayer/source/primitive3d/textureprimitive3d.cxx    |    6 
 drawinglayer/source/processor3d/defaultprocessor3d.cxx    |    6 
 drawinglayer/source/texture/texture.cxx                   |  146 +-
 drawinglayer/source/tools/wmfemfhelper.cxx                |   20 
 filter/source/msfilter/msdffimp.cxx                       |    8 
 filter/source/msfilter/svdfppt.cxx                        |   22 
 include/basegfx/utils/bgradient.hxx                       |  329 +++++
 include/basegfx/utils/gradienttools.hxx                   |  249 ----
 include/drawinglayer/attribute/fillgradientattribute.hxx  |   15 
 include/oox/export/drawingml.hxx                          |    9 
 include/svx/sidebar/AreaPropertyPanelBase.hxx             |   22 
 include/svx/sidebar/AreaTransparencyGradientPopup.hxx     |    2 
 include/svx/xflftrit.hxx                                  |    4 
 include/svx/xflgrit.hxx                                   |   13 
 include/svx/xgrad.hxx                                     |   85 -
 include/svx/xtable.hxx                                    |    8 
 oox/qa/unit/drawingml.cxx                                 |    3 
 oox/source/drawingml/fillproperties.cxx                   |   22 
 oox/source/export/chartexport.cxx                         |   48 
 oox/source/export/drawingml.cxx                           |  169 +--
 reportdesign/Library_rptui.mk                             |    1 
 reportdesign/inc/pch/precompiled_rptui.hxx                |    1 
 reportdesign/source/ui/misc/UITools.cxx                   |    4 
 reportdesign/source/ui/report/ReportController.cxx        |    4 
 sc/inc/pch/precompiled_sc.hxx                             |    1 
 sc/qa/unit/bugfix-test.cxx                                |    4 
 sc/source/ui/drawfunc/drawsh.cxx                          |    2 
 sd/inc/pch/precompiled_sdui.hxx                           |    1 
 sd/qa/unit/export-tests-ooxml1.cxx                        |    6 
 sd/qa/unit/export-tests-ooxml2.cxx                        |    3 
 sd/qa/unit/export-tests-ooxml3.cxx                        |    6 
 sd/qa/unit/misc-tests.cxx                                 |    3 
 sd/qa/unit/uiimpress.cxx                                  |    4 
 sd/source/core/drawdoc4.cxx                               |   18 
 sd/source/ui/sidebar/SlideBackground.cxx                  |   21 
 sd/source/ui/sidebar/SlideBackground.hxx                  |    7 
 sd/source/ui/view/drviews2.cxx                            |    2 
 sd/source/ui/view/drviews7.cxx                            |    2 
 sd/source/ui/view/drviews9.cxx                            |   21 
 solenv/clang-format/excludelist                           |    1 
 svx/inc/pch/precompiled_svx.hxx                           |    1 
 svx/source/customshapes/EnhancedCustomShape2d.cxx         |   11 
 svx/source/sdr/primitive2d/sdrattributecreator.cxx        |  317 -----
 svx/source/sidebar/area/AreaPropertyPanelBase.cxx         |   24 
 svx/source/sidebar/area/AreaTransparencyGradientPopup.cxx |   13 
 svx/source/svdraw/gradtrns.cxx                            |    8 
 svx/source/svdraw/gradtrns.hxx                            |    5 
 svx/source/svdraw/svdetc.cxx                              |    3 
 svx/source/svdraw/svdfmtf.cxx                             |   31 
 svx/source/svdraw/svdmrkv.cxx                             |    3 
 svx/source/svdraw/svdoashp.cxx                            |    4 
 svx/source/tbxctrls/fillctrl.cxx                          |    4 
 svx/source/unodraw/XPropertyTable.cxx                     |   54 
 svx/source/unodraw/unobrushitemhelper.cxx                 |    8 
 svx/source/xoutdev/xattr.cxx                              |  313 -----
 svx/source/xoutdev/xpool.cxx                              |    8 
 svx/source/xoutdev/xtabgrdt.cxx                           |   21 
 svx/source/xoutdev/xtable.cxx                             |    2 
 sw/inc/pch/precompiled_msword.hxx                         |    1 
 sw/inc/pch/precompiled_sw.hxx                             |    1 
 sw/inc/pch/precompiled_swui.hxx                           |    1 
 sw/qa/extras/odfexport/odfexport.cxx                      |    5 
 sw/qa/extras/ooxmlexport/ooxmlexport2.cxx                 |    5 
 sw/qa/extras/rtfexport/rtfexport.cxx                      |    7 
 sw/source/core/unocore/unoframe.cxx                       |    8 
 sw/source/filter/ww8/docxattributeoutput.cxx              |    2 
 sw/source/filter/ww8/rtfattributeoutput.cxx               |    4 
 sw/source/uibase/docvw/HeaderFooterWin.cxx                |    2 
 sw/source/uibase/docvw/ShadowOverlayObject.cxx            |    6 
 sw/source/uibase/shells/drawdlg.cxx                       |    4 
 sw/source/uibase/sidebar/PageStylesPanel.cxx              |   14 
 sw/source/uibase/sidebar/PageStylesPanel.hxx              |    2 
 sw/source/uibase/uiview/viewtab.cxx                       |    4 
 86 files changed, 1774 insertions(+), 1993 deletions(-)

New commits:
commit 4249e57b9fff2a66cb1fb1757154f4a98379be68
Author:     Armin Le Grand (allotropia) <armin.le.grand.ext...@allotropia.de>
AuthorDate: Tue May 16 15:59:42 2023 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Sun May 21 15:00:00 2023 +0200

    MCGR: Adaptions to WriteGradientFill and BGradient
    
    Added code to make WriteGradientFill directly use the
    available BGradient implementation. The goal is to
    never directly work on awt::Gradient2, but use
    BGradient & it's tooling methods.
    
    Added constructors and tooling to BGradient and
    BColorStops to make that easier (single line
    conversions between uno::Any, basesgfx classes
    and awt:: incarnations). Directly handle uno::Any
    and awt:: classes, changed stuff to make use of
    this.
    
    Change-Id: I083a323b9efee8ca4f3becb2966aac0a294b9a60
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151842
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <armin.le.gr...@me.com>

diff --git a/basegfx/source/tools/bgradient.cxx 
b/basegfx/source/tools/bgradient.cxx
index 7cb1ed85e859..1499b0c682fe 100644
--- a/basegfx/source/tools/bgradient.cxx
+++ b/basegfx/source/tools/bgradient.cxx
@@ -94,10 +94,12 @@ BColorStops::BColorStops(const css::awt::ColorStopSequence& 
rColorStops)
 
 BColorStops::BColorStops(const css::uno::Any& rVal)
 {
-    css::awt::Gradient2 aGradient2;
-    if (rVal >>= aGradient2)
+    if (rVal.has<css::awt::ColorStopSequence>())
     {
-        setColorStopSequence(aGradient2.ColorStops);
+        // we can use awt::ColorStopSequence
+        css::awt::ColorStopSequence aColorStopSequence;
+        rVal >>= aColorStopSequence;
+        setColorStopSequence(aColorStopSequence);
     }
 }
 
@@ -627,7 +629,7 @@ BGradient::BGradient(const basegfx::BColorStops& 
rColorStops, css::awt::Gradient
     SetColorStops(aColorStops);
 }
 
-BGradient::BGradient(const css::awt::Gradient2& rGradient2)
+void BGradient::setGradient2(const css::awt::Gradient2& rGradient2)
 {
     // set values
     SetGradientStyle(rGradient2.Style);
@@ -640,10 +642,24 @@ BGradient::BGradient(const css::awt::Gradient2& 
rGradient2)
     SetSteps(rGradient2.StepCount);
 
     // set ColorStops
-    aColorStops = BColorStops(rGradient2.ColorStops);
-    aColorStops.sortAndCorrect();
+    if (rGradient2.ColorStops.hasElements())
+    {
+        // if we have a awt::ColorStopSequence, use it
+        aColorStops = BColorStops(rGradient2.ColorStops);
+        aColorStops.sortAndCorrect();
+    }
+    else
+    {
+        // if not, for compatibility, use StartColor/EndColor
+        aColorStops = BColorStops{
+            BColorStop(0.0, 
ColorToBColorConverter(rGradient2.StartColor).getBColor()),
+            BColorStop(1.0, 
ColorToBColorConverter(rGradient2.EndColor).getBColor())
+        };
+    }
 }
 
+BGradient::BGradient(const css::awt::Gradient2& rGradient2) { 
setGradient2(rGradient2); }
+
 BGradient::BGradient(const css::uno::Any& rVal)
     : BGradient()
 {
@@ -653,19 +669,7 @@ BGradient::BGradient(const css::uno::Any& rVal)
         css::awt::Gradient2 aGradient2;
         rVal >>= aGradient2;
 
-        // set values
-        SetGradientStyle(aGradient2.Style);
-        SetAngle(Degree10(aGradient2.Angle));
-        SetBorder(aGradient2.Border);
-        SetXOffset(aGradient2.XOffset);
-        SetYOffset(aGradient2.YOffset);
-        SetStartIntens(aGradient2.StartIntensity);
-        SetEndIntens(aGradient2.EndIntensity);
-        SetSteps(aGradient2.StepCount);
-
-        // set ColorStops
-        aColorStops = BColorStops(aGradient2.ColorStops);
-        aColorStops.sortAndCorrect();
+        setGradient2(aGradient2);
     }
     else if (rVal.has<css::awt::Gradient>())
     {
diff --git a/basegfx/source/tools/gradienttools.cxx 
b/basegfx/source/tools/gradienttools.cxx
index c909108932cc..2cc455aa0342 100644
--- a/basegfx/source/tools/gradienttools.cxx
+++ b/basegfx/source/tools/gradienttools.cxx
@@ -265,47 +265,6 @@ namespace basegfx
 
     namespace utils
     {
-        /// Tooling method to fill awt::Gradient2 from data contained in the 
given Any
-        bool fillGradient2FromAny(css::awt::Gradient2& rGradient, const 
css::uno::Any& rVal)
-        {
-            bool bRetval(false);
-
-            if (rVal.has< css::awt::Gradient2 >())
-            {
-                // we can use awt::Gradient2 directly
-                bRetval = (rVal >>= rGradient);
-            }
-            else if (rVal.has< css::awt::Gradient >())
-            {
-                // 1st get awt::Gradient
-                css::awt::Gradient aTmp;
-
-                if (rVal >>= aTmp)
-                {
-                    // copy all awt::Gradient data to awt::Gradient2
-                    rGradient.Style = aTmp.Style;
-                    rGradient.StartColor = aTmp.StartColor;
-                    rGradient.EndColor = aTmp.EndColor;
-                    rGradient.Angle = aTmp.Angle;
-                    rGradient.Border = aTmp.Border;
-                    rGradient.XOffset = aTmp.XOffset;
-                    rGradient.YOffset = aTmp.YOffset;
-                    rGradient.StartIntensity = aTmp.StartIntensity;
-                    rGradient.EndIntensity = aTmp.EndIntensity;
-                    rGradient.StepCount = aTmp.StepCount;
-
-                    // complete data by creating ColorStops for awt::Gradient2
-                    const BColorStops aTempColorStops {
-                        BColorStop(0.0, 
ColorToBColorConverter(aTmp.StartColor).getBColor()),
-                        BColorStop(1.0, 
ColorToBColorConverter(aTmp.EndColor).getBColor()) };
-                    rGradient.ColorStops = 
aTempColorStops.getAsColorStopSequence();
-                    bRetval = true;
-                }
-            }
-
-            return bRetval;
-        }
-
         /* Tooling method to extract data from given awt::Gradient2
            to ColorStops, doing some corrections, partitally based
            on given SingleColor.
@@ -321,11 +280,11 @@ namespace basegfx
              directly
         */
         void prepareColorStops(
-            const com::sun::star::awt::Gradient2& rGradient,
+            const basegfx::BGradient& rGradient,
             BColorStops& rColorStops,
             BColor& rSingleColor)
         {
-            rColorStops = BColorStops(rGradient.ColorStops);
+            rColorStops = rGradient.GetColorStops();
 
             if (rColorStops.isSingleColor(rSingleColor))
             {
@@ -335,12 +294,12 @@ namespace basegfx
                 return;
             }
 
-            if (rGradient.StartIntensity != 100 || rGradient.EndIntensity != 
100)
+            if (100 != rGradient.GetStartIntens() || 100 != 
rGradient.GetEndIntens())
             {
                 // apply 'old' blend stuff, blend against black
                 rColorStops.blendToIntensity(
-                    rGradient.StartIntensity * 0.01,
-                    rGradient.EndIntensity * 0.01,
+                    rGradient.GetStartIntens() * 0.01,
+                    rGradient.GetEndIntens() * 0.01,
                     basegfx::BColor()); // COL_BLACK
 
                 // can lead to single color (e.g. both zero, so all black),
@@ -352,18 +311,18 @@ namespace basegfx
                 }
             }
 
-            if (rGradient.Border != 0)
+            if (0 != rGradient.GetBorder())
             {
                 // apply Border if set
                 // NOTE: no new start node is added. The new ColorStop
                 //       mechanism does not need entries at 0.0 and 1.0.
                 //       In case this is needed, do that in the caller
-                const double fFactor(rGradient.Border * 0.01);
+                const double fFactor(rGradient.GetBorder() * 0.01);
                 BColorStops aNewStops;
 
                 for (const auto& candidate : rColorStops)
                 {
-                    if (css::awt::GradientStyle_AXIAL == rGradient.Style)
+                    if (css::awt::GradientStyle_AXIAL == 
rGradient.GetGradientStyle())
                     {
                         // for axial add the 'gap' at the start due to reverse 
used gradient
                         aNewStops.emplace_back((1.0 - fFactor) * 
candidate.getStopOffset(), candidate.getStopColor());
diff --git a/include/basegfx/utils/bgradient.hxx 
b/include/basegfx/utils/bgradient.hxx
index 37de614faba7..4f85ed85a407 100644
--- a/include/basegfx/utils/bgradient.hxx
+++ b/include/basegfx/utils/bgradient.hxx
@@ -135,6 +135,8 @@ public:
     {
     }
     BColorStops(const css::awt::ColorStopSequence& rColorStops);
+
+    // needs true == rVal.has<css::awt::ColorStopSequence>()
     BColorStops(const css::uno::Any& rVal);
 
     // constuctor with two colors to explicitly create a
@@ -265,6 +267,7 @@ public:
 
 class BASEGFX_DLLPUBLIC BGradient final
 {
+private:
     css::awt::GradientStyle eStyle;
 
     // MCGS: ColorStops in the range [0.0 .. 1.0], including 
StartColor/EndColor
@@ -279,6 +282,7 @@ class BASEGFX_DLLPUBLIC BGradient final
     sal_uInt16 nStepCount;
 
     static std::string GradientStyleToString(css::awt::GradientStyle eStyle);
+    void setGradient2(const css::awt::Gradient2& rGradient2);
 
 public:
     BGradient();
@@ -288,6 +292,8 @@ public:
               sal_uInt16 nBorder = 0, sal_uInt16 nStartIntens = 100, 
sal_uInt16 nEndIntens = 100,
               sal_uInt16 nSteps = 0);
     BGradient(const css::awt::Gradient2& rGradient2);
+
+    // needs true == (rVal.has<css::awt::Gradient>() || 
rVal.has<css::awt::Gradient2>())
     BGradient(const css::uno::Any& rVal);
 
     bool operator==(const BGradient& rGradient) const;
diff --git a/include/basegfx/utils/gradienttools.hxx 
b/include/basegfx/utils/gradienttools.hxx
index 02d9b4ca68c8..50d58e8a39c0 100644
--- a/include/basegfx/utils/gradienttools.hxx
+++ b/include/basegfx/utils/gradienttools.hxx
@@ -186,11 +186,6 @@ namespace basegfx
 
     namespace utils
     {
-        /// Tooling method to fill awt::Gradient2 from data contained in the 
given Any
-        BASEGFX_DLLPUBLIC bool fillGradient2FromAny(
-            com::sun::star::awt::Gradient2& rGradient,
-            const com::sun::star::uno::Any& rVal);
-
         /* Tooling method to extract data from given awt::Gradient2
            to ColorStops, doing some corrections, partitally based
            on given SingleColor.
@@ -206,7 +201,7 @@ namespace basegfx
              directly
         */
         BASEGFX_DLLPUBLIC void prepareColorStops(
-            const com::sun::star::awt::Gradient2& rGradient,
+            const basegfx::BGradient& rGradient,
             BColorStops& rColorStops,
             BColor& rSingleColor);
 
diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index f7bd91669a1d..cdfb31af9c7c 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -49,6 +49,7 @@
 #include <tools/color.hxx>
 #include <vcl/mapmod.hxx>
 #include <svx/EnhancedCustomShape2d.hxx>
+#include <basegfx/utils/bgradient.hxx>
 
 class Graphic;
 class SdrObjCustomShape;
@@ -368,16 +369,16 @@ public:
     void WriteGradientFill( const css::uno::Reference< 
css::beans::XPropertySet >& rXPropSet );
 
     /* New API for WriteGradientFill:
-       If a awt::Gradient2 is given, it will be used. Else, the 'Fix' entry 
will be used for
+       If a BGradient is given, it will be used. Else, the 'Fix' entry will be 
used for
        Color or Transparency. That way, less 
Pseudo(Color|Transparency)Gradients have to be
        created at caller side.
        NOTE: Giving no Gradient at all (both nullptr) is an error.
     */
     void WriteGradientFill(
-        const css::awt::Gradient2* pColorGradient, sal_Int32 nFixColor,
-        const css::awt::Gradient2* pTransparenceGradient, double 
fFixTransparence = 0.0);
+        const basegfx::BGradient* pColorGradient, sal_Int32 nFixColor,
+        const basegfx::BGradient* pTransparenceGradient, double 
fFixTransparence = 0.0);
 
-    void WriteGrabBagGradientFill( const css::uno::Sequence< 
css::beans::PropertyValue >& aGradientStops, const css::awt::Gradient2& 
rGradient);
+    void WriteGrabBagGradientFill( const css::uno::Sequence< 
css::beans::PropertyValue >& aGradientStops, const basegfx::BGradient& 
rGradient);
 
     void WriteBlipOrNormalFill( const css::uno::Reference< 
css::beans::XPropertySet >& rXPropSet,
             const OUString& rURLPropName );
diff --git a/oox/source/export/chartexport.cxx 
b/oox/source/export/chartexport.cxx
index 359edfcb081b..e3704845407a 100644
--- a/oox/source/export/chartexport.cxx
+++ b/oox/source/export/chartexport.cxx
@@ -1903,37 +1903,26 @@ void ChartExport::exportSolidFill(const Reference< 
XPropertySet >& xPropSet)
     }
     // OOXML has no separate transparence gradient but uses transparency in 
the gradient stops.
     // So we merge transparency and color and use gradient fill in such case.
-    awt::Gradient2 aTransparenceGradient;
+    basegfx::BGradient aTransparenceGradient;
     bool bNeedGradientFill(false);
     OUString sFillTransparenceGradientName;
+
     if (GetProperty(xPropSet, "FillTransparenceGradientName")
         && (mAny >>= sFillTransparenceGradientName)
         && !sFillTransparenceGradientName.isEmpty())
     {
         uno::Reference< lang::XMultiServiceFactory > xFact( getModel(), 
uno::UNO_QUERY );
         uno::Reference< container::XNameAccess > 
xTransparenceGradient(xFact->createInstance("com.sun.star.drawing.TransparencyGradientTable"),
 uno::UNO_QUERY);
-        uno::Any rTransparenceValue = 
xTransparenceGradient->getByName(sFillTransparenceGradientName);
+        const uno::Any rTransparenceValue = 
xTransparenceGradient->getByName(sFillTransparenceGradientName);
 
-        if (basegfx::utils::fillGradient2FromAny(aTransparenceGradient, 
rTransparenceValue))
-        {
-            const basegfx::BColorStops aColorStops(rTransparenceValue);
-            basegfx::BColor aSingleColor;
-            bNeedGradientFill = !aColorStops.isSingleColor(aSingleColor);
-        }
+        aTransparenceGradient = basegfx::BGradient(rTransparenceValue);
+        basegfx::BColor aSingleColor;
+        bNeedGradientFill = 
!aTransparenceGradient.GetColorStops().isSingleColor(aSingleColor);
 
-        if (!bNeedGradientFill && 0 != aTransparenceGradient.StartColor)
+        if (!bNeedGradientFill)
         {
-            // Our alpha is a gray color value.
-            sal_uInt8 nRed(0);
-
-            if (aTransparenceGradient.ColorStops.getLength() > 0)
-            {
-                nRed = 
static_cast<sal_uInt8>(aTransparenceGradient.ColorStops[0].StopColor.Red * 
255.0);
-            }
-            else
-            {
-                nRed = ::Color(ColorTransparency, 
aTransparenceGradient.StartColor).GetRed();
-            }
+            // Our alpha is a single gray color value.
+            const sal_uInt8 nRed(aSingleColor.getRed() * 255.0);
 
             // drawingML alpha is a percentage on a 0..100000 scale.
             nAlpha = (255 - nRed) * oox::drawingml::MAX_PERCENT / 255;
@@ -2012,19 +2001,23 @@ void ChartExport::exportGradientFill( const Reference< 
XPropertySet >& xPropSet
     try
     {
         uno::Reference< container::XNameAccess > xGradient( 
xFact->createInstance("com.sun.star.drawing.GradientTable"), uno::UNO_QUERY );
-        uno::Any rGradientValue = xGradient->getByName( sFillGradientName );
-        awt::Gradient2 aGradient;
+        const uno::Any rGradientValue(xGradient->getByName( sFillGradientName 
));
+        const basegfx::BGradient aGradient(rGradientValue);
+        basegfx::BColor aSingleColor;
 
-        if (basegfx::utils::fillGradient2FromAny(aGradient, rGradientValue))
+        if (!aGradient.GetColorStops().isSingleColor(aSingleColor))
         {
-            awt::Gradient2 aTransparenceGradient;
+            basegfx::BGradient aTransparenceGradient;
             mpFS->startElementNS(XML_a, XML_gradFill);
             OUString sFillTransparenceGradientName;
+
             if( (xPropSet->getPropertyValue("FillTransparenceGradientName") 
>>= sFillTransparenceGradientName) && !sFillTransparenceGradientName.isEmpty())
             {
                 uno::Reference< container::XNameAccess > 
xTransparenceGradient(xFact->createInstance("com.sun.star.drawing.TransparencyGradientTable"),
 uno::UNO_QUERY);
-                uno::Any rTransparenceValue = 
xTransparenceGradient->getByName(sFillTransparenceGradientName);
-                basegfx::utils::fillGradient2FromAny(aTransparenceGradient, 
rTransparenceValue);
+                const uno::Any 
rTransparenceValue(xTransparenceGradient->getByName(sFillTransparenceGradientName));
+
+                aTransparenceGradient = basegfx::BGradient(rTransparenceValue);
+
                 WriteGradientFill(&aGradient, 0, &aTransparenceGradient);
             }
             else if (GetProperty(xPropSet, "FillTransparence") )
@@ -2038,7 +2031,7 @@ void ChartExport::exportGradientFill( const Reference< 
XPropertySet >& xPropSet
             }
             else
             {
-                WriteGradientFill(&aGradient, 0, &aTransparenceGradient);
+                WriteGradientFill(&aGradient, 0, nullptr);
             }
 
             mpFS->endElementNS(XML_a, XML_gradFill);
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 2f2aa2558f21..8646b056ff66 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -211,7 +211,7 @@ static css::uno::Any getLineDash( const 
css::uno::Reference<css::frame::XModel>&
 
 namespace
 {
-void WriteGradientPath(const awt::Gradient2& rGradient, const FSHelperPtr& 
pFS, const bool bCircle)
+void WriteGradientPath(const basegfx::BGradient& rBGradient, const 
FSHelperPtr& pFS, const bool bCircle)
 {
     pFS->startElementNS(XML_a, XML_path, XML_path, bCircle ? "circle" : 
"rect");
 
@@ -221,13 +221,13 @@ void WriteGradientPath(const awt::Gradient2& rGradient, 
const FSHelperPtr& pFS,
     // edge of the tile rectangle and 100% means the center of it.
     rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList(
         sax_fastparser::FastSerializerHelper::createAttrList());
-    sal_Int32 nLeftPercent = rGradient.XOffset;
+    sal_Int32 nLeftPercent = rBGradient.GetXOffset();
     pAttributeList->add(XML_l, OString::number(nLeftPercent * PER_PERCENT));
-    sal_Int32 nTopPercent = rGradient.YOffset;
+    sal_Int32 nTopPercent = rBGradient.GetYOffset();
     pAttributeList->add(XML_t, OString::number(nTopPercent * PER_PERCENT));
-    sal_Int32 nRightPercent = 100 - rGradient.XOffset;
+    sal_Int32 nRightPercent = 100 - rBGradient.GetXOffset();
     pAttributeList->add(XML_r, OString::number(nRightPercent * PER_PERCENT));
-    sal_Int32 nBottomPercent = 100 - rGradient.YOffset;
+    sal_Int32 nBottomPercent = 100 - rBGradient.GetYOffset();
     pAttributeList->add(XML_b, OString::number(nBottomPercent * PER_PERCENT));
     pFS->singleElementNS(XML_a, XML_fillToRect, pAttributeList);
 
@@ -469,31 +469,19 @@ void DrawingML::WriteSolidFill( const Reference< 
XPropertySet >& rXPropSet )
 
     // OOXML has no separate transparence gradient but uses transparency in 
the gradient stops.
     // So we merge transparency and color and use gradient fill in such case.
-    awt::Gradient2 aTransparenceGradient;
+    basegfx::BGradient aTransparenceGradient;
     bool bNeedGradientFill(false);
 
     if (GetProperty(rXPropSet, "FillTransparenceGradient"))
     {
-        if (basegfx::utils::fillGradient2FromAny(aTransparenceGradient, mAny))
-        {
-            const basegfx::BColorStops aColorStops(mAny);
-            basegfx::BColor aSingleColor;
-            bNeedGradientFill = !aColorStops.isSingleColor(aSingleColor);
-        }
+        aTransparenceGradient = basegfx::BGradient(mAny);
+        basegfx::BColor aSingleColor;
+        bNeedGradientFill = 
!aTransparenceGradient.GetColorStops().isSingleColor(aSingleColor);
 
-        if (!bNeedGradientFill && 0 != aTransparenceGradient.StartColor)
+        if (!bNeedGradientFill && aSingleColor != basegfx::BColor())
         {
             // Our alpha is a gray color value.
-            sal_uInt8 nRed(0);
-
-            if (aTransparenceGradient.ColorStops.getLength() > 0)
-            {
-                nRed = 
static_cast<sal_uInt8>(aTransparenceGradient.ColorStops[0].StopColor.Red * 
255.0);
-            }
-            else
-            {
-                nRed = ::Color(ColorTransparency, 
aTransparenceGradient.StartColor).GetRed();
-            }
+            const sal_uInt8 nRed(aSingleColor.getRed() * 255.0);
 
             // drawingML alpha is a percentage on a 0..100000 scale.
             nAlpha = (255 - nRed) * oox::drawingml::MAX_PERCENT / 255;
@@ -591,57 +579,16 @@ void DrawingML::WriteGradientStop(double fOffset, const 
basegfx::BColor& rColor,
         | ( ( ( ( ( nColor & 0xff0000 ) >> 8 ) * nIntensity ) / 100 ) << 8 ));
 }
 
-bool DrawingML::EqualGradients( const awt::Gradient2& rGradient1, const 
awt::Gradient2& rGradient2 )
-{
-    if (rGradient1.Style == rGradient2.Style &&
-            rGradient1.StartColor == rGradient2.StartColor &&
-            rGradient1.EndColor == rGradient2.EndColor &&
-            rGradient1.Angle == rGradient2.Angle &&
-            rGradient1.Border == rGradient2.Border &&
-            rGradient1.XOffset == rGradient2.XOffset &&
-            rGradient1.YOffset == rGradient2.YOffset &&
-            rGradient1.StartIntensity == rGradient2.StartIntensity &&
-            rGradient1.EndIntensity == rGradient2.EndIntensity &&
-            rGradient1.StepCount == rGradient2.StepCount &&
-            rGradient1.ColorStops.getLength() == 
rGradient2.ColorStops.getLength())
-    {
-        const sal_Int32 nLen(rGradient1.ColorStops.getLength());
-
-        if (0 == nLen)
-            return true;
-
-        const awt::ColorStop* 
pColorStop1(rGradient1.ColorStops.getConstArray());
-        const awt::ColorStop* 
pColorStop2(rGradient2.ColorStops.getConstArray());
-
-        for (sal_Int32 a(0); a < nLen; a++, pColorStop1++, pColorStop2++)
-        {
-            if (pColorStop1->StopOffset != pColorStop2->StopOffset ||
-                pColorStop1->StopColor.Red != pColorStop2->StopColor.Red ||
-                pColorStop1->StopColor.Green != pColorStop2->StopColor.Green ||
-                pColorStop1->StopColor.Blue != pColorStop2->StopColor.Blue)
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    return false;
-}
-
 void DrawingML::WriteGradientFill( const Reference< XPropertySet >& rXPropSet )
 {
-    awt::Gradient2 aGradient;
-
     if (!GetProperty(rXPropSet, "FillGradient"))
         return;
 
-    // use fillGradient2FromAny to evtl. take care of Gradient/Gradient2
-    basegfx::utils::fillGradient2FromAny(aGradient, mAny);
+    // use BGradient constructor directly, it will take care of 
Gradient/Gradient2
+    basegfx::BGradient aGradient(mAny);
 
     // get InteropGrabBag and search the relevant attributes
-    awt::Gradient2 aOriginalGradient;
+    basegfx::BGradient aOriginalGradient;
     Sequence< PropertyValue > aGradientStops;
     if ( GetProperty( rXPropSet, "InteropGrabBag" ) )
     {
@@ -651,14 +598,14 @@ void DrawingML::WriteGradientFill( const Reference< 
XPropertySet >& rXPropSet )
             if( rProp.Name == "GradFillDefinition" )
                 rProp.Value >>= aGradientStops;
             else if( rProp.Name == "OriginalGradFill" )
-                // use fillGradient2FromAny to evtl. take care of 
Gradient/Gradient2
-                basegfx::utils::fillGradient2FromAny(aOriginalGradient, 
rProp.Value);
+                // use BGradient constructor direcly, it will take care of 
Gradient/Gradient2
+                aOriginalGradient = basegfx::BGradient(rProp.Value);
     }
 
     // check if an ooxml gradient had been imported and if the user has 
modified it
     // Gradient grab-bag depends on theme grab-bag, which is implemented
     // only for DOCX.
-    if( EqualGradients( aOriginalGradient, aGradient ) && GetDocumentType() == 
DOCUMENT_DOCX)
+    if (aOriginalGradient == aGradient && GetDocumentType() == DOCUMENT_DOCX)
     {
         // If we have no gradient stops that means original gradient were 
defined by a theme.
         if( aGradientStops.hasElements() )
@@ -672,8 +619,8 @@ void DrawingML::WriteGradientFill( const Reference< 
XPropertySet >& rXPropSet )
     {
         mpFS->startElementNS(XML_a, XML_gradFill, XML_rotWithShape, "0");
 
-        awt::Gradient2 aTransparenceGradient;
-        awt::Gradient2* pTransparenceGradient(nullptr);
+        basegfx::BGradient aTransparenceGradient;
+        basegfx::BGradient* pTransparenceGradient(nullptr);
         double fTransparency(0.0);
         OUString sFillTransparenceGradientName;
 
@@ -682,7 +629,9 @@ void DrawingML::WriteGradientFill( const Reference< 
XPropertySet >& rXPropSet )
             && !sFillTransparenceGradientName.isEmpty())
         {
             if (GetProperty(rXPropSet, "FillTransparenceGradient"))
-                aTransparenceGradient = *o3tl::doAccess<awt::Gradient2>(mAny);
+            {
+                aTransparenceGradient = basegfx::BGradient(mAny);
+            }
 
             pTransparenceGradient = &aTransparenceGradient;
         }
@@ -702,7 +651,7 @@ void DrawingML::WriteGradientFill( const Reference< 
XPropertySet >& rXPropSet )
     }
 }
 
-void DrawingML::WriteGrabBagGradientFill( const Sequence< PropertyValue >& 
aGradientStops, const awt::Gradient2& rGradient )
+void DrawingML::WriteGrabBagGradientFill( const Sequence< PropertyValue >& 
aGradientStops, const basegfx::BGradient& rBGradient )
 {
     // write back the original gradient
     mpFS->startElementNS(XML_a, XML_gsLst);
@@ -748,44 +697,46 @@ void DrawingML::WriteGrabBagGradientFill( const Sequence< 
PropertyValue >& aGrad
     }
     mpFS->endElementNS( XML_a, XML_gsLst );
 
-    switch (rGradient.Style)
+    switch (rBGradient.GetGradientStyle())
     {
         default:
+        {
+            const sal_Int16 nAngle(rBGradient.GetAngle());
             mpFS->singleElementNS(
                 XML_a, XML_lin, XML_ang,
-                OString::number(((3600 - rGradient.Angle + 900) * 6000) % 
21600000));
+                OString::number(((3600 - static_cast<sal_Int32>(nAngle) + 900) 
* 6000) % 21600000));
             break;
+        }
         case awt::GradientStyle_RADIAL:
-            WriteGradientPath(rGradient, mpFS, true);
+        {
+            WriteGradientPath(rBGradient, mpFS, true);
             break;
+        }
     }
 }
 
 void DrawingML::WriteGradientFill(
-    const awt::Gradient2* pColorGradient, sal_Int32 nFixColor,
-    const awt::Gradient2* pTransparenceGradient, double fFixTransparence)
+    const basegfx::BGradient* pColorGradient, sal_Int32 nFixColor,
+    const basegfx::BGradient* pTransparenceGradient, double fFixTransparence)
 {
     basegfx::BColorStops aColorStops;
     basegfx::BColorStops aAlphaStops;
     basegfx::BColor aSingleColor(::Color(ColorTransparency, 
nFixColor).getBColor());
     basegfx::BColor aSingleAlpha(fFixTransparence);
-    awt::Gradient2 aGradient;
+    const basegfx::BGradient* pGradient(pColorGradient);
 
     if (nullptr != pColorGradient)
     {
-        // remember basic Gradient definition to use
-        aGradient = *pColorGradient;
-
-        // extract and corrrect/process ColorStops
+        // extract and correct/process ColorStops
         basegfx::utils::prepareColorStops(*pColorGradient, aColorStops, 
aSingleColor);
     }
 
     if (nullptr != pTransparenceGradient)
     {
         // remember basic Gradient definition to use
-        if (nullptr == pColorGradient)
+        if (nullptr == pGradient)
         {
-            aGradient = *pTransparenceGradient;
+            pGradient = pTransparenceGradient;
         }
 
         // extract and corrrect/process AlphaStops
@@ -797,10 +748,12 @@ void DrawingML::WriteGradientFill(
     // method (at import time) will be exported again
     basegfx::utils::synchronizeColorStops(aColorStops, aAlphaStops, 
aSingleColor, aSingleAlpha);
 
-    if (aColorStops.size() != aAlphaStops.size())
+    if (aColorStops.size() != aAlphaStops.size() || nullptr == pGradient)
     {
         // this is an error - synchronizeColorStops above *has* to create that
-        // state, see desciption there (!)
+        // state, see description there (!)
+        // also an error - see comment in header - is to give neither 
pColorGradient
+        // nor pTransparenceGradient
         assert(false && "oox::WriteGradientFill: non-synchronized gradients 
(!)");
         return;
     }
@@ -809,7 +762,7 @@ void DrawingML::WriteGradientFill(
     bool bLinear(false);
     bool bAxial(false);
 
-    switch (aGradient.Style)
+    switch (pGradient->GetGradientStyle())
     {
         case awt::GradientStyle_LINEAR:
         {
@@ -902,18 +855,19 @@ void DrawingML::WriteGradientFill(
     if (bLinear || bAxial)
     {
         // cases where gradient rotation has to be exported
+        const sal_Int16 nAngle(pGradient->GetAngle());
         mpFS->singleElementNS(
             XML_a, XML_lin, XML_ang,
-            OString::number(((3600 - aGradient.Angle + 900) * 6000) % 
21600000));
+            OString::number(((3600 - static_cast<sal_Int32>(nAngle) + 900) * 
6000) % 21600000));
     }
 
     if (bRadialOrEllipticalOrRectOrSquare)
     {
         // cases where gradient path has to be exported
-        const bool bCircle(aGradient.Style == awt::GradientStyle_RADIAL ||
-            aGradient.Style == awt::GradientStyle_ELLIPTICAL);
+        const bool bCircle(pGradient->GetGradientStyle() == 
awt::GradientStyle_RADIAL ||
+            pGradient->GetGradientStyle() == awt::GradientStyle_ELLIPTICAL);
 
-        WriteGradientPath(aGradient, mpFS, bCircle);
+        WriteGradientPath(*pGradient, mpFS, bCircle);
     }
 }
 
diff --git a/svx/source/unodraw/XPropertyTable.cxx 
b/svx/source/unodraw/XPropertyTable.cxx
index 8eb7401e0c36..3defe221d1f5 100644
--- a/svx/source/unodraw/XPropertyTable.cxx
+++ b/svx/source/unodraw/XPropertyTable.cxx
@@ -558,29 +558,10 @@ uno::Any SvxUnoXGradientTable::getAny( const 
XPropertyEntry* pEntry ) const noex
 
 std::unique_ptr<XPropertyEntry> SvxUnoXGradientTable::createEntry(const 
OUString& rName, const uno::Any& rAny) const
 {
-    awt::Gradient aGradient;
-    if(!(rAny >>= aGradient))
+    if (!rAny.has<css::awt::Gradient>() || !rAny.has<css::awt::Gradient2>())
         return std::unique_ptr<XPropertyEntry>();
 
-    basegfx::BGradient aBGradient(
-        basegfx::BColorStops(
-            Color(ColorTransparency, aGradient.StartColor).getBColor(),
-            Color(ColorTransparency, aGradient.EndColor).getBColor()));
-
-    aBGradient.SetGradientStyle( aGradient.Style );
-    aBGradient.SetAngle( Degree10(aGradient.Angle) );
-    aBGradient.SetBorder( aGradient.Border );
-    aBGradient.SetXOffset( aGradient.XOffset );
-    aBGradient.SetYOffset( aGradient.YOffset );
-    aBGradient.SetStartIntens( aGradient.StartIntensity );
-    aBGradient.SetEndIntens( aGradient.EndIntensity );
-    aBGradient.SetSteps( aGradient.StepCount );
-
-    // check if we have a awt::Gradient2 with a ColorStopSequence
-    const basegfx::BColorStops aColorStops(rAny);
-    if (!aColorStops.empty())
-        aBGradient.SetColorStops(aColorStops);
-
+    const basegfx::BGradient aBGradient(rAny);
     return std::make_unique<XGradientEntry>(aBGradient, rName);
 }
 
diff --git a/svx/source/xoutdev/xattr.cxx b/svx/source/xoutdev/xattr.cxx
index 9e9c1d74f59b..24807388535f 100644
--- a/svx/source/xoutdev/xattr.cxx
+++ b/svx/source/xoutdev/xattr.cxx
@@ -2151,37 +2151,6 @@ bool XFillGradientItem::GetPresentation
     return true;
 }
 
-namespace
-{
-    void fillXGradientFromAny(basegfx::BGradient& rBGradient, const 
css::uno::Any& rVal)
-    {
-        css::awt::Gradient aGradient;
-        if (!(rVal >>= aGradient))
-            return;
-
-        // for compatibility, read and set StartColor/EndColor
-        rBGradient.SetColorStops(
-            basegfx::BColorStops(
-                Color(ColorTransparency, aGradient.StartColor).getBColor(),
-                Color(ColorTransparency, aGradient.EndColor).getBColor()));
-
-        // set values
-        rBGradient.SetGradientStyle( aGradient.Style );
-        rBGradient.SetAngle( Degree10(aGradient.Angle) );
-        rBGradient.SetBorder( aGradient.Border );
-        rBGradient.SetXOffset( aGradient.XOffset );
-        rBGradient.SetYOffset( aGradient.YOffset );
-        rBGradient.SetStartIntens( aGradient.StartIntensity );
-        rBGradient.SetEndIntens( aGradient.EndIntensity );
-        rBGradient.SetSteps( aGradient.StepCount );
-
-        // check if we have a awt::Gradient2 with a ColorStopSequence
-        const basegfx::BColorStops aColorStops(rVal);
-        if (!aColorStops.empty())
-            rBGradient.SetColorStops(aColorStops);
-    }
-}
-
 bool XFillGradientItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) 
const
 {
     nMemberId &= ~CONVERT_TWIPS;
@@ -2270,10 +2239,9 @@ bool XFillGradientItem::PutValue( const css::uno::Any& 
rVal, sal_uInt8 nMemberId
 
                 SetName( aName );
 
-                if ( aGradientAny.hasValue() )
+                if (aGradientAny.hasValue() && 
(aGradientAny.has<css::awt::Gradient>() || 
aGradientAny.has<css::awt::Gradient2>()))
                 {
-                    basegfx::BGradient aBGradient;
-                    fillXGradientFromAny(aBGradient, aGradientAny);
+                    const basegfx::BGradient aBGradient(aGradientAny);
                     SetGradientValue(aBGradient);
                 }
 
@@ -2294,22 +2262,28 @@ bool XFillGradientItem::PutValue( const css::uno::Any& 
rVal, sal_uInt8 nMemberId
 
         case MID_FILLGRADIENT:
         {
-            basegfx::BGradient aBGradient;
-            fillXGradientFromAny(aBGradient, rVal);
-            SetGradientValue(aBGradient);
+            if (rVal.hasValue() && (rVal.has<css::awt::Gradient>() || 
rVal.has<css::awt::Gradient2>()))
+            {
+                const basegfx::BGradient aBGradient(rVal);
+                SetGradientValue(aBGradient);
+            }
+
             break;
         }
 
         case MID_GRADIENT_COLORSTOPSEQUENCE:
         {
-            // check if we have a awt::Gradient2 with a ColorStopSequence
-            const basegfx::BColorStops aColorStops(rVal);
-
-            if (!aColorStops.empty())
+            // check if we have a awt::ColorStopSequence
+            if (rVal.hasValue() && rVal.has<css::awt::ColorStopSequence>())
             {
-                basegfx::BGradient aBGradient(GetGradientValue());
-                aBGradient.SetColorStops(aColorStops);
-                SetGradientValue(aBGradient);
+                const basegfx::BColorStops aColorStops(rVal);
+
+                if (!aColorStops.empty())
+                {
+                    basegfx::BGradient aBGradient(GetGradientValue());
+                    aBGradient.SetColorStops(aColorStops);
+                    SetGradientValue(aBGradient);
+                }
             }
             break;
         }
commit b1e18601c6a8ff2a0b516b309739af1b233d013b
Author:     Armin Le Grand (allotropia) <armin.le.grand.ext...@allotropia.de>
AuthorDate: Fri May 12 15:32:51 2023 +0200
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Sun May 21 15:00:00 2023 +0200

    MCGR: consolidations/cleanups for changes so far
    
    Change-Id: I85cf40e4803b0485bb40349d8e81adc8123666c4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151706
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <armin.le.gr...@me.com>

diff --git a/basctl/inc/pch/precompiled_basctl.hxx 
b/basctl/inc/pch/precompiled_basctl.hxx
index 4f3566f3f6ea..257159149a3b 100644
--- a/basctl/inc/pch/precompiled_basctl.hxx
+++ b/basctl/inc/pch/precompiled_basctl.hxx
@@ -499,7 +499,6 @@
 #include <svx/svxdllapi.h>
 #include <svx/xdash.hxx>
 #include <svx/xdef.hxx>
-#include <svx/xgrad.hxx>
 #include <svx/xhatch.hxx>
 #include <svx/xpoly.hxx>
 #include <svx/xtable.hxx>
diff --git a/basegfx/Library_basegfx.mk b/basegfx/Library_basegfx.mk
index 2f9830d0dcfd..da257e2c9797 100644
--- a/basegfx/Library_basegfx.mk
+++ b/basegfx/Library_basegfx.mk
@@ -67,6 +67,7 @@ $(eval $(call gb_Library_add_exception_objects,basegfx,\
     basegfx/source/range/b3drange \
     basegfx/source/raster/rasterconvert3d \
     basegfx/source/tools/b2dclipstate \
+    basegfx/source/tools/bgradient \
     basegfx/source/tools/canvastools \
     basegfx/source/tools/gradienttools \
     basegfx/source/tools/keystoplerp \
diff --git a/basegfx/source/tools/bgradient.cxx 
b/basegfx/source/tools/bgradient.cxx
new file mode 100644
index 000000000000..7cb1ed85e859
--- /dev/null
+++ b/basegfx/source/tools/bgradient.cxx
@@ -0,0 +1,770 @@
+/* -*- 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/.
+ */
+
+#include <basegfx/utils/bgradient.hxx>
+#include <basegfx/utils/gradienttools.hxx>
+#include <com/sun/star/awt/Gradient2.hpp>
+#include <boost/property_tree/json_parser.hpp>
+#include <map>
+
+typedef std::map<OUString, OUString> StringMap;
+
+namespace
+{
+css::awt::GradientStyle lcl_getStyleFromString(std::u16string_view rStyle)
+{
+    if (rStyle == u"LINEAR")
+        return css::awt::GradientStyle_LINEAR;
+    else if (rStyle == u"AXIAL")
+        return css::awt::GradientStyle_AXIAL;
+    else if (rStyle == u"RADIAL")
+        return css::awt::GradientStyle_RADIAL;
+    else if (rStyle == u"ELLIPTICAL")
+        return css::awt::GradientStyle_ELLIPTICAL;
+    else if (rStyle == u"SQUARE")
+        return css::awt::GradientStyle_SQUARE;
+    else if (rStyle == u"RECT")
+        return css::awt::GradientStyle_RECT;
+
+    return css::awt::GradientStyle_LINEAR;
+}
+
+StringMap lcl_jsonToStringMap(std::u16string_view rJSON)
+{
+    StringMap aArgs;
+    if (rJSON.size() && rJSON[0] != '\0')
+    {
+        std::stringstream aStream(std::string(OUStringToOString(rJSON, 
RTL_TEXTENCODING_ASCII_US)));
+        boost::property_tree::ptree aTree;
+        boost::property_tree::read_json(aStream, aTree);
+
+        for (const auto& rPair : aTree)
+        {
+            aArgs[OUString::fromUtf8(rPair.first)]
+                = OUString::fromUtf8(rPair.second.get_value<std::string>("."));
+        }
+    }
+    return aArgs;
+}
+
+basegfx::BGradient lcl_buildGradientFromStringMap(StringMap& rMap)
+{
+    basegfx::BGradient aGradient(
+        
basegfx::BColorStops(ColorToBColorConverter(rMap["startcolor"].toInt32(16)).getBColor(),
+                             
ColorToBColorConverter(rMap["endcolor"].toInt32(16)).getBColor()));
+
+    aGradient.SetGradientStyle(lcl_getStyleFromString(rMap["style"]));
+    aGradient.SetAngle(Degree10(rMap["angle"].toInt32()));
+
+    return aGradient;
+}
+}
+
+namespace basegfx
+{
+void BColorStops::setColorStopSequence(const css::awt::ColorStopSequence& 
rColorStops)
+{
+    const sal_Int32 nLen(rColorStops.getLength());
+
+    if (0 != nLen)
+    {
+        // we have ColorStops
+        reserve(nLen);
+        const css::awt::ColorStop* 
pSourceColorStop(rColorStops.getConstArray());
+
+        for (sal_Int32 a(0); a < nLen; a++, pSourceColorStop++)
+        {
+            emplace_back(pSourceColorStop->StopOffset,
+                         BColor(pSourceColorStop->StopColor.Red, 
pSourceColorStop->StopColor.Green,
+                                pSourceColorStop->StopColor.Blue));
+        }
+    }
+}
+
+BColorStops::BColorStops(const css::awt::ColorStopSequence& rColorStops)
+{
+    setColorStopSequence(rColorStops);
+}
+
+BColorStops::BColorStops(const css::uno::Any& rVal)
+{
+    css::awt::Gradient2 aGradient2;
+    if (rVal >>= aGradient2)
+    {
+        setColorStopSequence(aGradient2.ColorStops);
+    }
+}
+
+// constuctor with two colors to explicitly create a
+// BColorStops for a single StartColor @0.0 & EndColor @1.0
+BColorStops::BColorStops(const BColor& rStart, const BColor& rEnd)
+{
+    emplace_back(0.0, rStart);
+    emplace_back(1.0, rEnd);
+}
+
+/* Helper to grep the correct ColorStop out of
+        ColorStops and interpolate as needed for given
+        relative value in fPosition in the range of [0.0 .. 1.0].
+        It also takes care of evtl. given RequestedSteps.
+    */
+BColor BColorStops::getInterpolatedBColor(double fPosition, sal_uInt32 
nRequestedSteps,
+                                          BColorStopRange& 
rLastColorStopRange) const
+{
+    // no color at all, done
+    if (empty())
+        return BColor();
+
+    // outside range -> at start
+    const double fMin(front().getStopOffset());
+    if (fPosition < fMin)
+        return front().getStopColor();
+
+    // outside range -> at end
+    const double fMax(back().getStopOffset());
+    if (fPosition > fMax)
+        return back().getStopColor();
+
+    // special case for the 'classic' case with just two colors:
+    // we can optimize that and keep the speed/resources low
+    // by avoiding some calculations and an O(log(N)) array access
+    if (2 == size())
+    {
+        // if same StopOffset use front color
+        if (fTools::equal(fMin, fMax))
+            return front().getStopColor();
+
+        const basegfx::BColor aCStart(front().getStopColor());
+        const basegfx::BColor aCEnd(back().getStopColor());
+
+        // if colors are equal just return one
+        if (aCStart == aCEnd)
+            return aCStart;
+
+        // calculate Steps
+        const sal_uInt32 nSteps(
+            basegfx::utils::calculateNumberOfSteps(nRequestedSteps, aCStart, 
aCEnd));
+
+        // we need to extend the interpolation to the local
+        // range of ColorStops. Despite having two ColorStops
+        // these are not necessarily at 0.0 and 1.0, so may be
+        // not the classical Start/EndColor (what is allowed)
+        fPosition = (fPosition - fMin) / (fMax - fMin);
+        return basegfx::interpolate(aCStart, aCEnd,
+                                    nSteps > 1 ? floor(fPosition * nSteps) / 
double(nSteps - 1)
+                                               : fPosition);
+    }
+
+    // check if we need to newly populate the needed interpolation data
+    // or if we can re-use from last time.
+    // If this scope is not entered, we do not need the binary search. It's
+    // only a single buffered entry, and only used when more than three
+    // ColorStops exist, but makes a huge difference compared with accessing
+    // the sorted ColorStop vector each time.
+    // NOTE: with this simple change I get very high hit rates, e.g. rotating
+    //       a donut with gradient test '1' hit rate is at 0.99909440357755486
+    if (rLastColorStopRange.mfOffsetStart == rLastColorStopRange.mfOffsetEnd
+        || fPosition < rLastColorStopRange.mfOffsetStart
+        || fPosition > rLastColorStopRange.mfOffsetEnd)
+    {
+        // access needed spot in sorted array using binary search
+        // NOTE: This *seems* slow(er) when developing compared to just
+        //       looping/accessing, but that's just due to the extensive
+        //       debug test code created by the stl. In a pro version,
+        //       all is good/fast as expected
+        const auto upperBound(std::upper_bound(begin(), end(), 
BColorStop(fPosition),
+                                               [](const BColorStop& x, const 
BColorStop& y) {
+                                                   return x.getStopOffset() < 
y.getStopOffset();
+                                               }));
+
+        // no upper bound, done
+        if (end() == upperBound)
+            return back().getStopColor();
+
+        // lower bound is one entry back, access that
+        const auto lowerBound(upperBound - 1);
+
+        // no lower bound, done
+        if (end() == lowerBound)
+            return back().getStopColor();
+
+        // we have lower and upper bound, get colors and offsets
+        rLastColorStopRange.maColorStart = lowerBound->getStopColor();
+        rLastColorStopRange.maColorEnd = upperBound->getStopColor();
+        rLastColorStopRange.mfOffsetStart = lowerBound->getStopOffset();
+        rLastColorStopRange.mfOffsetEnd = upperBound->getStopOffset();
+    }
+
+    // when there are just two color steps this cannot happen, but when using
+    // a range of colors this *may* be used inside the range to represent
+    // single-colored regions inside a ColorRange. Use that color & done
+    if (rLastColorStopRange.maColorStart == rLastColorStopRange.maColorEnd)
+        return rLastColorStopRange.maColorStart;
+
+    // calculate number of steps and adapted proportional
+    // range for scaler in [0.0 .. 1.0]
+    const double fAdaptedScaler(
+        (fPosition - rLastColorStopRange.mfOffsetStart)
+        / (rLastColorStopRange.mfOffsetEnd - 
rLastColorStopRange.mfOffsetStart));
+    const sal_uInt32 nSteps(basegfx::utils::calculateNumberOfSteps(
+        nRequestedSteps, rLastColorStopRange.maColorStart, 
rLastColorStopRange.maColorEnd));
+
+    // interpolate & evtl. apply steps
+    return interpolate(rLastColorStopRange.maColorStart, 
rLastColorStopRange.maColorEnd,
+                       nSteps > 1 ? floor(fAdaptedScaler * nSteps) / 
double(nSteps - 1)
+                                  : fAdaptedScaler);
+}
+
+/* Tooling method that allows to replace the StartColor in a
+        vector of ColorStops. A vector in 'ordered state' is expected,
+        so you may use/have used sortAndCorrect.
+        This method is for convenience & backwards compatibility, please
+        think about handling multi-colored gradients directly.
+    */
+void BColorStops::replaceStartColor(const BColor& rStart)
+{
+    BColorStops::iterator a1stNonStartColor(begin());
+
+    // search for highest existing non-StartColor - CAUTION,
+    // there might be none, one or multiple with StopOffset 0.0
+    while (a1stNonStartColor != end()
+           && basegfx::fTools::lessOrEqual(a1stNonStartColor->getStopOffset(), 
0.0))
+        a1stNonStartColor++;
+
+    // create new ColorStops by 1st adding new one and then all
+    // non-StartColor entries
+    BColorStops aNewColorStops;
+
+    aNewColorStops.reserve(size() + 1);
+    aNewColorStops.emplace_back(0.0, rStart);
+    aNewColorStops.insert(aNewColorStops.end(), a1stNonStartColor, end());
+
+    // assign & done
+    *this = aNewColorStops;
+}
+
+/* Tooling method that allows to replace the EndColor in a
+        vector of ColorStops. A vector in 'ordered state' is expected,
+        so you may use/have used sortAndCorrectColorStops.
+        This method is for convenience & backwards compatibility, please
+        think about handling multi-colored gradients directly.
+    */
+void BColorStops::replaceEndColor(const BColor& rEnd)
+{
+    // erase all evtl. existing EndColor(s)
+    while (!empty() && basegfx::fTools::moreOrEqual(back().getStopOffset(), 
1.0))
+        pop_back();
+
+    // add at the end of existing ColorStops
+    emplace_back(1.0, rEnd);
+}
+
+/* Tooling method to linearly blend the Colors contained in
+        a given ColorStop vector against a given Color using the
+        given intensity values.
+        The intensity values fStartIntensity, fEndIntensity are
+        in the range of [0.0 .. 1.0] and describe how much the
+        blend is supposed to be done at the start color position
+        and the end color position respectively, where 0.0 means
+        to fully use the given BlendColor, 1.0 means to not change
+        the existing color in the ColorStop.
+        Every color entry in the given ColorStop is blended
+        relative to it's StopPosition, interpolating the
+        given intensities with the range [0.0 .. 1.0] to do so.
+    */
+void BColorStops::blendToIntensity(double fStartIntensity, double 
fEndIntensity,
+                                   const BColor& rBlendColor)
+{
+    // no entries, done
+    if (empty())
+        return;
+
+    // correct intensities (maybe assert when input was wrong)
+    fStartIntensity = std::max(std::min(1.0, fStartIntensity), 0.0);
+    fEndIntensity = std::max(std::min(1.0, fEndIntensity), 0.0);
+
+    // all 100%, no real blend, done
+    if (basegfx::fTools::equal(fStartIntensity, 1.0) && 
basegfx::fTools::equal(fEndIntensity, 1.0))
+        return;
+
+    // blend relative to StopOffset position
+    for (auto& candidate : *this)
+    {
+        const double fOffset(candidate.getStopOffset());
+        const double fIntensity((fStartIntensity * (1.0 - fOffset)) + 
(fEndIntensity * fOffset));
+        candidate = basegfx::BColorStop(
+            fOffset, basegfx::interpolate(rBlendColor, 
candidate.getStopColor(), fIntensity));
+    }
+}
+
+/* Tooling method to guarantee sort and correctness for
+        the given ColorStops vector.
+        A vector fulfilling these conditions is called to be
+        in 'ordered state'.
+
+        At return, the following conditions are guaranteed:
+        - contains no ColorStops with offset < 0.0 (will
+            be removed)
+        - contains no ColorStops with offset > 1.0 (will
+            be removed)
+        - ColorStops with identical offsets are now allowed
+        - will be sorted from lowest offset to highest
+
+        Some more notes:
+        - It can happen that the result is empty
+        - It is allowed to have consecutive entries with
+            the same color, this represents single-color
+            regions inside the gradient
+        - A entry with 0.0 is not required or forced, so
+            no 'StartColor' is technically required
+        - A entry with 1.0 is not required or forced, so
+            no 'EndColor' is technically required
+
+        All this is done in one run (sort + O(N)) without
+        creating a copy of the data in any form
+    */
+void BColorStops::sortAndCorrect()
+{
+    // no content, we are done
+    if (empty())
+        return;
+
+    if (1 == size())
+    {
+        // no gradient at all, but preserve given color
+        // evtl. correct offset to be in valid range [0.0 .. 1.0]
+        // NOTE: This does not move it to 0.0 or 1.0, it *can* still
+        //       be somewhere in-between what is allowed
+        const BColorStop aEntry(front());
+        clear();
+        emplace_back(std::max(0.0, std::min(1.0, aEntry.getStopOffset())), 
aEntry.getStopColor());
+
+        // done
+        return;
+    }
+
+    // start with sorting the input data. Remember that
+    // this preserves the order of equal entries, where
+    // equal is defined here by offset (see use operator==)
+    std::sort(begin(), end());
+
+    // prepare status values
+    size_t write(0);
+
+    // use the paradigm of a band machine with two heads, read
+    // and write with write <= read all the time. Step over the
+    // data using read and check for valid entry. If valid, decide
+    // how to keep it
+    for (size_t read(0); read < size(); read++)
+    {
+        // get offset of entry at read position
+        double fOff((*this)[read].getStopOffset());
+
+        if (basegfx::fTools::less(fOff, 0.0) && read + 1 < size())
+        {
+            // value < 0.0 and we have a next entry. check for gradient snippet
+            // containing 0.0 resp. StartColor
+            const double fOff2((*this)[read + 1].getStopOffset());
+
+            if (basegfx::fTools::more(fOff2, 0.0))
+            {
+                // read is the start of a gradient snippet containing 0.0. 
Correct
+                // entry to StartColor, interpolate to correct StartColor
+                (*this)[read]
+                    = BColorStop(0.0, 
basegfx::interpolate((*this)[read].getStopColor(),
+                                                           (*this)[read + 
1].getStopColor(),
+                                                           (0.0 - fOff) / 
(fOff2 - fOff)));
+
+                // adapt fOff
+                fOff = 0.0;
+            }
+        }
+
+        // step over < 0 values, these are outside and will be removed
+        if (basegfx::fTools::less(fOff, 0.0))
+        {
+            continue;
+        }
+
+        if (basegfx::fTools::less(fOff, 1.0) && read + 1 < size())
+        {
+            // value < 1.0 and we have a next entry. check for gradient snippet
+            // containing 1.0 resp. EndColor
+            const double fOff2((*this)[read + 1].getStopOffset());
+
+            if (basegfx::fTools::more(fOff2, 1.0))
+            {
+                // read is the start of a gradient snippet containing 1.0. 
Correct
+                // next entry to EndColor, interpolate to correct EndColor
+                (*this)[read + 1]
+                    = BColorStop(1.0, 
basegfx::interpolate((*this)[read].getStopColor(),
+                                                           (*this)[read + 
1].getStopColor(),
+                                                           (1.0 - fOff) / 
(fOff2 - fOff)));
+
+                // adapt fOff
+                fOff = 1.0;
+            }
+        }
+
+        // step over > 1 values; even break, since all following
+        // entries will also be bigger due to being sorted, so done
+        if (basegfx::fTools::more(fOff, 1.0))
+        {
+            break;
+        }
+
+        // entry is valid value at read position
+        // copy if write target is empty (write at start) or when
+        // write target is different to read in color or offset
+        if (0 == write || !((*this)[read] == (*this)[write - 1]))
+        {
+            if (write != read)
+            {
+                // copy read to write backwards to close gaps
+                (*this)[write] = (*this)[read];
+            }
+
+            // always forward write position
+            write++;
+        }
+    }
+
+    // correct size when length is reduced. write is always at
+    // last used position + 1
+    if (size() > write)
+    {
+        if (0 == write)
+        {
+            // no valid entries at all, but not empty. This can only happen
+            // when all entries are below 0.0 or above 1.0 (else a gradient
+            // snippet spawning over both would have been detected)
+            if (basegfx::fTools::less(back().getStopOffset(), 0.0))
+            {
+                // all outside too low, rescue last due to being closest to 
content
+                const BColor aBackColor(back().getStopColor());
+                clear();
+                emplace_back(0.0, aBackColor);
+            }
+            else // if (basegfx::fTools::more(front().getStopOffset(), 1.0))
+            {
+                // all outside too high, rescue first due to being closest to 
content
+                const BColor aFrontColor(front().getStopColor());
+                clear();
+                emplace_back(1.0, aFrontColor);
+            }
+        }
+        else
+        {
+            resize(write);
+        }
+    }
+}
+
+bool BColorStops::checkPenultimate() const
+{
+    // not needed when no ColorStops
+    if (empty())
+        return false;
+
+    // not needed when last ColorStop at the end or outside
+    if (basegfx::fTools::moreOrEqual(back().getStopOffset(), 1.0))
+        return false;
+
+    // get penultimate entry
+    const auto penultimate(rbegin() + 1);
+
+    // if there is none, we need no correction and are done
+    if (penultimate == rend())
+        return false;
+
+    // not needed when the last two ColorStops have different offset, then
+    // a visible range will be processed already
+    if (!basegfx::fTools::equal(back().getStopOffset(), 
penultimate->getStopOffset()))
+        return false;
+
+    // not needed when the last two ColorStops have the same Color, then the
+    // range before solves the problem
+    if (back().getStopColor() == penultimate->getStopColor())
+        return false;
+
+    return true;
+}
+
+/* Tooling method to fill a awt::ColorStopSequence with
+        the data from the given ColorStops. This is used in
+        UNO API implementations.
+    */
+css::awt::ColorStopSequence BColorStops::getAsColorStopSequence() const
+{
+    css::awt::ColorStopSequence aRetval(size());
+    // rColorStopSequence.realloc(rColorStops.size());
+    css::awt::ColorStop* pTargetColorStop(aRetval.getArray());
+
+    for (const auto& candidate : *this)
+    {
+        pTargetColorStop->StopOffset = candidate.getStopOffset();
+        pTargetColorStop->StopColor = 
css::rendering::RGBColor(candidate.getStopColor().getRed(),
+                                                               
candidate.getStopColor().getGreen(),
+                                                               
candidate.getStopColor().getBlue());
+        pTargetColorStop++;
+    }
+
+    return aRetval;
+}
+
+/* Tooling method to check if a ColorStop vector is defined
+        by a single color. It returns true if this is the case.
+        If true is returned, rSingleColor contains that single
+        color for convenience.
+        NOTE: If no ColorStop is defined, a fallback to BColor-default
+                (which is black) and true will be returned
+    */
+bool BColorStops::isSingleColor(BColor& rSingleColor) const
+{
+    if (empty())
+    {
+        rSingleColor = BColor();
+        return true;
+    }
+
+    if (1 == size())
+    {
+        rSingleColor = front().getStopColor();
+        return true;
+    }
+
+    rSingleColor = front().getStopColor();
+
+    for (auto const& rCandidate : *this)
+    {
+        if (rCandidate.getStopColor() != rSingleColor)
+            return false;
+    }
+
+    return true;
+}
+
+/* Tooling method to reverse ColorStops, including offsets.
+        When also mirroring offsets a valid sort keeps valid.
+    */
+void BColorStops::reverseColorStops()
+{
+    // can use std::reverse, but also need to adapt offset(s)
+    std::reverse(begin(), end());
+    for (auto& candidate : *this)
+        candidate = BColorStop(1.0 - candidate.getStopOffset(), 
candidate.getStopColor());
+}
+
+std::string BGradient::GradientStyleToString(css::awt::GradientStyle eStyle)
+{
+    switch (eStyle)
+    {
+        case css::awt::GradientStyle::GradientStyle_LINEAR:
+            return "LINEAR";
+
+        case css::awt::GradientStyle::GradientStyle_AXIAL:
+            return "AXIAL";
+
+        case css::awt::GradientStyle::GradientStyle_RADIAL:
+            return "RADIAL";
+
+        case css::awt::GradientStyle::GradientStyle_ELLIPTICAL:
+            return "ELLIPTICAL";
+
+        case css::awt::GradientStyle::GradientStyle_SQUARE:
+            return "SQUARE";
+
+        case css::awt::GradientStyle::GradientStyle_RECT:
+            return "RECT";
+
+        case css::awt::GradientStyle::GradientStyle_MAKE_FIXED_SIZE:
+            return "MAKE_FIXED_SIZE";
+    }
+
+    return "";
+}
+
+BGradient BGradient::fromJSON(std::u16string_view rJSON)
+{
+    StringMap aMap(lcl_jsonToStringMap(rJSON));
+    return lcl_buildGradientFromStringMap(aMap);
+}
+
+BGradient::BGradient()
+    : eStyle(css::awt::GradientStyle_LINEAR)
+    , aColorStops()
+    , nAngle(0)
+    , nBorder(0)
+    , nOfsX(50)
+    , nOfsY(50)
+    , nIntensStart(100)
+    , nIntensEnd(100)
+    , nStepCount(0)
+{
+    aColorStops.emplace_back(0.0, BColor(0.0, 0.0, 0.0)); // COL_BLACK
+    aColorStops.emplace_back(1.0, BColor(1.0, 1.0, 1.0)); // COL_WHITE
+}
+
+BGradient::BGradient(const basegfx::BColorStops& rColorStops, 
css::awt::GradientStyle eTheStyle,
+                     Degree10 nTheAngle, sal_uInt16 nXOfs, sal_uInt16 nYOfs, 
sal_uInt16 nTheBorder,
+                     sal_uInt16 nStartIntens, sal_uInt16 nEndIntens, 
sal_uInt16 nSteps)
+    : eStyle(eTheStyle)
+    , aColorStops(rColorStops)
+    , nAngle(nTheAngle)
+    , nBorder(nTheBorder)
+    , nOfsX(nXOfs)
+    , nOfsY(nYOfs)
+    , nIntensStart(nStartIntens)
+    , nIntensEnd(nEndIntens)
+    , nStepCount(nSteps)
+{
+    SetColorStops(aColorStops);
+}
+
+BGradient::BGradient(const css::awt::Gradient2& rGradient2)
+{
+    // set values
+    SetGradientStyle(rGradient2.Style);
+    SetAngle(Degree10(rGradient2.Angle));
+    SetBorder(rGradient2.Border);
+    SetXOffset(rGradient2.XOffset);
+    SetYOffset(rGradient2.YOffset);
+    SetStartIntens(rGradient2.StartIntensity);
+    SetEndIntens(rGradient2.EndIntensity);
+    SetSteps(rGradient2.StepCount);
+
+    // set ColorStops
+    aColorStops = BColorStops(rGradient2.ColorStops);
+    aColorStops.sortAndCorrect();
+}
+
+BGradient::BGradient(const css::uno::Any& rVal)
+    : BGradient()
+{
+    if (rVal.has<css::awt::Gradient2>())
+    {
+        // we can use awt::Gradient2 directly
+        css::awt::Gradient2 aGradient2;
+        rVal >>= aGradient2;
+
+        // set values
+        SetGradientStyle(aGradient2.Style);
+        SetAngle(Degree10(aGradient2.Angle));
+        SetBorder(aGradient2.Border);
+        SetXOffset(aGradient2.XOffset);
+        SetYOffset(aGradient2.YOffset);
+        SetStartIntens(aGradient2.StartIntensity);
+        SetEndIntens(aGradient2.EndIntensity);
+        SetSteps(aGradient2.StepCount);
+
+        // set ColorStops
+        aColorStops = BColorStops(aGradient2.ColorStops);
+        aColorStops.sortAndCorrect();
+    }
+    else if (rVal.has<css::awt::Gradient>())
+    {
+        // use awt::Gradient
+        css::awt::Gradient aGradient;
+        rVal >>= aGradient;
+
+        // set values
+        SetGradientStyle(aGradient.Style);
+        SetAngle(Degree10(aGradient.Angle));
+        SetBorder(aGradient.Border);
+        SetXOffset(aGradient.XOffset);
+        SetYOffset(aGradient.YOffset);
+        SetStartIntens(aGradient.StartIntensity);
+        SetEndIntens(aGradient.EndIntensity);
+        SetSteps(aGradient.StepCount);
+
+        // complete data by creating ColorStops from fixe Start/EndColor
+        aColorStops = BColorStops{
+            BColorStop(0.0, 
ColorToBColorConverter(aGradient.StartColor).getBColor()),
+            BColorStop(1.0, 
ColorToBColorConverter(aGradient.EndColor).getBColor())
+        };
+    }
+}
+
+bool BGradient::operator==(const BGradient& rGradient) const
+{
+    return (eStyle == rGradient.eStyle && aColorStops == rGradient.aColorStops
+            && nAngle == rGradient.nAngle && nBorder == rGradient.nBorder
+            && nOfsX == rGradient.nOfsX && nOfsY == rGradient.nOfsY
+            && nIntensStart == rGradient.nIntensStart && nIntensEnd == 
rGradient.nIntensEnd
+            && nStepCount == rGradient.nStepCount);
+}
+
+void BGradient::SetColorStops(const basegfx::BColorStops& rSteps)
+{
+    aColorStops = rSteps;
+    aColorStops.sortAndCorrect();
+    if (aColorStops.empty())
+        aColorStops.emplace_back(0.0, basegfx::BColor());
+}
+
+namespace
+{
+OUString AsRGBHexString(const ColorToBColorConverter& rVal)
+{
+    std::stringstream ss;
+    ss << std::hex << std::setfill('0') << std::setw(6) << sal_uInt32(rVal);
+    return OUString::createFromAscii(ss.str());
+}
+}
+
+boost::property_tree::ptree BGradient::dumpAsJSON() const
+{
+    boost::property_tree::ptree aTree;
+
+    aTree.put("style", BGradient::GradientStyleToString(eStyle));
+    const ColorToBColorConverter 
aStart(GetColorStops().front().getStopColor());
+    aTree.put("startcolor", AsRGBHexString(aStart.GetRGBColor()));
+    const ColorToBColorConverter aEnd(GetColorStops().back().getStopColor());
+    aTree.put("endcolor", AsRGBHexString(aEnd.GetRGBColor()));
+    aTree.put("angle", std::to_string(nAngle.get()));
+    aTree.put("border", std::to_string(nBorder));
+    aTree.put("x", std::to_string(nOfsX));
+    aTree.put("y", std::to_string(nOfsY));
+    aTree.put("intensstart", std::to_string(nIntensStart));
+    aTree.put("intensend", std::to_string(nIntensEnd));
+    aTree.put("stepcount", std::to_string(nStepCount));
+
+    return aTree;
+}
+
+css::awt::Gradient2 BGradient::getAsGradient2() const
+{
+    css::awt::Gradient2 aRetval;
+
+    // standard values
+    aRetval.Style = GetGradientStyle();
+    aRetval.Angle = static_cast<short>(GetAngle());
+    aRetval.Border = GetBorder();
+    aRetval.XOffset = GetXOffset();
+    aRetval.YOffset = GetYOffset();
+    aRetval.StartIntensity = GetStartIntens();
+    aRetval.EndIntensity = GetEndIntens();
+    aRetval.StepCount = GetSteps();
+
+    // for compatibility, still set StartColor/EndColor
+    // const basegfx::BColorStops& rColorStops(GetColorStops());
+    aRetval.StartColor
+        = 
static_cast<sal_Int32>(ColorToBColorConverter(aColorStops.front().getStopColor()));
+    aRetval.EndColor
+        = 
static_cast<sal_Int32>(ColorToBColorConverter(aColorStops.back().getStopColor()));
+
+    // fill ColorStops to extended Gradient2
+    aRetval.ColorStops = aColorStops.getAsColorStopSequence();
+    // fillColorStopSequenceFromColorStops(rGradient2.ColorStops, rColorStops);
+
+    return aRetval;
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/source/tools/gradienttools.cxx 
b/basegfx/source/tools/gradienttools.cxx
index 12bbebd39c11..c909108932cc 100644
--- a/basegfx/source/tools/gradienttools.cxx
+++ b/basegfx/source/tools/gradienttools.cxx
@@ -265,38 +265,6 @@ namespace basegfx
 
     namespace utils
     {
-        /* Internal helper to convert ::Color from tools::color.hxx to BColor
-           without the need to link against tools library. Be on the
-           safe side by using the same union
-        */
-        namespace {
-        struct ColorToBColorConverter
-        {
-            union {
-                sal_uInt32 mValue;
-                struct {
-#ifdef OSL_BIGENDIAN
-                    sal_uInt8 T;
-                    sal_uInt8 R;
-                    sal_uInt8 G;
-                    sal_uInt8 B;
-#else
-                    sal_uInt8 B;
-                    sal_uInt8 G;
-                    sal_uInt8 R;
-                    sal_uInt8 T;
-#endif
-                };
-            };
-
-            ColorToBColorConverter(sal_uInt32 nColor) : mValue(nColor) { T=0; }
-            BColor getBColor() const
-            {
-                return BColor(R / 255.0, G / 255.0, B / 255.0);
-            }
-        };
-        }
-
         /// Tooling method to fill awt::Gradient2 from data contained in the 
given Any
         bool fillGradient2FromAny(css::awt::Gradient2& rGradient, const 
css::uno::Any& rVal)
         {
@@ -327,11 +295,10 @@ namespace basegfx
                     rGradient.StepCount = aTmp.StepCount;
 
                     // complete data by creating ColorStops for awt::Gradient2
-                    fillColorStopSequenceFromColorStops(
-                        rGradient.ColorStops,
-                        ColorStops {
-                            ColorStop(0.0, 
ColorToBColorConverter(aTmp.StartColor).getBColor()),
-                            ColorStop(1.0, 
ColorToBColorConverter(aTmp.EndColor).getBColor()) });
+                    const BColorStops aTempColorStops {
+                        BColorStop(0.0, 
ColorToBColorConverter(aTmp.StartColor).getBColor()),
+                        BColorStop(1.0, 
ColorToBColorConverter(aTmp.EndColor).getBColor()) };
+                    rGradient.ColorStops = 
aTempColorStops.getAsColorStopSequence();
                     bRetval = true;
                 }
             }
@@ -355,12 +322,12 @@ namespace basegfx
         */
         void prepareColorStops(
             const com::sun::star::awt::Gradient2& rGradient,
-            ColorStops& rColorStops,
+            BColorStops& rColorStops,
             BColor& rSingleColor)
         {
-            fillColorStopsFromGradient2(rColorStops, rGradient);
+            rColorStops = BColorStops(rGradient.ColorStops);
 
-            if (isSingleColor(rColorStops, rSingleColor))
+            if (rColorStops.isSingleColor(rSingleColor))
             {
                 // when single color, preserve value in rSingleColor
                 // and clear the ColorStops, done.
@@ -371,15 +338,14 @@ namespace basegfx
             if (rGradient.StartIntensity != 100 || rGradient.EndIntensity != 
100)
             {
                 // apply 'old' blend stuff, blend against black
-                blendColorStopsToIntensity(
-                    rColorStops,
+                rColorStops.blendToIntensity(
                     rGradient.StartIntensity * 0.01,
                     rGradient.EndIntensity * 0.01,
                     basegfx::BColor()); // COL_BLACK
 
                 // can lead to single color (e.g. both zero, so all black),
                 // so check again
-                if (isSingleColor(rColorStops, rSingleColor))
+                if (rColorStops.isSingleColor(rSingleColor))
                 {
                     rColorStops.clear();
                     return;
@@ -393,7 +359,7 @@ namespace basegfx
                 //       mechanism does not need entries at 0.0 and 1.0.
                 //       In case this is needed, do that in the caller
                 const double fFactor(rGradient.Border * 0.01);
-                ColorStops aNewStops;
+                BColorStops aNewStops;
 
                 for (const auto& candidate : rColorStops)
                 {
@@ -437,8 +403,8 @@ namespace basegfx
            'FillTransparenceGradient' method (at import time).
         */
         void synchronizeColorStops(
-            ColorStops& rColorStops,
-            ColorStops& rAlphaStops,
+            BColorStops& rColorStops,
+            BColorStops& rAlphaStops,
             const BColor& rSingleColor,
             const BColor& rSingleAlpha)
         {
@@ -448,12 +414,12 @@ namespace basegfx
                 {
                     // no AlphaStops and no ColorStops
                     // create two-stop fallbacks for both
-                    rColorStops = ColorStops {
-                        ColorStop(0.0, rSingleColor),
-                        ColorStop(1.0, rSingleColor) };
-                    rAlphaStops = ColorStops {
-                        ColorStop(0.0, rSingleAlpha),
-                        ColorStop(1.0, rSingleAlpha) };
+                    rColorStops = BColorStops {
+                        BColorStop(0.0, rSingleColor),
+                        BColorStop(1.0, rSingleColor) };
+                    rAlphaStops = BColorStops {
+                        BColorStop(0.0, rSingleAlpha),
+                        BColorStop(1.0, rSingleAlpha) };
                 }
                 else
                 {
@@ -489,8 +455,8 @@ namespace basegfx
             if (!bNeedToSyncronize)
             {
                 // check for same StopOffsets
-                ColorStops::const_iterator aCurrColor(rColorStops.begin());
-                ColorStops::const_iterator aCurrAlpha(rAlphaStops.begin());
+                BColorStops::const_iterator aCurrColor(rColorStops.begin());
+                BColorStops::const_iterator aCurrAlpha(rAlphaStops.begin());
 
                 while (!bNeedToSyncronize &&
                     aCurrColor != rColorStops.end() &&
@@ -511,12 +477,12 @@ namespace basegfx
             if (bNeedToSyncronize)
             {
                 // synchronize sizes & StopOffsets
-                ColorStops::const_iterator aCurrColor(rColorStops.begin());
-                ColorStops::const_iterator aCurrAlpha(rAlphaStops.begin());
-                ColorStops aNewColor;
-                ColorStops aNewAlpha;
-                ColorStopRange aColorStopRange;
-                ColorStopRange aAlphaStopRange;
+                BColorStops::const_iterator aCurrColor(rColorStops.begin());
+                BColorStops::const_iterator aCurrAlpha(rAlphaStops.begin());
+                BColorStops aNewColor;
+                BColorStops aNewAlpha;
+                BColorStops::BColorStopRange aColorStopRange;
+                BColorStops::BColorStopRange aAlphaStopRange;
                 bool bRealChange(false);
 
                 do {
@@ -532,14 +498,14 @@ namespace basegfx
                         {
                             // copy color, create alpha
                             aNewColor.emplace_back(fColorOff, 
aCurrColor->getStopColor());
-                            aNewAlpha.emplace_back(fColorOff, 
utils::modifyBColor(rAlphaStops, fColorOff, 0, aAlphaStopRange));
+                            aNewAlpha.emplace_back(fColorOff, 
rAlphaStops.getInterpolatedBColor(fColorOff, 0, aAlphaStopRange));
                             bRealChange = true;
                             aCurrColor++;
                         }
                         else if (fTools::more(fColorOff, fAlphaOff))
                         {
                             // copy alpha, create color
-                            aNewColor.emplace_back(fAlphaOff, 
utils::modifyBColor(rColorStops, fAlphaOff, 0, aColorStopRange));
+                            aNewColor.emplace_back(fAlphaOff, 
rColorStops.getInterpolatedBColor(fAlphaOff, 0, aColorStopRange));
                             aNewAlpha.emplace_back(fAlphaOff, 
aCurrAlpha->getStopColor());
                             bRealChange = true;
                             aCurrAlpha++;
@@ -556,14 +522,14 @@ namespace basegfx
                     else if (bColor)
                     {
                         const double fColorOff(aCurrColor->getStopOffset());
-                        aNewAlpha.emplace_back(fColorOff, 
utils::modifyBColor(rAlphaStops, fColorOff, 0, aAlphaStopRange));
+                        aNewAlpha.emplace_back(fColorOff, 
rAlphaStops.getInterpolatedBColor(fColorOff, 0, aAlphaStopRange));
                         bRealChange = true;
                         aCurrColor++;
                     }
                     else if (bAlpha)
                     {
                         const double fAlphaOff(aCurrAlpha->getStopOffset());
-                        aNewColor.emplace_back(fAlphaOff, 
utils::modifyBColor(rColorStops, fAlphaOff, 0, aColorStopRange));
+                        aNewColor.emplace_back(fAlphaOff, 
rColorStops.getInterpolatedBColor(fAlphaOff, 0, aColorStopRange));
                         bRealChange = true;
                         aCurrAlpha++;
                     }
@@ -586,467 +552,6 @@ namespace basegfx
             }
         }
 
-        /* Tooling method to linearly blend the Colors contained in
-           a given ColorStop vector against a given Color using the
-           given intensity values.
-           The intensity values fStartIntensity, fEndIntensity are
-           in the range of [0.0 .. 1.0] and describe how much the
-           blend is supposed to be done at the start color position
-           and the end color position resprectively, where 0.0 means
-           to fully use the given BlendColor, 1.0 means to not change
-           the existing color in the ColorStop.
-           Every color entry in the given ColorStop is blended
-           relative to it's StopPosition, interpolating the
-           given intensities with the range [0.0 .. 1.0] to do so.
-        */
-        void blendColorStopsToIntensity(ColorStops& rColorStops, double 
fStartIntensity, double fEndIntensity, const basegfx::BColor& rBlendColor)
-        {
-            // no entries, done
-            if (rColorStops.empty())
-                return;
-
-            // correct intensities (maybe assert when input was wrong)
-            fStartIntensity = std::max(std::min(1.0, fStartIntensity), 0.0);
-            fEndIntensity = std::max(std::min(1.0, fEndIntensity), 0.0);
-
-            // all 100%, no real blend, done
-            if (basegfx::fTools::equal(fStartIntensity, 1.0) && 
basegfx::fTools::equal(fEndIntensity, 1.0))
-                return;
-
-            // blend relative to StopOffset position
-            for (auto& candidate : rColorStops)
-            {
-                const double fOffset(candidate.getStopOffset());
-                const double fIntensity((fStartIntensity * (1.0 - fOffset)) + 
(fEndIntensity * fOffset));
-                candidate = basegfx::ColorStop(
-                    fOffset,
-                    basegfx::interpolate(rBlendColor, 
candidate.getStopColor(), fIntensity));
-            }
-        }
-
-        /* Tooling method to check if a ColorStop vector is defined
-           by a single color. It returns true if this is the case.
-           If true is returned, rSingleColor contains that single
-           color for convenience.
-           NOTE: If no ColorStop is defined, a fallback to BColor-default
-                 (which is black) and true will be returned
-        */
-        bool isSingleColor(const ColorStops& rColorStops, BColor& rSingleColor)
-        {
-            if (rColorStops.empty())
-            {
-                rSingleColor = BColor();
-                return true;
-            }
-
-            if (1 == rColorStops.size())
-            {
-                rSingleColor = rColorStops.front().getStopColor();
-                return true;
-            }
-
-            rSingleColor = rColorStops.front().getStopColor();
-
-            for (auto const& rCandidate : rColorStops)
-            {
-                if (rCandidate.getStopColor() != rSingleColor)
-                    return false;
-            }
-
-            return true;
-        }
-
-        /* Tooling method to reverse ColorStops, including offsets.
-           When also mirroring offsets a valid sort keeps valid.
-        */
-        void reverseColorStops(ColorStops& rColorStops)
-        {
-            // can use std::reverse, but also need to adapt offset(s)
-            std::reverse(rColorStops.begin(), rColorStops.end());
-            for (auto& candidate : rColorStops)
-                candidate = ColorStop(1.0 - candidate.getStopOffset(), 
candidate.getStopColor());
-        }
-
-        /* Tooling method to convert UNO API data to ColorStops.
-           This will try to extract ColorStop data from the given
-           awt::Gradient2.
-        */
-        void fillColorStopsFromGradient2(ColorStops& rColorStops, const 
com::sun::star::awt::Gradient2& rGradient)
-        {
-            const sal_Int32 nLen(rGradient.ColorStops.getLength());
-
-            if (0 == nLen)
-                return;
-
-            // we have ColorStops
-            rColorStops.clear();
-            rColorStops.reserve(nLen);
-            const css::awt::ColorStop* 
pSourceColorStop(rGradient.ColorStops.getConstArray());
-
-            for (sal_Int32 a(0); a < nLen; a++, pSourceColorStop++)
-            {
-                rColorStops.emplace_back(
-                    pSourceColorStop->StopOffset,
-                    BColor(pSourceColorStop->StopColor.Red, 
pSourceColorStop->StopColor.Green, pSourceColorStop->StopColor.Blue));
-            }
-        }
-
-        /* Tooling method to convert UNO API data to ColorStops.
-           This will try to extract ColorStop data from the given
-           Any, so if it's of type awt::Gradient2 that data will be
-           extracted, converted and copied into the given ColorStops.
-        */
-        void fillColorStopsFromAny(ColorStops& rColorStops, const 
css::uno::Any& rVal)
-        {
-            css::awt::Gradient2 aGradient2;
-            if (!(rVal >>= aGradient2))
-                return;
-
-            fillColorStopsFromGradient2(rColorStops, aGradient2);
-        }
-
-        /* Tooling method to fill a awt::ColorStopSequence with
-           the data from the given ColorStops. This is used in
-           UNO API implementations.
-        */
-        void fillColorStopSequenceFromColorStops(css::awt::ColorStopSequence& 
rColorStopSequence, const ColorStops& rColorStops)
-        {
-            // fill ColorStops to extended Gradient2
-            rColorStopSequence.realloc(rColorStops.size());
-            css::awt::ColorStop* 
pTargetColorStop(rColorStopSequence.getArray());
-
-            for (const auto& candidate : rColorStops)
-            {
-                pTargetColorStop->StopOffset = candidate.getStopOffset();
-                pTargetColorStop->StopColor = css::rendering::RGBColor(
-                    candidate.getStopColor().getRed(),
-                    candidate.getStopColor().getGreen(),
-                    candidate.getStopColor().getBlue());
-                pTargetColorStop++;
-            }
-        }
-
-        /* Tooling method that allows to replace the StartColor in a
-           vector of ColorStops. A vector in 'ordered state' is expected,
-           so you may use/have used sortAndCorrectColorStops, see below.
-           This method is for convenience & backwards compatibility, please
-           think about handling multi-colored gradients directly.
-        */
-        void replaceStartColor(ColorStops& rColorStops, const BColor& rStart)
-        {
-            ColorStops::iterator a1stNonStartColor(rColorStops.begin());
-
-            // search for highest existing non-StartColor
-            while (a1stNonStartColor != rColorStops.end() && 
basegfx::fTools::lessOrEqual(a1stNonStartColor->getStopOffset(), 0.0))
-                a1stNonStartColor++;
-
-            // create new ColorStops by 1st adding new one and then all
-            // non-StartColor entries
-            ColorStops aNewColorStops;
-
-            aNewColorStops.reserve(rColorStops.size() + 1);
-            aNewColorStops.emplace_back(0.0, rStart);
-            aNewColorStops.insert(aNewColorStops.end(), a1stNonStartColor, 
rColorStops.end());
-
-            // assign & done
-            rColorStops = aNewColorStops;
-        }
-
-        /* Tooling method that allows to replace the EndColor in a
-           vector of ColorStops. A vector in 'ordered state' is expected,
-           so you may use/have used sortAndCorrectColorStops, see below.
-           This method is for convenience & backwards compatibility, please
-           think about handling multi-colored gradients directly.
-        */
-        void replaceEndColor(ColorStops& rColorStops, const BColor& rEnd)
-        {
-            // erase all evtl. existing EndColor(s)
-            while (!rColorStops.empty() && 
basegfx::fTools::moreOrEqual(rColorStops.back().getStopOffset(), 1.0))
-                rColorStops.pop_back();
-
-            // add at the end of existing ColorStops
-            rColorStops.emplace_back(1.0, rEnd);
-        }
-
-        // Tooling method to quickly create a ColorStop vector for a given set 
of Start/EndColor
-        ColorStops createColorStopsFromStartEndColor(const BColor& rStart, 
const BColor& rEnd)
-        {
-            return ColorStops {
-                ColorStop(0.0, rStart),
-                ColorStop(1.0, rEnd) };
-        }
-
-        /* Tooling method to guarantee sort and correctness for
-           the given ColorStops vector.
-           A vector fulfilling these conditions is called to be
-           in 'ordered state'.
-
-           At return, the following conditions are guaranteed:
-           - contains no ColorStops with offset < 0.0 (will
-             be removed)
-           - contains no ColorStops with offset > 1.0 (will
-             be removed)
-           - ColorStops with identical offsets are now allowed
-           - will be sorted from lowest offset to highest
-
-           Some more notes:
-           - It can happen that the result is empty
-           - It is allowed to have consecutive entries with
-             the same color, this represents single-color
-             regions inside the gradient
-           - A entry with 0.0 is not required or forced, so
-             no 'StartColor' is technically required
-           - A entry with 1.0 is not required or forced, so
-             no 'EndColor' is technically required
-
-           All this is done in one run (sort + O(N)) without
-           creating a copy of the data in any form
-        */
-        void sortAndCorrectColorStops(ColorStops& rColorStops)
-        {
-            // no content, we are done
-            if (rColorStops.empty())
-                return;
-
-            if (1 == rColorStops.size())
-            {
-                // no gradient at all, but preserve given color
-                // evtl. correct offset to be in valid range [0.0 .. 1.0]
-                // NOTE: This does not move it to 0.0 or 1.0, it *can* still
-                //       be somewhere in-between what is allowed
-                rColorStops[0] = ColorStop(
-                    std::max(0.0, std::min(1.0, 
rColorStops[0].getStopOffset())),
-                    rColorStops[0].getStopColor());
-
-                // done
-                return;
-            }
-
-            // start with sorting the input data. Remember that
-            // this preserves the order of equal entries, where
-            // equal is defined here by offset (see use operator==)
-            std::sort(rColorStops.begin(), rColorStops.end());
-
-            // prepare status values
-            size_t write(0);
-
-            // use the paradigm of a band machine with two heads, read
-            // and write with write <= read all the time. Step over the
-            // data using read and check for valid entry. If valid, decide
-            // how to keep it
-            for (size_t read(0); read < rColorStops.size(); read++)
-            {
-                // get offset of entry at read position
-                double fOff(rColorStops[read].getStopOffset());
-
-                if (basegfx::fTools::less(fOff, 0.0) && read + 1 < 
rColorStops.size())
-                {
-                    // value < 0.0 and we have a next entry. check for 
gradient snippet
-                    // containing 0.0 resp. StartColor
-                    const double fOff2(rColorStops[read + 1].getStopOffset());
-
-                    if (basegfx::fTools::more(fOff2, 0.0))
-                    {
-                        // read is the start of a gradient snippet containing 
0.0. Correct
-                        // entry to StartColor, interpolate to correct 
StartColor
-                        rColorStops[read] = ColorStop(0.0, 
basegfx::interpolate(
-                            rColorStops[read].getStopColor(),
-                            rColorStops[read + 1].getStopColor(),
-                            (0.0 - fOff) / (fOff2 - fOff)));
-
-                        // adapt fOff
-                        fOff = 0.0;
-                    }
-                }
-
-                // step over < 0 values, these are outside and will be removed
-                if (basegfx::fTools::less(fOff, 0.0))
-                {
-                    continue;
-                }
-
-                if (basegfx::fTools::less(fOff, 1.0) && read + 1 < 
rColorStops.size())
-                {
-                    // value < 1.0 and we have a next entry. check for 
gradient snippet
-                    // containing 1.0 resp. EndColor
-                    const double fOff2(rColorStops[read + 1].getStopOffset());
-
-                    if (basegfx::fTools::more(fOff2, 1.0))
-                    {
-                        // read is the start of a gradient snippet containing 
1.0. Correct
-                        // next entry to EndColor, interpolate to correct 
EndColor
-                        rColorStops[read + 1] = ColorStop(1.0, 
basegfx::interpolate(
-                            rColorStops[read].getStopColor(),
-                            rColorStops[read + 1].getStopColor(),
-                            (1.0 - fOff) / (fOff2 - fOff)));
-
-                        // adapt fOff
-                        fOff = 1.0;
-                    }
-                }
-
-                // step over > 1 values; even break, since all following
-                // entries will also be bigger due to being sorted, so done
-                if (basegfx::fTools::more(fOff, 1.0))
-                {
-                    break;
-                }
-
-                // entry is valid value at read position
-                // copy if write target is empty (write at start) or when
-                // write target is different to read in color or offset
-                if (0 == write || !(rColorStops[read] == rColorStops[write-1]))
-                {
-                    if (write != read)
-                    {
-                        // copy read to write backwards to close gaps
-                        rColorStops[write] = rColorStops[read];
-                    }
-
-                    // always forward write position
-                    write++;
-                }
-            }
-
-            // correct size when length is reduced. write is always at
-            // last used position + 1
-            if (rColorStops.size() > write)
-            {
-                if (0 == write)
-                {
-                    // no valid entries at all, but not empty. This can only 
happen
-                    // when all entries are below 0.0 or above 1.0 (else a 
gradient
-                    // snippet spawning over both would have been detected)
-                    if 
(basegfx::fTools::less(rColorStops.back().getStopOffset(), 0.0))
-                    {
-                        // all outside too low, rescue last due to being 
closest to content
-                        rColorStops = ColorStops { ColorStop(0.0, 
rColorStops.back().getStopColor()) };
-                    }
-                    else // if 
(basegfx::fTools::more(rColorStops.front().getStopOffset(), 1.0))
-                    {
-                        // all outside too high, rescue first due to being 
closest to content
-                        rColorStops = ColorStops { ColorStop(1.0, 
rColorStops.front().getStopColor()) };
-                    }
-                }
-                else
-                {
-                    rColorStops.resize(write);
-                }
-            }
-        }
-
-        BColor modifyBColor(
-            const ColorStops& rColorStops,
-            double fScaler,
-            sal_uInt32 nRequestedSteps,
-            ColorStopRange& rLastColorStopRange)
-        {
-            // no color at all, done
-            if (rColorStops.empty())
-                return BColor();
-
-            // outside range -> at start
-            const double fMin(rColorStops.front().getStopOffset());
-            if (fScaler < fMin)
-                return rColorStops.front().getStopColor();
-
-            // outside range -> at end
-            const double fMax(rColorStops.back().getStopOffset());
-            if (fScaler > fMax)
-                return rColorStops.back().getStopColor();
-
-            // special case for the 'classic' case with just two colors:
-            // we can optimize that and keep the speed/resources low
-            // by avoiding some calculations and an O(log(N)) array access
-            if (2 == rColorStops.size())
-            {
-                if (fTools::equal(fMin, fMax))
-                    return rColorStops.front().getStopColor();
-
-                const basegfx::BColor 
aCStart(rColorStops.front().getStopColor());
-                const basegfx::BColor aCEnd(rColorStops.back().getStopColor());
-                const sal_uInt32 nSteps(
-                    calculateNumberOfSteps(
-                        nRequestedSteps,
-                        aCStart,
-                        aCEnd));
-
-                // we need to extend the interpolation to the local
-                // range of ColorStops. Despite having two ColorStops
-                // these are not necessarily at 0.0 and 1.0, so mabe
-                // not the classical Start/EndColor (what is allowed)
-                fScaler = (fScaler - fMin) / (fMax - fMin);
-                return basegfx::interpolate(
-                    aCStart,
-                    aCEnd,
-                    nSteps > 1 ? floor(fScaler * nSteps) / double(nSteps - 1) 
: fScaler);
-            }
-
-            // check if we need to newly populate the needed interpolation data
-            // or if we can re-use from last time.
-            // If this scope is not entered, we do not need the binary search. 
It's
-            // only a single buffered entry, and only used when more than three
-            // ColorStops exist, but makes a huge difference compared with 
acessing
-            // the sorted ColorStop vector each time.
-            // NOTE: with this simple change I get very high hit rates, e.g. 
rotating
-            //       a donut with gradient test '1' hit rate is at 
0.99909440357755486
-            if (rLastColorStopRange.mfOffsetStart == 
rLastColorStopRange.mfOffsetEnd
-                || fScaler < rLastColorStopRange.mfOffsetStart
-                || fScaler > rLastColorStopRange.mfOffsetEnd)
-            {
-                // access needed spot in sorted array using binary search
-                // NOTE: This *seems* slow(er) when developing compared to just
-                //       looping/accessing, but that's just due to the 
extensive
-                //       debug test code created by the stl. In a pro version,
-                //       all is good/fast as expected
-                const auto upperBound(
-                    std::upper_bound(
-                        rColorStops.begin(),
-                        rColorStops.end(),
-                        ColorStop(fScaler),
-                        [](const ColorStop& x, const ColorStop& y) { return 
x.getStopOffset() < y.getStopOffset(); }));
-
-                // no upper bound, done
-                if (rColorStops.end() == upperBound)
-                    return rColorStops.back().getStopColor();
-
-                // lower bound is one entry back, access that
-                const auto lowerBound(upperBound - 1);
-
-                // no lower bound, done
-                if (rColorStops.end() == lowerBound)
-                    return rColorStops.back().getStopColor();
-
-                // we have lower and upper bound, get colors and offsets
-                rLastColorStopRange.maColorStart = lowerBound->getStopColor();
-                rLastColorStopRange.maColorEnd = upperBound->getStopColor();
-                rLastColorStopRange.mfOffsetStart = 
lowerBound->getStopOffset();
-                rLastColorStopRange.mfOffsetEnd = upperBound->getStopOffset();
-            }
-
-            // when there are just two color steps this cannot happen, but 
when using
-            // a range of colors this *may* be used inside the range to 
represent
-            // single-colored regions inside a ColorRange. Use that color & 
done
-            if (rLastColorStopRange.maColorStart == 
rLastColorStopRange.maColorEnd)
-                return rLastColorStopRange.maColorStart;
-
-            // calculate number of steps and adapted proportinal
-            // range for scaler in [0.0 .. 1.0]
-            const double fAdaptedScaler((fScaler - 
rLastColorStopRange.mfOffsetStart) /
-                (rLastColorStopRange.mfOffsetEnd - 
rLastColorStopRange.mfOffsetStart));
-            const sal_uInt32 nSteps(
-                calculateNumberOfSteps(
-                    nRequestedSteps,
-                    rLastColorStopRange.maColorStart,
-                    rLastColorStopRange.maColorEnd));
-
-            // interpolate & evtl. apply steps
-            return interpolate(
-                rLastColorStopRange.maColorStart,
-                rLastColorStopRange.maColorEnd,
-                nSteps > 1 ? floor(fAdaptedScaler * nSteps) / double(nSteps - 
1) : fAdaptedScaler);
-        }
-
         sal_uInt32 calculateNumberOfSteps(
             sal_uInt32 nRequestedSteps,
             const BColor& rStart,
diff --git a/chart2/inc/pch/precompiled_chartcontroller.hxx 
b/chart2/inc/pch/precompiled_chartcontroller.hxx
index 6839b807696d..ba4ccbddf15e 100644
--- a/chart2/inc/pch/precompiled_chartcontroller.hxx
+++ b/chart2/inc/pch/precompiled_chartcontroller.hxx
@@ -409,7 +409,6 @@
 #include <svx/svxdllapi.h>
 #include <svx/xdash.hxx>
 #include <svx/xdef.hxx>
-#include <svx/xgrad.hxx>
 #include <svx/xhatch.hxx>
 #include <svx/xit.hxx>
 #include <svx/xpoly.hxx>
diff --git a/chart2/qa/extras/chart2import.cxx 
b/chart2/qa/extras/chart2import.cxx
index e309fa912c3a..243597a060ab 100644
--- a/chart2/qa/extras/chart2import.cxx
+++ b/chart2/qa/extras/chart2import.cxx
@@ -805,9 +805,7 @@ void Chart2ImportTest::testBnc889755()
     uno::Reference<beans::XPropertySet> xShapeProps(xPage->getByIndex(4), 
uno::UNO_QUERY_THROW);
     awt::Gradient2 aTransparence;
     xShapeProps->getPropertyValue("FillTransparenceGradient") >>= 
aTransparence;
-
-    basegfx::ColorStops aColorStops;
-    basegfx::utils::fillColorStopsFromGradient2(aColorStops, aTransparence);
+    const basegfx::BColorStops aColorStops(aTransparence.ColorStops);
 
     CPPUNIT_ASSERT_EQUAL(size_t(3), aColorStops.size());
     CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 
0.0));
@@ -850,9 +848,7 @@ void Chart2ImportTest::testTransparencyGradientValue()
     uno::Reference< container::XNameAccess > 
xTransparenceGradient(xFact->createInstance("com.sun.star.drawing.TransparencyGradientTable"),
 uno::UNO_QUERY);
     uno::Any rTransparenceValue = 
xTransparenceGradient->getByName(sTranspGradientName);
     CPPUNIT_ASSERT(rTransparenceValue >>= aTransparenceGradient);
-
-    basegfx::ColorStops aColorStops;
-    basegfx::utils::fillColorStopsFromGradient2(aColorStops, 
aTransparenceGradient);
+    const basegfx::BColorStops aColorStops(aTransparenceGradient.ColorStops);
 
     // MCGR: Use the whole completely imported transparency gradient to check 
for correctness
     CPPUNIT_ASSERT_EQUAL(size_t(2), aColorStops.size());
diff --git a/chart2/source/controller/main/ChartController_Tools.cxx 
b/chart2/source/controller/main/ChartController_Tools.cxx
index 8cd3fd99045c..b24ed653099b 100644
--- a/chart2/source/controller/main/ChartController_Tools.cxx
+++ b/chart2/source/controller/main/ChartController_Tools.cxx
@@ -74,7 +74,6 @@
 #include <svx/unoapi.hxx>
 #include <svx/unopage.hxx>
 #include <svx/unoshape.hxx>
-#include <svx/xgrad.hxx>
 #include <PropertyHelper.hxx>
 
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
@@ -957,8 +956,8 @@ void ChartController::executeDispatch_FillColor(sal_uInt32 
nColor)
 
 void ChartController::executeDispatch_FillGradient(std::u16string_view 
sJSONGradient)
 {
-    XGradient aXGradient = XGradient::fromJSON(sJSONGradient);
-    css::awt::Gradient aGradient = aXGradient.toGradientUNO();
+    basegfx::BGradient aBGradient = 
basegfx::BGradient::fromJSON(sJSONGradient);
+    css::awt::Gradient aGradient = aBGradient.getAsGradient2();
 
     try
     {
@@ -973,9 +972,9 @@ void 
ChartController::executeDispatch_FillGradient(std::u16string_view sJSONGrad
             if( xPropSet.is() )
             {
                 OUString aPrefferedName =
-                    
OUString::number(static_cast<sal_Int32>(Color(aXGradient.GetColorStops().front().getStopColor())))
-                    + 
OUString::number(static_cast<sal_Int32>(Color(aXGradient.GetColorStops().back().getStopColor())))
-                    + 
OUString::number(static_cast<sal_Int32>(aXGradient.GetAngle().get()));
+                    
OUString::number(static_cast<sal_Int32>(Color(aBGradient.GetColorStops().front().getStopColor())))
+                    + 
OUString::number(static_cast<sal_Int32>(Color(aBGradient.GetColorStops().back().getStopColor())))
+                    + 
OUString::number(static_cast<sal_Int32>(aBGradient.GetAngle().get()));
 
                 OUString aNewName = 
PropertyHelper::addGradientUniqueNameToTable(css::uno::Any(aGradient),
                                         xChartModel,
diff --git a/cui/source/inc/cuitabarea.hxx b/cui/source/inc/cuitabarea.hxx
index 55470628e0ae..b05ce7af425f 100644
--- a/cui/source/inc/cuitabarea.hxx

... etc. - the rest is truncated

Reply via email to