sw/qa/core/objectpositioning/data/floattable-vert-orient-top.odt   |binary
 sw/qa/core/objectpositioning/objectpositioning.cxx                 |   24 
++++++++++
 sw/source/core/inc/frame.hxx                                       |    2 
 sw/source/core/layout/findfrm.cxx                                  |   10 ++++
 sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx |    5 +-
 5 files changed, 40 insertions(+), 1 deletion(-)

New commits:
commit 38192482e552195a5c76a6e40fc3586cc6f0355c
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Sep 1 08:51:20 2023 +0200
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Mon Sep 4 17:26:09 2023 +0200

    Related: tdf#156318 sw floattable: fix handling of vert orient == top
    
    The bugdoc resulted in a layout loop on load. It was created by forcing
    pages to be in a single column + increasing the top+bottom margin of the
    page to 2.5cm.
    
    The problem was that the SwFormatVertOrient's m_eOrient is usually
    text::VertOrientation::NONE ("from top" with 0 offset), but here it's
    text::VertOrientation::TOP. These are meant to be more or less
    equivalent, but SwToContentAnchoredObjectPosition::CalcPosition() has
    different codepath for them.
    
    Fix the problem by making sure that TOP doesn't have a vertical offset
    for follow fly frame: do this by realizing that in case the "orient
    frame" and the "anchor" is not the same that may need no action, since
    the fly frame case changes the "orient" to the follow anchor and the
    "anchor" is the master anchor.
    
    The original scenario still needs more work, we don't hang anymore but
    the follow fly appears on page 3 instead of page 2.
    
    Change-Id: I1596a07b78575583070d494ddb8e1400e5653820
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156392
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins
    (cherry picked from commit 7d4213b9f0253b323750acceca8f4edb9d1a7fc5)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156530
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/qa/core/objectpositioning/data/floattable-vert-orient-top.odt 
b/sw/qa/core/objectpositioning/data/floattable-vert-orient-top.odt
new file mode 100644
index 000000000000..b10f0b7188fa
Binary files /dev/null and 
b/sw/qa/core/objectpositioning/data/floattable-vert-orient-top.odt differ
diff --git a/sw/qa/core/objectpositioning/objectpositioning.cxx 
b/sw/qa/core/objectpositioning/objectpositioning.cxx
index 4958b8b6deb4..611ce1294c22 100644
--- a/sw/qa/core/objectpositioning/objectpositioning.cxx
+++ b/sw/qa/core/objectpositioning/objectpositioning.cxx
@@ -313,6 +313,30 @@ CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testFloatingTableOverlapNever)
     CPPUNIT_ASSERT_GREATER(pFlyFrame1->getFrameArea().Bottom(), 
pFlyFrame2->getFrameArea().Top());
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testFloatingTableVertOrientTop)
+{
+    // Given a document with a vert-orient=from-top anchored floating table:
+    createSwDoc("floattable-vert-orient-top.odt");
+
+    // When laying out that document:
+    calcLayout();
+
+    // Then make sure we correctly split the table to two pages:
+    // Without the accompanying fix in place, this test would have produced a 
layout loop.
+    SwDoc* pDoc = getSwDoc();
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    auto pPage1 = pLayout->Lower()->DynCastPageFrame();
+    CPPUNIT_ASSERT(pPage1);
+    CPPUNIT_ASSERT(pPage1->GetSortedObjs());
+    const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size());
+    auto pPage2 = pPage1->GetNext()->DynCastPageFrame();
+    CPPUNIT_ASSERT(pPage2);
+    CPPUNIT_ASSERT(pPage2->GetSortedObjs());
+    const SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size());
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx
index ec47266ec468..885a0d223f24 100644
--- a/sw/source/core/inc/frame.hxx
+++ b/sw/source/core/inc/frame.hxx
@@ -874,6 +874,8 @@ public:
     inline bool IsTextFrame() const;
     SwTextFrame* DynCastTextFrame();
     const SwTextFrame* DynCastTextFrame() const;
+    SwPageFrame* DynCastPageFrame();
+    const SwPageFrame* DynCastPageFrame() const;
     inline bool IsNoTextFrame() const;
     // Frames where its PrtArea depends on their neighbors and that are
     // positioned in the content flow
diff --git a/sw/source/core/layout/findfrm.cxx 
b/sw/source/core/layout/findfrm.cxx
index 1a98f6cf6747..5331baacd93e 100644
--- a/sw/source/core/layout/findfrm.cxx
+++ b/sw/source/core/layout/findfrm.cxx
@@ -1944,4 +1944,14 @@ const SwTextFrame* SwFrame::DynCastTextFrame() const
     return IsTextFrame() ? static_cast<const SwTextFrame*>(this) : nullptr;
 }
 
+SwPageFrame* SwFrame::DynCastPageFrame()
+{
+    return IsPageFrame() ? static_cast<SwPageFrame*>(this) : nullptr;
+}
+
+const SwPageFrame* SwFrame::DynCastPageFrame() const
+{
+    return IsPageFrame() ? static_cast<const SwPageFrame*>(this) : nullptr;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx 
b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
index 33168ceba432..561c16fd8115 100644
--- a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
@@ -422,7 +422,10 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
             // the frame, the object is oriented at.
             // #i28701# - correction: adjust relative position,
             // only if the floating screen object has to follow the text flow.
-            if ( DoesObjFollowsTextFlow() && pOrientFrame != &rAnchorTextFrame 
)
+            // Also don't do this for split flys: pOrientFrame already points 
to the follow anchor,
+            // so pOrientFrame is not the anchor text frame anymore, and that 
would lead to an
+            // additional, unwanted increase of nRelPosY.
+            if (DoesObjFollowsTextFlow() && pOrientFrame != &rAnchorTextFrame 
&& !bFollowSplitFly)
             {
                 // #i11860# - use new method <GetTopForObjPos>
                 // to get top of frame for object positioning.

Reply via email to