summaryrefslogtreecommitdiff
path: root/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'oox/source/drawingml/diagram/diagramlayoutatoms.cxx')
-rw-r--r--oox/source/drawingml/diagram/diagramlayoutatoms.cxx119
1 files changed, 99 insertions, 20 deletions
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
index 0832bb1bfe7b..33f858386999 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
@@ -430,6 +430,42 @@ sal_Int32 AlgAtom::getVerticalShapesCount(const ShapePtr& rShape)
return nCount;
}
+namespace
+{
+/**
+ * Apply rConstraint to the rProperties shared layout state.
+ *
+ * Note that the order in which constraints are applied matters, given that constraints can refer to
+ * each other, and in case A depends on B and A is applied before B, the effect of A won't be
+ * updated when B is applied.
+ */
+void ApplyConstraintToLayout(const Constraint& rConstraint, LayoutPropertyMap& rProperties)
+{
+ const LayoutPropertyMap::const_iterator aRef = rProperties.find(rConstraint.msRefForName);
+ if (aRef != rProperties.end())
+ {
+ const LayoutProperty::const_iterator aRefType = aRef->second.find(rConstraint.mnRefType);
+ if (aRefType != aRef->second.end())
+ rProperties[rConstraint.msForName][rConstraint.mnType]
+ = aRefType->second * rConstraint.mfFactor;
+ else
+ {
+ // Values are never in EMU, while oox::drawingml::Shape position and size are always in
+ // EMU.
+ double fUnitFactor = 0;
+ if (isFontUnit(rConstraint.mnRefType))
+ // Points -> EMU.
+ fUnitFactor = EMU_PER_PT;
+ else
+ // Millimeters -> EMU.
+ fUnitFactor = EMU_PER_HMM * 100;
+ rProperties[rConstraint.msForName][rConstraint.mnType]
+ = rConstraint.mfValue * fUnitFactor;
+ }
+ }
+}
+}
+
void AlgAtom::layoutShape( const ShapePtr& rShape,
const std::vector<Constraint>& rConstraints )
{
@@ -467,31 +503,74 @@ void AlgAtom::layoutShape( const ShapePtr& rShape,
for (const auto & rConstr : rConstraints)
{
- const LayoutPropertyMap::const_iterator aRef = aProperties.find(rConstr.msRefForName);
- if (aRef != aProperties.end())
+ // Apply direct constraints for all layout nodes.
+ ApplyConstraintToLayout(rConstr, aProperties);
+ }
+
+ for (auto& aCurrShape : rShape->getChildren())
+ {
+ // Apply constraints from the current layout node for this child shape.
+ // Previous child shapes may have changed aProperties.
+ for (const auto& rConstr : rConstraints)
{
- const LayoutProperty::const_iterator aRefType = aRef->second.find(rConstr.mnRefType);
- if (aRefType != aRef->second.end())
- aProperties[rConstr.msForName][rConstr.mnType] = aRefType->second * rConstr.mfFactor;
- else
+ if (rConstr.msForName != aCurrShape->getInternalName())
{
- // Values are never in EMU, while oox::drawingml::Shape
- // position and size are always in EMU.
- double fUnitFactor = 0;
- if (isFontUnit(rConstr.mnRefType))
- // Points -> EMU.
- fUnitFactor = EMU_PER_PT;
- else
- // Millimeters -> EMU.
- fUnitFactor = EMU_PER_HMM * 100;
- aProperties[rConstr.msForName][rConstr.mnType]
- = rConstr.mfValue * fUnitFactor;
+ continue;
+ }
+
+ ApplyConstraintToLayout(rConstr, aProperties);
+ }
+
+ // Apply constraints from the child layout node for this child shape.
+ // This builds on top of the own parent state + the state of previous shapes in the
+ // same composite algorithm.
+ const LayoutNode& rLayoutNode = getLayoutNode();
+ for (const auto& pDirectChild : rLayoutNode.getChildren())
+ {
+ auto pLayoutNode = dynamic_cast<LayoutNode*>(pDirectChild.get());
+ if (!pLayoutNode)
+ {
+ continue;
+ }
+
+ if (pLayoutNode->getName() != aCurrShape->getInternalName())
+ {
+ continue;
+ }
+
+ for (const auto& pChild : pLayoutNode->getChildren())
+ {
+ auto pConstraintAtom = dynamic_cast<ConstraintAtom*>(pChild.get());
+ if (!pConstraintAtom)
+ {
+ continue;
+ }
+
+ const Constraint& rConstraint = pConstraintAtom->getConstraint();
+ if (!rConstraint.msForName.isEmpty())
+ {
+ continue;
+ }
+
+ if (!rConstraint.msRefForName.isEmpty())
+ {
+ continue;
+ }
+
+ // Either an absolute value or a factor of a property.
+ if (rConstraint.mfValue == 0.0 && rConstraint.mnRefType == XML_none)
+ {
+ continue;
+ }
+
+ Constraint aConstraint(rConstraint);
+ aConstraint.msForName = pLayoutNode->getName();
+ aConstraint.msRefForName = pLayoutNode->getName();
+
+ ApplyConstraintToLayout(aConstraint, aProperties);
}
}
- }
- for (auto & aCurrShape : rShape->getChildren())
- {
awt::Size aSize = rShape->getSize();
awt::Point aPos(0, 0);