sw/qa/core/layout/data/floattable-from-bottom.docx |binary
 sw/qa/core/layout/flycnt.cxx                       |   21 +++++++++++++++++++++
 sw/source/core/layout/fly.cxx                      |   15 ++++++++++++++-
 3 files changed, 35 insertions(+), 1 deletion(-)

New commits:
commit 4e94f0c68515fe10623c27db9bbeac35e1794314
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Aug 4 10:44:30 2023 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Wed Aug 9 09:59:45 2023 +0200

    sw floattable, crashtesting: fix PDF export of tdf73201-1.docx
    
    The direct cause is that in in the SwTextFrameBreak ctor, m_pFrame has
    IsInSct() as true, but FindSctFrame() then doesn't find anything, which
    should not happen.
    
    The bigger problem is that currently the fly split code assumes that
    frames grow from (logical) top to bottom, so in case the vertical
    orientation is bottom, and we have to grow from bottom to top, that
    needs re-positioning the fly, but the fly split code has no support for
    that.
    
    Fix the crash by denying this case in SwFlyFrame::IsFlySplitAllowed()
    for now, the document's table is not supposed to split in the first
    place.
    
    In case later there is a real need to split such flys, then more
    research is needed how that re-positioning works in detail for non-split
    flys and then we have to adapt the fly split code accordingly.
    
    (cherry picked from commit c545a0729e89ee2e8f14534b77422cc9eb4eb7cf)
    
    Change-Id: I56cf074a3d740ab716f7de232fbd131d17544d9e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155447
    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-from-bottom.docx 
b/sw/qa/core/layout/data/floattable-from-bottom.docx
new file mode 100644
index 000000000000..86374a68ba27
Binary files /dev/null and b/sw/qa/core/layout/data/floattable-from-bottom.docx 
differ
diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx
index 231890bd6739..00449f38e317 100644
--- a/sw/qa/core/layout/flycnt.cxx
+++ b/sw/qa/core/layout/flycnt.cxx
@@ -975,6 +975,27 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyNoFooterOverlap)
     const SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs();
     CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testSplitFlyGrowFromBottom)
+{
+    // Given a document with a floating table that grows from the bottom:
+    createSwDoc("floattable-from-bottom.docx");
+
+    // When calculating the layout:
+    calcLayout();
+
+    // Then make sure that such a floating table is not split, matching Word:
+    SwDoc* pDoc = getSwDoc();
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    auto pPage1 = dynamic_cast<SwPageFrame*>(pLayout->Lower());
+    CPPUNIT_ASSERT(pPage1);
+    CPPUNIT_ASSERT(pPage1->GetSortedObjs());
+    const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
+    const auto pFly = dynamic_cast<SwFlyAtContentFrame*>(rPage1Objs[0]);
+    // Without the accompanying fix in place, this test would have failed, we 
tried to split the fly
+    // frame on page 1 even when it would fit, and this lead to a crash on 
export later.
+    CPPUNIT_ASSERT(!pFly->GetFollow());
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx
index e8fd85e4475a..91fc6c85e18c 100644
--- a/sw/source/core/layout/fly.cxx
+++ b/sw/source/core/layout/fly.cxx
@@ -686,7 +686,20 @@ bool SwFlyFrame::IsFlySplitAllowed() const
         return false;
     }
 
-    return GetFormat()->GetFlySplit().GetValue();
+    const SwFlyFrameFormat* pFormat = GetFormat();
+    const SwFormatVertOrient& rVertOrient = pFormat->GetVertOrient();
+    if (rVertOrient.GetVertOrient() == text::VertOrientation::BOTTOM)
+    {
+        // We have to grow from bottom to top, and the fly split code assumes 
that we grow from top
+        // to bottom, so don't split for now.
+        if (rVertOrient.GetRelationOrient() == 
text::RelOrientation::PAGE_PRINT_AREA)
+        {
+            // Growing from the bottom of the body frame.
+            return false;
+        }
+    }
+
+    return pFormat->GetFlySplit().GetValue();
 }
 
 SwFrame *SwFlyFrame::FindLastLower()

Reply via email to