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 !!!
 }
 

Reply via email to