sc/inc/column.hxx | 5 + sc/inc/table.hxx | 8 + sc/source/core/data/column4.cxx | 112 ++++++++++++++++++--------- sc/source/core/data/table4.cxx | 161 +++++++++++++++++++++++++++++----------- 4 files changed, 206 insertions(+), 80 deletions(-)
New commits: commit 571070074671bd0102422dd8a0ac1c3be6358f80 Author: Kohei Yoshida <[email protected]> Date: Fri Jan 31 15:44:00 2014 -0500 Speed up simple fill of formula cells. Vertical direction only. Other cells could be optimized in a similar fashion, but they aren't that slow even with the current code. Change-Id: I0b71bf271fab68c9fba0b39463dfe3ef46dacfb0 diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 69ba1af..7fefa04 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -57,6 +57,7 @@ class EditTextIterator; struct NoteEntry; class DocumentStreamAccess; class CellValues; +struct RowSpan; } @@ -218,6 +219,8 @@ public: void DeleteRow( SCROW nStartRow, SCSIZE nSize ); void DeleteArea( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nDelFlag, bool bBroadcast = true ); + void DeleteRanges( const std::vector<sc::RowSpan>& rRanges, sal_uInt16 nDelFlag, bool bBroadcast ); + void CopyToClip( sc::CopyToClipContext& rCxt, SCROW nRow1, SCROW nRow2, ScColumn& rColumn ) const; void CopyStaticToDocument(SCROW nRow1, SCROW nRow2, ScColumn& rDestCol); @@ -289,6 +292,8 @@ public: ScFormulaCell* SetFormulaCell( SCROW nRow, ScFormulaCell* pCell ); ScFormulaCell* SetFormulaCell( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScFormulaCell* pCell ); + void CloneFormulaCell( const ScFormulaCell& rSrc, const std::vector<sc::RowSpan>& rRanges ); + svl::SharedString GetSharedString( SCROW nRow ) const; void SetRawString( SCROW nRow, const OUString& rStr, bool bBroadcast = true ); diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx index 661c38d..7a5998c 100644 --- a/sc/source/core/data/column4.cxx +++ b/sc/source/core/data/column4.cxx @@ -14,6 +14,8 @@ #include <attarray.hxx> #include <document.hxx> #include <cellvalues.hxx> +#include <columnspanset.hxx> +#include <listenercontext.hxx> #include <svl/sharedstring.hxx> @@ -49,6 +51,8 @@ void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1, if ((nFlags & IDF_CONTENTS) != 0) { + std::vector<sc::CellTextAttr> aTextAttrs(nDestSize); + switch (rSrcCell.meType) { case CELLTYPE_VALUE: @@ -56,13 +60,18 @@ void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1, std::vector<double> aVals(nDestSize, rSrcCell.mfValue); pBlockPos->miCellPos = maCells.set(pBlockPos->miCellPos, nRow1, aVals.begin(), aVals.end()); + pBlockPos->miCellTextAttrPos = + maCellTextAttrs.set(pBlockPos->miCellTextAttrPos, nRow1, aTextAttrs.begin(), aTextAttrs.end()); CellStorageModified(); } break; case CELLTYPE_STRING: { std::vector<svl::SharedString> aStrs(nDestSize, *rSrcCell.mpString); - maCells.set(pBlockPos->miCellPos, nRow1, aStrs.begin(), aStrs.end()); + pBlockPos->miCellPos = + maCells.set(pBlockPos->miCellPos, nRow1, aStrs.begin(), aStrs.end()); + pBlockPos->miCellTextAttrPos = + maCellTextAttrs.set(pBlockPos->miCellTextAttrPos, nRow1, aTextAttrs.begin(), aTextAttrs.end()); CellStorageModified(); } break; @@ -75,46 +84,17 @@ void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1, pBlockPos->miCellPos = maCells.set(pBlockPos->miCellPos, nRow1, aStrs.begin(), aStrs.end()); + pBlockPos->miCellTextAttrPos = + maCellTextAttrs.set(pBlockPos->miCellTextAttrPos, nRow1, aTextAttrs.begin(), aTextAttrs.end()); CellStorageModified(); } break; case CELLTYPE_FORMULA: { - std::vector<ScFormulaCell*> aFormulas; - ScAddress aPos(nCol, nRow1, nTab); - aFormulas.reserve(nDestSize); - ScFormulaCellGroupRef xGroup(new ScFormulaCellGroup); - xGroup->setCode(*rSrcCell.mpFormula->GetCode()); - xGroup->compileCode(*pDocument, aPos, pDocument->GetGrammar()); - for (size_t i = 0; i < nDestSize; ++i) - { - ScFormulaCell* pCell = new ScFormulaCell(pDocument, aPos, xGroup); - if (i == 0) - { - xGroup->mpTopCell = pCell; - xGroup->mnLength = nDestSize; - } - aFormulas.push_back(pCell); - aPos.IncRow(); - } - - pBlockPos->miCellPos = - maCells.set(pBlockPos->miCellPos, nRow1, aFormulas.begin(), aFormulas.end()); - - // Join the top and bottom of the pasted formula cells as needed. - sc::CellStoreType::position_type aPosObj = - maCells.position(pBlockPos->miCellPos, nRow1); - - assert(aPosObj.first->type == sc::element_type_formula); - ScFormulaCell* pCell = sc::formula_block::at(*aPosObj.first->data, aPosObj.second); - JoinNewFormulaCell(aPosObj, *pCell); - - aPosObj = maCells.position(aPosObj.first, nRow2); - assert(aPosObj.first->type == sc::element_type_formula); - pCell = sc::formula_block::at(*aPosObj.first->data, aPosObj.second); - JoinNewFormulaCell(aPosObj, *pCell); - - CellStorageModified(); + std::vector<sc::RowSpan> aRanges; + aRanges.reserve(1); + aRanges.push_back(sc::RowSpan(nRow1, nRow2)); + CloneFormulaCell(*rSrcCell.mpFormula, aRanges); } break; default: @@ -228,4 +208,64 @@ void ScColumn::CopyCellValuesFrom( SCROW nRow, const sc::CellValues& rSrc ) BroadcastCells(aRows, SC_HINT_DATACHANGED); } +void ScColumn::DeleteRanges( const std::vector<sc::RowSpan>& rRanges, sal_uInt16 nDelFlag, bool bBroadcast ) +{ + std::vector<sc::RowSpan>::const_iterator itSpan = rRanges.begin(), itSpanEnd = rRanges.end(); + for (; itSpan != itSpanEnd; ++itSpan) + DeleteArea(itSpan->mnRow1, itSpan->mnRow2, nDelFlag, bBroadcast); +} + +void ScColumn::CloneFormulaCell( const ScFormulaCell& rSrc, const std::vector<sc::RowSpan>& rRanges ) +{ + sc::CellStoreType::iterator itPos = maCells.begin(); + sc::CellTextAttrStoreType::iterator itAttrPos = maCellTextAttrs.begin(); + sc::StartListeningContext aCxt(*pDocument); + + std::vector<ScFormulaCell*> aFormulas; + std::vector<sc::RowSpan>::const_iterator itSpan = rRanges.begin(), itSpanEnd = rRanges.end(); + for (; itSpan != itSpanEnd; ++itSpan) + { + SCROW nRow1 = itSpan->mnRow1, nRow2 = itSpan->mnRow2; + size_t nLen = nRow2 - nRow1 + 1; + aFormulas.clear(); + aFormulas.reserve(nLen); + + ScAddress aPos(nCol, nRow1, nTab); + ScFormulaCellGroupRef xGroup(new ScFormulaCellGroup); + xGroup->setCode(*rSrc.GetCode()); + xGroup->compileCode(*pDocument, aPos, pDocument->GetGrammar()); + for (size_t i = 0; i < nLen; ++i, aPos.IncRow()) + { + ScFormulaCell* pCell = new ScFormulaCell(pDocument, aPos, xGroup); + if (i == 0) + { + xGroup->mpTopCell = pCell; + xGroup->mnLength = nLen; + } + pCell->StartListeningTo(aCxt); + pCell->SetDirty(); + aFormulas.push_back(pCell); + } + + itPos = maCells.set(itPos, nRow1, aFormulas.begin(), aFormulas.end()); + + // Join the top and bottom of the pasted formula cells as needed. + sc::CellStoreType::position_type aPosObj = maCells.position(itPos, nRow1); + + assert(aPosObj.first->type == sc::element_type_formula); + ScFormulaCell* pCell = sc::formula_block::at(*aPosObj.first->data, aPosObj.second); + JoinNewFormulaCell(aPosObj, *pCell); + + aPosObj = maCells.position(aPosObj.first, nRow2); + assert(aPosObj.first->type == sc::element_type_formula); + pCell = sc::formula_block::at(*aPosObj.first->data, aPosObj.second); + JoinNewFormulaCell(aPosObj, *pCell); + + std::vector<sc::CellTextAttr> aTextAttrs(nLen); + itAttrPos = maCellTextAttrs.set(itAttrPos, nRow1, aTextAttrs.begin(), aTextAttrs.end()); + } + + CellStorageModified(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/table4.cxx b/sc/source/core/data/table4.cxx index 6a21cef..3f586f5 100644 --- a/sc/source/core/data/table4.cxx +++ b/sc/source/core/data/table4.cxx @@ -60,6 +60,7 @@ #include "segmenttree.hxx" #include "conditio.hxx" #include "editutil.hxx" +#include <columnspanset.hxx> #include <math.h> #include <boost/scoped_ptr.hpp> @@ -1287,42 +1288,110 @@ void ScTable::FillSimple( SCCOLROW& rCol, SCCOLROW& rRow, bool bVertical, ScProgress* pProgress, sal_uLong& rProgress ) { bool bHidden = false; - SCCOLROW nHiddenValid = -1; + SCCOLROW nHiddenLast = -1; - switch (rSrcCell.meType) + if (bVertical) { - case CELLTYPE_FORMULA: + switch (rSrcCell.meType) { - for (rInner = nIMin; rInner <= nIMax; ++rInner) + case CELLTYPE_FORMULA: { - if (rInner > nHiddenValid) - bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenValid); + SCCOLROW nRowStart = -1, nRowEnd = -1; + std::vector<sc::RowSpan> aSpans; + for (rInner = nIMin; rInner <= nIMax; ++rInner) + { + if (rInner > nHiddenLast) + bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenLast); + + if (bHidden) + { + if (nRowStart >= 0) + { + nRowEnd = rInner - 1; + aSpans.push_back(sc::RowSpan(nRowStart, nRowEnd)); + nRowStart = -1; + } + rInner = nHiddenLast; + continue; + } - if (bHidden) - continue; + if (nRowStart < 0) + nRowStart = rInner; + } - FillFormula(rSrcCell.mpFormula, rCol, rRow, (rInner == nIMax)); + if (nRowStart >= 0) + { + nRowEnd = rInner - 1; + aSpans.push_back(sc::RowSpan(nRowStart, nRowEnd)); + } + + aCol[rCol].DeleteRanges(aSpans, IDF_CONTENTS, false); + aCol[rCol].CloneFormulaCell(*rSrcCell.mpFormula, aSpans); + + rProgress += nIMax - nIMin + 1; if (pProgress) - pProgress->SetStateOnPercent(++rProgress); + pProgress->SetStateOnPercent(rProgress); + } + break; + default: + { + for (rInner = nIMin; rInner <= nIMax; ++rInner) + { + if (rInner > nHiddenLast) + bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenLast); + + if (bHidden) + { + rInner = nHiddenLast; + continue; + } + + ScAddress aDestPos(rCol, rRow, nTab); + rSrcCell.commit(aCol[rCol], aDestPos.Row()); + } + rProgress += nIMax - nIMin + 1; + if (pProgress) + pProgress->SetStateOnPercent(rProgress); } } - break; - default: + } + else + { + switch (rSrcCell.meType) { - for (rInner = nIMin; rInner <= nIMax; ++rInner) + case CELLTYPE_FORMULA: + { + for (rInner = nIMin; rInner <= nIMax; ++rInner) + { + if (rInner > nHiddenLast) + bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenLast); + + if (bHidden) + continue; + + FillFormula(rSrcCell.mpFormula, rCol, rRow, (rInner == nIMax)); + if (pProgress) + pProgress->SetStateOnPercent(++rProgress); + } + } + break; + default: { - if (rInner > nHiddenValid) - bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenValid); + for (rInner = nIMin; rInner <= nIMax; ++rInner) + { + if (rInner > nHiddenLast) + bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenLast); - if (bHidden) - continue; + if (bHidden) + continue; - ScAddress aDestPos(rCol, rRow, nTab); - rSrcCell.commit(aCol[rCol], aDestPos.Row()); + ScAddress aDestPos(rCol, rRow, nTab); + rSrcCell.commit(aCol[rCol], aDestPos.Row()); + } + rProgress += nIMax - nIMin + 1; + if (pProgress) + pProgress->SetStateOnPercent(rProgress); } - rProgress += nIMax - nIMin + 1; - if (pProgress) - pProgress->SetStateOnPercent(rProgress); } } } commit 777e3930a1e85b9bc97c1852b09802fc389c5e2d Author: Kohei Yoshida <[email protected]> Date: Fri Jan 31 12:34:26 2014 -0500 Move the code for "fill simple" to its own method. Change-Id: I317f20eb4e8b6e41f12b7da872d158b859579861 diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 260a736..658b4c1 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -915,6 +915,10 @@ public: static void UpdateSearchItemAddressForReplace( const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow ); private: + void FillSimple( + ScCellValue& rSrcCell, SCCOLROW& rInner, SCCOLROW nIMin, SCCOLROW nIMax, + SCCOLROW& rCol, SCCOLROW& rRow, bool bVertical, ScProgress* pProgress, sal_uLong& rProgress ); + void FillSeries( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd, @@ -990,8 +994,8 @@ private: bool IsEmptyLine(SCROW nRow, SCCOL nStartCol, SCCOL nEndCol) const; void IncDate(double& rVal, sal_uInt16& nDayOfMonth, double nStep, FillDateCmd eCmd); - void FillFormula(sal_uLong& nFormulaCounter, bool bFirst, ScFormulaCell* pSrcCell, - SCCOL nDestCol, SCROW nDestRow, bool bLast ); + void FillFormula( + ScFormulaCell* pSrcCell, SCCOL nDestCol, SCROW nDestRow, bool bLast ); void UpdateInsertTabAbs(SCTAB nNewPos); bool GetNextSpellingCell(SCCOL& rCol, SCROW& rRow, bool bInSel, const ScMarkData& rMark) const; diff --git a/sc/source/core/data/table4.cxx b/sc/source/core/data/table4.cxx index ca89428..6a21cef 100644 --- a/sc/source/core/data/table4.cxx +++ b/sc/source/core/data/table4.cxx @@ -427,8 +427,8 @@ void ScTable::FillAnalyse( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, } } -void ScTable::FillFormula(sal_uLong& /* nFormulaCounter */, bool /* bFirst */, ScFormulaCell* pSrcCell, - SCCOL nDestCol, SCROW nDestRow, bool bLast ) +void ScTable::FillFormula( + ScFormulaCell* pSrcCell, SCCOL nDestCol, SCROW nDestRow, bool bLast ) { pDocument->SetNoListening( true ); // still the wrong reference @@ -753,7 +753,6 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, nDelta = -1.0; double nVal = 0.0; sal_uLong nFormulaCounter = nActFormCnt; - bool bFirst = true; bool bGetCell = true; sal_uInt16 nCellDigits = 0; short nHeadNoneTail = 0; @@ -843,7 +842,8 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, break; case CELLTYPE_FORMULA : - FillFormula( nFormulaCounter, bFirst, aSrcCell.mpFormula, + FillFormula( + aSrcCell.mpFormula, static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), (rInner == nIEnd) ); if (nFormulaCounter - nActFormCnt > nMaxFormCnt) @@ -870,7 +870,6 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, nDelta -= 1.0; } nFormulaCounter = nActFormCnt; - bFirst = false; } else if (bPositive) { @@ -1283,6 +1282,51 @@ bool HiddenRowColumn(ScTable* pTable, SCCOLROW nRowColumn, bool bVertical, SCCOL } +void ScTable::FillSimple( + ScCellValue& rSrcCell, SCCOLROW& rInner, SCCOLROW nIMin, SCCOLROW nIMax, + SCCOLROW& rCol, SCCOLROW& rRow, bool bVertical, ScProgress* pProgress, sal_uLong& rProgress ) +{ + bool bHidden = false; + SCCOLROW nHiddenValid = -1; + + switch (rSrcCell.meType) + { + case CELLTYPE_FORMULA: + { + for (rInner = nIMin; rInner <= nIMax; ++rInner) + { + if (rInner > nHiddenValid) + bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenValid); + + if (bHidden) + continue; + + FillFormula(rSrcCell.mpFormula, rCol, rRow, (rInner == nIMax)); + if (pProgress) + pProgress->SetStateOnPercent(++rProgress); + } + } + break; + default: + { + for (rInner = nIMin; rInner <= nIMax; ++rInner) + { + if (rInner > nHiddenValid) + bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenValid); + + if (bHidden) + continue; + + ScAddress aDestPos(rCol, rRow, nTab); + rSrcCell.commit(aCol[rCol], aDestPos.Row()); + } + rProgress += nIMax - nIMin + 1; + if (pProgress) + pProgress->SetStateOnPercent(rProgress); + } + } +} + void ScTable::FillSeries( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd, double nStepValue, double nMaxValue, sal_uInt16 nArgMinDigits, @@ -1449,43 +1493,7 @@ void ScTable::FillSeries( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, if (eFillCmd == FILL_SIMPLE) // copy { - bool bHidden = false; - SCCOLROW nHiddenValid = -1; - - if (eCellType == CELLTYPE_FORMULA) - { - bool bFirst = true; - for (rInner = nIMin; rInner <= nIMax; rInner++) - { - if (rInner > nHiddenValid) - bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenValid); - - if (bHidden) - continue; - sal_uLong nInd = nActFormCnt; - FillFormula(nInd, bFirst, aSrcCell.mpFormula, - static_cast<SCCOL>(nCol), nRow, (rInner == nIEnd) ); - bFirst = false; - if(pProgress) - pProgress->SetStateOnPercent( ++nProgress ); - } - } - else - { - for (rInner = nIMin; rInner <= nIMax; rInner++) - { - if (rInner > nHiddenValid) - bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenValid); - - if (bHidden) - continue; - ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab ); - aSrcCell.commit(aCol[nCol], aDestPos.Row()); - } - nProgress += nIMax - nIMin + 1; - if(pProgress) - pProgress->SetStateOnPercent( nProgress ); - } + FillSimple(aSrcCell, rInner, nIMin, nIMax, nCol, nRow, bVertical, pProgress, nProgress); } else if (eCellType == CELLTYPE_VALUE || eCellType == CELLTYPE_FORMULA) { _______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
