sc/inc/colorscale.hxx              |    8 +++---
 sc/source/core/data/colorscale.cxx |   47 +++++++++++++++++++++----------------
 2 files changed, 31 insertions(+), 24 deletions(-)

New commits:
commit be86af4142151a10a2cd46ff0bff94019c71981d
Author:     Caolán McNamara <[email protected]>
AuthorDate: Wed Oct 22 11:12:18 2025 +0100
Commit:     Xisco Fauli <[email protected]>
CommitDate: Mon Nov 3 17:06:08 2025 +0100

    tdf#168979 survive broken color percentile scales
    
    Change-Id: I3180d08272fd7355987f63f5379a044d98467cf0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192838
    Reviewed-by: Caolán McNamara <[email protected]>
    Tested-by: Jenkins
    Signed-off-by: Xisco Fauli <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192845
    Signed-off-by: Xisco Fauli <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192853
    Reviewed-by: Adolfo Jayme Barrientos <[email protected]>
    Tested-by: Ilmari Lauhakangas <[email protected]>

diff --git a/sc/inc/colorscale.hxx b/sc/inc/colorscale.hxx
index 52425a8d0658..79803d399bf9 100644
--- a/sc/inc/colorscale.hxx
+++ b/sc/inc/colorscale.hxx
@@ -258,7 +258,7 @@ private:
     double GetMaxValue() const;
 
     void calcMinMax(double& nMin, double& nMax) const;
-    double CalcValue(double nMin, double nMax, const 
ScColorScaleEntries::const_iterator& rItr) const;
+    std::optional<double> CalcValue(double nMin, double nMax, const 
ScColorScaleEntries::const_iterator& rItr) const;
 public:
     SC_DLLPUBLIC ScColorScaleFormat(ScDocument& rDoc);
     ScColorScaleFormat(ScDocument& rDoc, const ScColorScaleFormat& rFormat);
@@ -329,8 +329,8 @@ public:
     void EnsureSize();
 
 private:
-    double getMin(double nMin, double nMax) const;
-    double getMax(double nMin, double nMax) const;
+    std::optional<double> getMin(double nMin, double nMax) const;
+    std::optional<double> getMax(double nMin, double nMax) const;
 
     std::unique_ptr<ScDataBarFormatData> mpFormatData;
 };
@@ -410,7 +410,7 @@ private:
 
     double GetMinValue() const;
     double GetMaxValue() const;
-    double CalcValue(double nMin, double nMax, const 
ScIconSetFormat::const_iterator& itr) const;
+    std::optional<double> CalcValue(double nMin, double nMax, const 
ScIconSetFormat::const_iterator& itr) const;
 
     std::unique_ptr<ScIconSetFormatData> mpFormatData;
 };
diff --git a/sc/source/core/data/colorscale.cxx 
b/sc/source/core/data/colorscale.cxx
index 817a30a6ccb8..04767f1d60d2 100644
--- a/sc/source/core/data/colorscale.cxx
+++ b/sc/source/core/data/colorscale.cxx
@@ -607,9 +607,15 @@ Color CalcColor( double nVal, double nVal1, const Color& 
rCol1, double nVal2, co
  * @param rVector sorted vector of the array
  * @param fPercentile percentile
  */
-double GetPercentile( const std::vector<double>& rArray, double fPercentile )
+std::optional<double> GetPercentile( const std::vector<double>& rArray, double 
fPercentile )
 {
-    assert(!rArray.empty());
+    if (rArray.empty())
+    {
+        // An empty getValues() is invalid for COLORSCALE_PERCENTILE.
+        SAL_WARN("sc", "empty COLORSCALE_PERCENTILE");
+        return std::optional<double>();
+    }
+
     SAL_WARN_IF(fPercentile < 0, "sc", "negative percentile");
     if (fPercentile < 0)
         return rArray.front();
@@ -633,7 +639,7 @@ double GetPercentile( const std::vector<double>& rArray, 
double fPercentile )
 
 }
 
-double ScColorScaleFormat::CalcValue(double nMin, double nMax, const 
ScColorScaleEntries::const_iterator& itr) const
+std::optional<double> ScColorScaleFormat::CalcValue(double nMin, double nMax, 
const ScColorScaleEntries::const_iterator& itr) const
 {
     switch((*itr)->GetType())
     {
@@ -684,20 +690,16 @@ std::optional<Color> ScColorScaleFormat::GetColor( const 
ScAddress& rAddr ) cons
 
     ScColorScaleEntries::const_iterator itr = begin();
 
-    // CalcValue will call GetPercentile for COLORSCALE_PERCENTILE. An empty
-    // getValues() is invalid for COLORSCALE_PERCENTILE.
-    if ((*itr)->GetType() == COLORSCALE_PERCENTILE && getValues().empty())
-    {
-        SAL_WARN("sc", "empty COLORSCALE_PERCENTILE");
-        return std::optional<Color>();
-    }
-
-    double nValMin = CalcValue(nMin, nMax, itr);
+    std::optional<double> aValMin = CalcValue(nMin, nMax, itr);
     Color rColMin = (*itr)->GetColor();
     ++itr;
-    double nValMax = CalcValue(nMin, nMax, itr);
+    std::optional<double> aValMax = CalcValue(nMin, nMax, itr);
     Color rColMax = (*itr)->GetColor();
 
+    if (!aValMin || !aValMax)
+        return std::optional<Color>();
+    double nValMin(*aValMin), nValMax(*aValMax);
+
     // tdf#155321 for the last percentile value, use always the end of the 
color scale,
     // i.e. not the first possible color in the case of repeating values
     bool bEqual = COLORSCALE_PERCENTILE == (*itr)->GetType() && nVal == nMax 
&& nVal == nValMax;
@@ -708,7 +710,7 @@ std::optional<Color> ScColorScaleFormat::GetColor( const 
ScAddress& rAddr ) cons
         rColMin = rColMax;
         nValMin = !bEqual ? nValMax : nValMax - 1;
         rColMax = (*itr)->GetColor();
-        nValMax = CalcValue(nMin, nMax, itr);
+        nValMax = *CalcValue(nMin, nMax, itr);
         ++itr;
     }
 
@@ -906,7 +908,7 @@ void ScDataBarFormat::UpdateMoveTab( 
sc::RefUpdateMoveTabContext& rCxt )
     mpFormatData->mpLowerLimit->UpdateMoveTab(rCxt);
 }
 
-double ScDataBarFormat::getMin(double nMin, double nMax) const
+std::optional<double> ScDataBarFormat::getMin(double nMin, double nMax) const
 {
     switch(mpFormatData->mpLowerLimit->GetType())
     {
@@ -933,7 +935,7 @@ double ScDataBarFormat::getMin(double nMin, double nMax) 
const
     return mpFormatData->mpLowerLimit->GetValue();
 }
 
-double ScDataBarFormat::getMax(double nMin, double nMax) const
+std::optional<double> ScDataBarFormat::getMax(double nMin, double nMax) const
 {
     switch(mpFormatData->mpUpperLimit->GetType())
     {
@@ -967,8 +969,13 @@ std::unique_ptr<ScDataBarInfo> 
ScDataBarFormat::GetDataBarInfo(const ScAddress&
 
     double nValMin = getMinValue();
     double nValMax = getMaxValue();
-    double nMin = getMin(nValMin, nValMax);
-    double nMax = getMax(nValMin, nValMax);
+    std::optional<double> aMin = getMin(nValMin, nValMax);
+    std::optional<double> aMax = getMax(nValMin, nValMax);
+    if (!aMin || !aMax)
+        return nullptr;
+
+    double nMin(*aMin), nMax(*aMax);
+
     double nMinLength = mpFormatData->mnMinLength;
     double nMaxLength = mpFormatData->mnMaxLength;
 
@@ -1192,7 +1199,7 @@ std::unique_ptr<ScIconSetInfo> 
ScIconSetFormat::GetIconSetInfo(const ScAddress&
     int i = 0;
     while(itr != end())
     {
-        nValRef = CalcValue(nMin, nMax, itr);
+        nValRef = *CalcValue(nMin, nMax, itr);
         if (Compare(nVal, nValRef, itr))
         {
             nIndex = i;
@@ -1320,7 +1327,7 @@ double ScIconSetFormat::GetMaxValue() const
     }
 }
 
-double ScIconSetFormat::CalcValue(double nMin, double nMax, const 
ScIconSetFormat::const_iterator& itr) const
+std::optional<double> ScIconSetFormat::CalcValue(double nMin, double nMax, 
const ScIconSetFormat::const_iterator& itr) const
 {
     switch ((*itr)->GetType())
     {

Reply via email to