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 b000b2fde81a347e321a055cebe9569ed40809c1
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Sep 1 08:51:20 2023 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Tue Sep 5 09:42:44 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.
    
    (cherry picked from commit 7d4213b9f0253b323750acceca8f4edb9d1a7fc5)
    
    Change-Id: I1596a07b78575583070d494ddb8e1400e5653820
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156520
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

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 e610de6eab70..1bb2b008bc65 100644
--- a/sw/source/core/inc/frame.hxx
+++ b/sw/source/core/inc/frame.hxx
@@ -870,6 +870,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 ae2c7473baf3..f287d37a9dbb 100644
--- a/sw/source/core/layout/findfrm.cxx
+++ b/sw/source/core/layout/findfrm.cxx
@@ -1934,4 +1934,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