diff options
-rw-r--r-- | include/oox/core/xmlfilterbase.hxx | 8 | ||||
-rw-r--r-- | include/oox/drawingml/shape.hxx | 8 | ||||
-rw-r--r-- | oox/source/core/xmlfilterbase.cxx | 8 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/diagram.cxx | 9 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/diagram.hxx | 14 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/diagramlayoutatoms.cxx | 26 | ||||
-rw-r--r-- | oox/source/drawingml/diagram/diagramlayoutatoms.hxx | 12 | ||||
-rw-r--r-- | oox/source/drawingml/shape.cxx | 55 | ||||
-rw-r--r-- | oox/source/ppt/pptshape.cxx | 13 | ||||
-rw-r--r-- | sd/qa/unit/data/pptx/smartart-autofit-sync.pptx | bin | 0 -> 45546 bytes | |||
-rw-r--r-- | sd/qa/unit/import-tests-smartart.cxx | 30 |
11 files changed, 172 insertions, 11 deletions
diff --git a/include/oox/core/xmlfilterbase.hxx b/include/oox/core/xmlfilterbase.hxx index 68bd801eaefd..cb8be7117fdf 100644 --- a/include/oox/core/xmlfilterbase.hxx +++ b/include/oox/core/xmlfilterbase.hxx @@ -65,6 +65,7 @@ namespace sax_fastparser { namespace utl { class MediaDescriptor; } namespace oox { +namespace drawingml { class Shape; } namespace core { class FragmentHandler; @@ -79,6 +80,10 @@ typedef std::vector< TextField > TextFieldStack; struct XmlFilterBaseImpl; +using ShapePairs + = std::map<std::shared_ptr<drawingml::Shape>, css::uno::Reference<css::drawing::XShape>>; +using NamedShapePairs = std::map<OUString, ShapePairs>; + class OOX_DLLPUBLIC XmlFilterBase : public FilterBase { public: @@ -242,6 +247,9 @@ public: /// user about it. void setMissingExtDrawing(); + void setDiagramFontHeights(NamedShapePairs* pDiagramFontHeights); + NamedShapePairs* getDiagramFontHeights(); + void checkDocumentProperties( const css::uno::Reference<css::document::XDocumentProperties>& xDocProps); diff --git a/include/oox/drawingml/shape.hxx b/include/oox/drawingml/shape.hxx index 1895c2f2aad6..5b6fd21ce00d 100644 --- a/include/oox/drawingml/shape.hxx +++ b/include/oox/drawingml/shape.hxx @@ -29,6 +29,8 @@ #include <com/sun/star/beans/PropertyValue.hpp> #include <com/sun/star/uno/Reference.hxx> #include <com/sun/star/uno/Sequence.hxx> + +#include <oox/core/xmlfilterbase.hxx> #include <oox/dllapi.h> #include <oox/drawingml/color.hxx> #include <oox/drawingml/drawingmltypes.hxx> @@ -239,6 +241,8 @@ public: void keepDiagramDrawing(::oox::core::XmlFilterBase& rFilterBase, const OUString& rFragmentPath); + oox::core::NamedShapePairs& getDiagramFontHeights() { return maDiagramFontHeights; } + protected: enum FrameType @@ -272,6 +276,7 @@ protected: const basegfx::B2DHomMatrix& aTransformation ); void keepDiagramCompatibilityInfo(); + void syncDiagramFontHeights(); void convertSmartArtToMetafile( ::oox::core::XmlFilterBase const& rFilterBase ); css::uno::Reference< css::drawing::XShape > @@ -377,6 +382,9 @@ private: /// The shape fill should be set to that of the slide background surface. bool mbUseBgFill = false; + + /// For SmartArt, this contains groups of shapes: automatic font size is the same in each group. + oox::core::NamedShapePairs maDiagramFontHeights; }; } } diff --git a/oox/source/core/xmlfilterbase.cxx b/oox/source/core/xmlfilterbase.cxx index 2cc1daa54b04..fe449dd70909 100644 --- a/oox/source/core/xmlfilterbase.cxx +++ b/oox/source/core/xmlfilterbase.cxx @@ -180,6 +180,7 @@ struct XmlFilterBaseImpl RelationsMap maRelationsMap; TextFieldStack maTextFieldStack; const NamespaceMap& mrNamespaceMap; + NamedShapePairs* mpDiagramFontHeights = nullptr; /// @throws RuntimeException explicit XmlFilterBaseImpl(); @@ -957,6 +958,13 @@ void XmlFilterBase::setMissingExtDrawing() mbMissingExtDrawing = true; } +void XmlFilterBase::setDiagramFontHeights(NamedShapePairs* pDiagramFontHeights) +{ + mxImpl->mpDiagramFontHeights = pDiagramFontHeights; +} + +NamedShapePairs* XmlFilterBase::getDiagramFontHeights() { return mxImpl->mpDiagramFontHeights; } + OUString XmlFilterBase::getNamespaceURL(sal_Int32 nNSID) const { auto itr = mxImpl->mrNamespaceMap.maTransitionalNamespaceMap.find(nNSID); diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx index 509a1f845e25..21dea33204bc 100644 --- a/oox/source/drawingml/diagram/diagram.cxx +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -135,6 +135,11 @@ void Diagram::addTo( const ShapePtr & pParentShape ) aChildren.insert(aChildren.begin(), pBackground); } +Diagram::Diagram(const ShapePtr& pShape) + : mpShape(pShape) +{ +} + uno::Sequence<beans::PropertyValue> Diagram::getDomsAsPropertyValues() const { sal_Int32 length = maMainDomMap.size(); @@ -245,7 +250,7 @@ void loadDiagram( ShapePtr const & pShape, const OUString& rColorStylePath, const oox::core::Relations& rRelations ) { - DiagramPtr pDiagram( new Diagram ); + DiagramPtr pDiagram( new Diagram(pShape) ); DiagramDataPtr pData( new DiagramData() ); pDiagram->setData( pData ); @@ -365,7 +370,7 @@ void loadDiagram(ShapePtr const& pShape, const uno::Reference<xml::dom::XDocument>& colorDom, core::XmlFilterBase& rFilter) { - DiagramPtr pDiagram(new Diagram); + DiagramPtr pDiagram(new Diagram(pShape)); pDiagram->setData(pDiagramData); diff --git a/oox/source/drawingml/diagram/diagram.hxx b/oox/source/drawingml/diagram/diagram.hxx index a674e248961e..5cf562d075fd 100644 --- a/oox/source/drawingml/diagram/diagram.hxx +++ b/oox/source/drawingml/diagram/diagram.hxx @@ -49,7 +49,10 @@ typedef std::map<const dgm::Point*, ShapePtr> PresPointShapeMap; class DiagramLayout { public: - DiagramLayout(const Diagram& rDgm) : mrDgm(rDgm) {} + DiagramLayout(Diagram& rDgm) + : mrDgm(rDgm) + { + } void setDefStyle( const OUString & sDefStyle ) { msDefStyle = sDefStyle; } void setMinVer( const OUString & sMinVer ) @@ -60,8 +63,7 @@ public: { msTitle = sTitle; } void setDesc( const OUString & sDesc ) { msDesc = sDesc; } - const Diagram& getDiagram() const - { return mrDgm; } + Diagram& getDiagram() { return mrDgm; } LayoutNodePtr & getNode() { return mpNode; } const LayoutNodePtr & getNode() const @@ -80,7 +82,7 @@ public: { return maPresPointShapeMap; } private: - const Diagram& mrDgm; + Diagram& mrDgm; OUString msDefStyle; OUString msMinVer; OUString msUniqueId; @@ -128,6 +130,7 @@ typedef std::map<OUString,DiagramColor> DiagramColorMap; class Diagram { public: + explicit Diagram(const ShapePtr& pShape); void setData( const DiagramDataPtr & pData ) { mpData = pData; } const DiagramDataPtr& getData() const @@ -146,7 +149,10 @@ public: void addTo( const ShapePtr & pShape ); css::uno::Sequence<css::beans::PropertyValue> getDomsAsPropertyValues() const; + ShapePtr getShape() { return mpShape; } + private: + ShapePtr mpShape; DiagramDataPtr mpData; DiagramLayoutPtr mpLayout; DiagramQStyleMap maStyles; diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx index 44a66f819e98..6823e45b3043 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx @@ -217,7 +217,7 @@ namespace * Takes the connection list from rLayoutNode, navigates from rFrom on an edge * of type nType, using a direction determined by bSourceToDestination. */ -OUString navigate(const LayoutNode& rLayoutNode, sal_Int32 nType, const OUString& rFrom, +OUString navigate(LayoutNode& rLayoutNode, sal_Int32 nType, const OUString& rFrom, bool bSourceToDestination) { for (const auto& rConnection : rLayoutNode.getDiagram().getData()->getConnections()) @@ -649,6 +649,16 @@ void AlgAtom::layoutShape(const ShapePtr& rShape, const std::vector<Constraint>& nVertMin = std::min(aPos.Y, nVertMin); nVertMax = std::max(aPos.Y + aSize.Height, nVertMax); + + NamedShapePairs& rDiagramFontHeights + = getLayoutNode().getDiagram().getShape()->getDiagramFontHeights(); + auto it = rDiagramFontHeights.find(aCurrShape->getInternalName()); + if (it != rDiagramFontHeights.end()) + { + // Internal name matches: put drawingml::Shape to the relevant group, for + // syncronized font height handling. + it->second.insert({ aCurrShape, {} }); + } } // See if all vertical space is used or we have to center the content. @@ -943,6 +953,20 @@ void AlgAtom::layoutShape(const ShapePtr& rShape, const std::vector<Constraint>& } } + if (rConstraint.mnType == XML_primFontSz && rConstraint.mnFor == XML_des + && rConstraint.mnOperator == XML_equ) + { + NamedShapePairs& rDiagramFontHeights + = getLayoutNode().getDiagram().getShape()->getDiagramFontHeights(); + auto it = rDiagramFontHeights.find(rConstraint.msForName); + if (it == rDiagramFontHeights.end()) + { + // Start tracking all shapes with this internal name: they'll have the same + // font height. + rDiagramFontHeights[rConstraint.msForName] = {}; + } + } + // TODO: get values from differently named constraints as well if (rConstraint.msForName == "sp" || rConstraint.msForName == "space" || rConstraint.msForName == "sibTrans") { diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx index ab152bed0b70..7789007622dc 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx @@ -260,9 +260,13 @@ class LayoutNode public: typedef std::map<sal_Int32, OUString> VarMap; - LayoutNode(const Diagram& rDgm) : LayoutAtom(*this), mrDgm(rDgm), mnChildOrder(0) {} - const Diagram& getDiagram() const - { return mrDgm; } + LayoutNode(Diagram& rDgm) + : LayoutAtom(*this) + , mrDgm(rDgm) + , mnChildOrder(0) + { + } + Diagram& getDiagram() { return mrDgm; } virtual void accept( LayoutAtomVisitor& ) override; VarMap & variables() { return mVariables; } @@ -289,7 +293,7 @@ public: const LayoutNode* getParentLayoutNode() const; private: - const Diagram& mrDgm; + Diagram& mrDgm; VarMap mVariables; OUString msMoveWith; OUString msStyleLabel; diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx index 2e100a41c309..84e59293b335 100644 --- a/oox/source/drawingml/shape.cxx +++ b/oox/source/drawingml/shape.cxx @@ -190,6 +190,7 @@ Shape::Shape( const ShapePtr& pSourceShape ) , mnDataNodeType(pSourceShape->mnDataNodeType) , mfAspectRatio(pSourceShape->mfAspectRatio) , mbUseBgFill(pSourceShape->mbUseBgFill) +, maDiagramFontHeights(pSourceShape->maDiagramFontHeights) {} Shape::~Shape() @@ -300,6 +301,22 @@ void Shape::addShape( if( !SvtFilterOptions::Get().IsSmartArt2Shape() ) convertSmartArtToMetafile( rFilterBase ); } + + NamedShapePairs* pNamedShapePairs = rFilterBase.getDiagramFontHeights(); + if (xShape.is() && pNamedShapePairs) + { + auto itPairs = pNamedShapePairs->find(getInternalName()); + if (itPairs != pNamedShapePairs->end()) + { + auto it = itPairs->second.find(shared_from_this()); + if (it != itPairs->second.end()) + { + // Our drawingml::Shape is in the list of an internal name, remember the now + // inserted XShape. + it->second = xShape; + } + } + } } } catch( const Exception& ) @@ -1528,6 +1545,44 @@ void Shape::keepDiagramCompatibilityInfo() } } +void Shape::syncDiagramFontHeights() +{ + // Each name represents a group of shapes, for which the font height should have the same + // scaling. + for (const auto& rNameAndPairs : maDiagramFontHeights) + { + // Find out the minimum scale within this group. + const ShapePairs& rShapePairs = rNameAndPairs.second; + sal_Int16 nMinScale = 100; + for (const auto& rShapePair : rShapePairs) + { + uno::Reference<beans::XPropertySet> xPropertySet(rShapePair.second, uno::UNO_QUERY); + if (xPropertySet.is()) + { + sal_Int16 nTextFitToSizeScale = 0; + xPropertySet->getPropertyValue("TextFitToSizeScale") >>= nTextFitToSizeScale; + if (nTextFitToSizeScale > 0 && nTextFitToSizeScale < nMinScale) + { + nMinScale = nTextFitToSizeScale; + } + } + } + + // Set that minimum scale for all members of the group. + if (nMinScale < 100) + { + for (const auto& rShapePair : rShapePairs) + { + uno::Reference<beans::XPropertySet> xPropertySet(rShapePair.second, uno::UNO_QUERY); + if (xPropertySet.is()) + { + xPropertySet->setPropertyValue("TextFitToSizeScale", uno::makeAny(nMinScale)); + } + } + } + } +} + void Shape::convertSmartArtToMetafile(XmlFilterBase const & rFilterBase) { try diff --git a/oox/source/ppt/pptshape.cxx b/oox/source/ppt/pptshape.cxx index 88277219d0b0..71b94c727132 100644 --- a/oox/source/ppt/pptshape.cxx +++ b/oox/source/ppt/pptshape.cxx @@ -411,10 +411,23 @@ void PPTShape::addShape( // if this is a group shape, we have to add also each child shape Reference<XShapes> xShapes(xShape, UNO_QUERY); if (xShapes.is()) + { + if (meFrameType == FRAMETYPE_DIAGRAM) + { + rFilterBase.setDiagramFontHeights(&getDiagramFontHeights()); + } addChildren( rFilterBase, *this, pTheme, xShapes, pShapeMap, aTransformation ); + if (meFrameType == FRAMETYPE_DIAGRAM) + { + rFilterBase.setDiagramFontHeights(nullptr); + } + } if (meFrameType == FRAMETYPE_DIAGRAM) + { keepDiagramCompatibilityInfo(); + syncDiagramFontHeights(); + } } } catch (const Exception&) diff --git a/sd/qa/unit/data/pptx/smartart-autofit-sync.pptx b/sd/qa/unit/data/pptx/smartart-autofit-sync.pptx Binary files differnew file mode 100644 index 000000000000..f682c143f584 --- /dev/null +++ b/sd/qa/unit/data/pptx/smartart-autofit-sync.pptx diff --git a/sd/qa/unit/import-tests-smartart.cxx b/sd/qa/unit/import-tests-smartart.cxx index 110b7d2c81ea..0d41e3094052 100644 --- a/sd/qa/unit/import-tests-smartart.cxx +++ b/sd/qa/unit/import-tests-smartart.cxx @@ -107,6 +107,7 @@ public: void testOrgChart2(); void testFillColorList(); void testLinearRule(); + void testAutofitSync(); CPPUNIT_TEST_SUITE(SdImportTestSmartArt); @@ -153,6 +154,7 @@ public: CPPUNIT_TEST(testOrgChart2); CPPUNIT_TEST(testFillColorList); CPPUNIT_TEST(testLinearRule); + CPPUNIT_TEST(testAutofitSync); CPPUNIT_TEST_SUITE_END(); }; @@ -1530,6 +1532,34 @@ void SdImportTestSmartArt::testLinearRule() xDocShRef->DoClose(); } +void SdImportTestSmartArt::testAutofitSync() +{ + sd::DrawDocShellRef xDocShRef = loadURL( + m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/smartart-autofit-sync.pptx"), PPTX); + + uno::Reference<drawing::XShape> xDiagram(getShapeFromPage(0, 0, xDocShRef), uno::UNO_QUERY); + uno::Reference<drawing::XShape> xMiddle = getChildShape(xDiagram, 2); + uno::Reference<beans::XPropertySet> xFirstInner(getChildShape(getChildShape(xMiddle, 0), 0), + uno::UNO_QUERY); + sal_Int16 nFirstScale = 0; + CPPUNIT_ASSERT(xFirstInner->getPropertyValue("TextFitToSizeScale") >>= nFirstScale); + CPPUNIT_ASSERT_GREATER(static_cast<sal_Int16>(0), nFirstScale); + uno::Reference<beans::XPropertySet> xSecondInner(getChildShape(getChildShape(xMiddle, 2), 0), + uno::UNO_QUERY); + sal_Int16 nSecondScale = 0; + CPPUNIT_ASSERT(xSecondInner->getPropertyValue("TextFitToSizeScale") >>= nSecondScale); + CPPUNIT_ASSERT_GREATER(static_cast<sal_Int16>(0), nSecondScale); + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 56 + // - Actual : 100 + // i.e. the left shape had no scale-down and the right shape was scaled down, even if it was + // requested that their scaling matches. + CPPUNIT_ASSERT_EQUAL(nSecondScale, nFirstScale); + + xDocShRef->DoClose(); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SdImportTestSmartArt); CPPUNIT_PLUGIN_IMPLEMENT(); |