sw/qa/core/layout/data/floattable-in-inltbl-in-sect.docx |binary
 sw/qa/core/layout/flycnt.cxx                             |   26 +++++++++++++++
 sw/source/core/layout/flycnt.cxx                         |   26 ++++++++++++---
 3 files changed, 48 insertions(+), 4 deletions(-)

New commits:
commit a9d17d9a7ede982c8762a0c04ff95ac4200fda89
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed Oct 11 08:32:02 2023 +0200
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Wed Oct 11 13:38:53 2023 +0200

    sw floattable, crashtesting: fix PDF export of ooo91654-1.doc
    
    Regression from 89a75cd194371002247d0138e759835bc673f7b0 (tdf#126449 sw
    floattable: DOC import: handle inner floating table, 2023-10-04), the
    document crashed Writer layout when exporting to PDF, which triggers a
    layout calculation.
    
    The trouble seems to be that in case the split fly is anchored in a
    table which is in a section, then we assume that we can create a section
    on the next page and move the follow fly frame there, which will mean
    the follow anchor won't be in a table anymore.
    
    Fix this by not moving the follow anchor explicitly, similar to what the
    nested floating table (inline or floating outer table) code does. The
    layout will later figure out that the available space is not enough,
    split the outer table for us, which will lead to a correct result.
    
    Note that the original bugdoc is DOC, but just saving it as-is in Word
    hides the problem, so it's not easy to minimize the reproducer. Instead
    create a similar DOCX reproducer from scratch.
    
    Change-Id: I769615af467ccaa88057ab322da2865f11d3d2ee
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157803
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins
    (cherry picked from commit 6b9378154f9b504b9e924fe4565df444786e7d73)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157782
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/qa/core/layout/data/floattable-in-inltbl-in-sect.docx 
b/sw/qa/core/layout/data/floattable-in-inltbl-in-sect.docx
new file mode 100644
index 000000000000..ff329ecb5a5f
Binary files /dev/null and 
b/sw/qa/core/layout/data/floattable-in-inltbl-in-sect.docx differ
diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx
index 37b255945d9e..325b0078ecb0 100644
--- a/sw/qa/core/layout/flycnt.cxx
+++ b/sw/qa/core/layout/flycnt.cxx
@@ -1157,6 +1157,32 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyDelEmpty)
     // Then make sure that the page count matches Word:
     CPPUNIT_ASSERT_EQUAL(7, getPages());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testSplitFlyInTableInSection)
+{
+    // Given a document where page 2 and page 3 has a floating table inside an 
inline table, inside
+    // a section:
+    // Without the accompanying fix in place, this test would have crashed, we 
created a follow
+    // anchor which was marked as "in table", but had no table parent.
+    createSwDoc("floattable-in-inltbl-in-sect.docx");
+
+    // Then make sure that the floating table is on page 2 and page 3:
+    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);
+    CPPUNIT_ASSERT(pPage2->GetSortedObjs());
+    SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size());
+    auto pPage3 = pPage2->GetNext()->DynCastPageFrame();
+    CPPUNIT_ASSERT(pPage3);
+    CPPUNIT_ASSERT(pPage3->GetSortedObjs());
+    SwSortedObjs& rPage3Objs = *pPage3->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage3Objs.size());
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/flycnt.cxx b/sw/source/core/layout/flycnt.cxx
index faf991ddd9d2..09fd24f28c4a 100644
--- a/sw/source/core/layout/flycnt.cxx
+++ b/sw/source/core/layout/flycnt.cxx
@@ -1579,11 +1579,30 @@ SwLayoutFrame *SwFrame::GetNextFlyLeaf( MakePageType 
eMakePage )
     SwLayoutFrame *pLayLeaf = nullptr;
     // Look up the first candidate.
     SwSectionFrame* pFlyAnchorSection = pFlyAnchor ? 
pFlyAnchor->FindSctFrame() : nullptr;
+    bool bNesting = false;
     if (pFlyAnchorSection)
     {
-        // We can't just move the split anchor to the next page, that would be 
outside the section.
-        // Rather split that section as well.
-        pLayLeaf = pFlyAnchorSection->GetNextSctLeaf(eMakePage);
+        // The anchor is in a section.
+        if (pFlyAnchor)
+        {
+            SwTabFrame* pFlyAnchorTab = pFlyAnchor->FindTabFrame();
+            if (pFlyAnchorTab)
+            {
+                // The anchor is in table as well.
+                if (pFlyAnchorTab->FindSctFrame() == pFlyAnchorSection)
+                {
+                    // We're in a table-in-section, no anchor move in this 
case, because that would
+                    // mean we're not in a table anymore.
+                    bNesting = true;
+                }
+            }
+        }
+        if (!bNesting)
+        {
+            // We can't just move the split anchor to the next page, that 
would be outside the section.
+            // Rather split that section as well.
+            pLayLeaf = pFlyAnchorSection->GetNextSctLeaf(eMakePage);
+        }
     }
     else if (IsTabFrame())
     {
@@ -1597,7 +1616,6 @@ SwLayoutFrame *SwFrame::GetNextFlyLeaf( MakePageType 
eMakePage )
     }
 
     SwLayoutFrame* pOldLayLeaf = nullptr;
-    bool bNesting = false;
     while (true)
     {
         if (pLayLeaf)

Reply via email to