Kaydet (Commit) af0c93da authored tarafından Markus Mohrhard's avatar Markus Mohrhard

kill O(N^2) algorithm generating cond format render information, fdo#54396

Change-Id: I63536625eaf9b73c8e63d3cf88b6b798a6bf017b
üst bc63efc5
...@@ -35,8 +35,11 @@ ...@@ -35,8 +35,11 @@
#include "scdllapi.h" #include "scdllapi.h"
#include "rangelst.hxx" #include "rangelst.hxx"
#include <rtl/math.hxx>
#include <boost/ptr_container/ptr_set.hpp> #include <boost/ptr_container/ptr_set.hpp>
#include <boost/ptr_container/ptr_vector.hpp> #include <boost/ptr_container/ptr_vector.hpp>
#include <boost/scoped_ptr.hpp>
class ScBaseCell; class ScBaseCell;
class ScFormulaCell; class ScFormulaCell;
...@@ -116,11 +119,26 @@ public: ...@@ -116,11 +119,26 @@ public:
#if DUMP_FORMAT_INFO #if DUMP_FORMAT_INFO
virtual void dumpInfo(rtl::OUStringBuffer& rBuf) const = 0; virtual void dumpInfo(rtl::OUStringBuffer& rBuf) const = 0;
#endif #endif
virtual void startRendering();
virtual void endRendering();
protected: protected:
ScDocument* mpDoc; ScDocument* mpDoc;
}; };
class approx_less : public std::binary_function<double, double, bool>
{
public:
bool operator() (double nVal1, double nVal2)
{
if(nVal1 < nVal2 && !rtl::math::approxEqual(nVal1, nVal2))
return true;
return false;
}
};
class SC_DLLPUBLIC ScConditionEntry : public ScFormatEntry class SC_DLLPUBLIC ScConditionEntry : public ScFormatEntry
{ {
// stored data: // stored data:
...@@ -216,10 +234,27 @@ public: ...@@ -216,10 +234,27 @@ public:
virtual void dumpInfo(rtl::OUStringBuffer& ) const {} virtual void dumpInfo(rtl::OUStringBuffer& ) const {}
#endif #endif
virtual void endRendering();
virtual void startRendering();
protected: protected:
virtual void DataChanged( const ScRange* pModified ) const; virtual void DataChanged( const ScRange* pModified ) const;
ScDocument* GetDocument() const { return mpDoc; } ScDocument* GetDocument() const { return mpDoc; }
ScConditionalFormat* pCondFormat; ScConditionalFormat* pCondFormat;
private:
bool IsDuplicate(double nArg, const rtl::OUString& rStr, const ScAddress& rAddr, const ScRangeList& rRanges) const;
struct ScConditionEntryCache
{
typedef std::map<rtl::OUString, sal_Int32> StringCacheType;
StringCacheType maStrings;
typedef std::map<double, sal_Int32, approx_less> ValueCacheType;
ValueCacheType maValues;
};
mutable boost::scoped_ptr<ScConditionEntryCache> mpCache;
}; };
// //
...@@ -326,6 +361,9 @@ public: ...@@ -326,6 +361,9 @@ public:
// operator== only for sorting // operator== only for sorting
bool operator ==( const ScConditionalFormat& r ) const { return nKey == r.nKey; } bool operator ==( const ScConditionalFormat& r ) const { return nKey == r.nKey; }
bool operator < ( const ScConditionalFormat& r ) const { return nKey < r.nKey; } bool operator < ( const ScConditionalFormat& r ) const { return nKey < r.nKey; }
void startRendering();
void endRendering();
}; };
// //
...@@ -371,6 +409,9 @@ public: ...@@ -371,6 +409,9 @@ public:
size_t size() const; size_t size() const;
void erase(sal_uLong nIndex); void erase(sal_uLong nIndex);
void startRendering();
void endRendering();
}; };
// see http://www.boost.org/doc/libs/1_49_0/libs/ptr_container/doc/tutorial.html#cloneability // see http://www.boost.org/doc/libs/1_49_0/libs/ptr_container/doc/tutorial.html#cloneability
......
...@@ -72,6 +72,14 @@ bool ScFormatEntry::operator==( const ScFormatEntry& r ) const ...@@ -72,6 +72,14 @@ bool ScFormatEntry::operator==( const ScFormatEntry& r ) const
} }
} }
void ScFormatEntry::startRendering()
{
}
void ScFormatEntry::endRendering()
{
}
bool lcl_HasRelRef( ScDocument* pDoc, ScTokenArray* pFormula, sal_uInt16 nRecursion = 0 ) bool lcl_HasRelRef( ScDocument* pDoc, ScTokenArray* pFormula, sal_uInt16 nRecursion = 0 )
{ {
if (pFormula) if (pFormula)
...@@ -716,7 +724,7 @@ void ScConditionEntry::Interpret( const ScAddress& rPos ) ...@@ -716,7 +724,7 @@ void ScConditionEntry::Interpret( const ScAddress& rPos )
bFirstRun = false; bFirstRun = false;
} }
static bool lcl_GetCellContent( ScBaseCell* pCell, bool bIsStr1, double& rArg, String& rArgStr ) static bool lcl_GetCellContent( ScBaseCell* pCell, bool bIsStr1, double& rArg, rtl::OUString& rArgStr )
{ {
bool bVal = true; bool bVal = true;
...@@ -760,53 +768,84 @@ static bool lcl_GetCellContent( ScBaseCell* pCell, bool bIsStr1, double& rArg, S ...@@ -760,53 +768,84 @@ static bool lcl_GetCellContent( ScBaseCell* pCell, bool bIsStr1, double& rArg, S
return bVal; return bVal;
} }
static bool lcl_IsDuplicate( ScDocument *pDoc, double nArg, const String& rStr, const ScAddress& rAddr, const ScRangeList& rRanges ) bool ScConditionEntry::IsDuplicate( double nArg, const rtl::OUString& rStr, const ScAddress& rAddr, const ScRangeList& rRanges ) const
{ {
size_t nListCount = rRanges.size(); if(!mpCache)
for( size_t i = 0; i < nListCount; i++ )
{ {
const ScRange *aRange = rRanges[i]; mpCache.reset(new ScConditionEntryCache);
SCROW nRow = aRange->aEnd.Row(); size_t nListCount = rRanges.size();
SCCOL nCol = aRange->aEnd.Col(); for( size_t i = 0; i < nListCount; i++ )
SCCOL nColStart = aRange->aStart.Col();
SCROW nRowStart = aRange->aEnd.Row();
SCTAB nTab = aRange->aStart.Tab();
// temporary fix to workaorund slow duplicate entry
// conditions, prevent to use a whole row
if(nRow == MAXROW)
{ {
bool bShrunk = false; const ScRange *aRange = rRanges[i];
pDoc->ShrinkToUsedDataArea(bShrunk, nTab, nColStart, nRowStart, SCROW nRow = aRange->aEnd.Row();
nCol, nRow, false); SCCOL nCol = aRange->aEnd.Col();
} SCCOL nColStart = aRange->aStart.Col();
SCROW nRowStart = aRange->aStart.Row();
for( SCROW r = nRowStart; r <= nRow; r++ ) SCTAB nTab = aRange->aStart.Tab();
for( SCCOL c = nColStart; c <= nCol; c++ )
// temporary fix to workaorund slow duplicate entry
// conditions, prevent to use a whole row
if(nRow == MAXROW)
{ {
double nVal = 0.0; bool bShrunk = false;
ScBaseCell *pCell = NULL; mpDoc->ShrinkToUsedDataArea(bShrunk, nTab, nColStart, nRowStart,
String aStr; nCol, nRow, false);
}
if( c == rAddr.Col() && r == rAddr.Row() )
continue;
pDoc->GetCell( c, r, rAddr.Tab(), pCell );
if( !pCell )
continue;
if( !lcl_GetCellContent( pCell, false, nVal, aStr ) ) for( SCROW r = nRowStart; r <= nRow; r++ )
{ for( SCCOL c = nColStart; c <= nCol; c++ )
if( rStr.Len() &&
( ScGlobal::GetCollator()->compareString( rStr, aStr ) == COMPARE_EQUAL ) )
return true;
}
else
{ {
if( !rStr.Len() && ::rtl::math::approxEqual( nArg, nVal ) ) double nVal = 0.0;
return true; ScBaseCell *pCell = NULL;
mpDoc->GetCell( c, r, rAddr.Tab(), pCell );
if( !pCell )
continue;
rtl::OUString aStr;
if( !lcl_GetCellContent( pCell, false, nVal, aStr ) )
{
std::pair<ScConditionEntryCache::StringCacheType::iterator, bool> aResult = mpCache->maStrings.insert(std::pair<rtl::OUString, sal_Int32>(aStr, static_cast<sal_Int32>(1)));
if(!aResult.second)
aResult.first->second++;
}
else
{
std::pair<ScConditionEntryCache::ValueCacheType::iterator, bool> aResult = mpCache->maValues.insert(std::pair<double, sal_Int32>(nVal, (sal_Int32)1));
if(!aResult.second)
aResult.first->second++;
}
} }
} }
}
if(rStr.isEmpty())
{
ScConditionEntryCache::ValueCacheType::iterator itr = mpCache->maValues.find(nArg);
if(itr == mpCache->maValues.end())
return false;
else
{
if(itr->second > 1)
return true;
else
return false;
}
}
else
{
ScConditionEntryCache::StringCacheType::iterator itr = mpCache->maStrings.find(rStr);
if(itr == mpCache->maStrings.end())
return false;
else
{
if(itr->second > 1)
return true;
else
return false;
}
} }
return false; return false;
} }
...@@ -873,7 +912,7 @@ bool ScConditionEntry::IsValid( double nArg, const ScAddress& rAddr ) const ...@@ -873,7 +912,7 @@ bool ScConditionEntry::IsValid( double nArg, const ScAddress& rAddr ) const
if( pCondFormat ) if( pCondFormat )
{ {
const ScRangeList& aRanges = pCondFormat->GetRange(); const ScRangeList& aRanges = pCondFormat->GetRange();
bValid = lcl_IsDuplicate( mpDoc, nArg, String(), rAddr, aRanges ); bValid = IsDuplicate( nArg, rtl::OUString(), rAddr, aRanges );
if( eOp == SC_COND_NOTDUPLICATE ) if( eOp == SC_COND_NOTDUPLICATE )
bValid = !bValid; bValid = !bValid;
} }
...@@ -901,7 +940,7 @@ bool ScConditionEntry::IsValidStr( const String& rArg, const ScAddress& rAddr ) ...@@ -901,7 +940,7 @@ bool ScConditionEntry::IsValidStr( const String& rArg, const ScAddress& rAddr )
if( pCondFormat && rArg.Len() ) if( pCondFormat && rArg.Len() )
{ {
const ScRangeList& aRanges = pCondFormat->GetRange(); const ScRangeList& aRanges = pCondFormat->GetRange();
bValid = lcl_IsDuplicate( mpDoc, 0.0, rArg, rAddr, aRanges ); bValid = IsDuplicate( 0.0, rArg, rAddr, aRanges );
if( eOp == SC_COND_NOTDUPLICATE ) if( eOp == SC_COND_NOTDUPLICATE )
bValid = !bValid; bValid = !bValid;
return bValid; return bValid;
...@@ -980,7 +1019,7 @@ bool ScConditionEntry::IsCellValid( ScBaseCell* pCell, const ScAddress& rPos ) c ...@@ -980,7 +1019,7 @@ bool ScConditionEntry::IsCellValid( ScBaseCell* pCell, const ScAddress& rPos ) c
((ScConditionEntry*)this)->Interpret(rPos); // Formeln auswerten ((ScConditionEntry*)this)->Interpret(rPos); // Formeln auswerten
double nArg = 0.0; double nArg = 0.0;
String aArgStr; rtl::OUString aArgStr;
bool bVal = lcl_GetCellContent( pCell, bIsStr1, nArg, aArgStr ); bool bVal = lcl_GetCellContent( pCell, bIsStr1, nArg, aArgStr );
if (bVal) if (bVal)
return IsValid( nArg, rPos ); return IsValid( nArg, rPos );
...@@ -1278,6 +1317,17 @@ ScConditionMode ScConditionEntry::GetModeFromApi(sal_Int32 nOperation) ...@@ -1278,6 +1317,17 @@ ScConditionMode ScConditionEntry::GetModeFromApi(sal_Int32 nOperation)
} }
return eMode; return eMode;
} }
void ScConditionEntry::startRendering()
{
mpCache.reset();
}
void ScConditionEntry::endRendering()
{
mpCache.reset();
}
//------------------------------------------------------------------------ //------------------------------------------------------------------------
ScCondFormatEntry::ScCondFormatEntry( ScConditionMode eOper, ScCondFormatEntry::ScCondFormatEntry( ScConditionMode eOper,
...@@ -1578,6 +1628,22 @@ bool ScConditionalFormat::MarkUsedExternalReferences() const ...@@ -1578,6 +1628,22 @@ bool ScConditionalFormat::MarkUsedExternalReferences() const
return bAllMarked; return bAllMarked;
} }
void ScConditionalFormat::startRendering()
{
for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
{
itr->startRendering();
}
}
void ScConditionalFormat::endRendering()
{
for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
{
itr->endRendering();
}
}
//------------------------------------------------------------------------ //------------------------------------------------------------------------
ScConditionalFormatList::ScConditionalFormatList(const ScConditionalFormatList& rList) ScConditionalFormatList::ScConditionalFormatList(const ScConditionalFormatList& rList)
...@@ -1721,4 +1787,20 @@ void ScConditionalFormatList::erase( sal_uLong nIndex ) ...@@ -1721,4 +1787,20 @@ void ScConditionalFormatList::erase( sal_uLong nIndex )
} }
} }
void ScConditionalFormatList::startRendering()
{
for(iterator itr = begin(); itr != end(); ++itr)
{
itr->startRendering();
}
}
void ScConditionalFormatList::endRendering()
{
for(iterator itr = begin(); itr != end(); ++itr)
{
itr->endRendering();
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -363,6 +363,9 @@ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX ...@@ -363,6 +363,9 @@ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX
} }
ScConditionalFormatList* pCondFormList = GetCondFormList(nTab); ScConditionalFormatList* pCondFormList = GetCondFormList(nTab);
if(pCondFormList)
pCondFormList->startRendering();
for (nArrX=0; nArrX<=nX2+2; nArrX++) // links & rechts + 1 for (nArrX=0; nArrX<=nX2+2; nArrX++) // links & rechts + 1
{ {
nX = (nArrX>0) ? nArrX-1 : MAXCOL+1; // negativ -> ungueltig nX = (nArrX>0) ? nArrX-1 : MAXCOL+1; // negativ -> ungueltig
...@@ -647,6 +650,8 @@ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX ...@@ -647,6 +650,8 @@ void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX
// STD_COL_WIDTH ganz links und rechts wird fuer DrawExtraShadow gebraucht // STD_COL_WIDTH ganz links und rechts wird fuer DrawExtraShadow gebraucht
} }
if(pCondFormList)
pCondFormList->endRendering();
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// bedingte Formatierung auswerten // bedingte Formatierung auswerten
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment