diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2023-05-18 13:55:08 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2023-05-19 13:58:13 +0200 |
commit | 6737a76bca3b521e891511de791c0d4d732370da (patch) | |
tree | 479866e7751b90b792210707ecac5d37668cae8d /sw | |
parent | 779f8ec53a6395e7b97b93978d0f196b1f332f89 (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.docx | bin | 0 -> 21571 bytes | |||
-rw-r--r-- | sw/qa/core/layout/flycnt.cxx | 30 | ||||
-rw-r--r-- | sw/source/core/layout/tabfrm.cxx | 24 |
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 Binary files differnew file mode 100644 index 000000000000..cb1990c2a8ea --- /dev/null +++ b/sw/qa/core/layout/data/floattable-tab-join.docx 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 |