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 35a8e22495a4cf756e650e8e4d840da1e8df80af Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Aug 4 10:44:30 2023 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Tue Aug 8 10:18:15 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. Change-Id: I56cf074a3d740ab716f7de232fbd131d17544d9e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155339 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins (cherry picked from commit c545a0729e89ee2e8f14534b77422cc9eb4eb7cf) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155397 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> 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 a1e4c05c6c1d..6207a956f574 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 a365668c4ce2..4022e1995fe8 100644 --- a/sw/source/core/layout/fly.cxx +++ b/sw/source/core/layout/fly.cxx @@ -687,7 +687,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()