include/oox/shape/ShapeContextHandler.hxx                                   |  
  2 
 oox/source/shape/ShapeContextHandler.cxx                                    |  
  6 +
 writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx                      |  
 52 ++++++++++
 writerfilter/qa/cppunittests/dmapper/data/tdf149840_SmartArtBackground.docx 
|binary
 writerfilter/source/dmapper/GraphicHelpers.cxx                              |  
 47 +++++++++
 writerfilter/source/dmapper/GraphicHelpers.hxx                              |  
 14 ++
 writerfilter/source/ooxml/OOXMLFastContextHandler.cxx                       |  
 38 +++++++
 7 files changed, 158 insertions(+), 1 deletion(-)

New commits:
commit e4515c1305e4b7bf6e7f105636e9cf6eb50b382d
Author:     Regina Henschel <[email protected]>
AuthorDate: Tue Oct 11 14:46:37 2022 +0200
Commit:     Miklos Vajna <[email protected]>
CommitDate: Thu Oct 13 08:56:22 2022 +0200

    tdf#149840 Use actual outer size for SmartArt in Writer
    
    SmartArt import needs the outer size of the diagram for to define a
    background shape in the correct size and calculate the size of the
    diagram shapes relative to the outer size. The patch passes the values
    read from wp:extent in writerfilter to DiagramGraphicDataContext in oox.
    
    Change-Id: Ib39227bc645ac353336bab2c558d041974188f6f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141223
    Tested-by: Jenkins
    Reviewed-by: Regina Henschel <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/include/oox/shape/ShapeContextHandler.hxx 
b/include/oox/shape/ShapeContextHandler.hxx
index 1b024c6013e1..239ff8ec63b8 100644
--- a/include/oox/shape/ShapeContextHandler.hxx
+++ b/include/oox/shape/ShapeContextHandler.hxx
@@ -95,6 +95,7 @@ public:
     void pushStartToken( sal_Int32 _starttoken );
 
     void setPosition(const css::awt::Point& rPosition);
+    void setSize(const css::awt::Size& rSize);
 
     const bool& getFullWPGSupport() { return m_bFullWPGSUpport; }
     void setFullWPGSupport(bool bUse) { m_bFullWPGSUpport = bUse; }
@@ -118,6 +119,7 @@ private:
     std::stack<sal_uInt32> mnStartTokenStack;
 
     css::awt::Point maPosition;
+    css::awt::Size maSize;  // from cx and cy, in EMU
     bool m_bFullWPGSUpport; // Is this DrawingML shape supposed to be 
processed as WPG?
 
     drawingml::ShapePtr mpShape;
diff --git a/oox/source/shape/ShapeContextHandler.cxx 
b/oox/source/shape/ShapeContextHandler.cxx
index 2e4018e4703c..54a455452365 100644
--- a/oox/source/shape/ShapeContextHandler.cxx
+++ b/oox/source/shape/ShapeContextHandler.cxx
@@ -215,6 +215,7 @@ ShapeContextHandler::getDiagramShapeContext()
     {
         auto pFragmentHandler = 
std::make_shared<ShapeFragmentHandler>(*mxShapeFilterBase, 
msRelationFragmentPath);
         mpShape = std::make_shared<Shape>();
+        mpShape->setSize(maSize);
         mxDiagramShapeContext.set(new 
DiagramGraphicDataContext(*pFragmentHandler, mpShape));
     }
 
@@ -564,6 +565,11 @@ void ShapeContextHandler::setPosition(const awt::Point& 
rPosition)
     maPosition = rPosition;
 }
 
+void ShapeContextHandler::setSize(const awt::Size& rSize)
+{
+    maSize = rSize;
+}
+
 void ShapeContextHandler::setDocumentProperties(const 
uno::Reference<document::XDocumentProperties>& xDocProps)
 {
     mxDocumentProperties = xDocProps;
diff --git a/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx 
b/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx
index a20c8490501b..6d77ece16d9d 100644
--- a/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx
+++ b/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx
@@ -23,6 +23,7 @@
 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
 
 #include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <officecfg/Office/Common.hxx>
 
 using namespace ::com::sun::star;
 
@@ -406,6 +407,57 @@ CPPUNIT_TEST_FIXTURE(Test, testLayoutInCellOfHraphics)
     CPPUNIT_ASSERT(xShape->getPropertyValue("IsFollowingTextFlow") >>= 
bFollowingTextFlow);
     CPPUNIT_ASSERT(bFollowingTextFlow);
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testTdf149840SmartArtBackground)
+{
+    // Make sure SmartArt is loaded as group shape
+    bool bUseGroup = 
officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::get();
+    if (!bUseGroup)
+    {
+        std::shared_ptr<comphelper::ConfigurationChanges> pChange(
+            comphelper::ConfigurationChanges::create());
+        
officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::set(true,
 pChange);
+        pChange->commit();
+    }
+
+    OUString aURL
+        = m_directories.getURLFromSrc(DATA_DIRECTORY) + 
"tdf149840_SmartArtBackground.docx";
+    getComponent() = loadFromDesktop(aURL);
+    uno::Reference<drawing::XDrawPageSupplier> 
xDrawPageSupplier(getComponent(), uno::UNO_QUERY);
+    uno::Reference<drawing::XDrawPage> xDrawPage = 
xDrawPageSupplier->getDrawPage();
+    uno::Reference<container::XIndexAccess> xGroup(xDrawPage->getByIndex(0), 
uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), xGroup->getCount());
+
+    // The first shape in the group, which represents the SmartArt, 
corresponds to the background of
+    // the diagram. Without fix in place it has widht and height zero, which 
does not only result in
+    // not visible background but in wrong sizes of the diagram shapes too.
+    uno::Reference<drawing::XShape> xBackgroundShape(xGroup->getByIndex(0), 
uno::UNO_QUERY);
+    awt::Size aBackgroundSize = xBackgroundShape->getSize();
+    // Toleranzes are for rounding inaccuracies.
+    // The test would have failed with Expected: 9560x5036, Actual: 2x2
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<sal_Int32>(9560), 
aBackgroundSize.Width, 1);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<sal_Int32>(5036), 
aBackgroundSize.Height, 1);
+
+    uno::Reference<drawing::XShape> xShapeOne(xGroup->getByIndex(1), 
uno::UNO_QUERY);
+    awt::Size aShapeOneSize = xShapeOne->getSize();
+    // The test would have failed with Expected: 3282x3709, Actual: 3972x3709
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<sal_Int32>(3282), 
aShapeOneSize.Width, 1);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<sal_Int32>(3709), 
aShapeOneSize.Height, 1);
+
+    uno::Reference<drawing::XShape> xShapeTwo(xGroup->getByIndex(2), 
uno::UNO_QUERY);
+    awt::Size aShapeTwoSize = xShapeTwo->getSize();
+    // The test would have failed with Expected: 2404x5226, Actual: 2910x5226
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<sal_Int32>(2404), 
aShapeTwoSize.Width, 1);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<sal_Int32>(5226), 
aShapeTwoSize.Height, 1);
+
+    if (!bUseGroup)
+    {
+        std::shared_ptr<comphelper::ConfigurationChanges> pChange(
+            comphelper::ConfigurationChanges::create());
+        
officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::set(false,
 pChange);
+        pChange->commit();
+    }
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git 
a/writerfilter/qa/cppunittests/dmapper/data/tdf149840_SmartArtBackground.docx 
b/writerfilter/qa/cppunittests/dmapper/data/tdf149840_SmartArtBackground.docx
new file mode 100644
index 000000000000..318cef8f3c4b
Binary files /dev/null and 
b/writerfilter/qa/cppunittests/dmapper/data/tdf149840_SmartArtBackground.docx 
differ
diff --git a/writerfilter/source/dmapper/GraphicHelpers.cxx 
b/writerfilter/source/dmapper/GraphicHelpers.cxx
index 2c1a054b5c58..44949e28e754 100644
--- a/writerfilter/source/dmapper/GraphicHelpers.cxx
+++ b/writerfilter/source/dmapper/GraphicHelpers.cxx
@@ -324,6 +324,53 @@ sal_Int32 GraphicZOrderHelper::findZOrder( sal_Int32 
relativeHeight, bool bOldSt
     return 0; // this should not(?) happen
 }
 
+ExtentHandler::ExtentHandler()
+{
+}
+
+ExtentHandler::~ExtentHandler()
+{
+}
+
+void ExtentHandler::attribute(Id nName, Value & rValue)
+{
+    sal_Int32 nIntValue = rValue.getInt();
+    switch (nName)
+    {
+        case NS_ooxml::LN_CT_PositiveSize2D_cx:
+        {
+            m_Extent.Width = nIntValue;
+        }
+        break;
+        case NS_ooxml::LN_CT_PositiveSize2D_cy:
+        {
+            m_Extent.Height = nIntValue;
+        }
+        break;
+        default:
+        break;
+    }
+}
+
+void ExtentHandler::sprm(Sprm & rSprm)
+{
+    sal_uInt32 nSprmId = rSprm.getId();
+    switch(nSprmId)
+    {
+        case NS_ooxml::LN_CT_Inline_extent:
+        case NS_ooxml::LN_CT_Anchor_extent:
+        {
+            writerfilter::Reference<Properties>::Pointer_t pProperties = 
rSprm.getProps();
+            if( pProperties )
+            {
+                pProperties->resolve(*this);
+            }
+        }
+        break;
+        default:
+        break;
+    }
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/dmapper/GraphicHelpers.hxx 
b/writerfilter/source/dmapper/GraphicHelpers.hxx
index 1e7e7a5b3b5b..21eb65f88402 100644
--- a/writerfilter/source/dmapper/GraphicHelpers.hxx
+++ b/writerfilter/source/dmapper/GraphicHelpers.hxx
@@ -63,6 +63,20 @@ private:
     sal_Int32 m_nType;
     sal_Int32 m_nSide;
 };
+
+class ExtentHandler : public Properties
+{
+    css::awt::Size m_Extent; // width and height in EMU
+
+public:
+    typedef ::tools::SvRef<ExtentHandler> Pointer_t;
+    explicit ExtentHandler();
+    virtual ~ExtentHandler() override;
+
+    virtual void attribute(Id nName, Value& rValue) override;
+    virtual void sprm(Sprm& rSprm) override;
+    css::awt::Size getExtent() const { return m_Extent; }
+};
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx 
b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
index f91fbf0d9b2f..16169b318971 100644
--- a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
+++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
@@ -39,6 +39,8 @@
 #include <dmapper/PropertyIds.hxx>
 #include <comphelper/propertysequence.hxx>
 #include <comphelper/sequenceashashmap.hxx>
+#include "OOXMLPropertySet.hxx"
+#include <dmapper/GraphicHelpers.hxx>
 
 const sal_Unicode uCR = 0xd;
 const sal_Unicode uFtnEdnRef = 0x2;
@@ -231,7 +233,6 @@ void OOXMLFastContextHandler::lcl_startFastElement
         inPositionV = true;
     else if( Element == (NMSP_dmlWordDr|XML_positionH) )
         inPositionV = false;
-
 }
 
 void OOXMLFastContextHandler::lcl_endFastElement
@@ -1684,6 +1685,41 @@ void OOXMLFastContextHandlerShape::lcl_startFastElement
 
     if (mrShapeContext.is())
     {
+        if (Element == DGM_TOKEN(relIds))
+        {
+            // It is a SmartArt. Make size available for generated group.
+            // Search for PropertySet in parents
+            OOXMLFastContextHandler* pHandler = getParent();
+            while (pHandler && pHandler->getId() != NS_ooxml::LN_anchor_anchor
+                   && pHandler->getId() != NS_ooxml::LN_inline_inline)
+            {
+                pHandler = pHandler->getParent();
+            }
+            // Search for extent
+            if (pHandler)
+            {
+                if (const OOXMLPropertySet::Pointer_t pPropSet = 
pHandler->getPropertySet())
+                {
+                    auto aIt = pPropSet->begin();
+                    auto aItEnd = pPropSet->end();
+                    while (aIt != aItEnd && (*aIt)->getId() != 
NS_ooxml::LN_CT_Inline_extent
+                           && (*aIt)->getId() != NS_ooxml::LN_CT_Anchor_extent)
+                    {
+                        ++aIt;
+                    }
+                    if (aIt != aItEnd)
+                    {
+                        writerfilter::Reference<Properties>::Pointer_t 
pProperties = (*aIt)->getProps();
+                        if (pProperties)
+                        {
+                            writerfilter::dmapper::ExtentHandler::Pointer_t 
pExtentHandler(new writerfilter::dmapper::ExtentHandler());
+                            pProperties->resolve(*pExtentHandler);
+                            
mrShapeContext->setSize(pExtentHandler->getExtent());
+                        }
+                    }
+                }
+            }
+        }
         mrShapeContext->startFastElement(Element, Attribs);
     }
 }

Reply via email to