sc/qa/unit/tiledrendering/tiledrendering.cxx |   42 +++++++++++++++++++++++++--
 sc/source/ui/view/tabview.cxx                |    8 +++--
 2 files changed, 44 insertions(+), 6 deletions(-)

New commits:
commit 6ece9bae17307644774e53ef15b150e626239d9f
Author:     Caolán McNamara <[email protected]>
AuthorDate: Mon Jan 22 17:30:27 2024 +0000
Commit:     Miklos Vajna <[email protected]>
CommitDate: Tue Jan 23 14:44:59 2024 +0100

    produce non-overlapping invalidation rects on extending calc tiled area
    
    the intent is to create two rects, one for the area extended to the
    right and another for the area extended to the bottom, but they overlap
    so they end up merged and a single rect of the entire sheet is created
    which is defeats the original intention.
    
    Change-Id: Ie5b46ee1a36780d9f7a90ed11ebfd1264c17477a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162412
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx 
b/sc/qa/unit/tiledrendering/tiledrendering.cxx
index 8b092c49c0d2..7ec0d730180d 100644
--- a/sc/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx
@@ -177,6 +177,7 @@ public:
     void testCellMinimalInvalidations();
     void testCellInvalidationDocWithExistingZoom();
     void testOptimalRowHeight();
+    void testExtendedAreasDontOverlap();
 
     CPPUNIT_TEST_SUITE(ScTiledRenderingTest);
     CPPUNIT_TEST(testRowColumnHeaders);
@@ -255,6 +256,7 @@ public:
     CPPUNIT_TEST(testCellMinimalInvalidations);
     CPPUNIT_TEST(testCellInvalidationDocWithExistingZoom);
     CPPUNIT_TEST(testOptimalRowHeight);
+    CPPUNIT_TEST(testExtendedAreasDontOverlap);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -2107,7 +2109,7 @@ void 
ScTiledRenderingTest::testGetRowColumnHeadersInvalidation()
     Scheduler::ProcessEventsToIdle();
     CPPUNIT_ASSERT(aView1.m_bInvalidateTiles);
     CPPUNIT_ASSERT_EQUAL(size_t(1), aView1.m_aInvalidations.size());
-    CPPUNIT_ASSERT_EQUAL(tools::Rectangle(26775, 0, 49725, 13005), 
aView1.m_aInvalidations[0]);
+    CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(26775, 0), Size(22950, 
13005)), aView1.m_aInvalidations[0]);
 
     // Extend area top-to-bottom
     aView1.m_bInvalidateTiles = false;
@@ -2118,7 +2120,7 @@ void 
ScTiledRenderingTest::testGetRowColumnHeadersInvalidation()
     Scheduler::ProcessEventsToIdle();
     CPPUNIT_ASSERT(aView1.m_bInvalidateTiles);
     CPPUNIT_ASSERT_EQUAL(size_t(1), aView1.m_aInvalidations.size());
-    CPPUNIT_ASSERT_EQUAL(tools::Rectangle(0, 13005, 49725, 19380), 
aView1.m_aInvalidations[0]);
+    CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(0, 13005), Size(49725, 6375)), 
aView1.m_aInvalidations[0]);
 
     // Extend area left-to-right
     aView1.m_bInvalidateTiles = false;
@@ -2129,7 +2131,7 @@ void 
ScTiledRenderingTest::testGetRowColumnHeadersInvalidation()
     Scheduler::ProcessEventsToIdle();
     CPPUNIT_ASSERT(aView1.m_bInvalidateTiles);
     CPPUNIT_ASSERT_EQUAL(size_t(1), aView1.m_aInvalidations.size());
-    CPPUNIT_ASSERT_EQUAL(tools::Rectangle(49725, 0, 75225, 19380), 
aView1.m_aInvalidations[0]);
+    CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(49725, 0), Size(25500, 
19380)), aView1.m_aInvalidations[0]);
 }
 
 void ScTiledRenderingTest::testJumpHorizontallyInvalidation()
@@ -3917,6 +3919,40 @@ void ScTiledRenderingTest::testOptimalRowHeight()
     CPPUNIT_ASSERT_EQUAL_MESSAGE("After setOptimalHeight: Row#306 height is 
invalid!", sal_uInt16(504), pDoc->GetRowHeight(nRow, 0));
 }
 
+// if we extend the tiled area to the right and bottom we want two resulting 
area
+// that don't overlap. If they overlap that typically creates an unnecessary 
full
+// screen invalidation.
+void ScTiledRenderingTest::testExtendedAreasDontOverlap()
+{
+    ScModelObj* pModelObj = createDoc("empty.ods");
+    ScTabViewShell* pView = 
dynamic_cast<ScTabViewShell*>(SfxViewShell::Current());
+    CPPUNIT_ASSERT(pModelObj && pView);
+
+    Scheduler::ProcessEventsToIdle();
+
+    // register to track View #1 invalidations
+    ViewCallback aView1;
+
+    // extend to the right and bottom
+    pModelObj->setClientVisibleArea(tools::Rectangle(0, 0, 39750, 12780));
+
+    Scheduler::ProcessEventsToIdle();
+
+    // we should get two rectangles for the two new areas
+    CPPUNIT_ASSERT_EQUAL(size_t(2), aView1.m_aInvalidations.size());
+
+    // And those should not overlap, otherwise they would merge to form
+    // a mega rectangle, which defeats the purpose of creating two rects
+    // in the first place.
+    CPPUNIT_ASSERT_MESSAGE("Invalidations should not overlap",
+        !aView1.m_aInvalidations[0].Overlaps(aView1.m_aInvalidations[1]));
+
+    // But they should be adjacent
+    CPPUNIT_ASSERT_EQUAL(aView1.m_aInvalidations[0].Top() +
+                         aView1.m_aInvalidations[0].GetSize().Height(),
+                         aView1.m_aInvalidations[1].Top());
+}
+
 }
 
 CPPUNIT_TEST_SUITE_REGISTRATION(ScTiledRenderingTest);
diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx
index 05e08345075a..94892ca70c63 100644
--- a/sc/source/ui/view/tabview.cxx
+++ b/sc/source/ui/view/tabview.cxx
@@ -2689,10 +2689,12 @@ void lcl_ExtendTiledDimension(bool bColumn, const 
SCCOLROW nEnd, const SCCOLROW
     }
 
     // New area extended to the right/bottom of the sheet after last col/row
+    tools::Rectangle aNewArea(Point(0, 0), aNewSize);
     // excluding overlapping area with aNewArea
-    tools::Rectangle aNewArea = bColumn ?
-        tools::Rectangle(aOldSize.getWidth(), 0, aNewSize.getWidth(), 
aNewSize.getHeight()):
-        tools::Rectangle(0, aOldSize.getHeight(), aNewSize.getWidth(), 
aNewSize.getHeight());
+    if (bColumn)
+        aNewArea.SetLeft(aOldSize.getWidth());
+    else
+        aNewArea.SetTop(aOldSize.getHeight());
 
     // Only invalidate if spreadsheet has extended to the right or bottom
     if ((bColumn && aNewArea.getOpenWidth()) || (!bColumn && 
aNewArea.getOpenHeight()))

Reply via email to