summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2022-04-04 17:52:04 +0200
committerChristian Lohmaier <lohmaier+LibreOffice@googlemail.com>2022-05-18 17:11:40 +0200
commitb93421cf715dae0f05530b2e08796e1c57692a00 (patch)
tree08d7e5d4a41b7c8230208b718990b95bad37a734
parentf380c63d83d07b0a227478c19be4ea1a390a0e1b (diff)
try to limit cell interpreting to only visible cells when drawing
If there's a document with a huge formula group, InterpretDirtyCells() on load will only interpret the range needed for drawing. But then scrolling just a bit could result in e.g. IsValue() call on a cell, and that could result in unrestricted Interpret() on the whole huge formula group, which could be slow. So explicitly interpret just the drawn cells in the hope that it'll avoid any further Interpret() calls. Change-Id: I01c9f95cf8a1cf240b798feef27d21010957030c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133306 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com> (cherry picked from commit 64cb1d10fffccebbc825c858083f13eb717b0553) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134162 Reviewed-by: Christian Lohmaier <lohmaier+LibreOffice@googlemail.com>
-rw-r--r--sc/inc/column.hxx1
-rw-r--r--sc/inc/document.hxx2
-rw-r--r--sc/inc/table.hxx1
-rw-r--r--sc/source/core/data/column3.cxx39
-rw-r--r--sc/source/core/data/document.cxx17
-rw-r--r--sc/source/core/data/table1.cxx7
-rw-r--r--sc/source/ui/view/output2.cxx5
7 files changed, 66 insertions, 6 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 01e58fb9d055..b8e348d00e70 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -651,6 +651,7 @@ public:
bool IsDrawObjectsEmptyBlock(SCROW nStartRow, SCROW nEndRow) const;
void InterpretDirtyCells( SCROW nRow1, SCROW nRow2 );
+ void InterpretCellsIfNeeded( SCROW nRow1, SCROW nRow2 );
static void JoinNewFormulaCell( const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell );
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 5e3c3c7a824b..7b1563994bc0 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1320,6 +1320,8 @@ public:
void SetDirty( const ScRange&, bool bIncludeEmptyCells );
void SetTableOpDirty( const ScRange& ); // for Interpreter TableOp
void InterpretDirtyCells( const ScRangeList& rRanges );
+ // Interprets cells that have NeedsInterpret(), i.e. the same like calling MaybeInterpret() on them.
+ void InterpretCellsIfNeeded( const ScRangeList& rRanges );
SC_DLLPUBLIC void CalcAll();
SC_DLLPUBLIC void CalcAfterLoad( bool bStartListening = true );
void CompileAll();
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 5602d6dcacfe..27a1fcf67fd8 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -1031,6 +1031,7 @@ public:
void FillMatrix( ScMatrix& rMat, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, svl::SharedStringPool* pPool ) const;
void InterpretDirtyCells( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
+ void InterpretCellsIfNeeded( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
void SetFormulaResults( SCCOL nCol, SCROW nRow, const double* pResults, size_t nLen );
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 7e133d565558..d3c17d1da6d7 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -102,13 +102,11 @@ void ScColumn::BroadcastRows( SCROW nStartRow, SCROW nEndRow, SfxHintId nHint )
namespace {
-class DirtyCellInterpreter
+class CellInterpreterBase
{
-public:
- void operator() (size_t, ScFormulaCell* p)
+protected:
+ void Interpret(ScFormulaCell* p)
{
- if(!p->GetDirty())
- return;
// Interpret() takes a range in a formula group, so group those together.
if( firstCell != nullptr && p->GetCellGroup() == p->GetCellGroup()
&& p->aPos.Row() == lastPos.Row() + 1 )
@@ -127,7 +125,7 @@ public:
lastPos = p->aPos;
}
- ~DirtyCellInterpreter()
+ ~CellInterpreterBase()
{
flushPending();
}
@@ -144,6 +142,26 @@ private:
ScAddress lastPos;
};
+class DirtyCellInterpreter : public CellInterpreterBase
+{
+public:
+ void operator() (size_t, ScFormulaCell* p)
+ {
+ if(p->GetDirty())
+ Interpret(p);
+ }
+};
+
+class NeedsInterpretCellInterpreter : public CellInterpreterBase
+{
+public:
+ void operator() (size_t, ScFormulaCell* p)
+ {
+ if(p->NeedsInterpret())
+ Interpret(p);
+ }
+};
+
}
void ScColumn::InterpretDirtyCells( SCROW nRow1, SCROW nRow2 )
@@ -155,6 +173,15 @@ void ScColumn::InterpretDirtyCells( SCROW nRow1, SCROW nRow2 )
sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
}
+void ScColumn::InterpretCellsIfNeeded( SCROW nRow1, SCROW nRow2 )
+{
+ if (!GetDoc().ValidRow(nRow1) || !GetDoc().ValidRow(nRow2) || nRow1 > nRow2)
+ return;
+
+ NeedsInterpretCellInterpreter aFunc;
+ sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
+}
+
void ScColumn::DeleteContent( SCROW nRow, bool bBroadcast )
{
sc::CellStoreType::position_type aPos = maCells.position(nRow);
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index b62407916300..dbf6233efa6b 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -3923,6 +3923,23 @@ void ScDocument::InterpretDirtyCells( const ScRangeList& rRanges )
mpFormulaGroupCxt.reset();
}
+void ScDocument::InterpretCellsIfNeeded( const ScRangeList& rRanges )
+{
+ for (size_t nPos=0, nRangeCount = rRanges.size(); nPos < nRangeCount; nPos++)
+ {
+ const ScRange& rRange = rRanges[nPos];
+ for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
+ {
+ ScTable* pTab = FetchTable(nTab);
+ if (!pTab)
+ return;
+
+ pTab->InterpretCellsIfNeeded(
+ rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
+ }
+ }
+}
+
void ScDocument::AddTableOpFormulaCell( ScFormulaCell* pCell )
{
if (m_TableOpList.empty())
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index d613ec905575..a03ab678e7d0 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -2536,6 +2536,13 @@ void ScTable::InterpretDirtyCells( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW
aCol[nCol].InterpretDirtyCells(nRow1, nRow2);
}
+void ScTable::InterpretCellsIfNeeded( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
+{
+ nCol2 = ClampToAllocatedColumns(nCol2);
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ aCol[nCol].InterpretCellsIfNeeded(nRow1, nRow2);
+}
+
void ScTable::SetFormulaResults( SCCOL nCol, SCROW nRow, const double* pResults, size_t nLen )
{
if (!ValidCol(nCol))
diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx
index 0e38182a5725..56e428d557a2 100644
--- a/sc/source/ui/view/output2.cxx
+++ b/sc/source/ui/view/output2.cxx
@@ -1559,6 +1559,11 @@ tools::Rectangle ScOutputData::LayoutStrings(bool bPixelToLogic, bool bPaint, co
const SfxItemSet* pOldCondSet = nullptr;
SvtScriptType nOldScript = SvtScriptType::NONE;
+ // Try to limit interpreting to only visible cells. Calling e.g. IsValue()
+ // on a formula cell that needs interpreting would call Interpret()
+ // for the entire formula group, which could be large.
+ mpDoc->InterpretCellsIfNeeded( ScRange( nX1, nY1, nTab, nX2, nY2, nTab ));
+
// alternative pattern instances in case we need to modify the pattern
// before processing the cell value.
std::vector<std::unique_ptr<ScPatternAttr> > aAltPatterns;