summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
Diffstat (limited to 'sw')
-rw-r--r--sw/qa/extras/layout/layout.cxx58
-rw-r--r--sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx30
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