diff options
author | Kohei Yoshida <kohei.yoshida@suse.com> | 2011-12-05 19:20:53 -0500 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@suse.com> | 2011-12-05 19:25:13 -0500 |
commit | c81b005921b39c54b33777af126b87e9f4e92860 (patch) | |
tree | afd73aee8f2b4acb0a1cac957570279350b58a93 | |
parent | b5dfff9d34d1011ec552b35f223e75ca253bbd78 (diff) |
fdo#39847: Shrink chart's source ranges to data area.
Otherwise setting data area to e.g. the entire sheet, or even just
entire columns would freeze Calc as it tries to parse the entire data
range faithfully.
-rw-r--r-- | sc/source/ui/unoobj/chart2uno.cxx | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/sc/source/ui/unoobj/chart2uno.cxx b/sc/source/ui/unoobj/chart2uno.cxx index 7a5c520d1d5b..6e549964b27f 100644 --- a/sc/source/ui/unoobj/chart2uno.cxx +++ b/sc/source/ui/unoobj/chart2uno.cxx @@ -601,6 +601,10 @@ void Chart2Positioner::glueState() void Chart2Positioner::calcGlueState(SCCOL nColSize, SCROW nRowSize) { + // TODO: This code can use some space optimization. Using an array to + // store individual cell's states is terribly inefficient esp for large + // data ranges; let's use flat_segment_tree to reduce memory usage here. + sal_uInt32 nCR = static_cast<sal_uInt32>(nColSize*nRowSize); enum State { Hole = 0, Occupied = 1, Free = 2, Glue = 3 }; @@ -1386,6 +1390,53 @@ bool lcl_addUpperLeftCornerIfMissing(vector<ScTokenRef>& rRefTokens, return true; } +class ShrinkRefTokenToDataRange : std::unary_function<ScTokenRef, void> +{ + ScDocument* mpDoc; +public: + ShrinkRefTokenToDataRange(ScDocument* pDoc) : mpDoc(pDoc) {} + void operator() (ScTokenRef& rRef) + { + if (ScRefTokenHelper::isExternalRef(rRef)) + return; + + ScComplexRefData& rData = rRef->GetDoubleRef(); + ScSingleRefData& s = rData.Ref1; + ScSingleRefData& e = rData.Ref2; + + SCCOL nMinCol = MAXCOL, nMaxCol = 0; + SCROW nMinRow = MAXROW, nMaxRow = 0; + + // Determine the smallest range that encompasses the data ranges of all sheets. + SCTAB nTab1 = s.nTab, nTab2 = e.nTab; + for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab) + { + SCCOL nCol1 = 0, nCol2 = MAXCOL; + SCROW nRow1 = 0, nRow2 = MAXROW; + mpDoc->ShrinkToDataArea(nTab, nCol1, nRow1, nCol2, nRow2); + nMinCol = std::min(nMinCol, nCol1); + nMinRow = std::min(nMinRow, nRow1); + nMaxCol = std::max(nMaxCol, nCol2); + nMaxRow = std::max(nMaxRow, nRow2); + } + + // Shrink range to the data range if applicable. + if (s.nCol < nMinCol) + s.nCol = nMinCol; + if (s.nRow < nMinRow) + s.nRow = nMinRow; + if (e.nCol > nMaxCol) + e.nCol = nMaxCol; + if (e.nRow > nMaxRow) + e.nRow = nMaxRow; + } +}; + +void shrinkToDataRange(ScDocument* pDoc, vector<ScTokenRef>& rRefTokens) +{ + std::for_each(rRefTokens.begin(), rRefTokens.end(), ShrinkRefTokenToDataRange(pDoc)); +} + } uno::Reference< chart2::data::XDataSource> SAL_CALL @@ -1443,6 +1494,8 @@ ScChart2DataProvider::createDataSource( // Invalid range representation. Bail out. throw lang::IllegalArgumentException(); + shrinkToDataRange(m_pDocument, aRefTokens); + if (bLabel) lcl_addUpperLeftCornerIfMissing(aRefTokens); //#i90669# @@ -2028,6 +2081,8 @@ uno::Reference< chart2::data::XDataSequence > SAL_CALL if (aRefTokens.empty()) return xResult; + shrinkToDataRange(m_pDocument, aRefTokens); + // ScChart2DataSequence manages the life cycle of pRefTokens. vector<ScTokenRef>* pRefTokens = new vector<ScTokenRef>(); pRefTokens->swap(aRefTokens); |