diff options
-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); |