diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2019-09-19 16:41:06 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2019-09-19 18:30:57 +0200 |
commit | d37096f59e7e0286e55008153591a60bab92b9e8 (patch) | |
tree | 6c7760fbe0c0c44d8b6ffe29ac875a13c4104938 /sw | |
parent | 428b67cd0d490739f9a7bb5a724020179ba7591d (diff) |
Related: tdf#124600 sw anchored object allow overlap: add layout
If there is an overlap, then a shift towards the bottom or towards the
right would resolve that. Word seems to always push down, do the same
for compatibility.
Otherwise, let's see if some fine-tuning will be needed for the
behavior, sadly "20.4.2.3 anchor (Anchor for Floating DrawingML Object)"
in the OOXML spec (the allowOverlap part) only says the overlapping
object has to be re-positioned, but does no go into details.
Change-Id: Ie1b4626f6d06862d617e28e0cb74838107d993d1
Reviewed-on: https://gerrit.libreoffice.org/79141
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'sw')
-rw-r--r-- | sw/qa/extras/layout/layout.cxx | 58 | ||||
-rw-r--r-- | sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx | 30 |
2 files changed, 88 insertions, 0 deletions
diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index 59e1e08939e0..2110eed1e31c 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -3096,6 +3096,64 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf127235) pDoc->getIDocumentLayoutAccess().GetCurrentViewShell()->CalcLayout(); } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testShapeAllowOverlap) +{ +// Need to find out why this fails on macOS. +#ifndef MACOSX + // Create an empty document with two, intentionally overlapping shapes. + // Set their AllowOverlap property to false. + loadURL("private:factory/swriter", nullptr); + uno::Reference<lang::XMultiServiceFactory> xDocument(mxComponent, uno::UNO_QUERY); + awt::Point aPoint(1000, 1000); + awt::Size aSize(2000, 2000); + uno::Reference<drawing::XShape> xShape( + xDocument->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY); + xShape->setPosition(aPoint); + xShape->setSize(aSize); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xDocument, uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xShapeProperties(xShape, uno::UNO_QUERY); + xShapeProperties->setPropertyValue("AllowOverlap", uno::makeAny(false)); + xShapeProperties->setPropertyValue("AnchorType", + uno::makeAny(text::TextContentAnchorType_AT_CHARACTER)); + xDrawPageSupplier->getDrawPage()->add(xShape); + + aPoint = awt::Point(2000, 2000); + xShape.set(xDocument->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY); + xShape->setPosition(aPoint); + xShape->setSize(aSize); + xShapeProperties.set(xShape, uno::UNO_QUERY); + xShapeProperties->setPropertyValue("AllowOverlap", uno::makeAny(false)); + xShapeProperties->setPropertyValue("AnchorType", + uno::makeAny(text::TextContentAnchorType_AT_CHARACTER)); + xDrawPageSupplier->getDrawPage()->add(xShape); + + // Now verify that the rectangle of the anchored objects don't overlap. + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + SwFrame* pPageFrame = pLayout->GetLower(); + SwFrame* pBodyFrame = pPageFrame->GetLower(); + SwFrame* pTextFrame = pBodyFrame->GetLower(); + CPPUNIT_ASSERT(pTextFrame->GetDrawObjs()); + SwSortedObjs& rObjs = *pTextFrame->GetDrawObjs(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rObjs.size()); + SwAnchoredObject* pFirst = rObjs[0]; + SwAnchoredObject* pSecond = rObjs[1]; + // Without the accompanying fix in place, this test would have failed: the layout dump was + // <bounds left="1984" top="1984" width="1137" height="1137"/> + // <bounds left="2551" top="2551" width="1137" height="1137"/> + // so there was a clear vertical overlap. (Allow for 1px tolerance.) + OString aMessage("Unexpected overlap: first shape's bottom is "); + aMessage += OString::number(pFirst->GetObjRect().Bottom()); + aMessage += ", second shape's top is "; + aMessage += OString::number(pSecond->GetObjRect().Top()); + CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), + std::abs(pFirst->GetObjRect().Bottom() - pSecond->GetObjRect().Top()) + < 15); +#endif +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx index 25424dfaa3f3..f26b48ac0a98 100644 --- a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx +++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx @@ -42,6 +42,8 @@ #include <frmtool.hxx> #include <ndtxt.hxx> #include <dflyobj.hxx> +#include <fmtwrapinfluenceonobjpos.hxx> +#include <sortedobjs.hxx> using namespace objectpositioning; using namespace ::com::sun::star; @@ -971,6 +973,34 @@ void SwToContentAnchoredObjectPosition::CalcPosition() // keep layout frame vertical position is oriented at. mpVertPosOrientFrame = pUpperOfOrientFrame; + // If it was requested to not overlap with already formatted objects, take care of that + // here. + bool bAllowOverlap = rFrameFormat.GetWrapInfluenceOnObjPos().GetAllowOverlap(); + if (!bAllowOverlap) + { + // Get the list of objects. + const SwSortedObjs& rSortedObjs = *pAnchorFrameForVertPos->GetDrawObjs(); + for (const auto& pAnchoredObj : rSortedObjs) + { + if (pAnchoredObj == &GetAnchoredObj()) + { + // We found ourselves, stop iterating. + break; + } + + if (!GetAnchoredObj().GetObjRect().IsOver(pAnchoredObj->GetObjRect())) + { + // Found an already positioned object, but it doesn't overlap, ignore. + continue; + } + + // Already formatted, overlaps: resolve the conflict by shifting ourselves down. + SwTwips nYDiff + = pAnchoredObj->GetObjRect().Bottom() - GetAnchoredObj().GetObjRect().Top(); + aRelPos.setY(aRelPos.getY() + nYDiff + 1); + GetAnchoredObj().SetObjTop(nTopOfAnch + aRelPos.Y()); + } + } } // determine 'horizontal' position |