diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2023-09-27 08:36:12 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2023-09-27 09:33:35 +0200 |
commit | c86d6111525f09e895483c7c4919a4b9a5dbd9b9 (patch) | |
tree | 028838ff24e605b74acd68312e2cc6222ee02abd | |
parent | 4094e07ea738b47a99e30cbf70cdf943a5088355 (diff) |
Related: tdf#126449 sw floattable: fix bad join of inline tbl with inner flyHEADmaster
The problem is that the bugdoc has 3 pages with an inline outer table,
where pages 2 & 3 have an inner floating table. The outer table is only
on pages 1 -> 2, while it should be on pages 1 -> 2 -> 3.
The trouble is similar to point 4) of commit
cfe9c68a7a19dd77d1fcbde3a7dd75730634becc (tdf#157119 sw floattable: fix
moving master of split fly to next page, 2023-09-21), i.e. our normal
behavior would move up the follow table to page 2 from page 3 and simply
shift up the floating table, which is fine for images, but not for
floating tables.
Fix the problem by checking for flys on the old page when determining if
it's OK to move or not. Checking for flys on the new page is already
done in SwTabFrame::ShouldBwdMoved(), when it calls the precede's
CalcFlyOffsets().
This just fixes a simplified DOCX bugdoc (inline outer table, floating
inner table), the full document still needs more fixes.
Change-Id: I7946c0f3cb9995a497fdfff3bfac28b6f16ff844
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157306
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
-rw-r--r-- | sw/qa/core/layout/data/floattable-in-inlinetable.docx | bin | 0 -> 18597 bytes | |||
-rw-r--r-- | sw/qa/core/layout/tabfrm.cxx | 37 | ||||
-rw-r--r-- | sw/source/core/layout/tabfrm.cxx | 44 |
3 files changed, 81 insertions, 0 deletions
diff --git a/sw/qa/core/layout/data/floattable-in-inlinetable.docx b/sw/qa/core/layout/data/floattable-in-inlinetable.docx Binary files differnew file mode 100644 index 000000000000..56505316cd8e --- /dev/null +++ b/sw/qa/core/layout/data/floattable-in-inlinetable.docx diff --git a/sw/qa/core/layout/tabfrm.cxx b/sw/qa/core/layout/tabfrm.cxx index 705bf47af4bc..a5e448081b0f 100644 --- a/sw/qa/core/layout/tabfrm.cxx +++ b/sw/qa/core/layout/tabfrm.cxx @@ -61,6 +61,43 @@ CPPUNIT_TEST_FIXTURE(Test, testTableMissingJoin) // page 3. CPPUNIT_ASSERT(!pTab->HasFollow()); } + +CPPUNIT_TEST_FIXTURE(Test, testSplitFlyInInlineTable) +{ + // Outer inline table on pages 1 -> 2 -> 3, inner floating table on pages 2 -> 3: + // When laying out that document: + createSwDoc("floattable-in-inlinetable.docx"); + + // Then make sure that the outer table is not missing on page 3: + SwDoc* pDoc = getSwDoc(); + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + auto pPage1 = pLayout->Lower()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage1); + { + SwFrame* pBody = pPage1->FindBodyCont(); + auto pTab = pBody->GetLower()->DynCastTabFrame(); + CPPUNIT_ASSERT(!pTab->GetPrecede()); + CPPUNIT_ASSERT(pTab->GetFollow()); + } + auto pPage2 = pPage1->GetNext()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage2); + { + SwFrame* pBody = pPage2->FindBodyCont(); + auto pTab = pBody->GetLower()->DynCastTabFrame(); + CPPUNIT_ASSERT(pTab->GetPrecede()); + // Without the accompanying fix in place, this test would have failed, the outer table was + // missing on page 3. + CPPUNIT_ASSERT(pTab->GetFollow()); + } + auto pPage3 = pPage2->GetNext()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage3); + { + SwFrame* pBody = pPage3->FindBodyCont(); + auto pTab = pBody->GetLower()->DynCastTabFrame(); + CPPUNIT_ASSERT(pTab->GetPrecede()); + CPPUNIT_ASSERT(!pTab->GetFollow()); + } +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx index 693c180154df..183c5114178a 100644 --- a/sw/source/core/layout/tabfrm.cxx +++ b/sw/source/core/layout/tabfrm.cxx @@ -2357,6 +2357,50 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext) // when the upper has no space, but the follow is // empty. bFits = aRectFnSet.BottomDist(getFrameArea(), nDeadLine) >= 0; + + if (bFits) + { + // The follow table's wants to move backwards, see if the first row has a + // split fly anchored in it that would have more space than what we have: + SwRowFrame* pRow = GetFollow()->GetFirstNonHeadlineRow(); + if (pRow) + { + SwPageFrame* pPage = GetFollow()->FindPageFrame(); + SwSortedObjs* pPageObjs = pPage->GetSortedObjs(); + if (pPageObjs) + { + bool bSplitFly = false; + for (size_t i = 0; i < pPageObjs->size(); ++i) + { + SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i]; + auto pFly = pAnchoredObj->DynCastFlyFrame(); + if (!pFly || !pFly->IsFlySplitAllowed()) + { + continue; + } + + SwFrame* pFlyAnchor = pFly->FindAnchorCharFrame(); + if (!pFlyAnchor || !pRow->IsAnLower(pFlyAnchor)) + { + continue; + } + + bSplitFly = true; + break; + } + SwTwips nFollowFirstRowHeight = aRectFnSet.GetHeight(pRow->getFrameArea()); + SwTwips nSpace = aRectFnSet.BottomDist(getFrameArea(), nDeadLine); + if (bSplitFly && nFollowFirstRowHeight > 0 && nSpace < nFollowFirstRowHeight) + { + // The row has at least one split fly and the row would not fit + // to our remaining space, when also taking flys into account, + // so that's not a fit. + bFits = false; + } + } + } + } + if (bFits) { // First, we remove an existing follow flow line. |