sw/qa/core/layout/data/floattable-in-inltbl-in-sect.docx |binary sw/qa/core/layout/flycnt.cxx | 26 +++++++++++++++ sw/source/core/layout/flycnt.cxx | 26 ++++++++++++--- 3 files changed, 48 insertions(+), 4 deletions(-)
New commits: commit 814dc523ec69aff7a52697c550399bc66cb12481 Author: Miklos Vajna <[email protected]> AuthorDate: Wed Oct 11 08:32:02 2023 +0200 Commit: Caolán McNamara <[email protected]> CommitDate: Thu Oct 12 13:17:13 2023 +0200 sw floattable, crashtesting: fix PDF export of ooo91654-1.doc Regression from 89a75cd194371002247d0138e759835bc673f7b0 (tdf#126449 sw floattable: DOC import: handle inner floating table, 2023-10-04), the document crashed Writer layout when exporting to PDF, which triggers a layout calculation. The trouble seems to be that in case the split fly is anchored in a table which is in a section, then we assume that we can create a section on the next page and move the follow fly frame there, which will mean the follow anchor won't be in a table anymore. Fix this by not moving the follow anchor explicitly, similar to what the nested floating table (inline or floating outer table) code does. The layout will later figure out that the available space is not enough, split the outer table for us, which will lead to a correct result. Note that the original bugdoc is DOC, but just saving it as-is in Word hides the problem, so it's not easy to minimize the reproducer. Instead create a similar DOCX reproducer from scratch. (cherry picked from commit 6b9378154f9b504b9e924fe4565df444786e7d73) Change-Id: I769615af467ccaa88057ab322da2865f11d3d2ee Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157856 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Caolán McNamara <[email protected]> diff --git a/sw/qa/core/layout/data/floattable-in-inltbl-in-sect.docx b/sw/qa/core/layout/data/floattable-in-inltbl-in-sect.docx new file mode 100644 index 000000000000..ff329ecb5a5f Binary files /dev/null and b/sw/qa/core/layout/data/floattable-in-inltbl-in-sect.docx differ diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx index fecd87727d04..210d66b92eba 100644 --- a/sw/qa/core/layout/flycnt.cxx +++ b/sw/qa/core/layout/flycnt.cxx @@ -1157,6 +1157,32 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyDelEmpty) // Then make sure that the page count matches Word: CPPUNIT_ASSERT_EQUAL(7, getPages()); } + +CPPUNIT_TEST_FIXTURE(Test, testSplitFlyInTableInSection) +{ + // Given a document where page 2 and page 3 has a floating table inside an inline table, inside + // a section: + // Without the accompanying fix in place, this test would have crashed, we created a follow + // anchor which was marked as "in table", but had no table parent. + createSwDoc("floattable-in-inltbl-in-sect.docx"); + + // Then make sure that the floating table is on page 2 and page 3: + SwDoc* pDoc = getSwDoc(); + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + auto pPage1 = pLayout->Lower()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage1); + CPPUNIT_ASSERT(!pPage1->GetSortedObjs()); + auto pPage2 = pPage1->GetNext()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage2); + CPPUNIT_ASSERT(pPage2->GetSortedObjs()); + SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size()); + auto pPage3 = pPage2->GetNext()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage3); + CPPUNIT_ASSERT(pPage3->GetSortedObjs()); + SwSortedObjs& rPage3Objs = *pPage3->GetSortedObjs(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage3Objs.size()); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/flycnt.cxx b/sw/source/core/layout/flycnt.cxx index 0ff8b151613e..5be7a8b17e94 100644 --- a/sw/source/core/layout/flycnt.cxx +++ b/sw/source/core/layout/flycnt.cxx @@ -1579,11 +1579,30 @@ SwLayoutFrame *SwFrame::GetNextFlyLeaf( MakePageType eMakePage ) SwLayoutFrame *pLayLeaf = nullptr; // Look up the first candidate. SwSectionFrame* pFlyAnchorSection = pFlyAnchor ? pFlyAnchor->FindSctFrame() : nullptr; + bool bNesting = false; if (pFlyAnchorSection) { - // We can't just move the split anchor to the next page, that would be outside the section. - // Rather split that section as well. - pLayLeaf = pFlyAnchorSection->GetNextSctLeaf(eMakePage); + // The anchor is in a section. + if (pFlyAnchor) + { + SwTabFrame* pFlyAnchorTab = pFlyAnchor->FindTabFrame(); + if (pFlyAnchorTab) + { + // The anchor is in table as well. + if (pFlyAnchorTab->FindSctFrame() == pFlyAnchorSection) + { + // We're in a table-in-section, no anchor move in this case, because that would + // mean we're not in a table anymore. + bNesting = true; + } + } + } + if (!bNesting) + { + // We can't just move the split anchor to the next page, that would be outside the section. + // Rather split that section as well. + pLayLeaf = pFlyAnchorSection->GetNextSctLeaf(eMakePage); + } } else if (IsTabFrame()) { @@ -1597,7 +1616,6 @@ SwLayoutFrame *SwFrame::GetNextFlyLeaf( MakePageType eMakePage ) } SwLayoutFrame* pOldLayLeaf = nullptr; - bool bNesting = false; while (true) { if (pLayLeaf)
