sw/qa/core/layout/flycnt.cxx                                       |   19 
++++++++++
 sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx |   15 
+++++++
 2 files changed, 34 insertions(+)

New commits:
commit b9bf9bf9d1d1e0fb9eb765cd5060d611af7176df
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Mar 2 09:09:27 2023 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Thu Mar 2 09:10:41 2023 +0000

    sw floattable: fix vertical position of follow flys with rel orient = page
    
    The problem was that the follow frame's top was the 2nd page's top,
    because we ignore the vertical offset for follow fly frames.
    
    Ignoring the original offset is fine, but follow frames are still inside
    the body frame in Word, so their offset is effectively the header / top
    margin area.
    
    Fix the problem by improving how nRelPosY is tweaked for follow fly
    frames: an additional positive offset is wanted when the rel orient is
    page.
    
    With this, this bugdoc now renders perfectly.
    
    Change-Id: Iec4b85339a7b4b69944d25eb2e06a6e3f977f093
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148086
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx
index 10a84856da0a..5dfc8d5641bf 100644
--- a/sw/qa/core/layout/flycnt.cxx
+++ b/sw/qa/core/layout/flycnt.cxx
@@ -336,10 +336,29 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyFooter)
     SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
     auto pPage1 = dynamic_cast<SwPageFrame*>(pLayout->Lower());
     CPPUNIT_ASSERT(pPage1);
+    SwTwips nPage1Top = pPage1->getFrameArea().Top();
+    const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size());
+    auto pPage1Fly = dynamic_cast<SwFlyAtContentFrame*>(rPage1Objs[0]);
+    CPPUNIT_ASSERT(pPage1Fly);
+    SwTwips nPage1FlyTop = pPage1Fly->getFrameArea().Top();
+    // <w:tblpPr w:tblpY="3286"> from the bugdoc.
+    CPPUNIT_ASSERT_EQUAL(static_cast<SwTwips>(3286), nPage1FlyTop - nPage1Top);
     // Second page:
     auto pPage2 = dynamic_cast<SwPageFrame*>(pPage1->GetNext());
     // Without the accompanying fix in place, this test would have failed, 
there was no 2nd page.
     CPPUNIT_ASSERT(pPage2);
+    SwTwips nPage2Top = pPage2->getFrameArea().Top();
+    const SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size());
+    auto pPage2Fly = dynamic_cast<SwFlyAtContentFrame*>(rPage2Objs[0]);
+    CPPUNIT_ASSERT(pPage2Fly);
+    SwTwips nPage2FlyTop = pPage2Fly->getFrameArea().Top();
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 1440
+    // - Actual  : 0
+    // i.e. <w:pgMar w:top="1440"> from the bugdoc was lost, the follow fly 
had no vertical offset.
+    CPPUNIT_ASSERT_EQUAL(static_cast<SwTwips>(1440), nPage2FlyTop - nPage2Top);
 }
 }
 
diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx 
b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
index 8756da6a325c..9a9abc9f4dd8 100644
--- a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
@@ -609,6 +609,21 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
                     // This is a follow of a split fly: shift it up to match 
the anchor position,
                     // because the vertical offset is meant to be handled only 
on the first page.
                     nRelPosY -= aVert.GetPos();
+
+                    if (aVert.GetRelationOrient() == 
text::RelOrientation::PAGE_FRAME
+                        && rPageAlignLayFrame.IsPageFrame())
+                    {
+                        // Master is positioned relative to the edge of the 
page, with an offset.
+                        // Follow will have no offset, but is relative to the 
bottom of the header.
+                        auto& rPageFrame = static_cast<const 
SwPageFrame&>(rPageAlignLayFrame);
+                        const SwLayoutFrame* pBodyFrame = 
rPageFrame.FindBodyCont();
+                        if (pBodyFrame)
+                        {
+                            SwTwips nDiff = pBodyFrame->getFrameArea().Top()
+                                            - rPageFrame.getFrameArea().Top();
+                            nRelPosY += nDiff;
+                        }
+                    }
                 }
             }
 

Reply via email to