[Libreoffice-commits] core.git: sw/qa sw/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Thu Sep 19 16:32:23 UTC 2019


 sw/qa/extras/layout/layout.cxx                                     |   58 ++++++++++
 sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx |   30 +++++
 2 files changed, 88 insertions(+)

New commits:
commit d37096f59e7e0286e55008153591a60bab92b9e8
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Thu Sep 19 16:41:06 2019 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Sep 19 18:30:57 2019 +0200

    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 at collabora.com>
    Tested-by: Jenkins

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


More information about the Libreoffice-commits mailing list