diff options
Diffstat (limited to 'oox/source/drawingml/diagram/diagramlayoutatoms.cxx')
-rw-r--r-- | oox/source/drawingml/diagram/diagramlayoutatoms.cxx | 119 |
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); |