sw/qa/core/layout/data/floattable-from-bottom.docx |binary sw/qa/core/layout/flycnt.cxx | 21 +++++++++++++++++++++ sw/source/core/layout/fly.cxx | 15 ++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-)
New commits: commit 4e94f0c68515fe10623c27db9bbeac35e1794314 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Aug 4 10:44:30 2023 +0200 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Wed Aug 9 09:59:45 2023 +0200 sw floattable, crashtesting: fix PDF export of tdf73201-1.docx The direct cause is that in in the SwTextFrameBreak ctor, m_pFrame has IsInSct() as true, but FindSctFrame() then doesn't find anything, which should not happen. The bigger problem is that currently the fly split code assumes that frames grow from (logical) top to bottom, so in case the vertical orientation is bottom, and we have to grow from bottom to top, that needs re-positioning the fly, but the fly split code has no support for that. Fix the crash by denying this case in SwFlyFrame::IsFlySplitAllowed() for now, the document's table is not supposed to split in the first place. In case later there is a real need to split such flys, then more research is needed how that re-positioning works in detail for non-split flys and then we have to adapt the fly split code accordingly. (cherry picked from commit c545a0729e89ee2e8f14534b77422cc9eb4eb7cf) Change-Id: I56cf074a3d740ab716f7de232fbd131d17544d9e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155447 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/sw/qa/core/layout/data/floattable-from-bottom.docx b/sw/qa/core/layout/data/floattable-from-bottom.docx new file mode 100644 index 000000000000..86374a68ba27 Binary files /dev/null and b/sw/qa/core/layout/data/floattable-from-bottom.docx differ diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx index 231890bd6739..00449f38e317 100644 --- a/sw/qa/core/layout/flycnt.cxx +++ b/sw/qa/core/layout/flycnt.cxx @@ -975,6 +975,27 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyNoFooterOverlap) const SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs(); CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size()); } + +CPPUNIT_TEST_FIXTURE(Test, testSplitFlyGrowFromBottom) +{ + // Given a document with a floating table that grows from the bottom: + createSwDoc("floattable-from-bottom.docx"); + + // When calculating the layout: + calcLayout(); + + // Then make sure that such a floating table is not split, matching Word: + 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(); + const auto pFly = dynamic_cast<SwFlyAtContentFrame*>(rPage1Objs[0]); + // Without the accompanying fix in place, this test would have failed, we tried to split the fly + // frame on page 1 even when it would fit, and this lead to a crash on export later. + CPPUNIT_ASSERT(!pFly->GetFollow()); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx index e8fd85e4475a..91fc6c85e18c 100644 --- a/sw/source/core/layout/fly.cxx +++ b/sw/source/core/layout/fly.cxx @@ -686,7 +686,20 @@ bool SwFlyFrame::IsFlySplitAllowed() const return false; } - return GetFormat()->GetFlySplit().GetValue(); + const SwFlyFrameFormat* pFormat = GetFormat(); + const SwFormatVertOrient& rVertOrient = pFormat->GetVertOrient(); + if (rVertOrient.GetVertOrient() == text::VertOrientation::BOTTOM) + { + // We have to grow from bottom to top, and the fly split code assumes that we grow from top + // to bottom, so don't split for now. + if (rVertOrient.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA) + { + // Growing from the bottom of the body frame. + return false; + } + } + + return pFormat->GetFlySplit().GetValue(); } SwFrame *SwFlyFrame::FindLastLower()