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();
