summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--oox/source/drawingml/diagram/diagram.cxx20
-rw-r--r--oox/source/drawingml/diagram/diagramlayoutatoms.cxx72
-rw-r--r--oox/source/drawingml/diagram/layoutatomvisitors.cxx6
-rw-r--r--sd/qa/unit/data/pptx/smartart-linear-rule.pptxbin0 -> 43353 bytes
-rw-r--r--sd/qa/unit/import-tests-smartart.cxx19
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
new file mode 100644
index 000000000000..f5fbb5c87a54
--- /dev/null
+++ b/sd/qa/unit/data/pptx/smartart-linear-rule.pptx
Binary files differ
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();