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;

Reply via email to