diff options
-rw-r--r-- | include/oox/export/drawingml.hxx | 2 | ||||
-rw-r--r-- | oox/CppunitTest_oox_export.mk | 46 | ||||
-rw-r--r-- | oox/Module_oox.mk | 1 | ||||
-rw-r--r-- | oox/qa/unit/data/dml-groupshape-polygon.docx | bin | 0 -> 24492 bytes | |||
-rw-r--r-- | oox/qa/unit/export.cxx | 157 | ||||
-rw-r--r-- | oox/source/export/drawingml.cxx | 29 | ||||
-rw-r--r-- | oox/source/export/shapes.cxx | 8 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport6.cxx | 4 |
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 Binary files differnew file mode 100644 index 000000000000..6d20b0342f68 --- /dev/null +++ b/oox/qa/unit/data/dml-groupshape-polygon.docx 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") |