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()) {
