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 e2b2ecad7a0ffdf1e0c34ec70c1987698971cbad
Author:     Miklos Vajna <[email protected]>
AuthorDate: Wed Oct 15 08:36:44 2025 +0200
Commit:     Adolfo Jayme Barrientos <[email protected]>
CommitDate: Mon Oct 20 17:33:58 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/+/192433
    Reviewed-by: Miklos Vajna <[email protected]>
    Tested-by: Jenkins
    (cherry picked from commit 72e79a4d75cbbc8615fe9815bbbe9a38780ff856)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192717
    Reviewed-by: Adolfo Jayme Barrientos <[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 7e1104df9db9..cf2d93837792 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