sw/qa/extras/ooxmlexport/ooxmlexport9.cxx | 9 +++ sw/qa/extras/ooxmlimport/ooxmlimport.cxx | 8 ++ sw/source/core/inc/anchoredobjectposition.hxx | 4 + sw/source/core/objectpositioning/anchoredobjectposition.cxx | 29 +++++++++- sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx | 10 +-- 5 files changed, 54 insertions(+), 6 deletions(-)
New commits: commit 1de6bea27ed36167ec138818607da7b49e92ec4a Author: Justin Luth <jl...@mail.com> AuthorDate: Wed Aug 28 09:30:18 2024 -0400 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Mon Sep 9 12:48:11 2024 +0200 tdf#143899 compat15 layout: restrict body fly to PAGE_PRINT_AREA For some inexplicable reason, Microsoft decided to change a non-table layout restriction for DOCX >= 2013. Now most floating objects are not allowed to cross the vertical margin (header/footer) boundaries (although floating tables are one exception) (and so are framePr textboxes) (and horizontal margin boundaries can still be crossed). This is similar to layoutInCell's whimsical vertical aversion to margins. There are already good unit tests in place to ensure compat14 works, and for the compat15 table exception. (see earlier patchsets for all affected unit tests) make CppunitTest_sw_ooxmlexport9 CPPUNIT_TEST_NAME=testTdf103544 make CppunitTest_sw_ooxmlexport21 CPPUNIT_TEST_NAME=testTdf143899 Change-Id: I5788c35e57cbc84a6b5fcd0ef97dc4394b0f6395 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172536 Reviewed-by: Justin Luth <jl...@mail.com> Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx index 02b0f9466600..99e56fed1f19 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx @@ -721,6 +721,15 @@ DECLARE_OOXMLEXPORT_TEST(testTdf103544, "tdf103544.docx") uno::Reference<beans::XPropertySet> xImage(getShape(1), uno::UNO_QUERY); auto xGraphic = getProperty<uno::Reference<graphic::XGraphic> >(xImage, u"Graphic"_ustr); CPPUNIT_ASSERT(xGraphic.is()); + + // tdf#143899: framePr textbox not affected by compat15's aversion to vertical page margin + // The textbox requests to be 0.72inch above its anchor paragraph (the first paragraph) + xmlDocUniquePtr pDump = parseLayoutDump(); + CPPUNIT_ASSERT_EQUAL(OUString("Frame"), getXPathContent(pDump, "//fly[2]/txt"_ostr)); + sal_Int32 nShapeBottom = getXPath(pDump, "//fly[2]/infos/bounds"_ostr, "bottom"_ostr).toInt32(); + sal_Int32 nBodyTop = getXPath(pDump, "//page/body/infos/bounds"_ostr, "top"_ostr).toInt32(); + // The framePr textbox is NOT vertically limited like other shapes to the page margins + CPPUNIT_ASSERT(nBodyTop > nShapeBottom); // textbox is fully above the text body area } DECLARE_OOXMLEXPORT_TEST(testTdf103573, "tdf103573.docx") diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx index 7e0a1a7676c3..6b109ec3aa62 100644 --- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx +++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx @@ -1459,6 +1459,14 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf60351) CPPUNIT_ASSERT_EQUAL(sal_Int32(316), aPolygon[4].Y); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPolygon[5].X); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPolygon[5].Y); + + // tdf143899: image affected by compat15's aversion to vertical page margin. + // although the image is set to -0.3cm above the first paragraph, it can't move up at all. + xmlDocUniquePtr pDump = parseLayoutDump(); + sal_Int32 nBodyTop = getXPath(pDump, "//page/body/infos/bounds"_ostr, "top"_ostr).toInt32(); + sal_Int32 nImageTop = getXPath(pDump, "//fly/infos/bounds"_ostr, "top"_ostr).toInt32(); + // The image (like most floating objects) is vertically limited to the page margins + CPPUNIT_ASSERT_EQUAL(nBodyTop, nImageTop); } CPPUNIT_TEST_FIXTURE(Test, testTdf95970) diff --git a/sw/source/core/inc/anchoredobjectposition.hxx b/sw/source/core/inc/anchoredobjectposition.hxx index a3668330006e..2d87b5bde9bd 100644 --- a/sw/source/core/inc/anchoredobjectposition.hxx +++ b/sw/source/core/inc/anchoredobjectposition.hxx @@ -20,6 +20,7 @@ #ifndef INCLUDED_SW_SOURCE_CORE_INC_ANCHOREDOBJECTPOSITION_HXX #define INCLUDED_SW_SOURCE_CORE_INC_ANCHOREDOBJECTPOSITION_HXX +#include <fmtornt.hxx> #include <swtypes.hxx> #include "frame.hxx" #include <nodeoffset.hxx> @@ -72,6 +73,7 @@ namespace objectpositioning const bool bVert, const bool bVertL2R, const SwFrame& rPageAlignLayFrame, + const SwFormatVertOrient& rVertOrient, const SwTwips nProposedRelPosY, const bool bFollowTextFlow, const bool bCheckBottom ) const; @@ -184,6 +186,7 @@ namespace objectpositioning const bool bVert, const bool bVertL2R, const SwFrame& rPageAlignLayFrame, + const SwFormatVertOrient& rVertOrient, const SwTwips nProposedRelPosY, const bool bFollowTextFlow, const bool bCheckBottom = true ) const @@ -191,6 +194,7 @@ namespace objectpositioning return !mbDoNotCaptureAnchoredObj ? ImplAdjustVertRelPos( nTopOfAnch, bVert, bVertL2R, rPageAlignLayFrame, + rVertOrient, nProposedRelPosY, bFollowTextFlow, bCheckBottom ) diff --git a/sw/source/core/objectpositioning/anchoredobjectposition.cxx b/sw/source/core/objectpositioning/anchoredobjectposition.cxx index 11f14c3a41a3..667a88b9a9ec 100644 --- a/sw/source/core/objectpositioning/anchoredobjectposition.cxx +++ b/sw/source/core/objectpositioning/anchoredobjectposition.cxx @@ -18,9 +18,11 @@ */ #include <anchoredobjectposition.hxx> +#include <bodyfrm.hxx> #include <environmentofanchoredobject.hxx> #include <flyfrm.hxx> #include <flyfrms.hxx> +#include <formatflysplit.hxx> #include <txtfrm.hxx> #include <pagefrm.hxx> #include <frmatr.hxx> @@ -433,6 +435,7 @@ SwTwips SwAnchoredObjectPosition::ImplAdjustVertRelPos( const SwTwips nTopOfAnch const bool bVert, const bool bVertL2R, const SwFrame& rPageAlignLayFrame, + const SwFormatVertOrient& rVertOrient, const SwTwips nProposedRelPosY, const bool bFollowTextFlow, const bool bCheckBottom ) const @@ -471,7 +474,31 @@ SwTwips SwAnchoredObjectPosition::ImplAdjustVertRelPos( const SwTwips nTopOfAnch ( !bFollowTextFlow || !GetAnchoredObj().GetAnchorFrame()->IsInTab() ) ) { - aPgAlignArea = rPageAlignLayFrame.FindPageFrame()->getFrameArea(); + const SwPageFrame& rPageFrame = *rPageAlignLayFrame.FindPageFrame(); + aPgAlignArea = rPageFrame.getFrameArea(); + + // re-using existing compat option to determine old (<=compat14) behaviour + const bool bCompat15 = !rIDSA.get(DocumentSettingId::ADD_FLY_OFFSETS); + + // Instead of using the top of the page as the vertical limit, + // DOCX compatibilityMode 15 started to use the text body as the vertical limit + // for most paragraph or line-oriented anchored non-wrapthrough objects. + // Floating tables are an exception. + const bool bIsFloatingTable = mpFrameFormat->GetFlySplit().GetValue(); + // FramePr paragraph-defined textboxes are another exception. + // bVert is also untouched to avoid issues: who knows what should happen in that case. + if (!bVert && bCompat15 && !bWrapThrough && !bIsFloatingTable + && rPageAlignLayFrame.IsPageFrame() + && rVertOrient.GetRelationOrient() != text::RelOrientation::PAGE_FRAME + && rVertOrient.GetRelationOrient() != text::RelOrientation::PAGE_PRINT_AREA + && !SwTextBoxHelper::TextBoxIsFramePr(*mpFrameFormat)) + { + const SwBodyFrame* pBodyFrame = mpAnchorFrame->FindBodyFrame(); + while (pBodyFrame && !pBodyFrame->IsPageBodyFrame()) + pBodyFrame = pBodyFrame->GetUpper()->FindBodyFrame(); + if (pBodyFrame) + aPgAlignArea = pBodyFrame->getFrameArea(); + } } else { diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx index 71b062232907..f5d7a79f9de8 100644 --- a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx +++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx @@ -457,7 +457,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition() *(pOrientFrame->GetUpper()) ); const bool bCheckBottom = !DoesObjFollowsTextFlow(); nRelPosY = AdjustVertRelPos( nTopOfAnch, aRectFnSet.IsVert(), aRectFnSet.IsVertL2R(), - rVertEnvironLayFrame, nRelPosY, + rVertEnvironLayFrame, aVert, nRelPosY, DoesObjFollowsTextFlow(), bCheckBottom ); } @@ -680,7 +680,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition() // anchored object has to follow the text flow. const bool bCheckBottom = !DoesObjFollowsTextFlow(); nRelPosY = AdjustVertRelPos( nTopOfAnch, aRectFnSet.IsVert(), aRectFnSet.IsVertL2R(), - rVertEnvironLayFrame, nRelPosY, + rVertEnvironLayFrame, aVert, nRelPosY, !bIgnoreVertLayoutInCell && DoesObjFollowsTextFlow(), bCheckBottom ); if ( aRectFnSet.IsVert() ) @@ -720,7 +720,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition() // frame, if anchored object has to follow the text flow. const bool bCheckBottom = !DoesObjFollowsTextFlow(); nTmpRelPosY = AdjustVertRelPos( nTopOfAnch, aRectFnSet.IsVert(), aRectFnSet.IsVertL2R(), - rVertEnvironLayFrame, + rVertEnvironLayFrame, aVert, nTmpRelPosY, DoesObjFollowsTextFlow(), bCheckBottom ); @@ -811,7 +811,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition() const SwFrame& rVertEnvironLayFrame = aEnvOfObj.GetVertEnvironmentLayoutFrame( *pUpperOfOrientFrame ); nRelPosY = AdjustVertRelPos( nTopOfAnch, aRectFnSet.IsVert(), aRectFnSet.IsVertL2R(), - rVertEnvironLayFrame, + rVertEnvironLayFrame, aVert, nRelPosY, DoesObjFollowsTextFlow() ); if( aRectFnSet.IsVert() ) @@ -938,7 +938,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition() const SwLayoutFrame& rVertEnvironLayFrame = aEnvOfObj.GetVertEnvironmentLayoutFrame( *pUpperOfOrientFrame ); nTmpRelPosY = AdjustVertRelPos( nTopOfAnch, aRectFnSet.IsVert(), aRectFnSet.IsVertL2R(), - rVertEnvironLayFrame, + rVertEnvironLayFrame, aVert, nTmpRelPosY, DoesObjFollowsTextFlow(), false );