sc/inc/colorscale.hxx              |   13 ++-----
 sc/inc/conditio.hxx                |   20 +++++++++++
 sc/source/core/data/colorscale.cxx |   37 +++++++++++++++------
 sc/source/core/data/conditio.cxx   |   63 +++++++++++++++++++++++++++++++++++++
 4 files changed, 113 insertions(+), 20 deletions(-)

New commits:
commit c84a1928ea76cf175711942db9ca7bb2f0ec6f0b
Author:     Dennis Francis <dennis.fran...@collabora.com>
AuthorDate: Tue Oct 3 12:40:25 2023 +0530
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Mon Jan 15 17:19:38 2024 +0100

    sc: condfmt-perf: use a shared cache that...
    
    is reset only when the data changes. Resetting is done only on
    invalidation of associated ranges of data via a listener.
    
    Earlier there were three separate caches that resets on every draw.
    
    Change-Id: I1c185ece4b781bf6db7c82697cd5225d98c82651
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157508
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 1aa1a5340f63b31524117a3cfd6e05bee2aa1aa0)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161998
    Tested-by: Jenkins

diff --git a/sc/inc/colorscale.hxx b/sc/inc/colorscale.hxx
index 6652e224fe67..f43f533e8f60 100644
--- a/sc/inc/colorscale.hxx
+++ b/sc/inc/colorscale.hxx
@@ -224,7 +224,7 @@ public:
     virtual ~ScColorFormat() override;
 
     const ScRangeList& GetRange() const;
-    void SetCache(const std::vector<double>& aValues);
+    void SetCache(const std::vector<double>& aValues) const;
     std::vector<double> GetCache() const;
 
     virtual void SetParent(ScConditionalFormat* pParent) override;
@@ -240,14 +240,6 @@ protected:
     double getMaxValue() const;
 
     ScConditionalFormat* mpParent;
-
-private:
-
-    struct ScColorFormatCache
-    {
-        std::vector<double> maValues;
-    };
-    mutable std::unique_ptr<ScColorFormatCache> mpCache;
 };
 
 typedef std::vector<std::unique_ptr<ScColorScaleEntry, 
o3tl::default_delete<ScColorScaleEntry>>> ScColorScaleEntries;
@@ -265,7 +257,10 @@ private:
 public:
     ScColorScaleFormat(ScDocument* pDoc);
     ScColorScaleFormat(ScDocument* pDoc, const ScColorScaleFormat& rFormat);
+    ScColorScaleFormat(const ScColorScaleFormat&) = delete;
     virtual ~ScColorScaleFormat() override;
+    const ScColorScaleFormat& operator=(const ScColorScaleFormat&) = delete;
+
     virtual ScColorFormat* Clone(ScDocument* pDoc) const override;
 
     virtual void SetParent(ScConditionalFormat* pParent) override;
diff --git a/sc/inc/conditio.hxx b/sc/inc/conditio.hxx
index c3ef00e5cf93..ba5e0289bab8 100644
--- a/sc/inc/conditio.hxx
+++ b/sc/inc/conditio.hxx
@@ -538,6 +538,20 @@ private:
     OUString maStyleName;
 };
 
+class ScColorFormatCache final : public SvtListener
+{
+private:
+    ScDocument& mrDoc;
+
+public:
+    explicit ScColorFormatCache(ScDocument& rDoc, const ScRangeList& rRanges);
+    virtual ~ScColorFormatCache() override;
+
+    void Notify( const SfxHint& rHint ) override;
+
+    std::vector<double> maValues;
+};
+
 //  complete conditional formatting
 class SC_DLLPUBLIC ScConditionalFormat
 {
@@ -547,6 +561,8 @@ class SC_DLLPUBLIC ScConditionalFormat
     std::vector<std::unique_ptr<ScFormatEntry>> maEntries;
     ScRangeList maRanges;            // Ranges for conditional format
 
+    mutable std::unique_ptr<ScColorFormatCache> mpCache;
+
 public:
     ScConditionalFormat(sal_uInt32 nNewKey, ScDocument* pDocument);
     ~ScConditionalFormat();
@@ -606,6 +622,10 @@ public:
 
     // Forced recalculation for formulas
     void CalcAll();
+
+    void ResetCache() const;
+    void SetCache(const std::vector<double>& aValues) const;
+    std::vector<double>* GetCache() const;
 };
 
 class RepaintInIdle final : public Idle
diff --git a/sc/source/core/data/colorscale.cxx 
b/sc/source/core/data/colorscale.cxx
index eff6d050b13b..415dde5872e5 100644
--- a/sc/source/core/data/colorscale.cxx
+++ b/sc/source/core/data/colorscale.cxx
@@ -462,22 +462,39 @@ const ScRangeList& ScColorFormat::GetRange() const
 
 std::vector<double> ScColorFormat::GetCache() const
 {
-    std::vector<double> empty;
-    return mpCache ? mpCache->maValues : empty;
+    if (!mpParent)
+        return {};
+
+    std::vector<double>* pRes = mpParent->GetCache();
+    if (pRes)
+        return *pRes;
+
+    return {};
 }
 
-void ScColorFormat::SetCache(const std::vector<double>& aValues)
+void ScColorFormat::SetCache(const std::vector<double>& aValues) const
 {
-    mpCache.reset(new ScColorFormatCache);
-    mpCache->maValues = aValues;
+    if (!mpParent)
+        return;
+
+    mpParent->SetCache(aValues);
 }
 
 std::vector<double>& ScColorFormat::getValues() const
 {
-    if(!mpCache)
+    assert(mpParent);
+
+    std::vector<double>* pCache = mpParent->GetCache();
+    if (!pCache || pCache->empty())
     {
-        mpCache.reset(new ScColorFormatCache);
-        std::vector<double>& rValues = mpCache->maValues;
+        if (!pCache)
+        {
+            SetCache({});
+            pCache = mpParent->GetCache();
+            assert(pCache);
+        }
+
+        std::vector<double>& rValues = *pCache;
 
         size_t n = GetRange().size();
         const ScRangeList& aRanges = GetRange();
@@ -515,7 +532,7 @@ std::vector<double>& ScColorFormat::getValues() const
         std::sort(rValues.begin(), rValues.end());
     }
 
-    return mpCache->maValues;
+    return *pCache;
 }
 
 double ScColorFormat::getMinValue() const
@@ -536,12 +553,10 @@ double ScColorFormat::getMaxValue() const
 
 void ScColorFormat::startRendering()
 {
-    mpCache.reset();
 }
 
 void ScColorFormat::endRendering()
 {
-    mpCache.reset();
 }
 
 void ScColorFormat::updateValues()
diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx
index 7c78669d8a3f..4c4ad49c67e7 100644
--- a/sc/source/core/data/conditio.cxx
+++ b/sc/source/core/data/conditio.cxx
@@ -1729,6 +1729,36 @@ void ScCondDateFormatEntry::endRendering()
     mpCache.reset();
 }
 
+ScColorFormatCache::ScColorFormatCache(ScDocument& rDoc, const ScRangeList& 
rRanges) :
+    mrDoc(rDoc)
+{
+    if (mrDoc.IsClipOrUndo())
+        return;
+
+    for (const ScRange& rRange: rRanges)
+        mrDoc.StartListeningArea(rRange, false, this);
+}
+
+ScColorFormatCache::~ScColorFormatCache()
+{
+    if (mrDoc.IsClipOrUndo())
+        return;
+
+    EndListeningAll();
+}
+
+void ScColorFormatCache::Notify(const SfxHint& rHint)
+{
+    if (rHint.GetId() == SfxHintId::Dying)
+    {
+        EndListeningAll();
+        return;
+    }
+
+    maValues.clear();
+}
+
+
 ScConditionalFormat::ScConditionalFormat(sal_uInt32 nNewKey, ScDocument* 
pDocument) :
     pDoc( pDocument ),
     nKey( nNewKey )
@@ -1777,6 +1807,7 @@ void ScConditionalFormat::SetRange( const ScRangeList& 
rRanges )
 {
     maRanges = rRanges;
     SAL_WARN_IF(maRanges.empty(), "sc", "the conditional format range is 
empty! will result in a crash later!");
+    ResetCache();
 }
 
 void ScConditionalFormat::AddEntry( ScFormatEntry* pNew )
@@ -1920,16 +1951,20 @@ void ScConditionalFormat::UpdateReference( 
sc::RefUpdateContext& rCxt, bool bCop
             rxEntry->UpdateReference(rCxt);
         maRanges.UpdateReference(rCxt.meMode, pDoc, rCxt.maRange, 
rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
     }
+
+    ResetCache();
 }
 
 void ScConditionalFormat::InsertRow(SCTAB nTab, SCCOL nColStart, SCCOL 
nColEnd, SCROW nRowPos, SCSIZE nSize)
 {
     maRanges.InsertRow(nTab, nColStart, nColEnd, nRowPos, nSize);
+    ResetCache();
 }
 
 void ScConditionalFormat::InsertCol(SCTAB nTab, SCROW nRowStart, SCROW 
nRowEnd, SCCOL nColPos, SCSIZE nSize)
 {
     maRanges.InsertCol(nTab, nRowStart, nRowEnd, nColPos, nSize);
+    ResetCache();
 }
 
 void ScConditionalFormat::UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt 
)
@@ -1948,6 +1983,8 @@ void ScConditionalFormat::UpdateInsertTab( 
sc::RefUpdateInsertTabContext& rCxt )
         rRange.aEnd.IncTab(rCxt.mnSheets);
     }
 
+    ResetCache();
+
     for (auto& rxEntry : maEntries)
         rxEntry->UpdateInsertTab(rCxt);
 }
@@ -1977,6 +2014,8 @@ void ScConditionalFormat::UpdateDeleteTab( 
sc::RefUpdateDeleteTabContext& rCxt )
         rRange.aEnd.IncTab(-1*rCxt.mnSheets);
     }
 
+    ResetCache();
+
     for (auto& rxEntry : maEntries)
         rxEntry->UpdateDeleteTab(rCxt);
 }
@@ -2014,6 +2053,8 @@ void ScConditionalFormat::UpdateMoveTab( 
sc::RefUpdateMoveTabContext& rCxt )
         }
     }
 
+    ResetCache();
+
     for (auto& rxEntry : maEntries)
         rxEntry->UpdateMoveTab(rCxt);
 }
@@ -2025,6 +2066,7 @@ void ScConditionalFormat::DeleteArea( SCCOL nCol1, SCROW 
nRow1, SCCOL nCol2, SCR
 
     SCTAB nTab = maRanges[0].aStart.Tab();
     maRanges.DeleteArea( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
+    ResetCache();
 }
 
 void ScConditionalFormat::RenameCellStyle(std::u16string_view rOld, const 
OUString& rNew)
@@ -2092,6 +2134,27 @@ void ScConditionalFormat::CalcAll()
     }
 }
 
+void ScConditionalFormat::ResetCache() const
+{
+    if (!maRanges.empty() && pDoc)
+        mpCache = std::make_unique<ScColorFormatCache>(*pDoc, maRanges);
+    else
+        mpCache.reset();
+}
+
+void ScConditionalFormat::SetCache(const std::vector<double>& aValues) const
+{
+    if (!mpCache)
+        ResetCache();
+    if (mpCache)
+        mpCache->maValues = aValues;
+}
+
+std::vector<double>* ScConditionalFormat::GetCache() const
+{
+    return mpCache ? &mpCache->maValues : nullptr;
+}
+
 ScConditionalFormatList::ScConditionalFormatList(const 
ScConditionalFormatList& rList)
 {
     for(const auto& rxFormat : rList)

Reply via email to