sw/qa/core/layout/data/floattable-in-inlinetable.docx |binary
 sw/qa/core/layout/tabfrm.cxx                          |   37 +++++++++++++++
 sw/source/core/layout/tabfrm.cxx                      |   44 ++++++++++++++++++
 3 files changed, 81 insertions(+)

New commits:
commit 9f04cb0036399d9b5f9a1a31aab6625ac51b401d
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed Sep 27 08:36:12 2023 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Fri Sep 29 14:15:40 2023 +0200

    Related: tdf#126449 sw floattable: fix bad join of inline tbl with inner fly
    
    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.
    
    (cherry picked from commit c86d6111525f09e895483c7c4919a4b9a5dbd9b9)
    
    Change-Id: I7946c0f3cb9995a497fdfff3bfac28b6f16ff844
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157373
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/qa/core/layout/data/floattable-in-inlinetable.docx 
b/sw/qa/core/layout/data/floattable-in-inlinetable.docx
new file mode 100644
index 000000000000..56505316cd8e
Binary files /dev/null and 
b/sw/qa/core/layout/data/floattable-in-inlinetable.docx differ
diff --git a/sw/qa/core/layout/tabfrm.cxx b/sw/qa/core/layout/tabfrm.cxx
index d7df701a3351..64a30e8368db 100644
--- a/sw/qa/core/layout/tabfrm.cxx
+++ b/sw/qa/core/layout/tabfrm.cxx
@@ -45,6 +45,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 4edd8855656c..344039b1bffe 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -2321,6 +2321,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.

Reply via email to