summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRegina Henschel <rb.henschel@t-online.de>2022-10-11 14:46:37 +0200
committerMiklos Vajna <vmiklos@collabora.com>2022-10-13 08:56:22 +0200
commite4515c1305e4b7bf6e7f105636e9cf6eb50b382d (patch)
treeecf403a925df14f32fef926a12f051e11a72d57f
parent9e0dcfbaf0039d07609ed4e4a9ef9f1e2e1e6b55 (diff)
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 <rb.henschel@t-online.de> Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
-rw-r--r--include/oox/shape/ShapeContextHandler.hxx2
-rw-r--r--oox/source/shape/ShapeContextHandler.cxx6
-rw-r--r--writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx52
-rw-r--r--writerfilter/qa/cppunittests/dmapper/data/tdf149840_SmartArtBackground.docxbin0 -> 23200 bytes
-rw-r--r--writerfilter/source/dmapper/GraphicHelpers.cxx47
-rw-r--r--writerfilter/source/dmapper/GraphicHelpers.hxx14
-rw-r--r--writerfilter/source/ooxml/OOXMLFastContextHandler.cxx38
7 files changed, 158 insertions, 1 deletions
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
--- /dev/null
+++ b/writerfilter/qa/cppunittests/dmapper/data/tdf149840_SmartArtBackground.docx
Binary files 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);
}
}