summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2023-05-18 13:55:08 +0200
committerMiklos Vajna <vmiklos@collabora.com>2023-05-19 13:58:13 +0200
commit6737a76bca3b521e891511de791c0d4d732370da (patch)
tree479866e7751b90b792210707ecac5d37668cae8d /sw
parent779f8ec53a6395e7b97b93978d0f196b1f332f89 (diff)
sw floattable: fix missing table join when moving master fly to next page
A reduced bugdoc from tdf#155002 has 2 floating tables: one table on the first page, second table on the second page. The second page had 2 fly frames: the first row of the 2nd table in the first fly and the remaining rows from the 2nd table in the second fly, and they were not joined, which lead to overlapping text. It seems what happens is that the fly is split: first row goes to the first page, rest goes to the second page. Later we move the master fly to the 2nd page as well, but we don't try to join the table, since the master fly has no additional space. It's a circular problem: once we split the fly, we limit the master fly size to what's necessary, so once the 2 flys are on the same page, we don't move content from the follow fly to the master fly because we believe it has no space... but it has no space because the content is not moved. Solve this problem similar to what the web view already does: in case a table frame has a follow and the table frame is in a split fly that can grow to host at least one follow, then try to grow it to host all follows. This prevents layout loops, since we don't move content from a follow fly to a master fly when it would not fit anyway, but allows large enough master flys so table joining happens. The crash with the original tdf#155002 bugdoc needs more work, still. (cherry picked from commit 4cb6e54a3dcdd771ef76bd98b58f0bf1c4be4c45) Change-Id: I411b21d796be82ab5600d66b600cb50c116db4e9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151995 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Diffstat (limited to 'sw')
-rw-r--r--sw/qa/core/layout/data/floattable-tab-join.docxbin0 -> 21571 bytes
-rw-r--r--sw/qa/core/layout/flycnt.cxx30
-rw-r--r--sw/source/core/layout/tabfrm.cxx24
3 files changed, 54 insertions, 0 deletions
diff --git a/sw/qa/core/layout/data/floattable-tab-join.docx b/sw/qa/core/layout/data/floattable-tab-join.docx
new file mode 100644
index 000000000000..cb1990c2a8ea
--- /dev/null
+++ b/sw/qa/core/layout/data/floattable-tab-join.docx
Binary files differ
diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx
index 5f042b1958e6..8aec18461bee 100644
--- a/sw/qa/core/layout/flycnt.cxx
+++ b/sw/qa/core/layout/flycnt.cxx
@@ -825,6 +825,36 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyMultiCol)
// then hit an assertion failure.
CPPUNIT_ASSERT(!pPage1Fly->GetFollow());
}
+
+CPPUNIT_TEST_FIXTURE(Test, testSplitFlyTabJoin)
+{
+ // Given a document with 3 pages and 2 tables: table on first and second page, 3rd page has no
+ // table:
+ createSwDoc("floattable-tab-join.docx");
+
+ // When laying out that document:
+ calcLayout();
+
+ // Then make sure that all pages have the expected amount of fly frames:
+ SwDoc* pDoc = getSwDoc();
+ SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+ auto pPage1 = dynamic_cast<SwPageFrame*>(pLayout->Lower());
+ CPPUNIT_ASSERT(pPage1);
+ const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size());
+ auto pPage2 = dynamic_cast<SwPageFrame*>(pPage1->GetNext());
+ CPPUNIT_ASSERT(pPage2);
+ const SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 1
+ // - Actual : 2
+ // i.e. the 2nd page had 2 fly frames, hosting a split table, instead of joining that table and
+ // having 1 fly frame.
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size());
+ auto pPage3 = dynamic_cast<SwPageFrame*>(pPage2->GetNext());
+ CPPUNIT_ASSERT(pPage3);
+ CPPUNIT_ASSERT(!pPage3->GetSortedObjs());
+}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index 647bee556368..0c87e76b550f 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -2261,6 +2261,30 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext)
}
}
+ if (GetFollow() && GetUpper()->IsFlyFrame())
+ {
+ auto pUpper = static_cast<SwFlyFrame*>(GetUpper());
+ if (pUpper->IsFlySplitAllowed())
+ {
+ // We have a follow tab frame that may be joined, and we're directly in a split fly.
+ // See if the fly could grow.
+ SwTwips nTest = GetUpper()->Grow(LONG_MAX, /*bTst=*/true);
+ if (nTest >= aRectFnSet.GetHeight(GetFollow()->getFrameArea()))
+ {
+ // We have space to to join at least one follow tab frame.
+ SwTwips nRequest = 0;
+ for (SwTabFrame* pFollow = GetFollow(); pFollow; pFollow = pFollow->GetFollow())
+ {
+ nRequest += aRectFnSet.GetHeight(pFollow->getFrameArea());
+ }
+ // Try to grow the split fly to join all follows.
+ pUpper->Grow(nRequest);
+ // Determine what is space we actually got from the requested space.
+ nDistanceToUpperPrtBottom = aRectFnSet.BottomDist(getFrameArea(), aRectFnSet.GetPrtBottom(*pUpper));
+ }
+ }
+ }
+
// If there is still some space left in the upper, we check if we
// can join some rows of the follow.
// Setting bLastRowHasToMoveToFollow to true means we want to force