sw/qa/core/objectpositioning/data/floattable-tbl-overlap.docx      |binary
 sw/qa/core/objectpositioning/objectpositioning.cxx                 |   33 
++++++++++
 sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx |   22 
++++++
 3 files changed, 55 insertions(+)

New commits:
commit cffb2473b2d50ff3cf158dc3ed733156980a3764
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Aug 10 09:05:18 2023 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Fri Aug 11 11:17:58 2023 +0200

    sw floattable: handle AllowOverlap==false in the layout
    
    The bugdoc has two floating tables, and these would normally overlap,
    but SwFormatWrapInfluenceOnObjPos::mbAllowOverlap requests tweaking the
    position at a layout level to avoid that overlap.
    
    This is similar to what commit d37096f59e7e0286e55008153591a60bab92b9e8
    (Related: tdf#124600 sw anchored object allow overlap: add layout,
    2019-09-19) did, but that was for draw shapes and this is for split
    flys.
    
    Fix the problem by extending
    SwToContentAnchoredObjectPosition::CalcOverlap(): the overlap detection
    can be reused, just need to look for split flys on the entire page +
    need to check split flys against other split flys.
    
    The ODT filter works out of the box.
    
    (cherry picked from commit 905962db870e9d1cf1dcf3bd1be44c347cddafe1)
    
    Change-Id: Id31308a67ba502bcc830f15a1679996ec153f209
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155578
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/qa/core/objectpositioning/data/floattable-tbl-overlap.docx 
b/sw/qa/core/objectpositioning/data/floattable-tbl-overlap.docx
new file mode 100644
index 000000000000..b5b23931a240
Binary files /dev/null and 
b/sw/qa/core/objectpositioning/data/floattable-tbl-overlap.docx differ
diff --git a/sw/qa/core/objectpositioning/objectpositioning.cxx 
b/sw/qa/core/objectpositioning/objectpositioning.cxx
index bb3a12793ae8..4958b8b6deb4 100644
--- a/sw/qa/core/objectpositioning/objectpositioning.cxx
+++ b/sw/qa/core/objectpositioning/objectpositioning.cxx
@@ -15,6 +15,12 @@
 #include <wrtsh.hxx>
 #include <unotxdoc.hxx>
 #include <docsh.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <sortedobjs.hxx>
+#include <anchoredobject.hxx>
+#include <flyfrm.hxx>
 
 /// Covers sw/source/core/objectpositioning/ fixes.
 class SwCoreObjectpositioningTest : public SwModelTestBase
@@ -280,6 +286,33 @@ CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testVMLVertAlignBottomMargin)
     CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), nFifthVMLShapeOutside - 
nPageBottom);
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testFloatingTableOverlapNever)
+{
+    // Given a document with two floating tables, positioned in a way that 
normally these would
+    // overlap, but SwFormatWrapInfluenceOnObjPos::mbAllowOverlap == false 
explicitly asks to avoid
+    // overlaps:
+    createSwDoc("floattable-tbl-overlap.docx");
+
+    // When laying out that document:
+    calcLayout();
+
+    // Then make sure no overlap happens:
+    SwDoc* pDoc = getSwDoc();
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    auto pPage1 = dynamic_cast<SwPageFrame*>(pLayout->Lower());
+    CPPUNIT_ASSERT(pPage1);
+    CPPUNIT_ASSERT(pPage1->GetSortedObjs());
+    const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rPage1Objs.size());
+    auto pFlyFrame1 = rPage1Objs[0]->DynCastFlyFrame();
+    auto pFlyFrame2 = rPage1Objs[1]->DynCastFlyFrame();
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected greater than: 2291
+    // - Actual  : 2175
+    // i.e. the 2nd floating table overlapped with the first one.
+    CPPUNIT_ASSERT_GREATER(pFlyFrame1->getFrameArea().Bottom(), 
pFlyFrame2->getFrameArea().Top());
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx 
b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
index 9a9abc9f4dd8..33168ceba432 100644
--- a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
@@ -1194,6 +1194,21 @@ void 
SwToContentAnchoredObjectPosition::CalcOverlap(const SwTextFrame* pAnchorFr
 
     // Get the list of objects.
     auto pSortedObjs = pAnchorFrameForVertPos->GetDrawObjs();
+
+    bool bSplitFly = false;
+    SwFlyFrame* pFlyFrame = GetAnchoredObj().DynCastFlyFrame();
+    if (pFlyFrame && pFlyFrame->IsFlySplitAllowed())
+    {
+        // At least for split flys we need to consider objects on the same 
page, but anchored in
+        // different text frames.
+        bSplitFly = true;
+        const SwPageFrame* pPageFrame = 
pAnchorFrameForVertPos->FindPageFrame();
+        if (pPageFrame)
+        {
+            pSortedObjs = pPageFrame->GetSortedObjs();
+        }
+    }
+
     if (!pSortedObjs)
     {
         return;
@@ -1213,6 +1228,13 @@ void 
SwToContentAnchoredObjectPosition::CalcOverlap(const SwTextFrame* pAnchorFr
             continue;
         }
 
+        SwFlyFrame* pAnchoredObjFly = pAnchoredObj->DynCastFlyFrame();
+        if (bSplitFly && !pAnchoredObjFly)
+        {
+            // This is a split fly, then overlap is only checked against other 
split flys.
+            continue;
+        }
+
         css::text::WrapTextMode eWrap = 
pAnchoredObj->GetFrameFormat().GetSurround().GetSurround();
         if (eWrap == css::text::WrapTextMode_THROUGH)
         {

Reply via email to