sw/qa/extras/layout/layout2.cxx | 22 ++++++++++------------ sw/source/core/doc/textboxhelper.cxx | 31 +++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 18 deletions(-)
New commits: commit 0c2d2ca64f796b3f3f0bc8a8d123aa1be99414f1 Author: Justin Luth <jl...@mail.com> AuthorDate: Tue Aug 6 21:57:01 2024 -0400 Commit: Justin Luth <jl...@mail.com> CommitDate: Sat Aug 17 22:27:59 2024 +0200 tdf#162211 tdf#158384 layoutInCell: doTextBoxPositioning better by simply honouring FollowTextFlow as the comment states. I needed to look into this because of a failing unit test. I can't say I understand why sync needs to lay out two things instead of just laying out one and copying the screen position, but bug 158384 indicated that the wrong value was added, so I looked for alternatives to use instead of nLeftSpace. A better sounding alternative was textbox spacing to border, but that is already taken into account. Then I realized a negative offset was being applied against the cell edge - which is only allowed for bWrapThrough. Unfortunately, that once again breaks the unit test I have been trying to accommodate. I can only assume that the unit test's pressuppositions are false. So I'm changing the unit test to test things that are certain! make CppunitTest_sw_layoutwriter2 CPPUNIT_TEST_NAME=testTdf116256 Given how wonky textbox sync is, I'm not confident that ANYTHING here is actually correct. Change-Id: I2e73b7345b4d4c3da78d62644032cb573dc6821e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171577 Tested-by: Jenkins Reviewed-by: Justin Luth <jl...@mail.com> diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx index 8226c5100c78..50f2cba4d986 100644 --- a/sw/qa/extras/layout/layout2.cxx +++ b/sw/qa/extras/layout/layout2.cxx @@ -1756,16 +1756,14 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf116256) // Parse the layout auto pLayout = parseLayoutDump(); // Get the position of the shape - const auto nTextBoxShapeLeft = getXPath(pLayout, - "/root/page/body/txt/anchored/fly/tab/row[1]/cell/txt/" - "anchored/SwAnchoredDrawObject/bounds"_ostr, - "left"_ostr) - .toInt64(); - const auto nTextBoxShapeTop = getXPath(pLayout, - "/root/page/body/txt/anchored/fly/tab/row[1]/cell/txt/" - "anchored/SwAnchoredDrawObject/bounds"_ostr, - "top"_ostr) - .toInt64(); + const auto nCellLeft + = getXPath(pLayout, "//page/body/txt/anchored/fly/tab/row[1]/cell/infos/bounds"_ostr, + "left"_ostr) + .toInt64(); + const auto nCellTop + = getXPath(pLayout, "//page/body/txt/anchored/fly/tab/row[1]/cell/infos/bounds"_ostr, + "top"_ostr) + .toInt64(); // Get the position of the textframe too. const auto nTextBoxFrameLeft = getXPath( @@ -1781,8 +1779,8 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf116256) .toInt64(); // Without the fix in place these were less than they supposed to. - CPPUNIT_ASSERT_GREATEREQUAL(nTextBoxShapeLeft, nTextBoxFrameLeft); - CPPUNIT_ASSERT_GREATEREQUAL(nTextBoxShapeTop, nTextBoxFrameTop); + CPPUNIT_ASSERT_GREATEREQUAL(nCellLeft, nTextBoxFrameLeft); + CPPUNIT_ASSERT_GREATEREQUAL(nCellTop, nTextBoxFrameTop); } CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf138194) diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx index b51a5f3c8b5c..fabc18a7e4e9 100644 --- a/sw/source/core/doc/textboxhelper.cxx +++ b/sw/source/core/doc/textboxhelper.cxx @@ -16,6 +16,7 @@ #include <fmtfsize.hxx> #include <doc.hxx> #include <IDocumentLayoutAccess.hxx> +#include <IDocumentSettingAccess.hxx> #include <IDocumentState.hxx> #include <docsh.hxx> #include <unocoll.hxx> @@ -1440,9 +1441,6 @@ bool SwTextBoxHelper::doTextBoxPositioning(SwFrameFormat* pShape, SdrObject* pOb tools::Rectangle aRect = getRelativeTextRectangle(pObj ? pObj : pShape->FindRealSdrObject()); - // X Offset of the shape spacing - auto nLeftSpace = pShape->GetLRSpace().GetLeft(); - // Set the same position as the (child) shape has SwFormatHoriOrient aNewHOri(pShape->GetHoriOrient()); if (bIsGroupObj && aNewHOri.GetHoriOrient() != text::HoriOrientation::NONE) @@ -1482,6 +1480,14 @@ bool SwTextBoxHelper::doTextBoxPositioning(SwFrameFormat* pShape, SdrObject* pOb if (pShape->GetFollowTextFlow().GetValue() && pShape->GetAnchor().GetAnchorNode() && pShape->GetAnchor().GetAnchorNode()->FindTableNode()) { + // WARNING: It is highly likely that everything here is simplistic and incomplete. + + // Microsoft allows WrapThrough shapes to be placed outside of the cell + // despite having specified layoutInCell. + // (Re-using existing, appropriately-named, compat flag to identify MSO formats.) + const bool bMSOLayout = pFormat->getIDocumentSettingAccess().get( + DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION); + // Table position Point nTableOffset; // Floating table @@ -1505,12 +1511,25 @@ bool SwTextBoxHelper::doTextBoxPositioning(SwFrameFormat* pShape, SdrObject* pOb } } - // Add the table positions to the textbox. - aNewHOri.SetPos(aNewHOri.GetPos() + nTableOffset.getX() + nLeftSpace); + // stay within the cell limits (since following text flow) + // unless this is based on a Microsoft layout which has a through-wrap exception. + bool bWrapThrough = false; + getShapeWrapThrough(pShape, bWrapThrough); + sal_Int32 nPos = aNewHOri.GetPos(); + if (nPos < 0 && (!bMSOLayout || !bWrapThrough)) + nPos = 0; + // Add the table positions to the textbox + aNewHOri.SetPos(nPos + nTableOffset.getX()); + if (pShape->GetVertOrient().GetRelationOrient() == text::RelOrientation::PAGE_FRAME || pShape->GetVertOrient().GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA) - aNewVOri.SetPos(aNewVOri.GetPos() + nTableOffset.getY()); + { + nPos = aNewVOri.GetPos(); + if (nPos < 0 && (!bMSOLayout || !bWrapThrough)) + nPos = 0; + aNewVOri.SetPos(nPos + nTableOffset.getY()); + } } pFormat->SetFormatAttr(aNewHOri);