sw/qa/core/layout/data/floattable-in-section.docx |binary sw/qa/core/layout/flycnt.cxx | 6 ++++ sw/source/core/layout/fly.cxx | 32 ++++++++-------------- 3 files changed, 19 insertions(+), 19 deletions(-)
New commits: commit a1c5f77d3ee7c9907c8247aa0e896e07fe9427b6 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Apr 21 09:03:51 2023 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Fri Apr 21 11:47:43 2023 +0200 sw floattable, crashtesting: fix PDF export of forum-mso-de-117064.docx Converting the bugdoc to PDF crashed Writer layout since commit ce3308a926f036b87515b8cd97d2b197063dc77a (tdf#61594 sw floattable: import floating tables as split flys by default, 2023-04-12). What happened is that we hit a case in the SwTextFrameBreak ctor where the frame had the "is in section" bit set, but the frame wasn't actually in a section, so when looking up that parent section frame, we found nothing, and later code assumed that we always find something. This is fine, the root of the problem was that in the non-legacy case GetFlyAnchorBottom() assumed the upper of the anchor frame is the body frame, so in case you had a protected section in DOCX, we mapped that into a Writer section, resulting in a body -> section -> anchor frame hierarchy. Fix the problem by improving GetFlyAnchorBottom(), so it works with the body frame of the page (of the anchor), not with the anchor's upper, which breaks in the section case. This only happened in the compatibilityMode=15 case, i.e. DOCX files produced by Word >= 2013. Change-Id: I94ed22701d275e7a9048c6154652d40268850c34 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150741 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/qa/core/layout/data/floattable-in-section.docx b/sw/qa/core/layout/data/floattable-in-section.docx new file mode 100644 index 000000000000..a0e9090bcccf Binary files /dev/null and b/sw/qa/core/layout/data/floattable-in-section.docx differ diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx index 74368f01a01c..4a8578f58524 100644 --- a/sw/qa/core/layout/flycnt.cxx +++ b/sw/qa/core/layout/flycnt.cxx @@ -675,6 +675,12 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFly2ndRowSelect) // i.e. a follow fly was possible to select (instead of its master) CPPUNIT_ASSERT_EQUAL(pPage2Fly->GetPrecede()->GetFrameId(), pSelected->GetFrameId()); } + +CPPUNIT_TEST_FIXTURE(Test, testSplitFlyInSection) +{ + // This crashed, the layout assumed that the floating table is directly under the body frame. + createSwDoc("floattable-in-section.docx"); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx index ee05db8e30ad..c79f9f2080e9 100644 --- a/sw/source/core/layout/fly.cxx +++ b/sw/source/core/layout/fly.cxx @@ -87,24 +87,24 @@ SwTwips GetFlyAnchorBottom(SwFlyFrame* pFly, const SwFrame& rAnchor) { SwRectFnSet aRectFnSet(pFly); + const SwPageFrame* pPage = rAnchor.FindPageFrame(); + if (!pPage) + { + return 0; + } + + const SwFrame* pBody = pPage->FindBodyCont(); + if (!pBody) + { + return 0; + } + const IDocumentSettingAccess& rIDSA = pFly->GetFrameFormat().getIDocumentSettingAccess(); bool bLegacy = rIDSA.get(DocumentSettingId::TAB_OVER_MARGIN); if (bLegacy) { // Word <= 2010 style: the fly can overlap with the bottom margin / footer area in case the // fly height fits the body height and the fly bottom fits the page. - const SwPageFrame* pPage = rAnchor.FindPageFrame(); - if (!pPage) - { - return 0; - } - - const SwFrame* pBody = pPage->FindBodyCont(); - if (!pBody) - { - return 0; - } - // See if the fly height would fit at least the page height, ignoring the vertical offset. SwTwips nFlyHeight = aRectFnSet.GetHeight(pFly->getFrameArea()); SwTwips nPageHeight = aRectFnSet.GetHeight(pPage->getFramePrintArea()); @@ -125,13 +125,7 @@ SwTwips GetFlyAnchorBottom(SwFlyFrame* pFly, const SwFrame& rAnchor) } // Word >= 2013 style: the fly has to stay inside the body frame. - const SwFrame* pAnchorUpper = rAnchor.GetUpper(); - if (!pAnchorUpper) - { - return 0; - } - - return aRectFnSet.GetPrtBottom(*pAnchorUpper); + return aRectFnSet.GetPrtBottom(*pBody); } }