diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2022-08-29 09:23:22 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2022-08-29 10:40:41 +0200 |
commit | cbc6e67d3c88fb6ae39c304604a98eaa504f19cc (patch) | |
tree | 55e366d8db3c238634c1c4f63e954073c0172639 /xmloff | |
parent | 690458889fd875a7885b692d3204c45c5016b925 (diff) |
avmedia: implement video crop support in the ODP filter
And also import/export the video preview as well. The naming follows the
style used for table shape previews.
The preview is important, since the cropping is relative to the bitmap's
preferred logic size.
Change-Id: I6115284c1f4cf342b3296cd0ac3beb70a809fd1b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138959
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'xmloff')
-rw-r--r-- | xmloff/CppunitTest_xmloff_draw.mk | 3 | ||||
-rw-r--r-- | xmloff/qa/unit/data/video-snapshot.odp | bin | 0 -> 17605 bytes | |||
-rw-r--r-- | xmloff/qa/unit/draw.cxx | 50 | ||||
-rw-r--r-- | xmloff/source/draw/shapeexport.cxx | 54 | ||||
-rw-r--r-- | xmloff/source/draw/ximpshap.cxx | 14 |
5 files changed, 119 insertions, 2 deletions
diff --git a/xmloff/CppunitTest_xmloff_draw.mk b/xmloff/CppunitTest_xmloff_draw.mk index 42c7a9526661..a503cc9f2c1d 100644 --- a/xmloff/CppunitTest_xmloff_draw.mk +++ b/xmloff/CppunitTest_xmloff_draw.mk @@ -28,6 +28,9 @@ $(eval $(call gb_CppunitTest_use_libraries,xmloff_draw, \ test \ unotest \ utl \ + avmedia \ + svxcore \ + vcl \ )) $(eval $(call gb_CppunitTest_use_sdk_api,xmloff_draw)) diff --git a/xmloff/qa/unit/data/video-snapshot.odp b/xmloff/qa/unit/data/video-snapshot.odp Binary files differnew file mode 100644 index 000000000000..ca3b7f21dc6c --- /dev/null +++ b/xmloff/qa/unit/data/video-snapshot.odp diff --git a/xmloff/qa/unit/draw.cxx b/xmloff/qa/unit/draw.cxx index e8462ccc6181..6aab4c12a46f 100644 --- a/xmloff/qa/unit/draw.cxx +++ b/xmloff/qa/unit/draw.cxx @@ -24,6 +24,7 @@ #include <com/sun/star/util/Color.hpp> #include <com/sun/star/text/XTextRange.hpp> #include <com/sun/star/text/XTextTable.hpp> +#include <com/sun/star/text/GraphicCrop.hpp> #include <comphelper/propertyvalue.hxx> #include <comphelper/sequence.hxx> @@ -31,6 +32,9 @@ #include <unotools/tempfile.hxx> #include <unotools/ucbstreamhelper.hxx> #include <unotools/saveopt.hxx> +#include <svx/unopage.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdomedia.hxx> using namespace ::com::sun::star; @@ -173,6 +177,52 @@ CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testThemeExport) assertXPath(pXmlDoc, "//style:master-page/loext:theme/loext:color-table/loext:color", 12); } +CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testVideoSnapshot) +{ + // Execute ODP import: + OUString aURL = m_directories.getURLFromSrc(u"xmloff/qa/unit/data/video-snapshot.odp"); + getComponent() = loadFromDesktop(aURL, "com.sun.star.presentation.PresentationDocument"); + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), + uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT(xDrawPagesSupplier.is()); + uno::Reference<drawing::XDrawPages> xDrawPages(xDrawPagesSupplier->getDrawPages()); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(0), uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT(xDrawPage.is()); + auto pUnoPage = dynamic_cast<SvxDrawPage*>(xDrawPage.get()); + SdrPage* pSdrPage = pUnoPage->GetSdrPage(); + auto pMedia = dynamic_cast<SdrMediaObj*>(pSdrPage->GetObj(0)); + + // Check that the preview was imported: + const avmedia::MediaItem& rItem = pMedia->getMediaProperties(); + const Graphic& rGraphic = rItem.getGraphic(); + CPPUNIT_ASSERT(!rGraphic.IsNone()); + + // Check that the crop was imported: + const text::GraphicCrop& rCrop = rItem.getCrop(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), rCrop.Top); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), rCrop.Bottom); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1356), rCrop.Left); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1356), rCrop.Right); + + // Execute ODP export: + utl::TempFile aTempFile; + save("impress8", aTempFile); + + std::unique_ptr<SvStream> pStream = parseExportStream(aTempFile, "content.xml"); + xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); + // Check that the preview was exported: + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 0 + // - XPath '//draw:frame[@draw:style-name='gr1']/draw:image' number of nodes is incorrect + // i.e. the preview wasn't exported to ODP. + assertXPath(pXmlDoc, "//draw:frame[@draw:style-name='gr1']/draw:image", "href", + "Pictures/MediaPreview1.png"); + // Check that the crop was exported: + assertXPath(pXmlDoc, "//style:style[@style:name='gr1']/style:graphic-properties", "clip", + "rect(0cm, 1.356cm, 0cm, 1.356cm)"); +} + CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testThemeImport) { // Given a document that has a master page with a theme associated: diff --git a/xmloff/source/draw/shapeexport.cxx b/xmloff/source/draw/shapeexport.cxx index cd9c90efad24..6931c5684642 100644 --- a/xmloff/source/draw/shapeexport.cxx +++ b/xmloff/source/draw/shapeexport.cxx @@ -103,6 +103,7 @@ #include <tools/globname.hxx> #include <tools/helpers.hxx> #include <comphelper/diagnose_ex.hxx> +#include <vcl/graph.hxx> #include <xmloff/contextid.hxx> #include <xmloff/families.hxx> @@ -3400,7 +3401,7 @@ void XMLShapeExport::ImpExportMediaShape( mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MIME_TYPE, sMimeType ); // write plugin - SvXMLElementExport aPluginOBJ(mrExport, XML_NAMESPACE_DRAW, XML_PLUGIN, !( nFeatures & XMLShapeExportFlags::NO_WS ), true); + auto pPluginOBJ = std::make_unique<SvXMLElementExport>(mrExport, XML_NAMESPACE_DRAW, XML_PLUGIN, !( nFeatures & XMLShapeExportFlags::NO_WS ), true); // export parameters const OUString aFalseStr( "false" ), aTrueStr( "true" ); @@ -3450,6 +3451,57 @@ void XMLShapeExport::ImpExportMediaShape( delete new SvXMLElementExport( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true ); } + pPluginOBJ.reset(); + + uno::Reference<graphic::XGraphic> xGraphic; + xPropSet->getPropertyValue("Graphic") >>= xGraphic; + Graphic aGraphic(xGraphic); + if (!aGraphic.IsNone()) + { + // The media has a preview, export it. + uno::Reference<embed::XStorage> xPictureStorage; + uno::Reference<embed::XStorage> xStorage; + uno::Reference<io::XStream> xPictureStream; + OUString sPictureName; + xStorage.set(GetExport().GetTargetStorage(), uno::UNO_SET_THROW); + xPictureStorage.set( + xStorage->openStorageElement("Pictures", embed::ElementModes::READWRITE), + uno::UNO_SET_THROW); + sal_Int32 nIndex = 0; + while (true) + { + sPictureName = "MediaPreview" + OUString::number(++nIndex) + ".png"; + if (!xPictureStorage->hasByName(sPictureName)) + { + break; + } + } + + xPictureStream.set( + xPictureStorage->openStreamElement(sPictureName, ::embed::ElementModes::READWRITE), + uno::UNO_SET_THROW); + + uno::Reference<uno::XComponentContext> xContext = GetExport().getComponentContext(); + uno::Reference<graphic::XGraphicProvider> xProvider( + graphic::GraphicProvider::create(xContext)); + uno::Sequence<beans::PropertyValue> aArgs{ + comphelper::makePropertyValue("MimeType", OUString("image/png")), + comphelper::makePropertyValue("OutputStream", xPictureStream->getOutputStream()) + }; + xProvider->storeGraphic(xGraphic, aArgs); + if (xPictureStorage.is()) + { + uno::Reference<embed::XTransactedObject> xTrans(xPictureStorage, uno::UNO_QUERY); + if (xTrans.is()) + xTrans->commit(); + } + OUString sURL = "Pictures/" + sPictureName; + mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sURL); + mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE); + mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED); + mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD); + SvXMLElementExport aImageElem(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, false, true); + } } void XMLShapeExport::ImpExport3DSceneShape( const uno::Reference< drawing::XShape >& xShape, XMLShapeExportFlags nFeatures, awt::Point* pRefPoint) diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx index 1971c9b9f022..af0bfc1a7ef0 100644 --- a/xmloff/source/draw/ximpshap.cxx +++ b/xmloff/source/draw/ximpshap.cxx @@ -2918,6 +2918,12 @@ void SdXMLPluginShapeContext::startFastElement (sal_Int32 /*nElement*/, if( !mxShape.is() ) return; + if (mbMedia) + { + // The media may have a crop, apply it. + SetStyle(/*bSupportsStyle=*/false); + } + SetLayer(); if(bIsPresShape) @@ -3312,6 +3318,7 @@ css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLFrameShapeContext pShapeContext->setHyperlink( msHyperlink ); auto nToken = nElement & TOKEN_MASK; + bool bMedia = false; // Ignore gltf model if necessary and so the fallback image will be imported if( nToken == XML_PLUGIN ) { @@ -3321,10 +3328,15 @@ css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLFrameShapeContext mxImplContext = nullptr; return new SvXMLImportContext(GetImport()); } + else if (pPluginContext && pPluginContext->getMimeType() == "application/vnd.sun.star.media") + { + // The media may have a preview, import it. + bMedia = true; + } } mxImplContext = xContext; - mbSupportsReplacement = (nToken == XML_OBJECT ) || (nToken == XML_OBJECT_OLE); + mbSupportsReplacement = (nToken == XML_OBJECT ) || (nToken == XML_OBJECT_OLE) || bMedia; setSupportsMultipleContents(nToken == XML_IMAGE); if(getSupportsMultipleContents() && dynamic_cast< SdXMLGraphicObjectShapeContext* >(xContext.get())) |