summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/oox/export/drawingml.hxx2
-rw-r--r--oox/CppunitTest_oox_export.mk46
-rw-r--r--oox/Module_oox.mk1
-rw-r--r--oox/qa/unit/data/dml-groupshape-polygon.docxbin0 -> 24492 bytes
-rw-r--r--oox/qa/unit/export.cxx157
-rw-r--r--oox/source/export/drawingml.cxx29
-rw-r--r--oox/source/export/shapes.cxx8
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport6.cxx4
8 files changed, 235 insertions, 12 deletions
diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index 0a42eb84f001..00049fd94103 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -250,7 +250,7 @@ public:
void WriteShapeTransformation(const css::uno::Reference< css::drawing::XShape >& rXShape,
sal_Int32 nXmlNamespace, bool bFlipH = false, bool bFlipV = false, bool bSuppressRotation = false, bool bSuppressFlipping = false, bool bFlippedBeforeRotation = false);
- void WriteTransformation(const tools::Rectangle& rRectangle,
+ void WriteTransformation(const css::uno::Reference< css::drawing::XShape >& xShape, const tools::Rectangle& rRectangle,
sal_Int32 nXmlNamespace, bool bFlipH = false, bool bFlipV = false, sal_Int32 nRotation = 0, bool bIsGroupShape = false);
void WriteText( const css::uno::Reference< css::uno::XInterface >& rXIface, bool bBodyPr, bool bText = true, sal_Int32 nXmlNamespace = 0);
diff --git a/oox/CppunitTest_oox_export.mk b/oox/CppunitTest_oox_export.mk
new file mode 100644
index 000000000000..011ce3d2a5de
--- /dev/null
+++ b/oox/CppunitTest_oox_export.mk
@@ -0,0 +1,46 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,oox_export))
+
+$(eval $(call gb_CppunitTest_use_externals,oox_export,\
+ boost_headers \
+ libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,oox_export, \
+ oox/qa/unit/export \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,oox_export, \
+ comphelper \
+ cppu \
+ oox \
+ sal \
+ test \
+ unotest \
+ utl \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,oox_export))
+
+$(eval $(call gb_CppunitTest_use_ure,oox_export))
+$(eval $(call gb_CppunitTest_use_vcl,oox_export))
+
+$(eval $(call gb_CppunitTest_use_rdb,oox_export,services))
+
+$(eval $(call gb_CppunitTest_use_custom_headers,oox_export,\
+ officecfg/registry \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,oox_export))
+
+# vim: set noet sw=4 ts=4:
diff --git a/oox/Module_oox.mk b/oox/Module_oox.mk
index ed85ee68da2d..75ef85051f85 100644
--- a/oox/Module_oox.mk
+++ b/oox/Module_oox.mk
@@ -29,6 +29,7 @@ $(eval $(call gb_Module_add_check_targets,oox,\
CppunitTest_oox_drawingml \
CppunitTest_oox_vml \
CppunitTest_oox_shape \
+ CppunitTest_oox_export \
))
# vim: set noet sw=4 ts=4:
diff --git a/oox/qa/unit/data/dml-groupshape-polygon.docx b/oox/qa/unit/data/dml-groupshape-polygon.docx
new file mode 100644
index 000000000000..6d20b0342f68
--- /dev/null
+++ b/oox/qa/unit/data/dml-groupshape-polygon.docx
Binary files differ
diff --git a/oox/qa/unit/export.cxx b/oox/qa/unit/export.cxx
new file mode 100644
index 000000000000..6e6620ab63a4
--- /dev/null
+++ b/oox/qa/unit/export.cxx
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <unotest/macros_test.hxx>
+#include <test/xmltesttools.hxx>
+
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/packages/zip/ZipFileAccess.hpp>
+
+#include <unotools/mediadescriptor.hxx>
+#include <unotools/tempfile.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+/// Covers ooox/source/export/ fixes.
+class Test : public test::BootstrapFixture, public unotest::MacrosTest, public XmlTestTools
+{
+private:
+ uno::Reference<lang::XComponent> mxComponent;
+ utl::TempFile maTempFile;
+
+public:
+ void setUp() override;
+ void tearDown() override;
+ void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override;
+ utl::TempFile& getTempFile() { return maTempFile; }
+ void loadAndSave(const OUString& rURL, const OUString& rFilterName);
+};
+
+void Test::setUp()
+{
+ test::BootstrapFixture::setUp();
+
+ mxDesktop.set(frame::Desktop::create(mxComponentContext));
+}
+
+void Test::tearDown()
+{
+ if (mxComponent.is())
+ mxComponent->dispose();
+
+ test::BootstrapFixture::tearDown();
+}
+
+void Test::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx)
+{
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("w"),
+ BAD_CAST("http://schemas.openxmlformats.org/wordprocessingml/2006/main"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("v"), BAD_CAST("urn:schemas-microsoft-com:vml"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("mc"),
+ BAD_CAST("http://schemas.openxmlformats.org/markup-compatibility/2006"));
+ xmlXPathRegisterNs(
+ pXmlXpathCtx, BAD_CAST("wps"),
+ BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingShape"));
+ xmlXPathRegisterNs(
+ pXmlXpathCtx, BAD_CAST("wpg"),
+ BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"));
+ xmlXPathRegisterNs(
+ pXmlXpathCtx, BAD_CAST("wp"),
+ BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"));
+ xmlXPathRegisterNs(
+ pXmlXpathCtx, BAD_CAST("wp14"),
+ BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("a"),
+ BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/main"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("pic"),
+ BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/picture"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("rels"),
+ BAD_CAST("http://schemas.openxmlformats.org/package/2006/relationships"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("w14"),
+ BAD_CAST("http://schemas.microsoft.com/office/word/2010/wordml"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("m"),
+ BAD_CAST("http://schemas.openxmlformats.org/officeDocument/2006/math"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("ContentType"),
+ BAD_CAST("http://schemas.openxmlformats.org/package/2006/content-types"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("lc"),
+ BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas"));
+ xmlXPathRegisterNs(
+ pXmlXpathCtx, BAD_CAST("cp"),
+ BAD_CAST("http://schemas.openxmlformats.org/package/2006/metadata/core-properties"));
+ xmlXPathRegisterNs(
+ pXmlXpathCtx, BAD_CAST("extended-properties"),
+ BAD_CAST("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"));
+ xmlXPathRegisterNs(
+ pXmlXpathCtx, BAD_CAST("custom-properties"),
+ BAD_CAST("http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"));
+ xmlXPathRegisterNs(
+ pXmlXpathCtx, BAD_CAST("vt"),
+ BAD_CAST("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("dcterms"), BAD_CAST("http://purl.org/dc/terms/"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("a14"),
+ BAD_CAST("http://schemas.microsoft.com/office/drawing/2010/main"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("c"),
+ BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/chart"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("o"),
+ BAD_CAST("urn:schemas-microsoft-com:office:office"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("w10"),
+ BAD_CAST("urn:schemas-microsoft-com:office:word"));
+}
+
+void Test::loadAndSave(const OUString& rURL, const OUString& rFilterName)
+{
+ mxComponent = loadFromDesktop(rURL);
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= rFilterName;
+ maTempFile.EnableKillingFile();
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+ mxComponent->dispose();
+ mxComponent.clear();
+ // too many DOCX validation errors right now
+ if (rFilterName != "Office Open XML Text")
+ {
+ validate(maTempFile.GetFileName(), test::OOXML);
+ }
+}
+
+constexpr OUStringLiteral DATA_DIRECTORY = u"/oox/qa/unit/data/";
+
+CPPUNIT_TEST_FIXTURE(Test, testDmlGroupshapePolygon)
+{
+ // Given a document with a group shape, containing a single polygon child shape:
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "dml-groupshape-polygon.docx";
+
+ // When saving that to DOCX:
+ loadAndSave(aURL, "Office Open XML Text");
+
+ // Then make sure that the group shape, the group shape's child size and the child shape's size
+ // match:
+ uno::Reference<packages::zip::XZipFileAccess2> xNameAccess
+ = packages::zip::ZipFileAccess::createWithURL(mxComponentContext, getTempFile().GetURL());
+ uno::Reference<io::XInputStream> xInputStream(xNameAccess->getByName("word/document.xml"),
+ uno::UNO_QUERY);
+ std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
+ assertXPath(pXmlDoc, "//wpg:grpSpPr/a:xfrm/a:ext", "cx", "5328360");
+ // Without the accompanying fix in place, this test would have failed, the <a:chExt> element was
+ // not written.
+ assertXPath(pXmlDoc, "//wpg:grpSpPr/a:xfrm/a:chExt", "cx", "5328360");
+ assertXPath(pXmlDoc, "//wps:spPr/a:xfrm/a:ext", "cx", "5328360");
+}
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 94b67cb379f2..8cfd4a6dabc5 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -1686,7 +1686,22 @@ void DrawingML::WriteXGraphicStretch(uno::Reference<beans::XPropertySet> const &
mpFS->endElementNS(XML_a, XML_stretch);
}
-void DrawingML::WriteTransformation(const tools::Rectangle& rRect,
+namespace
+{
+bool IsTopGroupObj(const uno::Reference<drawing::XShape>& xShape)
+{
+ SdrObject* pObject = GetSdrObjectFromXShape(xShape);
+ if (!pObject)
+ return false;
+
+ if (pObject->getParentSdrObjectFromSdrObject())
+ return false;
+
+ return pObject->IsGroupObject();
+}
+}
+
+void DrawingML::WriteTransformation(const Reference< XShape >& xShape, const tools::Rectangle& rRect,
sal_Int32 nXmlNamespace, bool bFlipH, bool bFlipV, sal_Int32 nRotation, bool bIsGroupShape)
{
@@ -1696,7 +1711,9 @@ void DrawingML::WriteTransformation(const tools::Rectangle& rRect,
XML_rot, sax_fastparser::UseIf(OString::number(nRotation), nRotation % 21600000 != 0));
sal_Int32 nLeft = rRect.Left();
+ sal_Int32 nChildLeft = nLeft;
sal_Int32 nTop = rRect.Top();
+ sal_Int32 nChildTop = nTop;
if (GetDocumentType() == DOCUMENT_DOCX && !m_xParent.is())
{
nLeft = 0;
@@ -1710,11 +1727,11 @@ void DrawingML::WriteTransformation(const tools::Rectangle& rRect,
XML_cx, OString::number(oox::drawingml::convertHmmToEmu(rRect.GetWidth())),
XML_cy, OString::number(oox::drawingml::convertHmmToEmu(rRect.GetHeight())));
- if (GetDocumentType() != DOCUMENT_DOCX && bIsGroupShape)
+ if (bIsGroupShape && (GetDocumentType() != DOCUMENT_DOCX || IsTopGroupObj(xShape)))
{
mpFS->singleElementNS(XML_a, XML_chOff,
- XML_x, OString::number(oox::drawingml::convertHmmToEmu(nLeft)),
- XML_y, OString::number(oox::drawingml::convertHmmToEmu(nTop)));
+ XML_x, OString::number(oox::drawingml::convertHmmToEmu(nChildLeft)),
+ XML_y, OString::number(oox::drawingml::convertHmmToEmu(nChildTop)));
mpFS->singleElementNS(XML_a, XML_chExt,
XML_cx, OString::number(oox::drawingml::convertHmmToEmu(rRect.GetWidth())),
XML_cy, OString::number(oox::drawingml::convertHmmToEmu(rRect.GetHeight())));
@@ -1798,7 +1815,7 @@ void DrawingML::WriteShapeTransformation( const Reference< XShape >& rXShape, sa
if(bFlipH != bFlipV)
nRotation = nRotation * -1 + 36000;
- WriteTransformation(tools::Rectangle(Point(aPos.X, aPos.Y), Size(aSize.Width, aSize.Height)), nXmlNamespace,
+ WriteTransformation(rXShape, tools::Rectangle(Point(aPos.X, aPos.Y), Size(aSize.Width, aSize.Height)), nXmlNamespace,
bFlipHWrite, bFlipVWrite, ExportRotateClockwisify(nRotation + nCameraRotation), IsGroupShape( rXShape ));
}
@@ -4809,7 +4826,7 @@ void DrawingML::WriteDiagram(const css::uno::Reference<css::drawing::XShape>& rX
awt::Point aPos = xShapeBg->getPosition();
awt::Size aSize = xShapeBg->getSize();
WriteTransformation(
- tools::Rectangle(Point(aPos.X, aPos.Y), Size(aSize.Width, aSize.Height)),
+ xShapeBg, tools::Rectangle(Point(aPos.X, aPos.Y), Size(aSize.Width, aSize.Height)),
XML_p, false, false, 0, false);
}
diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx
index aae5ed633d85..b217358b6197 100644
--- a/oox/source/export/shapes.cxx
+++ b/oox/source/export/shapes.cxx
@@ -400,7 +400,9 @@ ShapeExport& ShapeExport::WritePolyPolygonShape( const Reference< XShape >& xSha
pFS->startElementNS(mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp));
tools::PolyPolygon aPolyPolygon = EscherPropertyContainer::GetPolyPolygon( xShape );
- tools::Rectangle aRect( aPolyPolygon.GetBoundRect() );
+ awt::Point aPos = xShape->getPosition();
+ awt::Size aSize = xShape->getSize();
+ tools::Rectangle aRect(Point(aPos.X, aPos.Y), Size(aSize.Width, aSize.Height));
#if OSL_DEBUG_LEVEL > 0
awt::Size size = MapSize( awt::Size( aRect.GetWidth(), aRect.GetHeight() ) );
@@ -425,7 +427,7 @@ ShapeExport& ShapeExport::WritePolyPolygonShape( const Reference< XShape >& xSha
// visual shape properties
pFS->startElementNS(mnXmlNamespace, XML_spPr);
- WriteTransformation( aRect, XML_a );
+ WriteTransformation( xShape, aRect, XML_a );
WritePolyPolygon(xShape, aPolyPolygon, bClosed);
Reference< XPropertySet > xProps( xShape, UNO_QUERY );
if( xProps.is() ) {
@@ -1344,7 +1346,7 @@ ShapeExport& ShapeExport::WriteConnectorShape( const Reference< XShape >& xShape
// visual shape properties
pFS->startElementNS(mnXmlNamespace, XML_spPr);
- WriteTransformation( aRect, XML_a, bFlipH, bFlipV );
+ WriteTransformation( xShape, aRect, XML_a, bFlipH, bFlipV );
// TODO: write adjustments (ppt export doesn't work well there either)
WritePresetShape( sGeometry );
Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY );
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
index d7bdc09c0c34..a8477c523e53 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
@@ -126,11 +126,11 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testDmlTextshapeB, "dml-textshapeB.docx")
uno::Reference<drawing::XShape> xShape(xGroup->getByIndex(3), uno::UNO_QUERY);
// Connector was incorrectly shifted towards the top left corner, X was 192, Y was -5743.
CPPUNIT_ASSERT_EQUAL(sal_Int32(3778), xShape->getPosition().X);
- CPPUNIT_ASSERT_EQUAL(sal_Int32(-5064), xShape->getPosition().Y);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-5066), xShape->getPosition().Y);
xShape.set(xGroup->getByIndex(5), uno::UNO_QUERY);
// This was incorrectly shifted towards the top of the page, Y was -5011.
- CPPUNIT_ASSERT_EQUAL(sal_Int32(-4713), xShape->getPosition().Y);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-4715), xShape->getPosition().Y);
}
DECLARE_OOXMLEXPORT_TEST(testDMLSolidfillAlpha, "dml-solidfill-alpha.docx")