From 4de4f1fd1125bc8cf6059cf143bb76d1ab212434 Mon Sep 17 00:00:00 2001 From: László Németh Date: Tue, 17 Feb 2015 16:43:38 +0100 Subject: tdf#89436 fix ScHorizontalAttrIterator performance Change-Id: I69be1a85b74ede8f02788a6370d4ebb40bddbe11 --- sc/inc/dociter.hxx | 3 +++ sc/source/core/data/dociter.cxx | 47 ++++++++++++++++++++++++++--------------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/sc/inc/dociter.hxx b/sc/inc/dociter.hxx index 2230b81c9c8e..65023b0434dd 100644 --- a/sc/inc/dociter.hxx +++ b/sc/inc/dociter.hxx @@ -487,11 +487,14 @@ private: SCROW nEndRow; SCROW* pNextEnd; + SCCOL* pPrevColEnd; SCSIZE* pIndices; const ScPatternAttr** ppPatterns; SCCOL nCol; SCROW nRow; bool bRowEmpty; + bool bRepeatedRow; + SCROW nMinNextEnd; public: ScHorizontalAttrIterator( ScDocument* pDocument, SCTAB nTable, diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx index ba625bea07a1..d685b8242c69 100644 --- a/sc/source/core/data/dociter.cxx +++ b/sc/source/core/data/dociter.cxx @@ -2235,12 +2235,14 @@ ScHorizontalAttrIterator::ScHorizontalAttrIterator( ScDocument* pDocument, SCTAB nRow = nStartRow; nCol = nStartCol; bRowEmpty = false; + bRepeatedRow = false; pIndices = new SCSIZE[nEndCol-nStartCol+1]; pNextEnd = new SCROW[nEndCol-nStartCol+1]; + pPrevColEnd = new SCCOL[nEndCol-nStartCol+1]; ppPatterns = new const ScPatternAttr*[nEndCol-nStartCol+1]; - SCROW nSkipTo = MAXROW; + nMinNextEnd = MAXROW; bool bEmpty = true; for (i=nStartCol; i<=nEndCol; i++) { @@ -2253,12 +2255,12 @@ ScHorizontalAttrIterator::ScHorizontalAttrIterator( ScDocument* pDocument, SCTAB const ScPatternAttr* pPattern = pArray->pData[nIndex].pPattern; SCROW nThisEnd = pArray->pData[nIndex].nRow; + + if ( nThisEnd < nMinNextEnd ) + nMinNextEnd = nThisEnd; // nMinNextEnd can be set here already + if ( IsDefaultItem( pPattern ) ) - { pPattern = NULL; - if ( nThisEnd < nSkipTo ) - nSkipTo = nThisEnd; // nSkipTo can be set here already - } else bEmpty = false; // Found attributes @@ -2268,7 +2270,7 @@ ScHorizontalAttrIterator::ScHorizontalAttrIterator( ScDocument* pDocument, SCTAB } if (bEmpty) - nRow = nSkipTo; // Skip until end of next section + nRow = nMinNextEnd; // Skip until end of next section bRowEmpty = bEmpty; } @@ -2277,6 +2279,7 @@ ScHorizontalAttrIterator::~ScHorizontalAttrIterator() { delete[] ppPatterns; delete[] pNextEnd; + delete[] pPrevColEnd; delete[] pIndices; } @@ -2297,8 +2300,15 @@ const ScPatternAttr* ScHorizontalAttrIterator::GetNext( SCCOL& rCol1, SCCOL& rCo const ScPatternAttr* pPat = ppPatterns[nCol-nStartCol]; rRow = nRow; rCol1 = nCol; - while ( nCol < nEndCol && ppPatterns[nCol+1-nStartCol] == pPat ) - ++nCol; + if ( bRepeatedRow ) + nCol = pPrevColEnd[nCol]; + else + { + while ( nCol < nEndCol && ( ppPatterns[nCol+1-nStartCol] == pPat) ) + ++nCol; + // store the result to avoid the previous very expensive comparisons + pPrevColEnd[rCol1] = nCol; + } rCol2 = nCol; ++nCol; // Count up for next call return pPat; // Found it! @@ -2309,7 +2319,13 @@ const ScPatternAttr* ScHorizontalAttrIterator::GetNext( SCCOL& rCol1, SCCOL& rCo ++nRow; if ( nRow > nEndRow ) // Already at the end? return NULL; // Found nothing + nCol = nStartCol; // Start at the left again + + if ( bRepeatedRow && ! nMinNextEnd < nRow ) // use the data of the previous row + continue; + bRepeatedRow = true; // ppPatterns is not modified + nMinNextEnd = MAXROW; bool bEmpty = true; SCCOL i; @@ -2319,6 +2335,7 @@ const ScPatternAttr* ScHorizontalAttrIterator::GetNext( SCCOL& rCol1, SCCOL& rCo if ( pNextEnd[nPos] < nRow ) { const ScAttrArray* pArray = pDoc->maTabs[nTab]->aCol[i].pAttrArray; + bRepeatedRow = false; SCSIZE nIndex = ++pIndices[nPos]; if ( nIndex < pArray->nCount ) @@ -2344,19 +2361,15 @@ const ScPatternAttr* ScHorizontalAttrIterator::GetNext( SCCOL& rCol1, SCCOL& rCo } else if ( ppPatterns[nPos] ) bEmpty = false; // Area not at the end yet + + if ( nMinNextEnd > pNextEnd[nPos] ) + nMinNextEnd = pNextEnd[nPos]; + } if (bEmpty) - { - SCCOL nCount = nEndCol-nStartCol+1; - SCROW nSkipTo = pNextEnd[0]; // Search next end of area - for (i=1; i