diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2023-10-11 08:32:02 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2023-10-11 09:47:26 +0200 |
commit | 6b9378154f9b504b9e924fe4565df444786e7d73 (patch) | |
tree | 3c9d1086d2a7744056034aa835dfbd9d5886cce1 /sw | |
parent | 1f9cd62b67d679da078c50b4b48295918657a70a (diff) |
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.
Change-Id: I769615af467ccaa88057ab322da2865f11d3d2ee
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157803
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'sw')
-rw-r--r-- | sw/qa/core/layout/data/floattable-in-inltbl-in-sect.docx | bin | 0 -> 18625 bytes | |||
-rw-r--r-- | sw/qa/core/layout/flycnt.cxx | 26 | ||||
-rw-r--r-- | sw/source/core/layout/flycnt.cxx | 26 |
3 files changed, 48 insertions, 4 deletions
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 Binary files differnew file mode 100644 index 000000000000..ff329ecb5a5f --- /dev/null +++ b/sw/qa/core/layout/data/floattable-in-inltbl-in-sect.docx diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx index 37b255945d9e..325b0078ecb0 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 3c0254f929b8..98843c2c0d47 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) |