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

New commits:
commit 56a9c6e985a99e64dece99c8d4b75bfb7fe1e43a
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Apr 25 08:05:55 2023 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Apr 26 11:06:21 2023 +0200

    sw floattable, crashtesting: fix PDF export of fdo72790-1.docx, part 1
    
    Converting the bugdoc to PDF crashed Writer layout since commit
    ce3308a926f036b87515b8cd97d2b197063dc77a (tdf#61594 sw floattable:
    import floating tables as split flys by default, 2023-04-12).
    
    What happens is that the DOCX file has a continuous section break, that
    is mapped to a Writer section, but then the fly splitting code didn't
    expect that the anchor might be inside a section frame.
    
    Fix this by explicitly checking for an in-section anchor in
    SwFrame::GetNextFlyLeaf(), which will give us a suitable insertion point
    on the next page.
    
    This does not fully fix the handling of the bugdoc, but at least now a
    reduced sample doesn't crash and is handled correctly.
    
    (cherry picked from commit 3c2e4d454aaabcd61593e670a90638a185046539)
    
    Change-Id: I52b5c901d899533bbb78131f443789d55db41000
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151032
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/core/layout/data/floattable-in-text-section.docx 
b/sw/qa/core/layout/data/floattable-in-text-section.docx
new file mode 100644
index 000000000000..5b377dd0379f
Binary files /dev/null and 
b/sw/qa/core/layout/data/floattable-in-text-section.docx differ
diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx
index ca2f0f7cbb95..14254b1dbc22 100644
--- a/sw/qa/core/layout/flycnt.cxx
+++ b/sw/qa/core/layout/flycnt.cxx
@@ -699,6 +699,14 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyThenTable)
     // This crashed, due to a stack overflow in layout code.
     save("writer_pdf_Export");
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testSplitFlyInTextSection)
+{
+    // The document contains a DOCX cont sect break, which is mapped to a 
TextSection.
+    // This crashed, the anchor was split directly, so the follow anchor was 
moved outside the
+    // section frame, which is broken.
+    createSwDoc("floattable-in-text-section.docx");
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/flycnt.cxx b/sw/source/core/layout/flycnt.cxx
index 5f9cd6a39a07..3821ac66b1df 100644
--- a/sw/source/core/layout/flycnt.cxx
+++ b/sw/source/core/layout/flycnt.cxx
@@ -1558,7 +1558,14 @@ SwLayoutFrame *SwFrame::GetNextFlyLeaf( MakePageType 
eMakePage )
     bool bBody = pFlyAnchor && pFlyAnchor->IsInDocBody();
     SwLayoutFrame *pLayLeaf = nullptr;
     // Look up the first candidate.
-    if (IsTabFrame())
+    SwSectionFrame* pFlyAnchorSection = pFlyAnchor ? 
pFlyAnchor->FindSctFrame() : nullptr;
+    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);
+    }
+    else if (IsTabFrame())
     {
         // If we're in a table, try to find the next frame of the table's last 
content.
         SwFrame* pContent = 
static_cast<SwTabFrame*>(this)->FindLastContentOrTable();
commit ae26b819875bd76acad079499d6ca3ff2aea3777
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Apr 24 12:43:26 2023 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Apr 26 11:06:09 2023 +0200

    sw floattable, crashtesting: fix PDF export of fdo80989-1.docx
    
    Converting the bugdoc to PDF crashed Writer layout since commit
    ce3308a926f036b87515b8cd97d2b197063dc77a (tdf#61594 sw floattable:
    import floating tables as split flys by default, 2023-04-12).
    
    There were two problems here:
    
    1) We assumed that when we move content to a next page, that page is
    empty. This may not be true, and in case the next page has content,
    we should insert the content at the start of the page, not at the end.
    Specifying the sibling for MoveSubTree() fixes this.
    
    2) We also hoped that if we ask for the next layout leaf, that will be
    from the next page. Again, this may not be true,
    SwFrame::GetNextSctLeaf() has quite complex conditions to detect this.
    Split flys don't have to span over multiple columns, so just require
    that the candidate is inside a different body then our anchor.
    
    The bugdoc has to be loaded in hidden mode, otherwise we already calc
    the layout on load, and then the problem is not visible.
    
    (cherry picked from commit e0017ad2a5b008111b716c0814c5a0c5b0f1e05b)
    
    Change-Id: I6e1533369db24c7c275ec1d7dceaddc4128c268a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150958
    Tested-by: Miklos Vajna <vmik...@collabora.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/core/layout/data/floattable-then-table.docx 
b/sw/qa/core/layout/data/floattable-then-table.docx
new file mode 100644
index 000000000000..eb06507bd8bb
Binary files /dev/null and b/sw/qa/core/layout/data/floattable-then-table.docx 
differ
diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx
index 4a8578f58524..ca2f0f7cbb95 100644
--- a/sw/qa/core/layout/flycnt.cxx
+++ b/sw/qa/core/layout/flycnt.cxx
@@ -10,6 +10,7 @@
 #include <swmodeltestbase.hxx>
 
 #include <svx/svdview.hxx>
+#include <comphelper/propertyvalue.hxx>
 
 #include <IDocumentLayoutAccess.hxx>
 #include <anchoredobject.hxx>
@@ -681,6 +682,23 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyInSection)
     // This crashed, the layout assumed that the floating table is directly 
under the body frame.
     createSwDoc("floattable-in-section.docx");
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testSplitFlyThenTable)
+{
+    // Given a document with a 2 page floating table, followed by an other 
table:
+    // Intentionally load the document as hidden to avoid layout during load 
(see TestTdf150616):
+    uno::Sequence<beans::PropertyValue> aFilterOptions = {
+        comphelper::makePropertyValue("Hidden", true),
+    };
+    mxComponent = 
loadFromDesktop(m_directories.getURLFromSrc(u"/sw/qa/core/layout/data/")
+                                      + "floattable-then-table.docx",
+                                  "com.sun.star.text.TextDocument", 
aFilterOptions);
+
+    // When layout is calculated during PDF export:
+    // Then make sure that finishes without errors:
+    // This crashed, due to a stack overflow in layout code.
+    save("writer_pdf_Export");
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/flycnt.cxx b/sw/source/core/layout/flycnt.cxx
index 1185a980dbc3..5f9cd6a39a07 100644
--- a/sw/source/core/layout/flycnt.cxx
+++ b/sw/source/core/layout/flycnt.cxx
@@ -51,6 +51,7 @@
 #include <fmtfollowtextflow.hxx>
 #include <unoprnms.hxx>
 #include <rootfrm.hxx>
+#include <bodyfrm.hxx>
 
 using namespace ::com::sun::star;
 
@@ -1577,7 +1578,17 @@ SwLayoutFrame *SwFrame::GetNextFlyLeaf( MakePageType 
eMakePage )
             bool bLeftBody = bBody && !pLayLeaf->IsInDocBody();
             // If the candiate is in a fly, make sure that the candidate is a 
child of our follow.
             bool bLeftFly = pLayLeaf->IsInFly() && pLayLeaf->FindFlyFrame() != 
pFly->GetFollow();
-            if (bLeftBody || bLeftFly)
+            bool bSameBody = false;
+            if (bBody && pLayLeaf->IsInDocBody())
+            {
+                // Make sure the candidate is not inside the same body frame, 
that would prevent
+                // inserting a new page.
+                if (pFlyAnchor->FindBodyFrame() == pLayLeaf->FindBodyFrame())
+                {
+                    bSameBody = true;
+                }
+            }
+            if (bLeftBody || bLeftFly || bSameBody)
             {
                 // The above conditions are not held, reject.
                 pOldLayLeaf = pLayLeaf;
@@ -1609,7 +1620,8 @@ SwLayoutFrame *SwFrame::GetNextFlyLeaf( MakePageType 
eMakePage )
             // Split the anchor at char 0: all the content goes to the follow 
of the anchor.
             pFlyAnchor->SplitFrame(TextFrameIndex(0));
             auto pNext = static_cast<SwTextFrame*>(pFlyAnchor->GetNext());
-            pNext->MoveSubTree(pLayLeaf);
+            // Move the new anchor frame, before the first child of pLayLeaf.
+            pNext->MoveSubTree(pLayLeaf, pLayLeaf->Lower());
 
             // Now create the follow of the fly and anchor it in the master of 
the anchor.
             pNew = new SwFlyAtContentFrame(*pFly);

Reply via email to