diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2019-02-27 17:04:02 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2019-02-27 20:24:54 +0100 |
commit | 279c7f83a57c4d3991930ee80e9d9c287c21270a (patch) | |
tree | 8f03db9ed59c3f09750a2bcb4247fbf0d2d46b68 | |
parent | b436b039b9b8eb0d289a2d7648d97f4a6b91df35 (diff) |
oox smartart, picture strip: fix lack of margin in text shapes
Shape text has two kind of spacing inside the shape's bounding box: the
shape-level margin and the paragraph-level one. Only the second was
handled in the tx algorithm so far, add support for the first.
The margins taken from constraints were way large by default: the only
explanation I found for that is that SmartArt layout sometimes
calculates in MMs, sometimes in Points, and the ratio between the two is
exactly the Impress / PowerPoint margin. So assume that indeed that unit
difference is the reason for the smaller in-PowerPoint margin values and
do the same on our side.
Change-Id: I6f1e54301e2e9b33a7e721be34244d968cccf42d
Reviewed-on: https://gerrit.libreoffice.org/68453
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
-rw-r--r-- | include/oox/drawingml/drawingmltypes.hxx | 7 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/diagramlayoutatoms.cxx | 58 | ||||
-rw-r--r-- | sd/qa/unit/import-tests-smartart.cxx | 15 |
3 files changed, 77 insertions, 3 deletions
diff --git a/include/oox/drawingml/drawingmltypes.hxx b/include/oox/drawingml/drawingmltypes.hxx index c4f05fcdd84e..2abe05767d6a 100644 --- a/include/oox/drawingml/drawingmltypes.hxx +++ b/include/oox/drawingml/drawingmltypes.hxx @@ -190,6 +190,13 @@ inline float convertEmuToPoints( sal_Int64 nValue ) return static_cast<float>(nValue) / EMU_PER_PT; } +/** Converts the passed double value from points to mm. */ +inline double convertPointToMms(double fValue) +{ + constexpr double fFactor = static_cast<double>(EMU_PER_PT) / (EMU_PER_HMM * 100); + return fValue * fFactor; +} + /** A structure for a point with 64-bit integer components. */ struct EmuPoint { diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx index 6893f04d63f7..7dc6e7622cb0 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx @@ -66,6 +66,24 @@ bool isFontUnit(sal_Int32 nUnit) return nUnit == oox::XML_primFontSz || nUnit == oox::XML_secFontSz; } +/// Determines which UNO property should be set for a given constraint type. +sal_Int32 getPropertyFromConstraint(sal_Int32 nConstraint) +{ + switch (nConstraint) + { + case oox::XML_lMarg: + return oox::PROP_TextLeftDistance; + case oox::XML_rMarg: + return oox::PROP_TextRightDistance; + case oox::XML_tMarg: + return oox::PROP_TextUpperDistance; + case oox::XML_bMarg: + return oox::PROP_TextLowerDistance; + } + + return 0; +} + /// Determines the connector shape type from a linear alg. sal_Int32 getConnectorType(const oox::drawingml::LayoutNode* pNode) { @@ -446,9 +464,20 @@ void ConstraintAtom::accept( LayoutAtomVisitor& rVisitor ) void ConstraintAtom::parseConstraint(std::vector<Constraint>& rConstraints, bool bRequireForName) const { - // The snake algorithm do want a space constraint even without a name. - if (bRequireForName && maConstraint.mnType == XML_sp) - bRequireForName = false; + // Whitelist for cases where empty forName is handled. + if (bRequireForName) + { + switch (maConstraint.mnType) + { + case XML_sp: + case XML_lMarg: + case XML_rMarg: + case XML_tMarg: + case XML_bMarg: + bRequireForName = false; + break; + } + } if (bRequireForName && maConstraint.msForName.isEmpty()) return; @@ -1065,6 +1094,29 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, case XML_tx: { // adjust text alignment + + // Parse constraints, only self margins as a start. + for (const auto& rConstr : rConstraints) + { + if (rConstr.mnRefType == XML_w) + { + if (!rConstr.msForName.isEmpty()) + continue; + + sal_Int32 nProperty = getPropertyFromConstraint(rConstr.mnType); + if (!nProperty) + continue; + + // PowerPoint takes size as points, but gives margin as MMs. + double fFactor = convertPointToMms(rConstr.mfFactor); + + // DrawingML works in EMUs, UNO API works in MM100s. + sal_Int32 nValue = rShape->getSize().Width * fFactor / EMU_PER_HMM; + + rShape->getShapeProperties().setProperty(nProperty, nValue); + } + } + // TODO: adjust text size to fit shape TextBodyPtr pTextBody = rShape->getTextBody(); if (!pTextBody || diff --git a/sd/qa/unit/import-tests-smartart.cxx b/sd/qa/unit/import-tests-smartart.cxx index 3d30f576cce0..3a98496735ef 100644 --- a/sd/qa/unit/import-tests-smartart.cxx +++ b/sd/qa/unit/import-tests-smartart.cxx @@ -15,6 +15,7 @@ #include <com/sun/star/text/XText.hpp> #include <comphelper/sequenceashashmap.hxx> +#include <oox/drawingml/drawingmltypes.hxx> using namespace ::com::sun::star; @@ -965,6 +966,20 @@ void SdImportTestSmartArt::testPictureStrip() CPPUNIT_ASSERT_GREATER(xTitle->getPosition().Y + xTitle->getSize().Height, xGroup->getPosition().Y); + // Make sure that left margin is 60% of width (if you count width in points and margin in mms). + uno::Reference<beans::XPropertySet> xFirstText(getChildShape(getChildShape(xGroup, 0), 0), + uno::UNO_QUERY); + CPPUNIT_ASSERT(xFirstText.is()); + sal_Int32 nTextLeftDistance = 0; + xFirstText->getPropertyValue("TextLeftDistance") >>= nTextLeftDistance; + uno::Reference<drawing::XShape> xFirstTextShape(xFirstText, uno::UNO_QUERY); + CPPUNIT_ASSERT(xFirstTextShape.is()); + sal_Int32 nWidth = xFirstTextShape->getSize().Width; + double fFactor = oox::drawingml::convertPointToMms(0.6); + // Without the accompanying fix in place, this test would have failed with 'Expected: 3440, + // Actual : 263', i.e. the left margin was too small. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(nWidth * fFactor), nTextLeftDistance); + xDocShRef->DoClose(); } |