diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2023-10-03 12:08:36 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2023-10-03 17:29:14 +0200 |
commit | 695390b08799af34b393c81c834d615bea330d89 (patch) | |
tree | fa6efc4d63e70a72910ede5526b3ac81f0328fcd /sw | |
parent | 140dc375adfffa59dff2652eb8b9625c23d81c8b (diff) |
tdf#126449 sw floattable: fix too small height of non-last anchors
The bugdoc had an outer inline table, a middle inline table and an inner
floating table. The floating table is expected to be on pages 2, 3 and
4; actually it was only on page 2 and 3.
This happened because the fly frame that should be on page 4 was on page
3, leading to overlapping text. And that bad fly position seems to
happen because the anchor frames just have a 1 line height (~269 twips
instead of the fly height).
Fix this similar to how "first paragraph only" wrapping works: increase
the (anchor) text frame height, even if the contained lines would not
require that amount of height.
With this, finally the DOCX version of the bugdoc lays out reasonable
(all 5 pages).
Change-Id: Ib08bf34be61eb2b4d8656887f83ac7fd17e3b252
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157507
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'sw')
-rw-r--r-- | sw/qa/core/text/data/floattable-anchor-height.docx | bin | 0 -> 19441 bytes | |||
-rw-r--r-- | sw/qa/core/text/porrst.cxx | 37 | ||||
-rw-r--r-- | sw/source/core/text/porrst.cxx | 26 |
3 files changed, 61 insertions, 2 deletions
diff --git a/sw/qa/core/text/data/floattable-anchor-height.docx b/sw/qa/core/text/data/floattable-anchor-height.docx Binary files differnew file mode 100644 index 000000000000..3052f0daef73 --- /dev/null +++ b/sw/qa/core/text/data/floattable-anchor-height.docx diff --git a/sw/qa/core/text/porrst.cxx b/sw/qa/core/text/porrst.cxx index 1c343dc0d9f2..f2e14e7f7f31 100644 --- a/sw/qa/core/text/porrst.cxx +++ b/sw/qa/core/text/porrst.cxx @@ -18,6 +18,7 @@ #include <pagefrm.hxx> #include <rootfrm.hxx> #include <txtfrm.hxx> +#include <sortedobjs.hxx> namespace { @@ -52,6 +53,42 @@ CPPUNIT_TEST_FIXTURE(Test, testFloattableLeftoverParaPortion) // also had some (duplicated) anchor text. CPPUNIT_ASSERT(!pPara2->GetPara()); } + +CPPUNIT_TEST_FIXTURE(Test, testFloattableAnchorHeight) +{ +#if !defined(MACOSX) // FIXME fails on macOS + // Given 3 tables, innermost table on pages 2-3-4: + createSwDoc("floattable-anchor-height.docx"); + + // When laying out the document: + calcLayout(); + + // Then make sure the flys are on the expected pages: + 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); + SwSortedObjs* pPage2Objs = pPage2->GetSortedObjs(); + CPPUNIT_ASSERT(pPage2Objs); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pPage2Objs->size()); + auto pPage3 = pPage2->GetNext()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage3); + SwSortedObjs* pPage3Objs = pPage3->GetSortedObjs(); + CPPUNIT_ASSERT(pPage3Objs); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 2 + // i.e. page 3 also had the fly frame of page 4 as well. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pPage3Objs->size()); + auto pPage4 = pPage3->GetNext()->DynCastPageFrame(); + SwSortedObjs* pPage4Objs = pPage4->GetSortedObjs(); + CPPUNIT_ASSERT(pPage4Objs); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pPage4Objs->size()); +#endif +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/text/porrst.cxx b/sw/source/core/text/porrst.cxx index 5c6ea428c1db..bd3589b25676 100644 --- a/sw/source/core/text/porrst.cxx +++ b/sw/source/core/text/porrst.cxx @@ -51,6 +51,8 @@ #include <crsrsh.hxx> #include <swtypes.hxx> #include <strings.hrc> +#include <flyfrms.hxx> +#include <bodyfrm.hxx> SwTmpEndPortion::SwTmpEndPortion( const SwLinePortion &rPortion, const FontLineStyle eUL, @@ -412,7 +414,8 @@ bool SwTextFrame::FormatEmpty() // sw_redlinehide: just disable FormatEmpty optimisation for now // Split fly frames: non-last parts of the anchor want this optimization to clear the old // content. - bool bHasNonLastSplitFlyDrawObj = HasNonLastSplitFlyDrawObj(); + SwFlyAtContentFrame* pNonLastSplitFlyDrawObj = HasNonLastSplitFlyDrawObj(); + bool bHasNonLastSplitFlyDrawObj = pNonLastSplitFlyDrawObj != nullptr; if ((HasFollow() && !bHasNonLastSplitFlyDrawObj) || GetMergedPara() || (GetTextNodeFirst()->GetpSwpHints() && !bHasNonLastSplitFlyDrawObj) || nullptr != GetTextNodeForParaProps()->GetNumRule() || GetTextNodeFirst()->HasHiddenCharAttribute(true) || @@ -468,7 +471,26 @@ bool SwTextFrame::FormatEmpty() } SwRectFnSet aRectFnSet(this); - const SwTwips nChg = nHeight - aRectFnSet.GetHeight(getFramePrintArea()); + SwTwips nChg = nHeight - aRectFnSet.GetHeight(getFramePrintArea()); + const SwBodyFrame* pBody = FindBodyFrame(); + if (pNonLastSplitFlyDrawObj && pBody) + { + // See if we need to increase the text frame height due to split flys. This is necessary for + // anchors of inner floating tables, where moving to a next page moves indirectly, so we + // want a correct text frame height. + SwTwips nFrameBottom = aRectFnSet.GetBottom(getFrameArea()) + nChg; + SwTwips nFlyBottom = aRectFnSet.GetBottom(pNonLastSplitFlyDrawObj->getFrameArea()); + SwTwips nBodyBottom = aRectFnSet.GetBottom(pBody->getFrameArea()); + if (nFlyBottom > nBodyBottom) + { + // This is the legacy case where flys may overlap with footer frames. + nFlyBottom = nBodyBottom; + } + if (pNonLastSplitFlyDrawObj->isFrameAreaPositionValid() && nFlyBottom > nFrameBottom) + { + nChg += (nFlyBottom - nFrameBottom); + } + } if( !nChg ) SetUndersized( false ); |