basegfx/source/tools/bgradient.cxx                        |   69 ++++++++------
 cui/source/tabpages/tpgradnt.cxx                          |   18 ---
 cui/source/tabpages/tptrans.cxx                           |   15 ---
 include/basegfx/utils/bgradient.hxx                       |   12 +-
 sd/source/ui/sidebar/SlideBackground.cxx                  |   18 ---
 svx/source/customshapes/EnhancedCustomShape2d.cxx         |   12 +-
 svx/source/sidebar/area/AreaPropertyPanelBase.cxx         |   16 ---
 svx/source/sidebar/area/AreaTransparencyGradientPopup.cxx |   14 --
 8 files changed, 69 insertions(+), 105 deletions(-)

New commits:
commit d37666e14fdd23b6c8e0abc80f1c67fd33e9fc9a
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Thu Dec 11 13:19:43 2025 +0900
Commit:     Tomaž Vajngerl <[email protected]>
CommitDate: Mon Dec 15 04:07:44 2025 +0100

    basegfx: don't allow in-place changing of BColorStops externally
    
    All the changes should go through BColorStops interface and not
    directly.
    
    Change-Id: I4c6dd42f8d6b6c43cdcf9d53557ccb12f8d0507c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195386
    Reviewed-by: Tomaž Vajngerl <[email protected]>
    Tested-by: Jenkins

diff --git a/basegfx/source/tools/bgradient.cxx 
b/basegfx/source/tools/bgradient.cxx
index 0c07327cd9c8..2e86774672d5 100644
--- a/basegfx/source/tools/bgradient.cxx
+++ b/basegfx/source/tools/bgradient.cxx
@@ -196,23 +196,24 @@ BColor BColorStops::getInterpolatedBColor(double 
fPosition, sal_uInt32 nRequeste
     */
 void BColorStops::replaceStartColor(const BColor& rStart)
 {
-    BColorStops::iterator a1stNonStartColor(begin());
+    auto a1stNonStartColorIterator(maStops.begin());
 
     // search for highest existing non-StartColor - CAUTION,
     // there might be none, one or multiple with StopOffset 0.0
-    while (a1stNonStartColor != end() && a1stNonStartColor->getStopOffset() <= 
0.0)
-        a1stNonStartColor++;
+    while (a1stNonStartColorIterator != end() && 
a1stNonStartColorIterator->getStopOffset() <= 0.0)
+        a1stNonStartColorIterator++;
 
     // create new ColorStops by 1st adding new one and then all
     // non-StartColor entries
     BColorStops aNewColorStops;
 
-    aNewColorStops.reserve(size() + 1);
+    aNewColorStops.maStops.reserve(size() + 1);
     aNewColorStops.addStop(0.0, rStart);
-    aNewColorStops.maStops.insert(aNewColorStops.end(), a1stNonStartColor, 
end());
+    aNewColorStops.maStops.insert(aNewColorStops.maStops.end(), 
a1stNonStartColorIterator,
+                                  maStops.end());
 
     // assign & done
-    *this = std::move(aNewColorStops);
+    maStops = std::move(aNewColorStops.maStops);
 }
 
 /* Tooling method that allows to replace the EndColor in a
@@ -260,12 +261,12 @@ void BColorStops::blendToIntensity(double 
fStartIntensity, double fEndIntensity,
         return;
 
     // blend relative to StopOffset position
-    for (auto& candidate : *this)
+    for (auto& rCandidate : maStops)
     {
-        const double fOffset(candidate.getStopOffset());
+        const double fOffset(rCandidate.getStopOffset());
         const double fIntensity((fStartIntensity * (1.0 - fOffset)) + 
(fEndIntensity * fOffset));
-        candidate = basegfx::BColorStop(
-            fOffset, basegfx::interpolate(rBlendColor, 
candidate.getStopColor(), fIntensity));
+        rCandidate = basegfx::BColorStop(
+            fOffset, basegfx::interpolate(rBlendColor, 
rCandidate.getStopColor(), fIntensity));
     }
 }
 
@@ -318,7 +319,7 @@ void BColorStops::sortAndCorrect()
     // 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());
+    std::sort(maStops.begin(), maStops.end());
 
     // prepare status values
     size_t write(0);
@@ -485,7 +486,7 @@ bool BColorStops::isSingleColor(BColor& rSingleColor) const
 
     rSingleColor = front().getStopColor();
 
-    for (auto const& rCandidate : *this)
+    for (auto const& rCandidate : maStops)
     {
         if (rCandidate.getStopColor() != rSingleColor)
             return false;
@@ -500,8 +501,8 @@ bool BColorStops::isSingleColor(BColor& rSingleColor) const
 void BColorStops::reverseColorStops()
 {
     // can use std::reverse, but also need to adapt offset(s)
-    std::reverse(begin(), end());
-    for (auto& candidate : *this)
+    std::reverse(maStops.begin(), maStops.end());
+    for (auto& candidate : maStops)
         candidate = BColorStop(1.0 - candidate.getStopOffset(), 
candidate.getStopColor());
 }
 
@@ -522,13 +523,13 @@ void BColorStops::createSpaceAtStart(double fOffset)
 
     BColorStops aNewStops;
 
-    for (const auto& candidate : *this)
+    for (const auto& candidate : maStops)
     {
         aNewStops.addStop(fOffset + (candidate.getStopOffset() * (1.0 - 
fOffset)),
                           candidate.getStopColor());
     }
 
-    *this = std::move(aNewStops);
+    maStops = std::move(aNewStops.maStops);
 }
 
 // removeSpaceAtStart removes fOffset space from start by
@@ -550,7 +551,7 @@ void BColorStops::removeSpaceAtStart(double fOffset)
     BColorStops aNewStops;
     const double fMul(basegfx::fTools::equal(fOffset, 1.0) ? 1.0 : 1.0 / (1.0 
- fOffset));
 
-    for (const auto& candidate : *this)
+    for (const auto& candidate : maStops)
     {
         if (basegfx::fTools::moreOrEqual(candidate.getStopOffset(), fOffset))
         {
@@ -559,7 +560,7 @@ void BColorStops::removeSpaceAtStart(double fOffset)
         }
     }
 
-    *this = std::move(aNewStops);
+    maStops = std::move(aNewStops.maStops);
 }
 
 // try to detect if an empty/no-color-change area exists
@@ -656,7 +657,7 @@ void BColorStops::doApplyAxial()
     }
 
     // apply color stops
-    *this = std::move(aNewColorStops);
+    maStops = std::move(aNewColorStops.maStops);
 }
 
 void BColorStops::doApplySteps(sal_uInt16 nStepCount)
@@ -729,7 +730,7 @@ void BColorStops::doApplySteps(sal_uInt16 nStepCount)
     }
 
     // apply the change to color stops
-    *this = std::move(aNewColorStops);
+    maStops = std::move(aNewColorStops.maStops);
 }
 
 void BColorStops::tryToApplyBColorModifierStack(const BColorModifierStack& 
rBColorModifierStack)
@@ -738,7 +739,7 @@ void BColorStops::tryToApplyBColorModifierStack(const 
BColorModifierStack& rBCol
         // no content on stack, done
         return;
 
-    for (auto& candidate : *this)
+    for (auto& candidate : maStops)
     {
         candidate = BColorStop(candidate.getStopOffset(),
                                
rBColorModifierStack.getModifiedColor(candidate.getStopColor()));
@@ -764,6 +765,21 @@ bool BColorStops::sameSizeAndDistances(const BColorStops& 
rComp) const
     return EntryA == end();
 }
 
+void BColorStops::changeStartAndEnd(BColor const& rStart, BColor const& rEnd)
+{
+    if (size() >= 2)
+    {
+        maStops.front() = BColorStop(maStops.front().getStopOffset(), rStart);
+        maStops.back() = BColorStop(maStops.back().getStopOffset(), rEnd);
+    }
+    else
+    {
+        clear();
+        addStop(0.0, rStart);
+        addStop(1.0, rEnd);
+    }
+}
+
 std::string BGradient::GradientStyleToString(css::awt::GradientStyle eStyle)
 {
     switch (eStyle)
@@ -839,9 +855,9 @@ bool BGradient::operator==(const BGradient& rGradient) const
             && nStepCount == rGradient.nStepCount);
 }
 
-void BGradient::SetColorStops(const basegfx::BColorStops& rSteps)
+void BGradient::SetColorStops(const basegfx::BColorStops& rStops)
 {
-    aColorStops = rSteps;
+    aColorStops = rStops;
     aColorStops.sortAndCorrect();
     if (aColorStops.empty())
         aColorStops.addStop(0.0, basegfx::BColor());
@@ -972,10 +988,10 @@ void BGradient::tryToApplyStartEndIntensity()
 void BGradient::tryToConvertToAxial()
 {
     if (css::awt::GradientStyle_LINEAR != GetGradientStyle() || 0 != 
GetBorder()
-        || GetColorStops().empty())
+        || aColorStops.empty())
         return;
 
-    if (!GetColorStops().isSymmetrical())
+    if (!aColorStops.isSymmetrical())
         return;
 
     SetGradientStyle(css::awt::GradientStyle_AXIAL);
@@ -983,8 +999,7 @@ void BGradient::tryToConvertToAxial()
     // Stretch the first half of the color stops to double width
     // and collect them in a new color stops vector.
     BColorStops aAxialColorStops;
-    aAxialColorStops.reserve(std::ceil(GetColorStops().size() / 2.0));
-    BColorStops::const_iterator aIter(GetColorStops().begin());
+    BColorStops::const_iterator aIter(aColorStops.begin());
     while (basegfx::fTools::lessOrEqual(aIter->getStopOffset(), 0.5))
     {
         BColorStop aNextStop(std::clamp((*aIter).getStopOffset() * 2.0, 0.0, 
1.0),
diff --git a/cui/source/tabpages/tpgradnt.cxx b/cui/source/tabpages/tpgradnt.cxx
index f29acef6d3ad..332c087fd537 100644
--- a/cui/source/tabpages/tpgradnt.cxx
+++ b/cui/source/tabpages/tpgradnt.cxx
@@ -659,21 +659,11 @@ sal_Int32 
SvxGradientTabPage::SearchGradientList(std::u16string_view rGradientNa
 
 basegfx::BColorStops SvxGradientTabPage::createColorStops()
 {
-    basegfx::BColorStops aColorStops;
+    basegfx::BColorStops aColorStops = m_aColorStops;
 
-    if(m_aColorStops.size() >= 2)
-    {
-        aColorStops = m_aColorStops;
-        aColorStops.front() = 
basegfx::BColorStop(m_aColorStops.front().getStopOffset(),
-                                                  
m_xLbColorFrom->GetSelectEntryColor().getBColor());
-        aColorStops.back() = 
basegfx::BColorStop(m_aColorStops.back().getStopOffset(),
-                                                 
m_xLbColorTo->GetSelectEntryColor().getBColor());
-    }
-    else
-    {
-        aColorStops.addStop(0.0, 
m_xLbColorFrom->GetSelectEntryColor().getBColor());
-        aColorStops.addStop(1.0, 
m_xLbColorTo->GetSelectEntryColor().getBColor());
-    }
+    aColorStops.changeStartAndEnd(
+                    m_xLbColorFrom->GetSelectEntryColor().getBColor(),
+                    m_xLbColorTo->GetSelectEntryColor().getBColor());
 
     return aColorStops;
 }
diff --git a/cui/source/tabpages/tptrans.cxx b/cui/source/tabpages/tptrans.cxx
index d787d087edec..b8eedeb11efb 100644
--- a/cui/source/tabpages/tptrans.cxx
+++ b/cui/source/tabpages/tptrans.cxx
@@ -512,24 +512,13 @@ void SvxTransparenceTabPage::InvalidatePreview (bool 
bEnable)
 
 basegfx::BColorStops SvxTransparenceTabPage::createColorStops()
 {
-    basegfx::BColorStops aColorStops;
     basegfx::BColor 
aStartBColor(m_xMtrTrgrStartValue->get_value(FieldUnit::PERCENT) / 100.0);
     aStartBColor.clamp();
     basegfx::BColor 
aEndBColor(m_xMtrTrgrEndValue->get_value(FieldUnit::PERCENT) / 100.0);
     aEndBColor.clamp();
 
-    if(maColorStops.size() >= 2)
-    {
-        aColorStops = maColorStops;
-        aColorStops.front() = 
basegfx::BColorStop(maColorStops.front().getStopOffset(), aStartBColor);
-        aColorStops.back() = 
basegfx::BColorStop(maColorStops.back().getStopOffset(), aEndBColor);
-    }
-    else
-    {
-        aColorStops.addStop(0.0, aStartBColor);
-        aColorStops.addStop(1.0, aEndBColor);
-    }
-
+    basegfx::BColorStops aColorStops = maColorStops;
+    aColorStops.changeStartAndEnd(aStartBColor, aEndBColor);
     return aColorStops;
 }
 
diff --git a/include/basegfx/utils/bgradient.hxx 
b/include/basegfx/utils/bgradient.hxx
index 2bafcc7f9fc1..2c84548b48ed 100644
--- a/include/basegfx/utils/bgradient.hxx
+++ b/include/basegfx/utils/bgradient.hxx
@@ -103,7 +103,6 @@ private:
 
 public:
     typedef typename std::vector<BColorStop>::size_type size_type;
-    typedef typename std::vector<BColorStop>::iterator iterator;
     typedef typename std::vector<BColorStop>::const_iterator const_iterator;
     typedef typename std::vector<BColorStop>::const_reverse_iterator 
const_reverse_iterator;
 
@@ -124,7 +123,7 @@ public:
 
     // constructor with two colors to explicitly create a
     // BColorStops for StartColor @0.0 & EndColor @1.0
-    BColorStops(const BColor& rStart, const BColor& rEnd);
+    BColorStops(BColor const& rStart, BColor const& rEnd);
 
     BColorStops& operator=(const BColorStops& rOther)
     {
@@ -143,7 +142,10 @@ public:
 
     BColorStop const& getStop(size_t i) const { return maStops[i]; }
     double getStopOffset(size_t i) const { return maStops[i].getStopOffset(); }
-    BColor const& getStopColor(size_t i) const { return 
maStops[i].getStopColor(); }
+
+    void changeStartAndEnd(BColor const& rStart, BColor const& rEnd);
+
+    BColor getStopColor(size_t i) const { return maStops[i].getStopColor(); }
 
     void removeLastStop() { return maStops.pop_back(); }
 
@@ -151,16 +153,12 @@ public:
     void clear() { maStops.clear(); }
     bool empty() const { return maStops.empty(); }
     size_type size() const { return maStops.size(); }
-    iterator begin() { return maStops.begin(); }
-    iterator end() { return maStops.end(); }
     const_iterator begin() const { return maStops.begin(); }
     const_iterator end() const { return maStops.end(); }
     const_reverse_iterator rbegin() const { return maStops.rbegin(); }
     const_reverse_iterator rend() const { return maStops.rend(); }
     const BColorStop& front() const { return maStops.front(); }
     const BColorStop& back() const { return maStops.back(); }
-    BColorStop& front() { return maStops.front(); }
-    BColorStop& back() { return maStops.back(); }
     bool operator==(BColorStops const& rOther) const { return maStops == 
rOther.maStops; }
 
     // helper data struct to support buffering entries in
diff --git a/sd/source/ui/sidebar/SlideBackground.cxx 
b/sd/source/ui/sidebar/SlideBackground.cxx
index ed852ec22b20..af856ce005ec 100644
--- a/sd/source/ui/sidebar/SlideBackground.cxx
+++ b/sd/source/ui/sidebar/SlideBackground.cxx
@@ -1289,21 +1289,11 @@ IMPL_LINK_NOARG( SlideBackground, ModifyMarginHdl, 
weld::ComboBox&, void )
 
 basegfx::BColorStops SlideBackground::createColorStops()
 {
-    basegfx::BColorStops aColorStops;
+    basegfx::BColorStops aColorStops = maColorStops;
 
-    if (maColorStops.size() >= 2)
-    {
-        aColorStops = maColorStops;
-        aColorStops.front() = 
basegfx::BColorStop(maColorStops.front().getStopOffset(),
-                                                  
mxFillGrad1->GetSelectEntryColor().getBColor());
-        aColorStops.back() = 
basegfx::BColorStop(maColorStops.back().getStopOffset(),
-                                                 
mxFillGrad2->GetSelectEntryColor().getBColor());
-    }
-    else
-    {
-        aColorStops.addStop(0.0, 
mxFillGrad1->GetSelectEntryColor().getBColor());
-        aColorStops.addStop(1.0, 
mxFillGrad2->GetSelectEntryColor().getBColor());
-    }
+    aColorStops.changeStartAndEnd(
+        mxFillGrad1->GetSelectEntryColor().getBColor(),
+        mxFillGrad2->GetSelectEntryColor().getBColor());
 
     return aColorStops;
 }
diff --git a/svx/source/customshapes/EnhancedCustomShape2d.cxx 
b/svx/source/customshapes/EnhancedCustomShape2d.cxx
index 9f1cf355991a..83edaec4a6dc 100644
--- a/svx/source/customshapes/EnhancedCustomShape2d.cxx
+++ b/svx/source/customshapes/EnhancedCustomShape2d.cxx
@@ -2821,15 +2821,15 @@ void EnhancedCustomShape2d::AdaptObjColor(
 
             if ( nColorCount || 0.0 != dBrightness )
             {
-                basegfx::BColorStops aColorStops(aBGradient.GetColorStops());
-                for (auto& candidate : aColorStops)
+                basegfx::BColorStops aColorStops;
+                for (auto const& candidate : aBGradient.GetColorStops())
                 {
-                    candidate = basegfx::BColorStop(
-                        candidate.getStopOffset(),
-                        GetColorData(
+                    basegfx::BColor aBColor = GetColorData(
                             Color(candidate.getStopColor()),
                             nColorCount ? std::min(nColorIndex, nColorCount-1) 
: nColorIndex,
-                            dBrightness ).getBColor());
+                            dBrightness).getBColor();
+
+                    aColorStops.addStop(candidate.getStopOffset(), aBColor);
                 }
                 aBGradient.SetColorStops(aColorStops);
             }
diff --git a/svx/source/sidebar/area/AreaPropertyPanelBase.cxx 
b/svx/source/sidebar/area/AreaPropertyPanelBase.cxx
index 1cc38dcf4f55..fed25aba8160 100644
--- a/svx/source/sidebar/area/AreaPropertyPanelBase.cxx
+++ b/svx/source/sidebar/area/AreaPropertyPanelBase.cxx
@@ -1371,19 +1371,11 @@ sal_Int32 
AreaPropertyPanelBase::GetSelectedTransparencyTypeIndex() const
 
 basegfx::BColorStops AreaPropertyPanelBase::createColorStops()
 {
-    basegfx::BColorStops aColorStops;
+    basegfx::BColorStops aColorStops = maColorStops;
 
-    if (maColorStops.size() >= 2)
-    {
-        aColorStops = maColorStops;
-        aColorStops.front() = 
basegfx::BColorStop(maColorStops.front().getStopOffset(), 
mxLbFillGradFrom->GetSelectEntryColor().getBColor());
-        aColorStops.back() = 
basegfx::BColorStop(maColorStops.back().getStopOffset(), 
mxLbFillGradTo->GetSelectEntryColor().getBColor());
-    }
-    else
-    {
-        aColorStops.addStop(0.0, 
mxLbFillGradFrom->GetSelectEntryColor().getBColor());
-        aColorStops.addStop(1.0, 
mxLbFillGradTo->GetSelectEntryColor().getBColor());
-    }
+    aColorStops.changeStartAndEnd(
+        mxLbFillGradFrom->GetSelectEntryColor().getBColor(),
+        mxLbFillGradTo->GetSelectEntryColor().getBColor());
 
     return aColorStops;
 }
diff --git a/svx/source/sidebar/area/AreaTransparencyGradientPopup.cxx 
b/svx/source/sidebar/area/AreaTransparencyGradientPopup.cxx
index d734d1062850..d1c07603ee85 100644
--- a/svx/source/sidebar/area/AreaTransparencyGradientPopup.cxx
+++ b/svx/source/sidebar/area/AreaTransparencyGradientPopup.cxx
@@ -133,23 +133,13 @@ void AreaTransparencyGradientPopup::ExecuteValueModify()
     mxMtrTrgrAngle->set_value(nVal, FieldUnit::DEGREE);
     //End of new code
 
-    basegfx::BColorStops aColorStops;
     basegfx::BColor 
aStartBColor(mxMtrTrgrStartValue->get_value(FieldUnit::PERCENT) / 100.0);
     aStartBColor.clamp();
     basegfx::BColor 
aEndBColor(mxMtrTrgrEndValue->get_value(FieldUnit::PERCENT) / 100.0);
     aEndBColor.clamp();
 
-    if (maColorStops.size() >= 2)
-    {
-        aColorStops = maColorStops;
-        aColorStops.front()  = 
basegfx::BColorStop(maColorStops.front().getStopOffset(), aStartBColor);
-        aColorStops.back() = 
basegfx::BColorStop(maColorStops.back().getStopOffset(), aEndBColor);
-    }
-    else
-    {
-        aColorStops.addStop(0.0, aStartBColor);
-        aColorStops.addStop(1.0, aEndBColor);
-    }
+    basegfx::BColorStops aColorStops = maColorStops; // copy
+    aColorStops.changeStartAndEnd(aStartBColor, aEndBColor);
 
     basegfx::BGradient aTmpGradient(
         aColorStops,

Reply via email to