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; + } + } } }