diff options
| -rw-r--r-- | oox/source/drawingml/diagram/diagram.cxx | 20 | ||||
| -rw-r--r-- | oox/source/drawingml/diagram/diagramlayoutatoms.cxx | 72 | ||||
| -rw-r--r-- | oox/source/drawingml/diagram/layoutatomvisitors.cxx | 6 | ||||
| -rw-r--r-- | sd/qa/unit/data/pptx/smartart-linear-rule.pptx | bin | 0 -> 43353 bytes | |||
| -rw-r--r-- | sd/qa/unit/import-tests-smartart.cxx | 19 |
5 files changed, 106 insertions, 11 deletions
diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx index 5a4fef99cfcb..8265ae7b3a88 100644 --- a/oox/source/drawingml/diagram/diagram.cxx +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -82,6 +82,25 @@ static void sortChildrenByZOrder(const ShapePtr& pShape) sortChildrenByZOrder(rChild); } +/// Removes empty group shapes, now that their spacing influenced the layout. +static void removeUnneededGroupShapes(const ShapePtr& pShape) +{ + std::vector<ShapePtr>& rChildren = pShape->getChildren(); + + rChildren.erase(std::remove_if(rChildren.begin(), rChildren.end(), + [](const ShapePtr& aChild) { + return aChild->getServiceName() + == "com.sun.star.drawing.GroupShape" + && aChild->getChildren().empty(); + }), + rChildren.end()); + + for (const auto& pChild : rChildren) + { + removeUnneededGroupShapes(pChild); + } +} + void Diagram::addTo( const ShapePtr & pParentShape ) { if (pParentShape->getSize().Width == 0 || pParentShape->getSize().Height == 0) @@ -103,6 +122,7 @@ void Diagram::addTo( const ShapePtr & pParentShape ) mpLayout->getNode()->accept(aLayoutingVisitor); sortChildrenByZOrder(pParentShape); + removeUnneededGroupShapes(pParentShape); } ShapePtr pBackground = std::make_shared<Shape>("com.sun.star.drawing.CustomShape"); diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx index 2aebfc85bcdc..60843571d8b2 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx @@ -19,6 +19,8 @@ #include "diagramlayoutatoms.hxx" +#include <set> + #include "layoutatomvisitorbase.hxx" #include <basegfx/numeric/ftools.hxx> @@ -478,10 +480,21 @@ void ApplyConstraintToLayout(const Constraint& rConstraint, LayoutPropertyMap& r } } -void AlgAtom::layoutShape( const ShapePtr& rShape, - const std::vector<Constraint>& rConstraints, - const std::vector<Rule>& /*rRules*/ ) +void AlgAtom::layoutShape(const ShapePtr& rShape, const std::vector<Constraint>& rConstraints, + const std::vector<Rule>& rRules) { + if (mnType != XML_lin) + { + // TODO Handle spacing from constraints for non-lin algorithms as well. + rShape->getChildren().erase( + std::remove_if(rShape->getChildren().begin(), rShape->getChildren().end(), + [](const ShapePtr& aChild) { + return aChild->getServiceName() == "com.sun.star.drawing.GroupShape" + && aChild->getChildren().empty(); + }), + rShape->getChildren().end()); + } + switch(mnType) { case XML_composite: @@ -928,6 +941,45 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, } // first approximation of children size + std::set<OUString> aChildrenToShrink; + for (const auto& rRule : rRules) + { + // Consider rules: when scaling down, only change children where the rule allows + // doing so. + aChildrenToShrink.insert(rRule.msForName); + } + + if (!aChildrenToShrink.empty()) + { + // Have scaling info from rules: then only count scaled children. + for (auto& aCurrShape : rShape->getChildren()) + { + if (aChildrenToShrink.find(aCurrShape->getInternalName()) + == aChildrenToShrink.end()) + { + if (nCount > 1) + { + --nCount; + } + } + } + + // No manual spacing: spacings are children as well. + aSpaceSize = awt::Size(); + } + else + { + // TODO Handle spacing from constraints without rules as well. + rShape->getChildren().erase( + std::remove_if(rShape->getChildren().begin(), rShape->getChildren().end(), + [](const ShapePtr& aChild) { + return aChild->getServiceName() + == "com.sun.star.drawing.GroupShape" + && aChild->getChildren().empty(); + }), + rShape->getChildren().end()); + nCount = rShape->getChildren().size(); + } awt::Size aChildSize = rShape->getSize(); if (nDir == XML_fromL || nDir == XML_fromR) aChildSize.Width /= nCount; @@ -979,8 +1031,18 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, aSize.Width = oWidth.get(); if (oHeight.has()) aSize.Height = oHeight.get(); - aSize.Width *= fWidthScale; - aSize.Height *= fHeightScale; + if (aChildrenToShrink.empty() + || aChildrenToShrink.find(aCurrShape->getInternalName()) + != aChildrenToShrink.end()) + { + aSize.Width *= fWidthScale; + } + if (aChildrenToShrink.empty() + || aChildrenToShrink.find(aCurrShape->getInternalName()) + != aChildrenToShrink.end()) + { + aSize.Height *= fHeightScale; + } aCurrShape->setSize(aSize); aCurrShape->setChildSize(aSize); diff --git a/oox/source/drawingml/diagram/layoutatomvisitors.cxx b/oox/source/drawingml/diagram/layoutatomvisitors.cxx index 6b064e28b39b..5d31fd21cc71 100644 --- a/oox/source/drawingml/diagram/layoutatomvisitors.cxx +++ b/oox/source/drawingml/diagram/layoutatomvisitors.cxx @@ -123,12 +123,6 @@ void ShapeCreationVisitor::visit(LayoutNode& rAtom) meLookFor = LAYOUT_NODE; defaultVisit(rAtom); - // remove unneeded empty group shapes - pCurrParent->getChildren().erase( - std::remove_if(pCurrParent->getChildren().begin(), pCurrParent->getChildren().end(), - [] (const ShapePtr & aChild) { return aChild->getServiceName() == "com.sun.star.drawing.GroupShape" && aChild->getChildren().empty(); }), - pCurrParent->getChildren().end()); - meLookFor = ALGORITHM; defaultVisit(rAtom); meLookFor = LAYOUT_NODE; diff --git a/sd/qa/unit/data/pptx/smartart-linear-rule.pptx b/sd/qa/unit/data/pptx/smartart-linear-rule.pptx Binary files differnew file mode 100644 index 000000000000..f5fbb5c87a54 --- /dev/null +++ b/sd/qa/unit/data/pptx/smartart-linear-rule.pptx diff --git a/sd/qa/unit/import-tests-smartart.cxx b/sd/qa/unit/import-tests-smartart.cxx index bbbe6880d8a8..cbe1507cd33c 100644 --- a/sd/qa/unit/import-tests-smartart.cxx +++ b/sd/qa/unit/import-tests-smartart.cxx @@ -110,6 +110,7 @@ public: void testTdf131553(); void testFillColorList(); void testTdf134221(); + void testLinearRule(); CPPUNIT_TEST_SUITE(SdImportTestSmartArt); @@ -157,6 +158,7 @@ public: CPPUNIT_TEST(testTdf131553); CPPUNIT_TEST(testFillColorList); CPPUNIT_TEST(testTdf134221); + CPPUNIT_TEST(testLinearRule); CPPUNIT_TEST_SUITE_END(); }; @@ -1525,6 +1527,23 @@ void SdImportTestSmartArt::testTdf134221() xDocShRef->DoClose(); } +void SdImportTestSmartArt::testLinearRule() +{ + sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/smartart-linear-rule.pptx"), PPTX); + + uno::Reference<drawing::XShape> xGroup(getShapeFromPage(0, 0, xDocShRef), uno::UNO_QUERY); + // Last child, then again last child. + uno::Reference<drawing::XShape> xShape = getChildShape(getChildShape(xGroup, 1), 3); + + // Without the accompanying fix in place, this test would have failed with: + // - Expected greater than: 17500 (19867) + // - Actual : 4966 + // i.e. the width of the background arrow was too small. + CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(17500), xShape->getSize().Width); + + xDocShRef->DoClose(); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SdImportTestSmartArt); CPPUNIT_PLUGIN_IMPLEMENT(); |
