sw/qa/core/layout/data/floattable-footer-2rows.docx |binary sw/qa/core/layout/flycnt.cxx | 30 ++++++++++++++++++++ sw/source/core/layout/findfrm.cxx | 11 ++++++- sw/source/core/layout/tabfrm.cxx | 17 ++++++----- 4 files changed, 48 insertions(+), 10 deletions(-)
New commits: commit e66632b023ee1cf25a381536f53458f631964bb8 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Mar 3 09:27:05 2023 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Fri Mar 3 09:11:41 2023 +0000 sw floattable: try to grow fly parent when trying section/table The bugdoc is meant to be of 2 pages, but the last row of the table went to a 3rd page, even if there was still space in page 2. SwTabFrame::MakeAll() had a case where it tried to grow section or table parents, that's how a similar case worked for multi-page tables in section frames. Extend this to also consider split fly parents, which avoids the unwanted 3rd page. This broke the rendering floattable-3pages.docx (it had 2 pages), which pointed out that SwFrame::ImplGetNextLayoutLeaf() was buggy for split flys. That function is meant to find the next layout frame which is not a lower of the current frame, but it had to be extended to handle the split anchor frame of split flys. Also, if we're here, remove the other split fly check in SwTabFrame::MakeAll(), which now looks redundant and is odd (there is no similar check for sections). Change-Id: I83090ac04ca27b71f62315e3b9755c8196057b5d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148162 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/qa/core/layout/data/floattable-footer-2rows.docx b/sw/qa/core/layout/data/floattable-footer-2rows.docx new file mode 100644 index 000000000000..72013be28fbd Binary files /dev/null and b/sw/qa/core/layout/data/floattable-footer-2rows.docx differ diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx index 5dfc8d5641bf..d400fd85de0a 100644 --- a/sw/qa/core/layout/flycnt.cxx +++ b/sw/qa/core/layout/flycnt.cxx @@ -360,6 +360,36 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyFooter) // i.e. <w:pgMar w:top="1440"> from the bugdoc was lost, the follow fly had no vertical offset. CPPUNIT_ASSERT_EQUAL(static_cast<SwTwips>(1440), nPage2FlyTop - nPage2Top); } + +CPPUNIT_TEST_FIXTURE(Test, testSplitFlyFooter2Rows) +{ + // Given a document with a 2nd page that contains the second half of a split row + a last row: + std::shared_ptr<comphelper::ConfigurationChanges> pChanges( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Writer::Filter::Import::DOCX::ImportFloatingTableAsSplitFly::set(true, + pChanges); + pChanges->commit(); + comphelper::ScopeGuard g([pChanges] { + officecfg::Office::Writer::Filter::Import::DOCX::ImportFloatingTableAsSplitFly::set( + false, pChanges); + pChanges->commit(); + }); + createSwDoc("floattable-footer-2rows.docx"); + + // When laying out that document: + calcLayout(); + + // Then make sure that the table is split to 2 pages: + SwDoc* pDoc = getSwDoc(); + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + auto pPage1 = dynamic_cast<SwPageFrame*>(pLayout->Lower()); + CPPUNIT_ASSERT(pPage1); + auto pPage2 = dynamic_cast<SwPageFrame*>(pPage1->GetNext()); + CPPUNIT_ASSERT(pPage2); + // Without the accompanying fix in place, this test would have failed. The 2nd page only had the + // 2nd half of the split row and the last row went to a 3rd page. + CPPUNIT_ASSERT(!pPage2->GetNext()); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/findfrm.cxx b/sw/source/core/layout/findfrm.cxx index 07290dee5f2a..0e425e0a1eb5 100644 --- a/sw/source/core/layout/findfrm.cxx +++ b/sw/source/core/layout/findfrm.cxx @@ -338,6 +338,8 @@ const SwLayoutFrame *SwFrame::ImplGetNextLayoutLeaf( bool bFwd ) const const SwLayoutFrame *pLayoutFrame = nullptr; const SwFrame *p = nullptr; bool bGoingUp = !bFwd; // false for forward, true for backward + // The anchor is this frame, unless we traverse the anchor of a split fly. + const SwFrame* pAnchor = this; do { bool bGoingFwdOrBwd = false; @@ -366,7 +368,12 @@ const SwLayoutFrame *SwFrame::ImplGetNextLayoutLeaf( bool bFwd ) const const SwFlyFrame* pFlyFrame = pFrame->FindFlyFrame(); if (pFlyFrame->IsFlySplitAllowed()) { - p = pFlyFrame->GetAnchorFrame(); + p = const_cast<SwFlyFrame*>(pFlyFrame)->FindAnchorCharFrame(); + // Remember the anchor frame, so if we look for the leaf of a frame in a + // split fly (anchored in the master of a text frame, but rendered on the + // next page), we won't return a frame on the next page, rather return + // nullptr. + pAnchor = p; } } @@ -388,7 +395,7 @@ const SwLayoutFrame *SwFrame::ImplGetNextLayoutLeaf( bool bFwd ) const } while( ( p && !p->IsFlowFrame() ) || pFrame == this || nullptr == ( pLayoutFrame = pFrame->IsLayoutFrame() ? static_cast<const SwLayoutFrame*>(pFrame) : nullptr ) || - pLayoutFrame->IsAnLower( this ) ); + pLayoutFrame->IsAnLower( pAnchor ) ); return pLayoutFrame; } diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx index 78005c0699e8..cf773326fc9a 100644 --- a/sw/source/core/layout/tabfrm.cxx +++ b/sw/source/core/layout/tabfrm.cxx @@ -2469,7 +2469,14 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext) if ( pFirstNonHeadlineRow->GetNext() || bTryToSplit ) { SwTwips nDeadLine = aRectFnSet.GetPrtBottom(*GetUpper()); - if( IsInSct() || GetUpper()->IsInTab() ) // TABLE IN TABLE) + bool bFlySplit = false; + if (GetUpper()->IsFlyFrame()) + { + // See if this is a split fly that can also grow. + auto pUpperFly = static_cast<SwFlyFrame*>(GetUpper()); + bFlySplit = pUpperFly->IsFlySplitAllowed(); + } + if( IsInSct() || GetUpper()->IsInTab() || bFlySplit ) nDeadLine = aRectFnSet.YInc( nDeadLine, GetUpper()->Grow( LONG_MAX, true ) ); @@ -2736,13 +2743,7 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext) // allowed to split. SwTwips nDistToUpperPrtBottom = aRectFnSet.BottomDist( getFrameArea(), aRectFnSet.GetPrtBottom(*GetUpper())); - bool bFlySplit = false; - if (GetUpper()->IsFlyFrame()) - { - auto pUpperFly = static_cast<SwFlyFrame*>(GetUpper()); - bFlySplit = pUpperFly->IsFlySplitAllowed(); - } - if ( nDistToUpperPrtBottom >= 0 || bTryToSplit || bFlySplit ) + if ( nDistToUpperPrtBottom >= 0 || bTryToSplit ) { lcl_RecalcTable( *this, nullptr, aNotify ); m_bLowersFormatted = true;