sw/qa/core/objectpositioning/data/floattable-nested-overlap.docx   |binary
 sw/qa/core/objectpositioning/objectpositioning.cxx                 |   27 
++++++++++
 sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx |   10 +++
 3 files changed, 37 insertions(+)

New commits:
commit f6b8d237f072fd5fe8fa40068d08c8f753fe261c
Author:     Miklos Vajna <[email protected]>
AuthorDate: Wed Oct 15 08:36:44 2025 +0200
Commit:     Michael Stahl <[email protected]>
CommitDate: Wed Oct 15 13:29:59 2025 +0200

    tdf#165615 sw floattable, no overlap: avoid check against an own follow
    
    Load the bugdoc, the layuot loop control kicks in:
    warn:sw.layout:20117:20117:sw/source/core/layout/tabfrm.cxx:1853: 
LoopControl in SwContentFrame::CalcLowers
    and then the content is laid out on 3 pages, while it fits 2 pages in
    Word.
    
    What happens is that the document has an inline table, then a floating
    table inside that. The inner floating table has tblOverlap set to
    'never', and then things go wrong in
    SwToContentAnchoredObjectPosition::CalcOverlap().
    
    Fix the problem by checking if the two overlapping fly frames are
    actually next to each other in a split fly chain: if we're the precede
    of the other fly, then no need to worry about the overlap, that follow
    fly will move to the next page anyway.
    
    In theory this would be also interesting for toplevel floating tables,
    too -- but in practice CppunitTest_sw_core_layout's testSplitFlyHeader
    shows doing this in general would need more work, so just do this for
    floating tables which are inside tables.
    
    Change-Id: I4d0f1bd5229f8fbc3bb49af57f88fd6ef911cbfe
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192426
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Michael Stahl <[email protected]>

diff --git a/sw/qa/core/objectpositioning/data/floattable-nested-overlap.docx 
b/sw/qa/core/objectpositioning/data/floattable-nested-overlap.docx
new file mode 100644
index 000000000000..a852d9c1e7ba
Binary files /dev/null and 
b/sw/qa/core/objectpositioning/data/floattable-nested-overlap.docx differ
diff --git a/sw/qa/core/objectpositioning/objectpositioning.cxx 
b/sw/qa/core/objectpositioning/objectpositioning.cxx
index e290a0c1e77f..d89f73a6b8c5 100644
--- a/sw/qa/core/objectpositioning/objectpositioning.cxx
+++ b/sw/qa/core/objectpositioning/objectpositioning.cxx
@@ -540,6 +540,33 @@ CPPUNIT_TEST_FIXTURE(Test, 
testDoNotCaptureDrawObjsDrawObjNoCapture)
     // i.e. the draw object was captured inside the page frame, but it was not 
in Word.
     CPPUNIT_ASSERT_GREATER(nDrawObjLeft, nPageLeft);
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testFloattableNestedOverlap)
+{
+    // Given a document with an outer inline table, an inner floating table, 
the floating table's
+    // overlap is set to 'never':
+    createSwDoc("floattable-nested-overlap.docx");
+
+    // When laying out that document:
+    calcLayout();
+
+    // Then make sure the content fits two pages and the floating table is 
split:
+    SwDoc* pDoc = getSwDoc();
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    SwPageFrame* pPage1 = pLayout->Lower()->DynCastPageFrame();
+    CPPUNIT_ASSERT(pPage1);
+    CPPUNIT_ASSERT(pPage1->GetSortedObjs());
+    const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size());
+    SwPageFrame* pPage2 = pPage1->GetNext()->DynCastPageFrame();
+    CPPUNIT_ASSERT(pPage2);
+    CPPUNIT_ASSERT(pPage2->GetSortedObjs());
+    const SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size());
+    // Without the accompanying fix in place, this test would have failed, the 
content was laid out
+    // on 3 pages in Writer.
+    CPPUNIT_ASSERT(!pPage2->GetNext());
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx 
b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
index 9ffb25400fd7..48aed01d206e 100644
--- a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
@@ -1290,6 +1290,16 @@ void 
SwToContentAnchoredObjectPosition::CalcOverlap(const SwTextFrame* pAnchorFr
                 // A fly overlapping with a fly from another upper is fine.
                 continue;
             }
+
+            bool bAnchoredObjFlyAnchorInTable
+                = pAnchoredObjFlyAnchor && pAnchoredObjFlyAnchor->IsInTab();
+            SwFlyAtContentFrame* pAnchoredObjSplitFly = 
pAnchoredObjFly->DynCastFlyAtContentFrame();
+            if (pAnchoredObjSplitFly && pAnchoredObjSplitFly->GetPrecede() == 
pFlyFrame
+                && bAnchoredObjFlyAnchorInTable)
+            {
+                // A follow fly will move to the next page anyway, ignore.
+                continue;
+            }
         }
 
         css::text::WrapTextMode eWrap = 
pAnchoredObj->GetFrameFormat()->GetSurround().GetSurround();

Reply via email to