[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - sc/inc sc/source

Kohei Yoshida kohei.yoshida at gmail.com
Thu May 16 15:37:22 PDT 2013


 sc/inc/column.hxx                       |    4 +
 sc/inc/columnspanset.hxx                |    6 ++
 sc/inc/document.hxx                     |    3 +
 sc/inc/listenercontext.hxx              |    2 
 sc/inc/table.hxx                        |    2 
 sc/source/core/data/column.cxx          |   49 -----------------------
 sc/source/core/data/column2.cxx         |   66 +++++++++++++++++++++++++++++++-
 sc/source/core/data/column3.cxx         |   37 +++++++++++++++++
 sc/source/core/data/columnspanset.cxx   |   27 ++++++++++---
 sc/source/core/data/documen6.cxx        |   58 ++++++++++++++++++++++++++++
 sc/source/core/data/listenercontext.cxx |    4 -
 sc/source/core/data/table1.cxx          |    9 ++++
 sc/source/ui/view/viewfunc.cxx          |   12 -----
 13 files changed, 210 insertions(+), 69 deletions(-)

New commits:
commit 53d2aae88262df683fc94c0d99d060d48116050c
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu May 16 18:37:12 2013 -0400

    Optimize ScViewFunc::GetSelectionScriptType().
    
    This change reduces the duration of this method from somewhere in the
    ballpark of 10 seconds down to a tiny fraction of a second.
    
    Change-Id: I0278dc06a4f134b43cd08bd94693b6dec4893f1f

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index a697bed..f1584b1 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -446,6 +446,8 @@ public:
     void SetTextWidth(SCROW nRow, sal_uInt16 nWidth);
 
     sal_uInt8 GetScriptType( SCROW nRow ) const;
+    sal_uInt8 GetRangeScriptType( sc::CellTextAttrStoreType::iterator& itPos, SCROW nRow1, SCROW nRow2 );
+
     void SetScriptType( SCROW nRow, sal_uInt8 nType );
 
     size_t GetFormulaHash( SCROW nRow ) const;
@@ -464,6 +466,8 @@ public:
     void DeleteBroadcasters( SCROW nRow1, SCROW nRow2 );
 
 private:
+    void UpdateScriptType( sc::CellTextAttr& rAttr, SCROW nRow );
+
     void DeleteRange(
         SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDelFlag, std::vector<SCROW>& rDeletedRows );
 
diff --git a/sc/inc/columnspanset.hxx b/sc/inc/columnspanset.hxx
index afd1797..35d94bf 100644
--- a/sc/inc/columnspanset.hxx
+++ b/sc/inc/columnspanset.hxx
@@ -30,17 +30,21 @@ class ColumnSpanSet : boost::noncopyable
 
     DocType maDoc;
 
+    ColumnSpansType& getColumnSpans(SCTAB nTab, SCCOL nCol);
+
 public:
     class Action
     {
     public:
         virtual ~Action() = 0;
+        virtual void startColumn(SCTAB nTab, SCCOL nCol);
         virtual void execute(const ScAddress& rPos, SCROW nLength, bool bVal) = 0;
     };
 
     ~ColumnSpanSet();
 
-    void set(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bVal);
+    void set(SCTAB nTab, SCCOL nCol, SCROW nRow, bool bVal);
+    void set(SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2, bool bVal);
 
     void executeFromTop(Action& ac) const;
     void executeFromBottom(Action& ac) const;
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index e2ea7e3..5f63d85 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1277,6 +1277,9 @@ public:
     SC_DLLPUBLIC sal_uInt8          GetStringScriptType( const OUString& rString );
     SC_DLLPUBLIC sal_uInt8 GetCellScriptType( const ScAddress& rPos, sal_uLong nNumberFormat );
     SC_DLLPUBLIC sal_uInt8 GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab );
+    sal_uInt8 GetRangeScriptType(
+        sc::ColumnBlockPosition& rBlockPos, const ScAddress& rPos, SCROW nLength );
+    sal_uInt8 GetRangeScriptType( const ScRangeList& rRanges );
 
     bool            HasDetectiveOperations() const;
     void            AddDetectiveOperation( const ScDetOpData& rData );
diff --git a/sc/inc/listenercontext.hxx b/sc/inc/listenercontext.hxx
index 2fc55a7..36f26d8 100644
--- a/sc/inc/listenercontext.hxx
+++ b/sc/inc/listenercontext.hxx
@@ -27,7 +27,7 @@ public:
     EndListeningContext(ScDocument& rDoc);
     ScDocument& getDoc();
 
-    void addEmptyBroadcasterPosition(SCCOL nCol, SCROW nRow, SCTAB nTab);
+    void addEmptyBroadcasterPosition(SCTAB nTab, SCCOL nCol, SCROW nRow);
     void purgeEmptyBroadcasters();
 };
 
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 00255fe..333eb9a 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -829,6 +829,8 @@ public:
     sal_uInt8 GetScriptType( SCCOL nCol, SCROW nRow ) const;
     void SetScriptType( SCCOL nCol, SCROW nRow, sal_uInt8 nType );
 
+    sal_uInt8 GetRangeScriptType( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol, SCROW nRow1, SCROW nRow2 );
+
     size_t GetFormulaHash( SCCOL nCol, SCROW nRow ) const;
 
     ScFormulaVectorState GetFormulaVectorState( SCCOL nCol, SCROW nRow ) const;
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 704bdff..77bf89a 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -2296,9 +2296,6 @@ bool ScColumn::HasEditCells(SCROW nStartRow, SCROW nEndRow, SCROW& rFirst)
     if (itCell == itCellEnd)
         return false;
 
-    SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
-    ScConditionalFormatList* pCFList = pDocument->GetCondFormList(nTab);
-
     sc::CellTextAttrStoreType::iterator itAttrPos = maCellTextAttrs.begin();
     for (; itCell != itCellEnd && itCell->nRow <= nEndRow; ++itCell)
     {
@@ -2313,51 +2310,7 @@ bool ScColumn::HasEditCells(SCROW nStartRow, SCROW nEndRow, SCROW& rFirst)
             return true;
         }
 
-        // Check the script type next.
-        std::pair<sc::CellTextAttrStoreType::iterator,size_t> itPos =
-            maCellTextAttrs.position(itAttrPos, nRow);
-
-        sal_uInt16 nScriptType = 0;
-        itAttrPos = itPos.first; // Track the position of cell text attribute array.
-        if (itAttrPos->type == sc::element_type_celltextattr)
-        {
-            sc::CellTextAttr& rVal =
-                sc::custom_celltextattr_block::at(*itAttrPos->data, itPos.second);
-            nScriptType = rVal.mnScriptType;
-
-            if (nScriptType == SC_SCRIPTTYPE_UNKNOWN)
-            {
-                // Script type not yet determined. Determine the real script
-                // type, and store it.
-                const ScPatternAttr* pPattern = GetPattern(nRow);
-                if (pPattern)
-                {
-                    ScRefCellValue aCell;
-                    ScAddress aPos(nCol, nRow, nTab);
-                    aCell.assign(*pDocument, aPos);
-
-                    const SfxItemSet* pCondSet = NULL;
-                    if (pCFList)
-                    {
-                        const ScCondFormatItem& rItem =
-                            static_cast<const ScCondFormatItem&>(pPattern->GetItem(ATTR_CONDITIONAL));
-                        const std::vector<sal_uInt32>& rData = rItem.GetCondFormatData();
-                        pCondSet = pDocument->GetCondResult(aCell, aPos, *pCFList, rData);
-                    }
-
-                    OUString aStr;
-                    Color* pColor;
-                    sal_uLong nFormat = pPattern->GetNumberFormat(pFormatter, pCondSet);
-                    ScCellFormat::GetString(aCell, nFormat, aStr, &pColor, *pFormatter);
-                    nScriptType = pDocument->GetStringScriptType(aStr);
-
-                    if (nScriptType && nScriptType != SC_SCRIPTTYPE_UNKNOWN)
-                        // Store the real script type to the array.
-                        rVal.mnScriptType = nScriptType;
-                }
-            }
-        }
-
+        sal_uInt8 nScriptType = GetRangeScriptType(itAttrPos, nRow, nRow);
         if (IsAmbiguousScriptNonZero(nScriptType))
         {
             rFirst = nRow;
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 4d2d74c..1b8afa2 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1603,6 +1603,70 @@ sal_uInt8 ScColumn::GetScriptType( SCROW nRow ) const
     return maCellTextAttrs.get<sc::CellTextAttr>(nRow).mnScriptType;
 }
 
+sal_uInt8 ScColumn::GetRangeScriptType(
+    sc::CellTextAttrStoreType::iterator& itPos, SCROW nRow1, SCROW nRow2 )
+{
+    if (!ValidRow(nRow1) || !ValidRow(nRow2) || nRow1 > nRow2)
+        return 0;
+
+    SCROW nRow = nRow1;
+    std::pair<sc::CellTextAttrStoreType::iterator,size_t> aRet =
+        maCellTextAttrs.position(itPos, nRow1);
+
+    itPos = aRet.first; // Track the position of cell text attribute array.
+
+    sal_uInt8 nScriptType = 0;
+
+    if (itPos->type == sc::element_type_celltextattr)
+    {
+        sc::custom_celltextattr_block::iterator it = sc::custom_celltextattr_block::begin(*itPos->data);
+        sc::custom_celltextattr_block::iterator itEnd = sc::custom_celltextattr_block::end(*itPos->data);
+        std::advance(it, aRet.second);
+        for (; it != itEnd; ++it, ++nRow)
+        {
+            if (nRow > nRow2)
+                return nScriptType;
+
+            sc::CellTextAttr& rVal = *it;
+            UpdateScriptType(rVal, nRow);
+            nScriptType |= rVal.mnScriptType;
+        }
+    }
+    else
+    {
+        // Skip this whole block.
+        nRow += itPos->size - aRet.second;
+    }
+
+    while (nRow <= nRow2)
+    {
+        ++itPos;
+        if (itPos == maCellTextAttrs.end())
+            return nScriptType;
+
+        if (itPos->type != sc::element_type_celltextattr)
+        {
+            // Skip this whole block.
+            nRow += itPos->size;
+            continue;
+        }
+
+        sc::custom_celltextattr_block::iterator it = sc::custom_celltextattr_block::begin(*itPos->data);
+        sc::custom_celltextattr_block::iterator itEnd = sc::custom_celltextattr_block::end(*itPos->data);
+        for (; it != itEnd; ++it, ++nRow)
+        {
+            if (nRow > nRow2)
+                return nScriptType;
+
+            sc::CellTextAttr& rVal = *it;
+            UpdateScriptType(rVal, nRow);
+            nScriptType |= rVal.mnScriptType;
+        }
+    }
+
+    return nScriptType;
+}
+
 void ScColumn::SetScriptType( SCROW nRow, sal_uInt8 nType )
 {
     if (!ValidRow(nRow))
@@ -1999,7 +2063,7 @@ void ScColumn::EndListening( sc::EndListeningContext& rCxt, SCROW nRow, SvtListe
     rListener.EndListening(*pBC);
     if (!pBC->HasListeners())
         // There is no more listeners for this cell. Add it to the purge list for later purging.
-        rCxt.addEmptyBroadcasterPosition(nCol, nRow, nTab);
+        rCxt.addEmptyBroadcasterPosition(nTab, nCol, nRow);
 }
 
 void ScColumn::CompileDBFormula()
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 2939edb..a29f791 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -275,6 +275,43 @@ void ScColumn::DeleteRow( SCROW nStartRow, SCSIZE nSize )
     pDocument->SetAutoCalc( bOldAutoCalc );
 }
 
+void ScColumn::UpdateScriptType( sc::CellTextAttr& rAttr, SCROW nRow )
+{
+    if (rAttr.mnScriptType != SC_SCRIPTTYPE_UNKNOWN)
+        // Already updated. Nothing to do.
+        return;
+
+    // Script type not yet determined. Determine the real script
+    // type, and store it.
+    const ScPatternAttr* pPattern = GetPattern(nRow);
+    if (!pPattern)
+        return;
+
+    ScRefCellValue aCell;
+    ScAddress aPos(nCol, nRow, nTab);
+    aCell.assign(*pDocument, aPos);
+
+    const SfxItemSet* pCondSet = NULL;
+    ScConditionalFormatList* pCFList = pDocument->GetCondFormList(nTab);
+    if (pCFList)
+    {
+        const ScCondFormatItem& rItem =
+            static_cast<const ScCondFormatItem&>(pPattern->GetItem(ATTR_CONDITIONAL));
+        const std::vector<sal_uInt32>& rData = rItem.GetCondFormatData();
+        pCondSet = pDocument->GetCondResult(aCell, aPos, *pCFList, rData);
+    }
+
+    SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
+
+    OUString aStr;
+    Color* pColor;
+    sal_uLong nFormat = pPattern->GetNumberFormat(pFormatter, pCondSet);
+    ScCellFormat::GetString(aCell, nFormat, aStr, &pColor, *pFormatter);
+
+    // Store the real script type to the array.
+    rAttr.mnScriptType = pDocument->GetStringScriptType(aStr);
+}
+
 namespace {
 
 bool isDate(const ScDocument& rDoc, const ScColumn& rCol, SCROW nRow)
diff --git a/sc/source/core/data/columnspanset.cxx b/sc/source/core/data/columnspanset.cxx
index de78539..ea4f706 100644
--- a/sc/source/core/data/columnspanset.cxx
+++ b/sc/source/core/data/columnspanset.cxx
@@ -15,6 +15,7 @@
 namespace sc {
 
 ColumnSpanSet::Action::~Action() {}
+void ColumnSpanSet::Action::startColumn(SCTAB /*nTab*/, SCCOL /*nCol*/) {}
 
 ColumnSpanSet::~ColumnSpanSet()
 {
@@ -30,11 +31,8 @@ ColumnSpanSet::~ColumnSpanSet()
     }
 }
 
-void ColumnSpanSet::set(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bVal)
+ColumnSpanSet::ColumnSpansType& ColumnSpanSet::getColumnSpans(SCTAB nTab, SCCOL nCol)
 {
-    if (!ValidTab(nTab) || !ValidCol(nCol) || !ValidRow(nRow))
-        return;
-
     if (static_cast<size_t>(nTab) >= maDoc.size())
         maDoc.resize(nTab+1, NULL);
 
@@ -48,10 +46,27 @@ void ColumnSpanSet::set(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bVal)
     if (!rTab[nCol])
         rTab[nCol] = new ColumnSpansType(0, MAXROW+1, false);
 
-    ColumnSpansType& rCol = *rTab[nCol];
+    return *rTab[nCol];
+}
+
+void ColumnSpanSet::set(SCTAB nTab, SCCOL nCol, SCROW nRow, bool bVal)
+{
+    if (!ValidTab(nTab) || !ValidCol(nCol) || !ValidRow(nRow))
+        return;
+
+    ColumnSpansType& rCol = getColumnSpans(nTab, nCol);
     rCol.insert_back(nRow, nRow+1, bVal);
 }
 
+void ColumnSpanSet::set(SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2, bool bVal)
+{
+    if (!ValidTab(nTab) || !ValidCol(nCol) || !ValidRow(nRow1) || !ValidRow(nRow2))
+        return;
+
+    ColumnSpansType& rCol = getColumnSpans(nTab, nCol);
+    rCol.insert_back(nRow1, nRow2+1, bVal);
+}
+
 void ColumnSpanSet::executeFromTop(Action& ac) const
 {
     for (size_t nTab = 0; nTab < maDoc.size(); ++nTab)
@@ -65,6 +80,7 @@ void ColumnSpanSet::executeFromTop(Action& ac) const
             if (!rTab[nCol])
                 continue;
 
+            ac.startColumn(nTab, nCol);
             ColumnSpansType& rCol = *rTab[nCol];
             ColumnSpansType::const_iterator it = rCol.begin(), itEnd = rCol.end();
             SCROW nRow1, nRow2;
@@ -94,6 +110,7 @@ void ColumnSpanSet::executeFromBottom(Action& ac) const
             if (!rTab[nCol])
                 continue;
 
+            ac.startColumn(nTab, nCol);
             ColumnSpansType& rCol = *rTab[nCol];
             ColumnSpansType::const_reverse_iterator it = rCol.rbegin(), itEnd = rCol.rend();
             SCROW nRow1, nRow2;
diff --git a/sc/source/core/data/documen6.cxx b/sc/source/core/data/documen6.cxx
index bd55fc4..819b7a5 100644
--- a/sc/source/core/data/documen6.cxx
+++ b/sc/source/core/data/documen6.cxx
@@ -33,6 +33,8 @@
 #include "poolhelp.hxx"
 #include "attrib.hxx"
 #include "globalnames.hxx"
+#include "columnspanset.hxx"
+#include "table.hxx"
 
 using namespace com::sun::star;
 
@@ -153,4 +155,60 @@ sal_uInt8 ScDocument::GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab )
     return GetCellScriptType(aPos, nFormat);
 }
 
+namespace {
+
+class ScriptTypeAggregator : public sc::ColumnSpanSet::Action
+{
+    ScDocument& mrDoc;
+    sc::ColumnBlockPosition maBlockPos;
+    sal_uInt8 mnScriptType;
+
+public:
+    ScriptTypeAggregator(ScDocument& rDoc) : mrDoc(rDoc), mnScriptType(0) {}
+
+    virtual void startColumn(SCTAB nTab, SCCOL nCol)
+    {
+        mrDoc.InitColumnBlockPosition(maBlockPos, nTab, nCol);
+    }
+
+    virtual void execute(const ScAddress& rPos, SCROW nLength, bool bVal)
+    {
+        if (!bVal)
+            return;
+
+        mnScriptType |= mrDoc.GetRangeScriptType(maBlockPos, rPos, nLength);
+    };
+
+    sal_uInt8 getScriptType() const { return mnScriptType; }
+};
+
+}
+
+sal_uInt8 ScDocument::GetRangeScriptType(
+    sc::ColumnBlockPosition& rBlockPos, const ScAddress& rPos, SCROW nLength )
+{
+    if (!TableExists(rPos.Tab()))
+        return 0;
+
+    return maTabs[rPos.Tab()]->GetRangeScriptType(rBlockPos, rPos.Col(), rPos.Row(), rPos.Row()+nLength-1);
+}
+
+sal_uInt8 ScDocument::GetRangeScriptType( const ScRangeList& rRanges )
+{
+    sc::ColumnSpanSet aSet;
+    for (size_t i = 0, n = rRanges.size(); i < n; ++i)
+    {
+        const ScRange& rRange = *rRanges[i];
+        SCTAB nTab = rRange.aStart.Tab();
+        SCROW nRow1 = rRange.aStart.Row();
+        SCROW nRow2 = rRange.aEnd.Row();
+        for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
+            aSet.set(nTab, nCol, nRow1, nRow2, true);
+    }
+
+    ScriptTypeAggregator aAction(*this);
+    aSet.executeFromTop(aAction);
+    return aAction.getScriptType();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/listenercontext.cxx b/sc/source/core/data/listenercontext.cxx
index 4d8afb3..a288494 100644
--- a/sc/source/core/data/listenercontext.cxx
+++ b/sc/source/core/data/listenercontext.cxx
@@ -35,9 +35,9 @@ ScDocument& EndListeningContext::getDoc()
     return mrDoc;
 }
 
-void EndListeningContext::addEmptyBroadcasterPosition(SCCOL nCol, SCROW nRow, SCTAB nTab)
+void EndListeningContext::addEmptyBroadcasterPosition(SCTAB nTab, SCCOL nCol, SCROW nRow)
 {
-    maSet.set(nCol, nRow, nTab, true);
+    maSet.set(nTab, nCol, nRow, true);
 }
 
 void EndListeningContext::purgeEmptyBroadcasters()
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index 4c50eaf..d1654a6 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -2097,6 +2097,15 @@ void ScTable::SetScriptType( SCCOL nCol, SCROW nRow, sal_uInt8 nType )
     aCol[nCol].SetScriptType(nRow, nType);
 }
 
+sal_uInt8 ScTable::GetRangeScriptType(
+    sc::ColumnBlockPosition& rBlockPos, SCCOL nCol, SCROW nRow1, SCROW nRow2 )
+{
+    if (!ValidCol(nCol))
+        return 0;
+
+    return aCol[nCol].GetRangeScriptType(rBlockPos.miCellTextAttrPos, nRow1, nRow2);
+}
+
 size_t ScTable::GetFormulaHash( SCCOL nCol, SCROW nRow ) const
 {
     if (!ValidCol(nCol))
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index 9c7ca49..e85f780 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -823,17 +823,7 @@ sal_uInt8 ScViewFunc::GetSelectionScriptType()
     {
         ScRangeList aRanges;
         rMark.FillRangeListWithMarks( &aRanges, false );
-        size_t nCount = aRanges.size();
-        for ( size_t i=0; i < nCount; i++ )
-        {
-            ScRange aRange = *aRanges[i];
-            ScCellIterator aIter( pDoc, aRange );
-            for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
-            {
-                nScript |= pDoc->GetScriptType(
-                    aIter.GetPos().Col(), aIter.GetPos().Row(), aIter.GetPos().Tab());
-            }
-        }
+        nScript = pDoc->GetRangeScriptType(aRanges);
     }
 
     if (nScript == 0)


More information about the Libreoffice-commits mailing list