sc/inc/colorscale.hxx | 8 ++--- sc/source/core/data/colorscale.cxx | 52 ++++++++++++++++++++++--------------- 2 files changed, 35 insertions(+), 25 deletions(-)
New commits: commit 7de34daac7dc0ce903f1af44771b7900a43f7cae Author: Caolán McNamara <[email protected]> AuthorDate: Wed Oct 22 11:12:18 2025 +0100 Commit: Miklos Vajna <[email protected]> CommitDate: Wed Oct 22 16:38:48 2025 +0200 tdf#168979 survive broken color percentile scales Change-Id: I3180d08272fd7355987f63f5379a044d98467cf0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192836 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Miklos Vajna <[email protected]> diff --git a/sc/inc/colorscale.hxx b/sc/inc/colorscale.hxx index 373c06eda05c..2f7d633c1416 100644 --- a/sc/inc/colorscale.hxx +++ b/sc/inc/colorscale.hxx @@ -256,7 +256,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* pDoc); ScColorScaleFormat(ScDocument* pDoc, const ScColorScaleFormat& rFormat); @@ -327,8 +327,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; }; @@ -408,7 +408,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 e947857b7497..4625888184ac 100644 --- a/sc/source/core/data/colorscale.cxx +++ b/sc/source/core/data/colorscale.cxx @@ -606,9 +606,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(); @@ -632,7 +638,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()) { @@ -683,20 +689,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; @@ -707,7 +709,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; } @@ -905,7 +907,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()) { @@ -932,7 +934,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()) { @@ -966,8 +968,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; @@ -1165,7 +1172,10 @@ std::unique_ptr<ScIconSetInfo> ScIconSetFormat::GetIconSetInfo(const ScAddress& sal_Int32 nIndex = 0; const_iterator itr = begin(); ++itr; - double nValMax = CalcValue(nMin, nMax, itr); + std::optional<double> aValMax = CalcValue(nMin, nMax, itr); + if (!aValMax) + return nullptr; + double nValMax(*aValMax); ++itr; bool bGreaterThanOrEqual = true; @@ -1173,7 +1183,7 @@ std::unique_ptr<ScIconSetInfo> ScIconSetFormat::GetIconSetInfo(const ScAddress& { bGreaterThanOrEqual = (*itr)->GetGreaterThanOrEqual(); ++nIndex; - nValMax = CalcValue(nMin, nMax, itr); + nValMax = *CalcValue(nMin, nMax, itr); ++itr; } @@ -1303,7 +1313,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()) {
