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) {