summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@suse.com>2011-12-05 19:20:53 -0500
committerKohei Yoshida <kohei.yoshida@suse.com>2011-12-05 19:25:13 -0500
commitc81b005921b39c54b33777af126b87e9f4e92860 (patch)
treeafd73aee8f2b4acb0a1cac957570279350b58a93 /sc
parentb5dfff9d34d1011ec552b35f223e75ca253bbd78 (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.
Diffstat (limited to 'sc')
-rw-r--r--sc/source/ui/unoobj/chart2uno.cxx55
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);