sw/qa/core/layout/data/floattable-in-section.docx |binary
 sw/qa/core/layout/flycnt.cxx                      |    6 ++++
 sw/source/core/layout/fly.cxx                     |   32 ++++++++--------------
 3 files changed, 19 insertions(+), 19 deletions(-)

New commits:
commit a1c5f77d3ee7c9907c8247aa0e896e07fe9427b6
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Apr 21 09:03:51 2023 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Apr 21 11:47:43 2023 +0200

    sw floattable, crashtesting: fix PDF export of forum-mso-de-117064.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).
    
    What happened is that we hit a case in the SwTextFrameBreak ctor where
    the frame had the "is in section" bit set, but the frame wasn't actually
    in a section, so when looking up that parent section frame, we found
    nothing, and later code assumed that we always find something. This is
    fine, the root of the problem was that in the non-legacy case
    GetFlyAnchorBottom() assumed the upper of the anchor frame is the body
    frame, so in case you had a protected section in DOCX, we mapped that
    into a Writer section, resulting in a body -> section -> anchor frame
    hierarchy.
    
    Fix the problem by improving GetFlyAnchorBottom(), so it works with the
    body frame of the page (of the anchor), not with the anchor's upper,
    which breaks in the section case.
    
    This only happened in the compatibilityMode=15 case, i.e. DOCX files
    produced by Word >= 2013.
    
    Change-Id: I94ed22701d275e7a9048c6154652d40268850c34
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150741
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/qa/core/layout/data/floattable-in-section.docx 
b/sw/qa/core/layout/data/floattable-in-section.docx
new file mode 100644
index 000000000000..a0e9090bcccf
Binary files /dev/null and b/sw/qa/core/layout/data/floattable-in-section.docx 
differ
diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx
index 74368f01a01c..4a8578f58524 100644
--- a/sw/qa/core/layout/flycnt.cxx
+++ b/sw/qa/core/layout/flycnt.cxx
@@ -675,6 +675,12 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFly2ndRowSelect)
     // i.e. a follow fly was possible to select (instead of its master)
     CPPUNIT_ASSERT_EQUAL(pPage2Fly->GetPrecede()->GetFrameId(), 
pSelected->GetFrameId());
 }
+
+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");
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx
index ee05db8e30ad..c79f9f2080e9 100644
--- a/sw/source/core/layout/fly.cxx
+++ b/sw/source/core/layout/fly.cxx
@@ -87,24 +87,24 @@ SwTwips GetFlyAnchorBottom(SwFlyFrame* pFly, const SwFrame& 
rAnchor)
 {
     SwRectFnSet aRectFnSet(pFly);
 
+    const SwPageFrame* pPage = rAnchor.FindPageFrame();
+    if (!pPage)
+    {
+        return 0;
+    }
+
+    const SwFrame* pBody = pPage->FindBodyCont();
+    if (!pBody)
+    {
+        return 0;
+    }
+
     const IDocumentSettingAccess& rIDSA = 
pFly->GetFrameFormat().getIDocumentSettingAccess();
     bool bLegacy = rIDSA.get(DocumentSettingId::TAB_OVER_MARGIN);
     if (bLegacy)
     {
         // Word <= 2010 style: the fly can overlap with the bottom margin / 
footer area in case the
         // fly height fits the body height and the fly bottom fits the page.
-        const SwPageFrame* pPage = rAnchor.FindPageFrame();
-        if (!pPage)
-        {
-            return 0;
-        }
-
-        const SwFrame* pBody = pPage->FindBodyCont();
-        if (!pBody)
-        {
-            return 0;
-        }
-
         // See if the fly height would fit at least the page height, ignoring 
the vertical offset.
         SwTwips nFlyHeight = aRectFnSet.GetHeight(pFly->getFrameArea());
         SwTwips nPageHeight = aRectFnSet.GetHeight(pPage->getFramePrintArea());
@@ -125,13 +125,7 @@ SwTwips GetFlyAnchorBottom(SwFlyFrame* pFly, const 
SwFrame& rAnchor)
     }
 
     // Word >= 2013 style: the fly has to stay inside the body frame.
-    const SwFrame* pAnchorUpper = rAnchor.GetUpper();
-    if (!pAnchorUpper)
-    {
-        return 0;
-    }
-
-    return aRectFnSet.GetPrtBottom(*pAnchorUpper);
+    return aRectFnSet.GetPrtBottom(*pBody);
 }
 }
 

Reply via email to