From 51b0a654b2c75c7b4e42763603a4e23c25317dc5 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Tue, 19 Jan 2021 16:59:38 +0100 Subject: oox smartart: composite algo: handle right constraint when left+width is given The bugdoc had this constraint: While img has no "r", it has: Which is enough to fix the x position of the text to not overlap with img. (cherry picked from commit 1359e8c566970fcef860f7ba7f54a07d8e6e0513) Change-Id: I80db290bd1695884ffb7b1eabaffa09462e8883d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/109703 Tested-by: Jenkins CollaboraOffice Reviewed-by: Miklos Vajna --- .../drawingml/diagram/diagramlayoutatoms.cxx | 42 +++++++++++++++++++++ .../data/pptx/smartart-composite-infer-right.pptx | Bin 0 -> 23234 bytes sd/qa/unit/import-tests-smartart.cxx | 26 +++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 sd/qa/unit/data/pptx/smartart-composite-infer-right.pptx diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx index 6e9626c2f9fe..410b2c9e677e 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx @@ -820,6 +820,37 @@ sal_Int32 AlgAtom::getVerticalShapesCount(const ShapePtr& rShape) namespace { +/** + * Decides if a certain reference type (e.g. "right") can be inferred from the available properties + * in rMap (e.g. left and width). Returns true if rValue is written to. + */ +bool InferFromLayoutProperty(const LayoutProperty& rMap, sal_Int32 nRefType, sal_Int32& rValue) +{ + switch (nRefType) + { + case XML_r: + { + auto it = rMap.find(XML_l); + if (it == rMap.end()) + { + return false; + } + sal_Int32 nLeft = it->second; + it = rMap.find(XML_w); + if (it == rMap.end()) + { + return false; + } + rValue = nLeft + it->second; + return true; + } + default: + break; + } + + return false; +} + /** * Apply rConstraint to the rProperties shared layout state. * @@ -840,11 +871,22 @@ void ApplyConstraintToLayout(const Constraint& rConstraint, LayoutPropertyMap& r return; const LayoutProperty::const_iterator aRefType = aRef->second.find(rConstraint.mnRefType); + sal_Int32 nInferredValue = 0; if (aRefType != aRef->second.end()) + { + // Reference is found directly. rProperties[rConstraint.msForName][rConstraint.mnType] = aRefType->second * rConstraint.mfFactor; + } + else if (InferFromLayoutProperty(aRef->second, rConstraint.mnRefType, nInferredValue)) + { + // Reference can be inferred. + rProperties[rConstraint.msForName][rConstraint.mnType] + = nInferredValue * rConstraint.mfFactor; + } else { + // Reference not found, assume a fixed value. // Values are never in EMU, while oox::drawingml::Shape position and size are always in // EMU. double fUnitFactor = 0; diff --git a/sd/qa/unit/data/pptx/smartart-composite-infer-right.pptx b/sd/qa/unit/data/pptx/smartart-composite-infer-right.pptx new file mode 100644 index 000000000000..ca417499fa16 Binary files /dev/null and b/sd/qa/unit/data/pptx/smartart-composite-infer-right.pptx differ diff --git a/sd/qa/unit/import-tests-smartart.cxx b/sd/qa/unit/import-tests-smartart.cxx index edb8edaed9f2..35920ae76ac0 100644 --- a/sd/qa/unit/import-tests-smartart.cxx +++ b/sd/qa/unit/import-tests-smartart.cxx @@ -111,6 +111,7 @@ public: void testLinearRuleVert(); void testAutofitSync(); void testSnakeRows(); + void testCompositeInferRight(); CPPUNIT_TEST_SUITE(SdImportTestSmartArt); @@ -161,6 +162,7 @@ public: CPPUNIT_TEST(testLinearRuleVert); CPPUNIT_TEST(testAutofitSync); CPPUNIT_TEST(testSnakeRows); + CPPUNIT_TEST(testCompositeInferRight); CPPUNIT_TEST_SUITE_END(); }; @@ -1637,6 +1639,30 @@ void SdImportTestSmartArt::testSnakeRows() xDocShRef->DoClose(); } +void SdImportTestSmartArt::testCompositeInferRight() +{ + // Load a smartart which contains a composite algorithm. + // One contraint says that the left of the text should be the right of the image. + sd::DrawDocShellRef xDocShRef = loadURL( + m_directories.getURLFromSrc(u"/sd/qa/unit/data/pptx/smartart-composite-infer-right.pptx"), + PPTX); + + uno::Reference xDiagram(getShapeFromPage(0, 0, xDocShRef), uno::UNO_QUERY); + uno::Reference xMiddle = getChildShape(xDiagram, 1); + uno::Reference xImage = getChildShape(xMiddle, 1); + uno::Reference xText = getChildShape(xMiddle, 2); + sal_Int32 nRightOfImage = xImage->getPosition().X + xImage->getSize().Width; + sal_Int32 nLeftOfText = xText->getPosition().X; + + // Without the accompanying fix in place, this test would have failed with: + // - Expected greater than: 7925 + // - Actual : 2430 + // i.e. the text was overlapping with the image. + CPPUNIT_ASSERT_GREATER(nRightOfImage, nLeftOfText); + + xDocShRef->DoClose(); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SdImportTestSmartArt); CPPUNIT_PLUGIN_IMPLEMENT(); -- cgit