[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.2' - 2 commits - oox/source sd/qa

Grzegorz Araminowicz (via logerrit) logerrit at kemper.freedesktop.org
Wed Jul 10 20:11:52 UTC 2019


 oox/source/drawingml/diagram/diagram.hxx            |   10 ++++
 oox/source/drawingml/diagram/diagramlayoutatoms.cxx |   27 ++++++++++--
 oox/source/drawingml/diagram/diagramlayoutatoms.hxx |   18 ++++++--
 oox/source/drawingml/diagram/layoutatomvisitors.cxx |   38 ++++++++++++++----
 oox/source/drawingml/diagram/layoutatomvisitors.hxx |    6 ++
 oox/source/drawingml/diagram/layoutnodecontext.cxx  |    5 +-
 sd/qa/unit/data/pptx/smartart-recursion.pptx        |binary
 sd/qa/unit/import-tests-smartart.cxx                |   42 ++++++++++++++++++++
 8 files changed, 128 insertions(+), 18 deletions(-)

New commits:
commit 674d58312a3682df6be2cf8680aab4e3d1528789
Author:     Grzegorz Araminowicz <grzegorz.araminowicz at collabora.com>
AuthorDate: Tue Jun 11 08:31:18 2019 +0200
Commit:     Grzegorz Araminowicz <grzegorz.araminowicz at collabora.com>
CommitDate: Wed Jul 10 22:11:24 2019 +0200

    SmartArt: support ForEach references
    
    ForEach 'ref' parameter causes specified ForEach node to be used instead.
    Used to create recursive structures like organisation charts.
    
    Change-Id: Iee61b2e103759355b59beb8d3f33eb3cce47c590
    Reviewed-on: https://gerrit.libreoffice.org/74271
    Tested-by: Jenkins
    Reviewed-by: Grzegorz Araminowicz <grzegorz.araminowicz at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/75340
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>

diff --git a/oox/source/drawingml/diagram/diagram.hxx b/oox/source/drawingml/diagram/diagram.hxx
index a0955b124230..c5b8ec10eaf6 100644
--- a/oox/source/drawingml/diagram/diagram.hxx
+++ b/oox/source/drawingml/diagram/diagram.hxx
@@ -149,6 +149,8 @@ typedef std::vector< Point >        Points;
 class Diagram;
 class LayoutNode;
 typedef std::shared_ptr< LayoutNode > LayoutNodePtr;
+class LayoutAtom;
+typedef std::shared_ptr<LayoutAtom> LayoutAtomPtr;
 
 typedef std::map< OUString, css::uno::Reference<css::xml::dom::XDocument> > DiagramDomMap;
 
@@ -205,6 +207,8 @@ private:
 
 typedef std::shared_ptr< DiagramData > DiagramDataPtr;
 
+typedef std::map<OUString, LayoutAtomPtr> LayoutAtomMap;
+
 class DiagramLayout
 {
 public:
@@ -233,6 +237,8 @@ public:
         { return mpStyleData; }
     const DiagramDataPtr & getStyleData() const
         { return mpStyleData; }
+    LayoutAtomMap & getLayoutAtomMap()
+        { return maLayoutAtomMap; }
 
 private:
     const Diagram& mrDgm;
@@ -248,6 +254,8 @@ private:
     // TODO
     // catLst
     // clrData
+
+    LayoutAtomMap maLayoutAtomMap;
 };
 
 typedef std::shared_ptr< DiagramLayout > DiagramLayoutPtr;
@@ -283,6 +291,8 @@ public:
         { return mpData; }
     void setLayout( const DiagramLayoutPtr & pLayout )
         { mpLayout = pLayout; }
+    const DiagramLayoutPtr& getLayout() const
+        { return mpLayout; }
 
     DiagramQStyleMap& getStyles() { return maStyles; }
     const DiagramQStyleMap& getStyles() const { return maStyles; }
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
index ad4e8962a4a4..63aceb0df920 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
@@ -281,6 +281,20 @@ void ForEachAtom::accept( LayoutAtomVisitor& rVisitor )
     rVisitor.visit(*this);
 }
 
+LayoutAtomPtr ForEachAtom::getRefAtom()
+{
+    if (!msRef.isEmpty())
+    {
+        const LayoutAtomMap& rLayoutAtomMap = getLayoutNode().getDiagram().getLayout()->getLayoutAtomMap();
+        LayoutAtomMap::const_iterator pRefAtom = rLayoutAtomMap.find(msRef);
+        if (pRefAtom != rLayoutAtomMap.end())
+            return pRefAtom->second;
+        else
+            SAL_WARN("oox.drawingml", "ForEach reference \"" << msRef << "\" not found");
+    }
+    return LayoutAtomPtr();
+}
+
 void ChooseAtom::accept( LayoutAtomVisitor& rVisitor )
 {
     rVisitor.visit(*this);
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
index 0291b87cc97a..842acc0757f6 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
@@ -191,10 +191,16 @@ public:
 
     IteratorAttr & iterator()
         { return maIter; }
+    void setRef(const OUString& rsRef)
+        { msRef = rsRef; }
+    const OUString& getRef() const
+        { return msRef; }
     virtual void accept( LayoutAtomVisitor& ) override;
+    LayoutAtomPtr getRefAtom();
 
 private:
     IteratorAttr maIter;
+    OUString msRef;
 };
 
 typedef std::shared_ptr< ForEachAtom > ForEachAtomPtr;
diff --git a/oox/source/drawingml/diagram/layoutatomvisitors.cxx b/oox/source/drawingml/diagram/layoutatomvisitors.cxx
index 5b79dafbc46b..d7c8448666fb 100644
--- a/oox/source/drawingml/diagram/layoutatomvisitors.cxx
+++ b/oox/source/drawingml/diagram/layoutatomvisitors.cxx
@@ -48,6 +48,13 @@ void ShapeCreationVisitor::visit(AlgAtom& rAtom)
 
 void ShapeCreationVisitor::visit(ForEachAtom& rAtom)
 {
+    if (!rAtom.getRef().isEmpty())
+    {
+        if (LayoutAtomPtr pRefAtom = rAtom.getRefAtom())
+            pRefAtom->accept(*this);
+        return;
+    }
+
     if (rAtom.iterator().mnAxis == XML_followSib)
     {
         // If the axis is the follow sibling, then the last atom should not be
@@ -276,6 +283,13 @@ void ShapeLayoutingVisitor::visit(AlgAtom& rAtom)
 
 void ShapeLayoutingVisitor::visit(ForEachAtom& rAtom)
 {
+    if (!rAtom.getRef().isEmpty())
+    {
+        if (LayoutAtomPtr pRefAtom = rAtom.getRefAtom())
+            pRefAtom->accept(*this);
+        return;
+    }
+
     defaultVisit(rAtom);
 }
 
diff --git a/oox/source/drawingml/diagram/layoutnodecontext.cxx b/oox/source/drawingml/diagram/layoutnodecontext.cxx
index 10070063c8ec..0d022ca41504 100644
--- a/oox/source/drawingml/diagram/layoutnodecontext.cxx
+++ b/oox/source/drawingml/diagram/layoutnodecontext.cxx
@@ -142,8 +142,11 @@ public:
     ForEachContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs, const ForEachAtomPtr& pAtom )
         : LayoutNodeContext( rParent, rAttribs, pAtom )
         {
-            rAttribs.getString( XML_ref );
+            pAtom->setRef(rAttribs.getString(XML_ref).get());
             pAtom->iterator().loadFromXAttr( rAttribs.getFastAttributeList() );
+
+            LayoutAtomMap& rLayoutAtomMap = pAtom->getLayoutNode().getDiagram().getLayout()->getLayoutAtomMap();
+            rLayoutAtomMap[pAtom->getName()] = pAtom;
         }
 };
 
diff --git a/sd/qa/unit/data/pptx/smartart-recursion.pptx b/sd/qa/unit/data/pptx/smartart-recursion.pptx
new file mode 100644
index 000000000000..205db6b703de
Binary files /dev/null and b/sd/qa/unit/data/pptx/smartart-recursion.pptx differ
diff --git a/sd/qa/unit/import-tests-smartart.cxx b/sd/qa/unit/import-tests-smartart.cxx
index 930006fd3931..59d09a7d4204 100644
--- a/sd/qa/unit/import-tests-smartart.cxx
+++ b/sd/qa/unit/import-tests-smartart.cxx
@@ -76,6 +76,7 @@ public:
     void testFontSize();
     void testVerticalBlockList();
     void testBulletList();
+    void testRecursion();
 
     CPPUNIT_TEST_SUITE(SdImportTestSmartArt);
 
@@ -114,6 +115,7 @@ public:
     CPPUNIT_TEST(testFontSize);
     CPPUNIT_TEST(testVerticalBlockList);
     CPPUNIT_TEST(testBulletList);
+    CPPUNIT_TEST(testRecursion);
 
     CPPUNIT_TEST_SUITE_END();
 };
@@ -1105,6 +1107,46 @@ void SdImportTestSmartArt::testBulletList()
     xDocShRef->DoClose();
 }
 
+void SdImportTestSmartArt::testRecursion()
+{
+    sd::DrawDocShellRef xDocShRef = loadURL(
+        m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/smartart-recursion.pptx"), PPTX);
+
+    uno::Reference<drawing::XShapes> xGroup(getShapeFromPage(0, 0, xDocShRef), uno::UNO_QUERY);
+    uno::Reference<drawing::XShapes> xGroup1(xGroup->getByIndex(1), uno::UNO_QUERY);
+
+    uno::Reference<drawing::XShapes> xGroupA(xGroup1->getByIndex(0), uno::UNO_QUERY);
+    uno::Reference<text::XText> xTextA(xGroupA->getByIndex(0), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("A"), xTextA->getString());
+
+    uno::Reference<drawing::XShapes> xGroupB(xGroup1->getByIndex(1), uno::UNO_QUERY);
+    // 5 connectors, B1 with children, B2 with children
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(7), xGroupB->getCount());
+
+    uno::Reference<drawing::XShapes> xGroupB1(xGroupB->getByIndex(1), uno::UNO_QUERY);
+
+    uno::Reference<drawing::XShapes> xGroupB1a(xGroupB1->getByIndex(0), uno::UNO_QUERY);
+    uno::Reference<text::XText> xTextB1(xGroupB1a->getByIndex(0), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("B1"), xTextB1->getString());
+
+    uno::Reference<drawing::XShape> xGroupC12(xGroupB1->getByIndex(1), uno::UNO_QUERY);
+    uno::Reference<text::XText> xTextC1(getChildShape(getChildShape(getChildShape(xGroupC12, 0), 0), 0), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("C1"), xTextC1->getString());
+    uno::Reference<text::XText> xTextC2(getChildShape(getChildShape(getChildShape(xGroupC12, 1), 0), 0), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("C2"), xTextC2->getString());
+
+    uno::Reference<drawing::XShapes> xGroupB2(xGroupB->getByIndex(5), uno::UNO_QUERY);
+
+    uno::Reference<drawing::XShapes> xGroupB2a(xGroupB2->getByIndex(0), uno::UNO_QUERY);
+    uno::Reference<text::XText> xTextB2(xGroupB2a->getByIndex(0), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("B2"), xTextB2->getString());
+
+    uno::Reference<drawing::XShape> xGroupC3(xGroupB2->getByIndex(1), uno::UNO_QUERY);
+    uno::Reference<text::XText> xTextC3(getChildShape(getChildShape(getChildShape(xGroupC3, 0), 0), 0), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("C3"), xTextC3->getString());
+
+    xDocShRef->DoClose();
+}
 
 CPPUNIT_TEST_SUITE_REGISTRATION(SdImportTestSmartArt);
 
commit 70f9f5fb2a724373742285ecc1e74393d5226421
Author:     Grzegorz Araminowicz <grzegorz.araminowicz at collabora.com>
AuthorDate: Fri Jun 14 15:12:33 2019 +0200
Commit:     Grzegorz Araminowicz <grzegorz.araminowicz at collabora.com>
CommitDate: Wed Jul 10 22:11:13 2019 +0200

    SmartArt: support multiple levels of shapes in LayoutNodes
    
    it is needed for recurrent ForEach node, so that shapes on different levels
    are divided and can be layouted separately
    
    Change-Id: Iefbc82925078fe2346858748259680fa8ea252d6
    Reviewed-on: https://gerrit.libreoffice.org/74043
    Tested-by: Jenkins
    Reviewed-by: Grzegorz Araminowicz <grzegorz.araminowicz at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/75366
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>

diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
index a4b80548e3dd..ad4e8962a4a4 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
@@ -159,12 +159,16 @@ bool containsDataNodeType(const oox::drawingml::ShapePtr& pShape, sal_Int32 nTyp
  */
 void calculateHierChildOffsetScale(const oox::drawingml::ShapePtr& pShape,
                                    const oox::drawingml::LayoutNode* pParent, sal_Int32& rXOffset,
-                                   double& rWidthScale)
+                                   double& rWidthScale, sal_Int32 nLevel)
 {
     if (!pParent)
         return;
 
-    const std::vector<oox::drawingml::ShapePtr>& rParents = pParent->getNodeShapes();
+    auto pShapes = pParent->getNodeShapes().find(nLevel - 1);
+    if (pShapes == pParent->getNodeShapes().end())
+        return;
+
+    const std::vector<oox::drawingml::ShapePtr>& rParents = pShapes->second;
     for (size_t nParent = 0; nParent < rParents.size(); ++nParent)
     {
         const oox::drawingml::ShapePtr& pParentShape = rParents[nParent];
@@ -499,7 +503,8 @@ void AlgAtom::accept( LayoutAtomVisitor& rVisitor )
 }
 
 void AlgAtom::layoutShape( const ShapePtr& rShape,
-                           const std::vector<Constraint>& rConstraints )
+                           const std::vector<Constraint>& rConstraints,
+                           sal_Int32 nShapeLevel )
 {
     switch(mnType)
     {
@@ -743,7 +748,7 @@ void AlgAtom::layoutShape( const ShapePtr& rShape,
             sal_Int32 nXOffset = 0;
             double fWidthScale = 1.0;
             if (mnType == XML_hierChild)
-                calculateHierChildOffsetScale(rShape, getLayoutNode().getParentLayoutNode(), nXOffset, fWidthScale);
+                calculateHierChildOffsetScale(rShape, getLayoutNode().getParentLayoutNode(), nXOffset, fWidthScale, nShapeLevel);
 
             awt::Size aChildSize = rShape->getSize();
             if (nDir == XML_fromT)
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
index d70878e063aa..0291b87cc97a 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
@@ -161,7 +161,8 @@ public:
     void addParam( sal_Int32 nType, sal_Int32 nVal )
         { maMap[nType]=nVal; }
     void layoutShape( const ShapePtr& rShape,
-                      const std::vector<Constraint>& rConstraints );
+                      const std::vector<Constraint>& rConstraints,
+                      sal_Int32 nShapeLevel );
 
     /// Gives access to <dgm:alg type="..."/>.
     sal_Int32 getType() const { return mnType; }
@@ -239,6 +240,7 @@ class LayoutNode
 {
 public:
     typedef std::map<sal_Int32, OUString> VarMap;
+    typedef std::map<sal_Int32, std::vector<ShapePtr>> ShapeLevelMap;
 
     LayoutNode(const Diagram& rDgm) : LayoutAtom(*this), mrDgm(rDgm), mnChildOrder(0) {}
     const Diagram& getDiagram() const
@@ -256,10 +258,10 @@ public:
         { mpExistingShape = pShape; }
     const ShapePtr& getExistingShape() const
         { return mpExistingShape; }
-    const std::vector<ShapePtr> & getNodeShapes() const
+    const ShapeLevelMap& getNodeShapes() const
         { return mpNodeShapes; }
-    void addNodeShape(const ShapePtr& pShape)
-        { mpNodeShapes.push_back(pShape); }
+    void addNodeShape(const ShapePtr& pShape, sal_Int32 nLevel)
+        { mpNodeShapes[nLevel].push_back(pShape); }
 
     bool setupShape( const ShapePtr& rShape,
                      const dgm::Point* pPresNode ) const;
@@ -276,7 +278,7 @@ private:
     OUString                     msMoveWith;
     OUString                     msStyleLabel;
     ShapePtr                     mpExistingShape;
-    std::vector<ShapePtr>        mpNodeShapes;
+    ShapeLevelMap                mpNodeShapes;
     sal_Int32                    mnChildOrder;
     std::weak_ptr<AlgAtom>       mpAlgAtom;
 };
diff --git a/oox/source/drawingml/diagram/layoutatomvisitors.cxx b/oox/source/drawingml/diagram/layoutatomvisitors.cxx
index 4e1a3689e3e4..5b79dafbc46b 100644
--- a/oox/source/drawingml/diagram/layoutatomvisitors.cxx
+++ b/oox/source/drawingml/diagram/layoutatomvisitors.cxx
@@ -135,7 +135,7 @@ void ShapeCreationVisitor::visit(LayoutNode& rAtom)
             pShape->setInternalName(rAtom.getName());
             if (AlgAtomPtr pAlgAtom = rAtom.getAlgAtom())
                 pShape->setAspectRatio(pAlgAtom->getAspectRatio());
-            rAtom.addNodeShape(pShape);
+            rAtom.addNodeShape(pShape, mnCurrLevel);
         }
     }
     else
@@ -148,9 +148,8 @@ void ShapeCreationVisitor::visit(LayoutNode& rAtom)
         {
             SAL_INFO(
                 "oox.drawingml",
-                "processing shape type "
-                    << (pShape->getCustomShapeProperties()
-                        ->getShapePresetType()));
+                "processing shape type " << (pShape->getCustomShapeProperties()->getShapePresetType())
+                << " level " << mnCurrLevel);
 
             if (rAtom.setupShape(pShape, pNewNode))
             {
@@ -159,7 +158,7 @@ void ShapeCreationVisitor::visit(LayoutNode& rAtom)
                     pShape->setAspectRatio(pAlgAtom->getAspectRatio());
                 pCurrParent->addChild(pShape);
                 pCurrParent = pShape;
-                rAtom.addNodeShape(pShape);
+                rAtom.addNodeShape(pShape, mnCurrLevel);
             }
         }
         else
@@ -174,11 +173,13 @@ void ShapeCreationVisitor::visit(LayoutNode& rAtom)
     // set new parent for children
     ShapePtr pPreviousParent(mpParentShape);
     mpParentShape=pCurrParent;
+    mnCurrLevel++;
 
     // process children
     defaultVisit(rAtom);
 
     // restore parent
+    mnCurrLevel--;
     mpParentShape=pPreviousParent;
     mpCurrentNode = pPreviousNode;
 
@@ -266,8 +267,10 @@ void ShapeLayoutingVisitor::visit(AlgAtom& rAtom)
 {
     if (meLookFor == ALGORITHM)
     {
-        for (const auto& pShape : rAtom.getLayoutNode().getNodeShapes())
-            rAtom.layoutShape(pShape, maConstraints);
+        auto pShapes = rAtom.getLayoutNode().getNodeShapes().find(mnCurrLevel);
+        if (pShapes != rAtom.getLayoutNode().getNodeShapes().end())
+            for (const auto& pShape : pShapes->second)
+                rAtom.layoutShape(pShape, maConstraints, mnCurrLevel);
     }
 }
 
@@ -291,6 +294,10 @@ void ShapeLayoutingVisitor::visit(LayoutNode& rAtom)
     if (meLookFor != LAYOUT_NODE)
         return;
 
+    // stop processing if there is no more shapes on this level
+    if (rAtom.getNodeShapes().empty() || mnCurrLevel > rAtom.getNodeShapes().rbegin()->first)
+        return;
+
     size_t nParentConstraintsNumber = maConstraints.size();
 
     // process alg atoms first, nested layout nodes afterwards
@@ -298,8 +305,11 @@ void ShapeLayoutingVisitor::visit(LayoutNode& rAtom)
     defaultVisit(rAtom);
     meLookFor = ALGORITHM;
     defaultVisit(rAtom);
+
+    mnCurrLevel++;
     meLookFor = LAYOUT_NODE;
     defaultVisit(rAtom);
+    mnCurrLevel--;
 
     // delete added constraints, keep parent constraints
     maConstraints.erase(maConstraints.begin() + nParentConstraintsNumber, maConstraints.end());
diff --git a/oox/source/drawingml/diagram/layoutatomvisitors.hxx b/oox/source/drawingml/diagram/layoutatomvisitors.hxx
index f395f6a68668..4a61a75eb0f5 100644
--- a/oox/source/drawingml/diagram/layoutatomvisitors.hxx
+++ b/oox/source/drawingml/diagram/layoutatomvisitors.hxx
@@ -35,6 +35,7 @@ class ShapeCreationVisitor : public LayoutAtomVisitor
     sal_Int32 mnCurrIdx;
     sal_Int32 mnCurrStep = 0;
     sal_Int32 mnCurrCnt = 0;
+    sal_Int32 mnCurrLevel;
     const dgm::Point* mpCurrentNode;
 
     void defaultVisit(LayoutAtom const & rAtom);
@@ -52,6 +53,7 @@ public:
         mpParentShape(rParentShape),
         mrDgm(rDgm),
         mnCurrIdx(0),
+        mnCurrLevel(0),
         mpCurrentNode(rDgm.getData()->getRootPoint())
     {}
 };
@@ -78,6 +80,7 @@ class ShapeLayoutingVisitor : public LayoutAtomVisitor
 {
     std::vector<Constraint> maConstraints;
     enum {LAYOUT_NODE, CONSTRAINT, ALGORITHM} meLookFor;
+    sal_Int32 mnCurrLevel;
 
     void defaultVisit(LayoutAtom const & rAtom);
     virtual void visit(ConstraintAtom& rAtom) override;
@@ -90,7 +93,8 @@ class ShapeLayoutingVisitor : public LayoutAtomVisitor
 
 public:
     ShapeLayoutingVisitor() :
-        meLookFor(LAYOUT_NODE)
+        meLookFor(LAYOUT_NODE),
+        mnCurrLevel(0)
     {}
 };
 


More information about the Libreoffice-commits mailing list