oox/Library_oox.mk                                     |    1 
 oox/source/drawingml/diagram/diagram.cxx               |    7 
 oox/source/drawingml/diagram/diagram.hxx               |    4 
 oox/source/drawingml/diagram/diagramlayoutatoms.cxx    |  128 +++++------
 oox/source/drawingml/diagram/diagramlayoutatoms.hxx    |   26 --
 oox/source/drawingml/diagram/layoutatomvisitorbase.cxx |  173 ++++++++++++++
 oox/source/drawingml/diagram/layoutatomvisitorbase.hxx |   99 ++++++++
 oox/source/drawingml/diagram/layoutatomvisitors.cxx    |  197 ++---------------
 oox/source/drawingml/diagram/layoutatomvisitors.hxx    |   93 ++------
 sd/qa/unit/data/pptx/smartart-data-follow.pptx         |binary
 sd/qa/unit/import-tests-smartart.cxx                   |   40 +++
 solenv/clang-format/blacklist                          |    2 
 12 files changed, 445 insertions(+), 325 deletions(-)

New commits:
commit b3ee043d469cd1b67fd66e929df58a42a8f12015
Author:     Grzegorz Araminowicz <grzegorz.araminow...@collabora.com>
AuthorDate: Wed Jun 26 10:42:28 2019 +0200
Commit:     Grzegorz Araminowicz <grzegorz.araminow...@collabora.com>
CommitDate: Mon Jul 1 14:11:10 2019 +0200

    SmartArt: all visitors follow data presentation nodes
    
    * visitors now are keeping track of current presentation node instead of
      looking it up by name
    * extracted visitor base class that follows if/else and for-each nodes
    * moved condition logic from ConditionAtom to visitor, as it depends on
      visitor state
    
    Change-Id: Iede86cd74a6098f2398a77b6cb3e9c6272dbfe4b
    Reviewed-on: https://gerrit.libreoffice.org/74732
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/74951
    Reviewed-by: Grzegorz Araminowicz <grzegorz.araminow...@collabora.com>

diff --git a/oox/Library_oox.mk b/oox/Library_oox.mk
index 7da04f81a6ce..2d4718a320cb 100644
--- a/oox/Library_oox.mk
+++ b/oox/Library_oox.mk
@@ -144,6 +144,7 @@ $(eval $(call gb_Library_add_exception_objects,oox,\
     oox/source/drawingml/diagram/diagramdefinitioncontext \
     oox/source/drawingml/diagram/diagramfragmenthandler \
     oox/source/drawingml/diagram/diagramlayoutatoms \
+    oox/source/drawingml/diagram/layoutatomvisitorbase \
     oox/source/drawingml/diagram/layoutatomvisitors \
     oox/source/drawingml/diagram/layoutnodecontext \
     oox/source/drawingml/drawingmltypes \
diff --git a/oox/source/drawingml/diagram/diagram.cxx 
b/oox/source/drawingml/diagram/diagram.cxx
index 7460c52f1fed..2a5f2d054721 100644
--- a/oox/source/drawingml/diagram/diagram.cxx
+++ b/oox/source/drawingml/diagram/diagram.cxx
@@ -348,15 +348,16 @@ void Diagram::addTo( const ShapePtr & pParentShape )
 
     pParentShape->setChildSize(pParentShape->getSize());
 
-    if( mpLayout->getNode() )
+    const dgm::Point* pRootPoint = mpData->getRootPoint();
+    if (mpLayout->getNode() && pRootPoint)
     {
         // create Shape hierarchy
-        ShapeCreationVisitor aCreationVisitor(pParentShape, *this);
+        ShapeCreationVisitor aCreationVisitor(*this, pRootPoint, pParentShape);
         mpLayout->getNode()->setExistingShape(pParentShape);
         mpLayout->getNode()->accept(aCreationVisitor);
 
         // layout shapes - now all shapes are created
-        ShapeLayoutingVisitor aLayoutingVisitor;
+        ShapeLayoutingVisitor aLayoutingVisitor(*this, pRootPoint);
         mpLayout->getNode()->accept(aLayoutingVisitor);
 
         sortChildrenByZOrder(pParentShape);
diff --git a/oox/source/drawingml/diagram/diagram.hxx 
b/oox/source/drawingml/diagram/diagram.hxx
index cf12dce576a7..e8839d1b0fe6 100644
--- a/oox/source/drawingml/diagram/diagram.hxx
+++ b/oox/source/drawingml/diagram/diagram.hxx
@@ -208,6 +208,7 @@ private:
 typedef std::shared_ptr< DiagramData > DiagramDataPtr;
 
 typedef std::map<OUString, LayoutAtomPtr> LayoutAtomMap;
+typedef std::map<const dgm::Point*, ShapePtr> PresPointShapeMap;
 
 class DiagramLayout
 {
@@ -239,6 +240,8 @@ public:
         { return mpStyleData; }
     LayoutAtomMap & getLayoutAtomMap()
         { return maLayoutAtomMap; }
+    PresPointShapeMap & getPresPointShapeMap()
+        { return maPresPointShapeMap; }
 
 private:
     const Diagram& mrDgm;
@@ -256,6 +259,7 @@ private:
     // clrData
 
     LayoutAtomMap maLayoutAtomMap;
+    PresPointShapeMap maPresPointShapeMap;
 };
 
 typedef std::shared_ptr< DiagramLayout > DiagramLayoutPtr;
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx 
b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
index 6497e3ba22cf..d4845c768331 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
@@ -19,6 +19,8 @@
 
 #include "diagramlayoutatoms.hxx"
 
+#include "layoutatomvisitorbase.hxx"
+
 #include <basegfx/numeric/ftools.hxx>
 #include <sal/log.hxx>
 
@@ -248,17 +250,6 @@ void ChooseAtom::accept( LayoutAtomVisitor& rVisitor )
     rVisitor.visit(*this);
 }
 
-const std::vector<LayoutAtomPtr>& ChooseAtom::getChildren() const
-{
-    for (const auto& pChild : mpChildNodes)
-    {
-        const ConditionAtomPtr pCond = 
std::dynamic_pointer_cast<ConditionAtom>(pChild);
-        if (pCond && pCond->getDecision())
-            return pCond->getChildren();
-    }
-    return maEmptyChildren;
-}
-
 ConditionAtom::ConditionAtom(LayoutNode& rLayoutNode, bool isElse, const 
Reference< XFastAttributeList >& xAttributes) :
     LayoutAtom(rLayoutNode),
     mIsElse(isElse)
@@ -283,18 +274,6 @@ bool ConditionAtom::compareResult(sal_Int32 nOperator, 
sal_Int32 nFirst, sal_Int
     }
 }
 
-const dgm::Point* ConditionAtom::getPresNode() const
-{
-    const DiagramData::PointsNameMap& rPoints = 
mrLayoutNode.getDiagram().getData()->getPointsPresNameMap();
-    DiagramData::PointsNameMap::const_iterator aDataNode = 
rPoints.find(mrLayoutNode.getName());
-    if (aDataNode != rPoints.end())
-    {
-        SAL_WARN_IF(aDataNode->second.size() > 1, "oox.drawingml", "multiple 
nodes found; taking first one");
-        return aDataNode->second.front();
-    }
-    return nullptr;
-}
-
 namespace
 {
 /**
@@ -325,69 +304,63 @@ OUString navigate(const LayoutNode& rLayoutNode, 
sal_Int32 nType, const OUString
 }
 }
 
-sal_Int32 ConditionAtom::getNodeCount() const
+sal_Int32 ConditionAtom::getNodeCount(const dgm::Point* pPresPoint) const
 {
     sal_Int32 nCount = 0;
-    const dgm::Point* pPoint = getPresNode();
-    if (pPoint)
-    {
-        OUString sNodeId
-            = navigate(mrLayoutNode, XML_presOf, pPoint->msModelId, 
/*bSourceToDestination*/ false);
+    OUString sNodeId = navigate(mrLayoutNode, XML_presOf, 
pPresPoint->msModelId, /*bSourceToDestination*/ false);
 
-        if (sNodeId.isEmpty())
-        {
-            // The current layout node is not a presentation of anything. Look
-            // up the first presentation child of the layout node.
-            OUString sFirstPresChildId = navigate(mrLayoutNode, XML_presParOf, 
pPoint->msModelId,
-                                                  /*bSourceToDestination*/ 
true);
-            if (!sFirstPresChildId.isEmpty())
-                // It has a presentation child: is that a presentation of a
-                // model node?
-                sNodeId = navigate(mrLayoutNode, XML_presOf, sFirstPresChildId,
-                                   /*bSourceToDestination*/ false);
-        }
+    if (sNodeId.isEmpty())
+    {
+        // The current layout node is not a presentation of anything. Look
+        // up the first presentation child of the layout node.
+        OUString sFirstPresChildId = navigate(mrLayoutNode, XML_presParOf, 
pPresPoint->msModelId,
+                                                /*bSourceToDestination*/ true);
+        if (!sFirstPresChildId.isEmpty())
+            // It has a presentation child: is that a presentation of a
+            // model node?
+            sNodeId = navigate(mrLayoutNode, XML_presOf, sFirstPresChildId,
+                                /*bSourceToDestination*/ false);
+    }
 
-        if (!sNodeId.isEmpty())
-        {
-            for (const auto& aCxn : 
mrLayoutNode.getDiagram().getData()->getConnections())
-                if (aCxn.mnType == XML_parOf && aCxn.msSourceId == sNodeId)
-                    nCount++;
-        }
-        else
-        {
-            // No presentation child is a presentation of a model node: just
-            // count presentation children.
-            for (const auto& aCxn : 
mrLayoutNode.getDiagram().getData()->getConnections())
-                if (aCxn.mnType == XML_presParOf && aCxn.msSourceId == 
pPoint->msModelId)
-                    nCount++;
-        }
+    if (!sNodeId.isEmpty())
+    {
+        for (const auto& aCxn : 
mrLayoutNode.getDiagram().getData()->getConnections())
+            if (aCxn.mnType == XML_parOf && aCxn.msSourceId == sNodeId)
+                nCount++;
+    }
+    else
+    {
+        // No presentation child is a presentation of a model node: just
+        // count presentation children.
+        for (const auto& aCxn : 
mrLayoutNode.getDiagram().getData()->getConnections())
+            if (aCxn.mnType == XML_presParOf && aCxn.msSourceId == 
pPresPoint->msModelId)
+                nCount++;
     }
+
     return nCount;
 }
 
-bool ConditionAtom::getDecision() const
+bool ConditionAtom::getDecision(const dgm::Point* pPresPoint) const
 {
     if (mIsElse)
         return true;
+    if (!pPresPoint)
+        return false;
 
     switch (maCond.mnFunc)
     {
     case XML_var:
     {
-        const dgm::Point* pPoint = getPresNode();
-        if (!pPoint)
-            break;
-
         if (maCond.mnArg == XML_dir)
-            return compareResult(maCond.mnOp, pPoint->mnDirection, 
maCond.mnVal);
+            return compareResult(maCond.mnOp, pPresPoint->mnDirection, 
maCond.mnVal);
         else if (maCond.mnArg == XML_hierBranch)
         {
-            sal_Int32 nHierarchyBranch = 
pPoint->moHierarchyBranch.get(XML_std);
-            if (!pPoint->moHierarchyBranch.has())
+            sal_Int32 nHierarchyBranch = 
pPresPoint->moHierarchyBranch.get(XML_std);
+            if (!pPresPoint->moHierarchyBranch.has())
             {
                 // If <dgm:hierBranch> is missing in the current presentation
                 // point, ask the parent.
-                OUString aParent = navigate(mrLayoutNode, XML_presParOf, 
pPoint->msModelId,
+                OUString aParent = navigate(mrLayoutNode, XML_presParOf, 
pPresPoint->msModelId,
                                             /*bSourceToDestination*/ false);
                 DiagramData::PointNameMap& rPointNameMap
                     = mrLayoutNode.getDiagram().getData()->getPointNameMap();
@@ -405,11 +378,18 @@ bool ConditionAtom::getDecision() const
     }
 
     case XML_cnt:
-        return compareResult(maCond.mnOp, getNodeCount(), 
maCond.msVal.toInt32());
+        return compareResult(maCond.mnOp, getNodeCount(pPresPoint), 
maCond.msVal.toInt32());
 
     case XML_maxDepth:
+        // TODO: probably depth from current point - docs are unclear
         return compareResult(maCond.mnOp, 
mrLayoutNode.getDiagram().getData()->getMaxDepth(), maCond.msVal.toInt32());
 
+    case XML_depth:
+    case XML_pos:
+    case XML_revPos:
+    case XML_posEven:
+    case XML_posOdd:
+        // TODO
     default:
         SAL_WARN("oox.drawingml", "unknown function " << maCond.mnFunc);
         break;
@@ -732,7 +712,12 @@ void AlgAtom::layoutShape( const ShapePtr& rShape,
             // hierRoot is the manager -> employees vertical linear path,
             // hierChild is the first employee -> last employee horizontal
             // linear path.
-            const sal_Int32 nDir = mnType == XML_hierRoot ? XML_fromT : 
XML_fromL;
+            sal_Int32 nDir = XML_fromL;
+            if (mnType == XML_hierRoot)
+                nDir = XML_fromT;
+            else if (maMap.count(XML_linDir))
+                nDir = maMap.find(XML_linDir)->second;
+
             if (rShape->getChildren().empty() || rShape->getSize().Width == 0
                 || rShape->getSize().Height == 0)
                 break;
@@ -782,18 +767,25 @@ void AlgAtom::layoutShape( const ShapePtr& rShape,
                 aChildSize.Width /= nCount;
             aChildSize.Height *= fHeightScale;
             aChildSize.Width *= fWidthScale;
+            awt::Size aConnectorSize = aChildSize;
+            aConnectorSize.Width = 1;
 
             awt::Point aChildPos(nXOffset, 0);
             for (auto& pChild : rShape->getChildren())
             {
                 pChild->setPosition(aChildPos);
-                pChild->setSize(aChildSize);
-                pChild->setChildSize(aChildSize);
 
                 if (mnType == XML_hierChild && pChild->getSubType() == 
XML_conn)
+                {
                     // Connectors should not influence the position of
                     // non-connect shapes.
+                    pChild->setSize(aConnectorSize);
+                    pChild->setChildSize(aConnectorSize);
                     continue;
+                }
+
+                pChild->setSize(aChildSize);
+                pChild->setChildSize(aChildSize);
 
                 if (nDir == XML_fromT)
                     aChildPos.Y += aChildSize.Height + aChildSize.Height * 
fSpace;
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx 
b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
index ef99229b66ab..dc58fc4b8621 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
@@ -112,7 +112,7 @@ private:
     void setParent(const LayoutAtomPtr& pParent) { mpParent = pParent; }
 
 public:
-    virtual const std::vector<LayoutAtomPtr>& getChildren() const
+    const std::vector<LayoutAtomPtr>& getChildren() const
         { return mpChildNodes; }
 
     LayoutAtomPtr getParent() const { return mpParent.lock(); }
@@ -208,11 +208,11 @@ class ConditionAtom
 public:
     explicit ConditionAtom(LayoutNode& rLayoutNode, bool isElse, const 
css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttributes);
     virtual void accept( LayoutAtomVisitor& ) override;
-    bool getDecision() const;
+    bool getDecision(const dgm::Point* pPresPoint) const;
+
 private:
     static bool compareResult(sal_Int32 nOperator, sal_Int32 nFirst, sal_Int32 
nSecond);
-    const dgm::Point* getPresNode() const;
-    sal_Int32 getNodeCount() const;
+    sal_Int32 getNodeCount(const dgm::Point* pPresPoint) const;
 
     bool const    mIsElse;
     IteratorAttr  maIter;
@@ -228,14 +228,8 @@ class ChooseAtom
 public:
     ChooseAtom(LayoutNode& rLayoutNode)
         : LayoutAtom(rLayoutNode)
-#if defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 8
-        , maEmptyChildren()
-#endif
     {}
     virtual void accept( LayoutAtomVisitor& ) override;
-    virtual const std::vector<LayoutAtomPtr>& getChildren() const override;
-private:
-    const std::vector<LayoutAtomPtr> maEmptyChildren;
 };
 
 class LayoutNode
@@ -298,18 +292,6 @@ private:
 
 typedef std::shared_ptr< ShapeAtom > ShapeAtomPtr;
 
-struct LayoutAtomVisitor
-{
-    virtual ~LayoutAtomVisitor() {}
-    virtual void visit(ConstraintAtom& rAtom) = 0;
-    virtual void visit(AlgAtom& rAtom) = 0;
-    virtual void visit(ForEachAtom& rAtom) = 0;
-    virtual void visit(ConditionAtom& rAtom) = 0;
-    virtual void visit(ChooseAtom& rAtom) = 0;
-    virtual void visit(LayoutNode& rAtom) = 0;
-    virtual void visit(ShapeAtom& rAtom) = 0;
-};
-
 } }
 
 #endif
diff --git a/oox/source/drawingml/diagram/layoutatomvisitorbase.cxx 
b/oox/source/drawingml/diagram/layoutatomvisitorbase.cxx
new file mode 100644
index 000000000000..49b1d801bee9
--- /dev/null
+++ b/oox/source/drawingml/diagram/layoutatomvisitorbase.cxx
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "layoutatomvisitorbase.hxx"
+
+#include <sal/log.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace oox { namespace drawingml {
+
+void LayoutAtomVisitorBase::defaultVisit(LayoutAtom const& rAtom)
+{
+    for (const auto& pAtom : rAtom.getChildren())
+        pAtom->accept(*this);
+}
+
+void LayoutAtomVisitorBase::visit(ChooseAtom& rAtom)
+{
+    for (const auto& pChild : rAtom.getChildren())
+    {
+        const ConditionAtomPtr pCond = 
std::dynamic_pointer_cast<ConditionAtom>(pChild);
+        if (pCond && pCond->getDecision(mpCurrentNode))
+        {
+            SAL_INFO("oox.drawingml", "Entering if node: " << 
pCond->getName());
+            pCond->accept(*this);
+            break;
+        }
+    }
+}
+
+void LayoutAtomVisitorBase::visit(ConditionAtom& rAtom)
+{
+    defaultVisit(rAtom);
+}
+
+void LayoutAtomVisitorBase::visit(ForEachAtom& rAtom)
+{
+    if (!rAtom.getRef().isEmpty())
+    {
+        if (LayoutAtomPtr pRefAtom = rAtom.getRefAtom())
+            pRefAtom->accept(*this);
+        return;
+    }
+
+    if (rAtom.iterator().mbHideLastTrans && rAtom.iterator().mnAxis == 
XML_followSib)
+    {
+        // If last transition is hidden and the axis is the follow sibling,
+        // then the last atom should not be visited.
+        if (mnCurrIdx + mnCurrStep >= mnCurrCnt)
+            return;
+    }
+
+    sal_Int32 nChildren = 1;
+    // Approximate the non-assistant type with the node type.
+    if (rAtom.iterator().mnPtType == XML_node || rAtom.iterator().mnPtType == 
XML_nonAsst)
+    {
+        // count child data nodes - check all child Atoms for "name"
+        // attribute that is contained in diagram's
+        // getPointsPresNameMap()
+        ShallowPresNameVisitor aVisitor(mrDgm, mpCurrentNode);
+        for (const auto& pAtom : rAtom.getChildren())
+            pAtom->accept(aVisitor);
+        nChildren = aVisitor.getCount();
+    }
+
+    const sal_Int32 nCnt = std::min(
+        nChildren,
+        rAtom.iterator().mnCnt==-1 ? nChildren : rAtom.iterator().mnCnt);
+
+    const sal_Int32 nOldIdx = mnCurrIdx;
+    const sal_Int32 nOldStep = mnCurrStep;
+    const sal_Int32 nOldCnt = mnCurrCnt;
+    const sal_Int32 nStep = rAtom.iterator().mnStep;
+    mnCurrStep = nStep;
+    mnCurrCnt = nCnt;
+    for( mnCurrIdx=0; mnCurrIdx<nCnt && nStep>0; mnCurrIdx+=nStep )
+    {
+        // TODO there is likely some conditions
+        for (const auto& pAtom : rAtom.getChildren())
+            pAtom->accept(*this);
+    }
+
+    // and restore idx
+    mnCurrIdx = nOldIdx;
+    mnCurrStep = nOldStep;
+    mnCurrCnt = nOldCnt;
+}
+
+void LayoutAtomVisitorBase::visit(LayoutNode& rAtom)
+{
+    // TODO: deduplicate code in descendants
+
+    // stop processing if it's not a child of previous LayoutNode
+
+    const DiagramData::PointsNameMap::const_iterator aDataNode
+        = mrDgm.getData()->getPointsPresNameMap().find(rAtom.getName());
+    if (aDataNode == mrDgm.getData()->getPointsPresNameMap().end()
+        || mnCurrIdx >= static_cast<sal_Int32>(aDataNode->second.size()))
+        return;
+
+    const dgm::Point* pNewNode = aDataNode->second.at(mnCurrIdx);
+    if (!mpCurrentNode || !pNewNode)
+        return;
+
+    bool bIsChild = false;
+    for (const auto& aConnection : mrDgm.getData()->getConnections())
+        if (aConnection.msSourceId == mpCurrentNode->msModelId
+            && aConnection.msDestId == pNewNode->msModelId)
+            bIsChild = true;
+
+    if (!bIsChild)
+        return;
+
+    const dgm::Point* pPreviousNode = mpCurrentNode;
+    mpCurrentNode = pNewNode;
+    mnCurrLevel++;
+
+    defaultVisit(rAtom);
+
+    mnCurrLevel--;
+    mpCurrentNode = pPreviousNode;
+}
+
+void ShallowPresNameVisitor::visit(ConstraintAtom& /*rAtom*/)
+{
+    // stop processing
+}
+
+void ShallowPresNameVisitor::visit(AlgAtom& /*rAtom*/)
+{
+    // stop processing
+}
+
+void ShallowPresNameVisitor::visit(ForEachAtom& rAtom)
+{
+    defaultVisit(rAtom);
+}
+
+void ShallowPresNameVisitor::visit(LayoutNode& rAtom)
+{
+    DiagramData::PointsNameMap::const_iterator aDataNode =
+        mrDgm.getData()->getPointsPresNameMap().find(rAtom.getName());
+    if( aDataNode != mrDgm.getData()->getPointsPresNameMap().end() )
+        mnCnt = std::max(mnCnt,
+                         aDataNode->second.size());
+}
+
+void ShallowPresNameVisitor::visit(ShapeAtom& /*rAtom*/)
+{
+    // stop processing
+}
+
+} }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/diagram/layoutatomvisitorbase.hxx 
b/oox/source/drawingml/diagram/layoutatomvisitorbase.hxx
new file mode 100644
index 000000000000..25f2b4dea54b
--- /dev/null
+++ b/oox/source/drawingml/diagram/layoutatomvisitorbase.hxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_OOX_SOURCE_DRAWINGML_DIAGRAM_LAYOUTATOMVISITORBASE_HXX
+#define INCLUDED_OOX_SOURCE_DRAWINGML_DIAGRAM_LAYOUTATOMVISITORBASE_HXX
+
+#include <memory>
+
+#include <oox/drawingml/shape.hxx>
+#include "diagram.hxx"
+#include "diagramlayoutatoms.hxx"
+
+namespace oox { namespace drawingml {
+
+struct LayoutAtomVisitor
+{
+    virtual ~LayoutAtomVisitor() {}
+    virtual void visit(ConstraintAtom& rAtom) = 0;
+    virtual void visit(AlgAtom& rAtom) = 0;
+    virtual void visit(ForEachAtom& rAtom) = 0;
+    virtual void visit(ConditionAtom& rAtom) = 0;
+    virtual void visit(ChooseAtom& rAtom) = 0;
+    virtual void visit(LayoutNode& rAtom) = 0;
+    virtual void visit(ShapeAtom& rAtom) = 0;
+};
+
+// basic visitor implementation that follows if/else and for-each nodes
+// and keeps track of current position in data tree
+class LayoutAtomVisitorBase : public LayoutAtomVisitor
+{
+public:
+    LayoutAtomVisitorBase(const Diagram& rDgm, const dgm::Point* pRootPoint) :
+        mrDgm(rDgm),
+        mpCurrentNode(pRootPoint),
+        mnCurrIdx(0),
+        mnCurrStep(0),
+        mnCurrCnt(0),
+        mnCurrLevel(0)
+    {}
+
+    void defaultVisit(LayoutAtom const& rAtom);
+
+    using LayoutAtomVisitor::visit;
+    virtual void visit(ForEachAtom& rAtom) override;
+    virtual void visit(ConditionAtom& rAtom) override;
+    virtual void visit(ChooseAtom& rAtom) override;
+    virtual void visit(LayoutNode& rAtom) override;
+
+protected:
+    const Diagram& mrDgm;
+    const dgm::Point* mpCurrentNode;
+    sal_Int32 mnCurrIdx;
+    sal_Int32 mnCurrStep;
+    sal_Int32 mnCurrCnt;
+    sal_Int32 mnCurrLevel;
+};
+
+class ShallowPresNameVisitor : public LayoutAtomVisitorBase
+{
+public:
+    explicit ShallowPresNameVisitor(const Diagram& rDgm, const dgm::Point* 
pRootPoint) :
+        LayoutAtomVisitorBase(rDgm, pRootPoint),
+        mnCnt(0)
+    {}
+
+    using LayoutAtomVisitorBase::visit;
+    virtual void visit(ConstraintAtom& rAtom) override;
+    virtual void visit(AlgAtom& rAtom) override;
+    virtual void visit(ForEachAtom& rAtom) override;
+    virtual void visit(LayoutNode& rAtom) override;
+    virtual void visit(ShapeAtom& rAtom) override;
+
+    size_t getCount() const { return mnCnt; }
+
+private:
+    size_t mnCnt;
+};
+
+} }
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/diagram/layoutatomvisitors.cxx 
b/oox/source/drawingml/diagram/layoutatomvisitors.cxx
index aa1d21b179f1..b72133033470 100644
--- a/oox/source/drawingml/diagram/layoutatomvisitors.cxx
+++ b/oox/source/drawingml/diagram/layoutatomvisitors.cxx
@@ -30,12 +30,6 @@ using namespace ::oox::core;
 
 namespace oox { namespace drawingml {
 
-void ShapeCreationVisitor::defaultVisit(LayoutAtom const & rAtom)
-{
-    for (const auto& pAtom : rAtom.getChildren())
-        pAtom->accept(*this);
-}
-
 void ShapeCreationVisitor::visit(ConstraintAtom& /*rAtom*/)
 {
     // stop processing
@@ -46,71 +40,6 @@ void ShapeCreationVisitor::visit(AlgAtom& rAtom)
     mpParentShape->setAspectRatio(rAtom.getAspectRatio());
 }
 
-void ShapeCreationVisitor::visit(ForEachAtom& rAtom)
-{
-    if (!rAtom.getRef().isEmpty())
-    {
-        if (LayoutAtomPtr pRefAtom = rAtom.getRefAtom())
-            pRefAtom->accept(*this);
-        return;
-    }
-
-    if (rAtom.iterator().mbHideLastTrans && rAtom.iterator().mnAxis == 
XML_followSib)
-    {
-        // If last transition is hidden and the axis is the follow sibling,
-        // then the last atom should not be visited.
-        if (mnCurrIdx + mnCurrStep >= mnCurrCnt)
-            return;
-    }
-
-    const std::vector<LayoutAtomPtr>& rChildren=rAtom.getChildren();
-
-    sal_Int32 nChildren=1;
-    // Approximate the non-assistant type with the node type.
-    if (rAtom.iterator().mnPtType == XML_node || rAtom.iterator().mnPtType == 
XML_nonAsst)
-    {
-        // count child data nodes - check all child Atoms for "name"
-        // attribute that is contained in diagram's
-        // getPointsPresNameMap()
-        ShallowPresNameVisitor aVisitor(mrDgm);
-        for (const auto& pAtom : rChildren)
-            pAtom->accept(aVisitor);
-        nChildren = aVisitor.getCount();
-    }
-
-    const sal_Int32 nCnt = std::min(
-        nChildren,
-        rAtom.iterator().mnCnt==-1 ? nChildren : rAtom.iterator().mnCnt);
-
-    const sal_Int32 nOldIdx=mnCurrIdx;
-    const sal_Int32 nOldStep = mnCurrStep;
-    const sal_Int32 nOldCnt = mnCurrCnt;
-    const sal_Int32 nStep=rAtom.iterator().mnStep;
-    mnCurrStep = nStep;
-    mnCurrCnt = nCnt;
-    for( mnCurrIdx=0; mnCurrIdx<nCnt && nStep>0; mnCurrIdx+=nStep )
-    {
-        // TODO there is likely some conditions
-        for (const auto& pAtom : rChildren)
-            pAtom->accept(*this);
-    }
-
-    // and restore idx
-    mnCurrIdx = nOldIdx;
-    mnCurrStep = nOldStep;
-    mnCurrCnt = nOldCnt;
-}
-
-void ShapeCreationVisitor::visit(ConditionAtom& rAtom)
-{
-    defaultVisit(rAtom);
-}
-
-void ShapeCreationVisitor::visit(ChooseAtom& rAtom)
-{
-    defaultVisit(rAtom);
-}
-
 void ShapeCreationVisitor::visit(LayoutNode& rAtom)
 {
     // stop processing if it's not a child of previous LayoutNode
@@ -141,11 +70,12 @@ void ShapeCreationVisitor::visit(LayoutNode& rAtom)
         {
             pShape->setInternalName(rAtom.getName());
             rAtom.addNodeShape(pShape, mnCurrLevel);
+            mrDgm.getLayout()->getPresPointShapeMap()[pNewNode] = pShape;
         }
     }
     else
     {
-        ShapeTemplateVisitor aTemplateVisitor;
+        ShapeTemplateVisitor aTemplateVisitor(mrDgm, pNewNode);
         aTemplateVisitor.defaultVisit(rAtom);
         ShapePtr pShape = aTemplateVisitor.getShapeCopy();
 
@@ -162,6 +92,7 @@ void ShapeCreationVisitor::visit(LayoutNode& rAtom)
                 pCurrParent->addChild(pShape);
                 pCurrParent = pShape;
                 rAtom.addNodeShape(pShape, mnCurrLevel);
+                mrDgm.getLayout()->getPresPointShapeMap()[pNewNode] = pShape;
             }
         }
         else
@@ -198,13 +129,6 @@ void ShapeCreationVisitor::visit(ShapeAtom& /*rAtom*/)
     // stop processing
 }
 
-void ShapeTemplateVisitor::defaultVisit(LayoutAtom const & rAtom)
-{
-    // visit all children, one of them needs to be the layout algorithm
-    for (const auto& pAtom : rAtom.getChildren())
-        pAtom->accept(*this);
-}
-
 void ShapeTemplateVisitor::visit(ConstraintAtom& /*rAtom*/)
 {
     // stop processing
@@ -220,16 +144,6 @@ void ShapeTemplateVisitor::visit(ForEachAtom& /*rAtom*/)
     // stop processing
 }
 
-void ShapeTemplateVisitor::visit(ConditionAtom& rAtom)
-{
-    defaultVisit(rAtom);
-}
-
-void ShapeTemplateVisitor::visit(ChooseAtom& rAtom)
-{
-    defaultVisit(rAtom);
-}
-
 void ShapeTemplateVisitor::visit(LayoutNode& /*rAtom*/)
 {
     // stop processing - only traverse Condition/Choose atoms
@@ -253,13 +167,6 @@ void ShapeTemplateVisitor::visit(ShapeAtom& rAtom)
     mpShape->cloneFillProperties();
 }
 
-void ShapeLayoutingVisitor::defaultVisit(LayoutAtom const & rAtom)
-{
-    // visit all children, one of them needs to be the layout algorithm
-    for (const auto& pAtom : rAtom.getChildren())
-        pAtom->accept(*this);
-}
-
 void ShapeLayoutingVisitor::visit(ConstraintAtom& rAtom)
 {
     if (meLookFor == CONSTRAINT)
@@ -270,46 +177,44 @@ void ShapeLayoutingVisitor::visit(AlgAtom& rAtom)
 {
     if (meLookFor == ALGORITHM)
     {
-        auto pShapes = rAtom.getLayoutNode().getNodeShapes().find(mnCurrLevel);
-        if (pShapes != rAtom.getLayoutNode().getNodeShapes().end())
-            for (const auto& pShape : pShapes->second)
-                rAtom.layoutShape(pShape, maConstraints, mnCurrLevel);
+        const PresPointShapeMap aMap = 
rAtom.getLayoutNode().getDiagram().getLayout()->getPresPointShapeMap();
+        auto pShape = aMap.find(mpCurrentNode);
+        if (pShape != aMap.end())
+            rAtom.layoutShape(pShape->second, maConstraints, mnCurrLevel);
     }
 }
 
-void ShapeLayoutingVisitor::visit(ForEachAtom& rAtom)
+void ShapeLayoutingVisitor::visit(LayoutNode& rAtom)
 {
-    if (!rAtom.getRef().isEmpty())
-    {
-        if (LayoutAtomPtr pRefAtom = rAtom.getRefAtom())
-            pRefAtom->accept(*this);
+    if (meLookFor != LAYOUT_NODE)
         return;
-    }
-
-    defaultVisit(rAtom);
-}
 
-void ShapeLayoutingVisitor::visit(ConditionAtom& rAtom)
-{
-    defaultVisit(rAtom);
-}
+    // stop processing if it's not a child of previous LayoutNode
 
-void ShapeLayoutingVisitor::visit(ChooseAtom& rAtom)
-{
-    defaultVisit(rAtom);
-}
+    const DiagramData::PointsNameMap::const_iterator aDataNode
+        = mrDgm.getData()->getPointsPresNameMap().find(rAtom.getName());
+    if (aDataNode == mrDgm.getData()->getPointsPresNameMap().end()
+        || mnCurrIdx >= static_cast<sal_Int32>(aDataNode->second.size()))
+        return;
 
-void ShapeLayoutingVisitor::visit(LayoutNode& rAtom)
-{
-    if (meLookFor != LAYOUT_NODE)
+    const dgm::Point* pNewNode = aDataNode->second.at(mnCurrIdx);
+    if (!mpCurrentNode || !pNewNode)
         return;
 
-    // stop processing if there is no more shapes on this level
-    if (rAtom.getNodeShapes().empty() || mnCurrLevel > 
rAtom.getNodeShapes().rbegin()->first)
+    bool bIsChild = false;
+    for (const auto& aConnection : mrDgm.getData()->getConnections())
+        if (aConnection.msSourceId == mpCurrentNode->msModelId
+            && aConnection.msDestId == pNewNode->msModelId)
+            bIsChild = true;
+
+    if (!bIsChild)
         return;
 
     size_t nParentConstraintsNumber = maConstraints.size();
 
+    const dgm::Point* pPreviousNode = mpCurrentNode;
+    mpCurrentNode = pNewNode;
+
     // process alg atoms first, nested layout nodes afterwards
     meLookFor = CONSTRAINT;
     defaultVisit(rAtom);
@@ -320,6 +225,7 @@ void ShapeLayoutingVisitor::visit(LayoutNode& rAtom)
     meLookFor = LAYOUT_NODE;
     defaultVisit(rAtom);
     mnCurrLevel--;
+    mpCurrentNode = pPreviousNode;
 
     // delete added constraints, keep parent constraints
     maConstraints.erase(maConstraints.begin() + nParentConstraintsNumber, 
maConstraints.end());
@@ -330,53 +236,6 @@ void ShapeLayoutingVisitor::visit(ShapeAtom& /*rAtom*/)
     // stop processing
 }
 
-void ShallowPresNameVisitor::defaultVisit(LayoutAtom const & rAtom)
-{
-    // visit all children, at least one of them needs to have proper
-    // name set
-    for (const auto& pAtom : rAtom.getChildren())
-        pAtom->accept(*this);
-}
-
-void ShallowPresNameVisitor::visit(ConstraintAtom& /*rAtom*/)
-{
-    // stop processing
-}
-
-void ShallowPresNameVisitor::visit(AlgAtom& /*rAtom*/)
-{
-    // stop processing
-}
-
-void ShallowPresNameVisitor::visit(ForEachAtom& rAtom)
-{
-    defaultVisit(rAtom);
-}
-
-void ShallowPresNameVisitor::visit(ConditionAtom& rAtom)
-{
-    defaultVisit(rAtom);
-}
-
-void ShallowPresNameVisitor::visit(ChooseAtom& rAtom)
-{
-    defaultVisit(rAtom);
-}
-
-void ShallowPresNameVisitor::visit(LayoutNode& rAtom)
-{
-    DiagramData::PointsNameMap::const_iterator aDataNode=
-        mrDgm.getData()->getPointsPresNameMap().find(rAtom.getName());
-    if( aDataNode != mrDgm.getData()->getPointsPresNameMap().end() )
-        mnCnt = std::max(mnCnt,
-                         aDataNode->second.size());
-}
-
-void ShallowPresNameVisitor::visit(ShapeAtom& /*rAtom*/)
-{
-    // stop processing
-}
-
 } }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/diagram/layoutatomvisitors.hxx 
b/oox/source/drawingml/diagram/layoutatomvisitors.hxx
index 4a61a75eb0f5..2950fb01a17c 100644
--- a/oox/source/drawingml/diagram/layoutatomvisitors.hxx
+++ b/oox/source/drawingml/diagram/layoutatomvisitors.hxx
@@ -25,101 +25,68 @@
 #include <oox/drawingml/shape.hxx>
 #include "diagram.hxx"
 #include "diagramlayoutatoms.hxx"
+#include "layoutatomvisitorbase.hxx"
 
 namespace oox { namespace drawingml {
 
-class ShapeCreationVisitor : public LayoutAtomVisitor
+class ShapeCreationVisitor : public LayoutAtomVisitorBase
 {
-    ShapePtr mpParentShape;
-    const Diagram& mrDgm;
-    sal_Int32 mnCurrIdx;
-    sal_Int32 mnCurrStep = 0;
-    sal_Int32 mnCurrCnt = 0;
-    sal_Int32 mnCurrLevel;
-    const dgm::Point* mpCurrentNode;
-
-    void defaultVisit(LayoutAtom const & rAtom);
+public:
+    ShapeCreationVisitor(const Diagram& rDgm,
+                         const dgm::Point* pRootPoint,
+                         const ShapePtr& rParentShape) :
+        LayoutAtomVisitorBase(rDgm, pRootPoint),
+        mpParentShape(rParentShape)
+    {}
+
+    using LayoutAtomVisitorBase::visit;
     virtual void visit(ConstraintAtom& rAtom) override;
     virtual void visit(AlgAtom& rAtom) override;
-    virtual void visit(ForEachAtom& rAtom) override;
-    virtual void visit(ConditionAtom& rAtom) override;
-    virtual void visit(ChooseAtom& rAtom) override;
     virtual void visit(LayoutNode& rAtom) override;
     virtual void visit(ShapeAtom& rAtom) override;
 
-public:
-    ShapeCreationVisitor(const ShapePtr& rParentShape,
-                         const Diagram& rDgm) :
-        mpParentShape(rParentShape),
-        mrDgm(rDgm),
-        mnCurrIdx(0),
-        mnCurrLevel(0),
-        mpCurrentNode(rDgm.getData()->getRootPoint())
-    {}
+private:
+    ShapePtr mpParentShape;
 };
 
-class ShapeTemplateVisitor : public LayoutAtomVisitor
+class ShapeTemplateVisitor : public LayoutAtomVisitorBase
 {
-    ShapePtr mpShape;
+public:
+    ShapeTemplateVisitor(const Diagram& rDgm, const dgm::Point* pRootPoint)
+        : LayoutAtomVisitorBase(rDgm, pRootPoint)
+    {}
 
+    using LayoutAtomVisitorBase::visit;
     virtual void visit(ConstraintAtom& rAtom) override;
     virtual void visit(AlgAtom& rAtom) override;
     virtual void visit(ForEachAtom& rAtom) override;
-    virtual void visit(ConditionAtom& rAtom) override;
-    virtual void visit(ChooseAtom& rAtom) override;
     virtual void visit(LayoutNode& rAtom) override;
     virtual void visit(ShapeAtom& rAtom) override;
 
-public:
-    void defaultVisit(LayoutAtom const & rAtom);
     ShapePtr const & getShapeCopy() const
         { return mpShape; }
+
+private:
+    ShapePtr mpShape;
 };
 
-class ShapeLayoutingVisitor : public LayoutAtomVisitor
+class ShapeLayoutingVisitor : public LayoutAtomVisitorBase
 {
-    std::vector<Constraint> maConstraints;
-    enum {LAYOUT_NODE, CONSTRAINT, ALGORITHM} meLookFor;
-    sal_Int32 mnCurrLevel;
-
-    void defaultVisit(LayoutAtom const & rAtom);
-    virtual void visit(ConstraintAtom& rAtom) override;
-    virtual void visit(AlgAtom& rAtom) override;
-    virtual void visit(ForEachAtom& rAtom) override;
-    virtual void visit(ConditionAtom& rAtom) override;
-    virtual void visit(ChooseAtom& rAtom) override;
-    virtual void visit(LayoutNode& rAtom) override;
-    virtual void visit(ShapeAtom& rAtom) override;
-
 public:
-    ShapeLayoutingVisitor() :
-        meLookFor(LAYOUT_NODE),
-        mnCurrLevel(0)
+    ShapeLayoutingVisitor(const Diagram& rDgm, const dgm::Point* pRootPoint) :
+        LayoutAtomVisitorBase(rDgm, pRootPoint),
+        meLookFor(LAYOUT_NODE)
     {}
-};
 
-class ShallowPresNameVisitor : public LayoutAtomVisitor
-{
-    const Diagram& mrDgm;
-    size_t mnCnt;
-
-    void defaultVisit(LayoutAtom const & rAtom);
+    using LayoutAtomVisitorBase::visit;
     virtual void visit(ConstraintAtom& rAtom) override;
     virtual void visit(AlgAtom& rAtom) override;
-    virtual void visit(ForEachAtom& rAtom) override;
-    virtual void visit(ConditionAtom& rAtom) override;
-    virtual void visit(ChooseAtom& rAtom) override;
     virtual void visit(LayoutNode& rAtom) override;
     virtual void visit(ShapeAtom& rAtom) override;
 
-public:
-    explicit ShallowPresNameVisitor(const Diagram& rDgm) :
-        mrDgm(rDgm),
-        mnCnt(0)
-    {}
-
-    size_t getCount() const
-        { return mnCnt; }
+private:
+    std::vector<Constraint> maConstraints;
+    enum {LAYOUT_NODE, CONSTRAINT, ALGORITHM} meLookFor;
 };
 
 } }
diff --git a/sd/qa/unit/data/pptx/smartart-data-follow.pptx 
b/sd/qa/unit/data/pptx/smartart-data-follow.pptx
new file mode 100644
index 000000000000..7e906462d012
Binary files /dev/null and b/sd/qa/unit/data/pptx/smartart-data-follow.pptx 
differ
diff --git a/sd/qa/unit/import-tests-smartart.cxx 
b/sd/qa/unit/import-tests-smartart.cxx
index 944e583df040..fde35bd0a48d 100644
--- a/sd/qa/unit/import-tests-smartart.cxx
+++ b/sd/qa/unit/import-tests-smartart.cxx
@@ -80,6 +80,7 @@ public:
     void testVerticalBlockList();
     void testBulletList();
     void testRecursion();
+    void testDataFollow();
 
     CPPUNIT_TEST_SUITE(SdImportTestSmartArt);
 
@@ -121,6 +122,7 @@ public:
     CPPUNIT_TEST(testVerticalBlockList);
     CPPUNIT_TEST(testBulletList);
     CPPUNIT_TEST(testRecursion);
+    CPPUNIT_TEST(testDataFollow);
 
     CPPUNIT_TEST_SUITE_END();
 };
@@ -1316,6 +1318,44 @@ void SdImportTestSmartArt::testRecursion()
     xDocShRef->DoClose();
 }
 
+void SdImportTestSmartArt::testDataFollow()
+{
+    // checks if data nodes are followed correctly
+    // different variables are set for two presentation points with the same 
name
+    // they should be layouted differently - one horizontally and one 
vertically
+
+    sd::DrawDocShellRef xDocShRef = loadURL(
+        
m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/smartart-data-follow.pptx"), 
PPTX);
+
+    uno::Reference<drawing::XShapes> xGroup(getShapeFromPage(0, 0, xDocShRef), 
uno::UNO_QUERY);
+
+    uno::Reference<drawing::XShapes> xGroupLeft(xGroup->getByIndex(1), 
uno::UNO_QUERY);
+    uno::Reference<drawing::XShape> xGroupB(xGroupLeft->getByIndex(1), 
uno::UNO_QUERY);
+    uno::Reference<drawing::XShape> 
xShapeB1(getChildShape(getChildShape(getChildShape(xGroupB, 1), 0), 0), 
uno::UNO_QUERY);
+    uno::Reference<text::XText> xTextB1(xShapeB1, uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("B1"), xTextB1->getString());
+    uno::Reference<drawing::XShape> 
xShapeB2(getChildShape(getChildShape(getChildShape(xGroupB, 3), 0), 0), 
uno::UNO_QUERY);
+    uno::Reference<text::XText> xTextB2(xShapeB2, uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("B2"), xTextB2->getString());
+
+    CPPUNIT_ASSERT_EQUAL(xShapeB1->getPosition().Y, xShapeB2->getPosition().Y);
+    CPPUNIT_ASSERT_GREATEREQUAL(xShapeB1->getPosition().X + 
xShapeB1->getSize().Width, xShapeB2->getPosition().X);
+
+    uno::Reference<drawing::XShapes> xGroupRight(xGroup->getByIndex(2), 
uno::UNO_QUERY);
+    uno::Reference<drawing::XShape> xGroupC(xGroupRight->getByIndex(1), 
uno::UNO_QUERY);
+    uno::Reference<drawing::XShape> 
xShapeC1(getChildShape(getChildShape(getChildShape(xGroupC, 3), 0), 0), 
uno::UNO_QUERY);
+    uno::Reference<text::XText> xTextC1(xShapeC1, uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("C1"), xTextC1->getString());
+    uno::Reference<drawing::XShape> 
xShapeC2(getChildShape(getChildShape(getChildShape(xGroupC, 5), 0), 0), 
uno::UNO_QUERY);
+    uno::Reference<text::XText> xTextC2(xShapeC2, uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("C2"), xTextC2->getString());
+
+    CPPUNIT_ASSERT_EQUAL(xShapeC1->getPosition().X, xShapeC2->getPosition().X);
+    CPPUNIT_ASSERT_GREATEREQUAL(xShapeC1->getPosition().Y + 
xShapeC1->getSize().Height, xShapeC2->getPosition().Y);
+
+    xDocShRef->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdImportTestSmartArt);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/solenv/clang-format/blacklist b/solenv/clang-format/blacklist
index c1cb77b9209f..5f24a5461c4e 100644
--- a/solenv/clang-format/blacklist
+++ b/solenv/clang-format/blacklist
@@ -8944,6 +8944,8 @@ oox/source/drawingml/diagram/diagramfragmenthandler.cxx
 oox/source/drawingml/diagram/diagramfragmenthandler.hxx
 oox/source/drawingml/diagram/diagramlayoutatoms.cxx
 oox/source/drawingml/diagram/diagramlayoutatoms.hxx
+oox/source/drawingml/diagram/layoutatomvisitorbase.cxx
+oox/source/drawingml/diagram/layoutatomvisitorbase.hxx
 oox/source/drawingml/diagram/layoutatomvisitors.cxx
 oox/source/drawingml/diagram/layoutatomvisitors.hxx
 oox/source/drawingml/diagram/layoutnodecontext.cxx
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to