sc/source/core/data/patattr.cxx | 71 ++++++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 14 deletions(-)
New commits: commit eb13c889c760cfe153d5b41188e218bdda797d52 Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Wed Jun 21 10:28:43 2023 +0200 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Thu Jun 22 15:11:04 2023 +0200 Speed up scrolling through large document with lots of patterns Optimise comparison in ScPatternAttr::IsVisibleEqual Change-Id: I8e569c888c695a3ce89c2b9993ed729754d402e9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153454 Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sc/source/core/data/patattr.cxx b/sc/source/core/data/patattr.cxx index 25900b7ac099..706ab6ae5c19 100644 --- a/sc/source/core/data/patattr.cxx +++ b/sc/source/core/data/patattr.cxx @@ -47,6 +47,7 @@ #include <editeng/justifyitem.hxx> #include <svl/intitem.hxx> #include <svl/numformat.hxx> +#include <svl/whiter.hxx> #include <svl/zforlist.hxx> #include <vcl/outdev.hxx> #include <tools/fract.hxx> @@ -1217,24 +1218,66 @@ bool ScPatternAttr::IsVisible() const return false; } -static bool OneEqual( const SfxItemSet& rSet1, const SfxItemSet& rSet2, sal_uInt16 nId ) -{ - const SfxPoolItem* pItem1 = &rSet1.Get(nId); - const SfxPoolItem* pItem2 = &rSet2.Get(nId); - return ( pItem1 == pItem2 || *pItem1 == *pItem2 ); -} - bool ScPatternAttr::IsVisibleEqual( const ScPatternAttr& rOther ) const { - const SfxItemSet& rThisSet = GetItemSet(); - const SfxItemSet& rOtherSet = rOther.GetItemSet(); + // This method is hot, so we do an optimised comparison here, by + // walking the two itemsets in parallel, avoiding doing repeated searches. + auto IsInterestingWhich = [](sal_uInt16 n) + { + return n == ATTR_BORDER_TLBR || n == ATTR_BORDER_BLTR || n == ATTR_BACKGROUND + || n == ATTR_BORDER || n == ATTR_SHADOW; + }; + SfxWhichIter aIter1(GetItemSet()); + SfxWhichIter aIter2(rOther.GetItemSet()); + sal_uInt16 nWhich1 = aIter1.FirstWhich(); + sal_uInt16 nWhich2 = aIter2.FirstWhich(); + for (;;) + { + while (nWhich1 != nWhich2) + { + SfxWhichIter* pIterToIncrement; + sal_uInt16* pSmallerWhich; + if (nWhich1 == 0 || nWhich1 > nWhich2) + { + pSmallerWhich = &nWhich2; + pIterToIncrement = &aIter2; + } + else + { + pSmallerWhich = &nWhich1; + pIterToIncrement = &aIter1; + } - return OneEqual( rThisSet, rOtherSet, ATTR_BACKGROUND ) && - OneEqual( rThisSet, rOtherSet, ATTR_BORDER ) && - OneEqual( rThisSet, rOtherSet, ATTR_BORDER_TLBR ) && - OneEqual( rThisSet, rOtherSet, ATTR_BORDER_BLTR ) && - OneEqual( rThisSet, rOtherSet, ATTR_SHADOW ); + if (IsInterestingWhich(*pSmallerWhich)) + { + // the iter with larger which has already passed this point, and has no interesting + // item available in the other - so indeed these are unequal + return false; + } + + *pSmallerWhich = pIterToIncrement->NextWhich(); + } + + // Here nWhich1 == nWhich2 + if (!nWhich1 /* && !nWhich2*/) + return true; + + if (IsInterestingWhich(nWhich1)) + { + const SfxPoolItem* pItem1 = nullptr; + const SfxPoolItem* pItem2 = nullptr; + SfxItemState state1 = aIter1.GetItemState(true, &pItem1); + SfxItemState state2 = aIter2.GetItemState(true, &pItem2); + if (state1 != state2 + && (state1 < SfxItemState::DEFAULT || state2 < SfxItemState::DEFAULT)) + return false; + if (pItem1 != pItem2) + return false; + } + nWhich1 = aIter1.NextWhich(); + nWhich2 = aIter2.NextWhich(); + } //TODO: also here only check really visible values !!! }