include/svx/unoshape.hxx               |    2 +
 svx/source/unodraw/unoshap4.cxx        |   25 +++++++++++++++
 xmloff/CppunitTest_xmloff_draw.mk      |    3 +
 xmloff/qa/unit/data/video-snapshot.odp |binary
 xmloff/qa/unit/draw.cxx                |   50 ++++++++++++++++++++++++++++++
 xmloff/source/draw/shapeexport.cxx     |   54 ++++++++++++++++++++++++++++++++-
 xmloff/source/draw/ximpshap.cxx        |   14 +++++++-
 7 files changed, 146 insertions(+), 2 deletions(-)

New commits:
commit 3b88c304dce2e9d64b9d19b25ed57df5b581e834
Author:     Miklos Vajna <[email protected]>
AuthorDate: Mon Aug 29 09:23:22 2022 +0200
Commit:     Miklos Vajna <[email protected]>
CommitDate: Mon Aug 29 16:51:26 2022 +0200

    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.
    
    (cherry picked from commit cbc6e67d3c88fb6ae39c304604a98eaa504f19cc)
    
    Conflicts:
            xmloff/qa/unit/draw.cxx
            xmloff/source/draw/shapeexport.cxx
    
    Change-Id: I6115284c1f4cf342b3296cd0ac3beb70a809fd1b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138970
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/include/svx/unoshape.hxx b/include/svx/unoshape.hxx
index 3d3d5bea3a9b..b8d50458a4a1 100644
--- a/include/svx/unoshape.hxx
+++ b/include/svx/unoshape.hxx
@@ -843,6 +843,8 @@ private:
     // override these for special property handling in subcasses. Return true 
if property is handled
     virtual bool setPropertyValueImpl( const OUString& rName, const 
SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) override;
     virtual bool getPropertyValueImpl( const OUString& rName, const 
SfxItemPropertyMapEntry* pProperty, css::uno::Any& rValue ) override;
+    bool getPropertyStateImpl(const SfxItemPropertyMapEntry* pProperty,
+                              css::beans::PropertyState& rState) override;
 
     OUString referer_;
 };
diff --git a/svx/source/unodraw/unoshap4.cxx b/svx/source/unodraw/unoshap4.cxx
index 50a2a7a09a12..a5f2516161ac 100644
--- a/svx/source/unodraw/unoshap4.cxx
+++ b/svx/source/unodraw/unoshap4.cxx
@@ -1064,4 +1064,29 @@ bool SvxMediaShape::getPropertyValueImpl( const 
OUString& rName, const SfxItemPr
     }
 }
 
+bool SvxMediaShape::getPropertyStateImpl(const SfxItemPropertyMapEntry* 
pProperty,
+                                         css::beans::PropertyState& rState)
+{
+#if HAVE_FEATURE_AVMEDIA
+    if (pProperty->nWID == SDRATTR_GRAFCROP)
+    {
+        auto pMedia = static_cast<SdrMediaObj*>(GetSdrObject());
+        const avmedia::MediaItem& rItem = pMedia->getMediaProperties();
+        const text::GraphicCrop& rCrop = rItem.getCrop();
+        if (rCrop.Bottom > 0 || rCrop.Left > 0 || rCrop.Right > 0 || rCrop.Top 
> 0)
+        {
+            // The media has a crop, expose it to UNO-based export filters.
+            rState = beans::PropertyState_DIRECT_VALUE;
+        }
+        else
+        {
+            rState = beans::PropertyState_AMBIGUOUS_VALUE;
+        }
+        return true;
+    }
+#endif
+
+    return SvxShape::getPropertyStateImpl(pProperty, rState);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/CppunitTest_xmloff_draw.mk 
b/xmloff/CppunitTest_xmloff_draw.mk
index 46188eb0c438..686cc60d7ab4 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
new file mode 100644
index 000000000000..ca3b7f21dc6c
Binary files /dev/null and b/xmloff/qa/unit/data/video-snapshot.odp differ
diff --git a/xmloff/qa/unit/draw.cxx b/xmloff/qa/unit/draw.cxx
index 0b7c93c89073..a31c98be5a02 100644
--- a/xmloff/qa/unit/draw.cxx
+++ b/xmloff/qa/unit/draw.cxx
@@ -21,10 +21,14 @@
 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
 #include <com/sun/star/drawing/XMasterPageTarget.hpp>
 #include <com/sun/star/util/Color.hpp>
+#include <com/sun/star/text/GraphicCrop.hpp>
 
 #include <unotools/mediadescriptor.hxx>
 #include <unotools/tempfile.hxx>
 #include <unotools/ucbstreamhelper.hxx>
+#include <svx/unopage.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdomedia.hxx>
 
 using namespace ::com::sun::star;
 
@@ -155,6 +159,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 d47ea15b2758..0f3e86ee8d5a 100644
--- a/xmloff/source/draw/shapeexport.cxx
+++ b/xmloff/source/draw/shapeexport.cxx
@@ -99,6 +99,7 @@
 #include <tools/globname.hxx>
 #include <tools/helpers.hxx>
 #include <tools/diagnose_ex.h>
+#include <vcl/graph.hxx>
 
 #include <xmloff/contextid.hxx>
 #include <xmloff/families.hxx>
@@ -3387,7 +3388,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"  );
@@ -3437,6 +3438,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 76ca2c4fe4d9..442116980270 100644
--- a/xmloff/source/draw/ximpshap.cxx
+++ b/xmloff/source/draw/ximpshap.cxx
@@ -2908,6 +2908,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)
@@ -3302,6 +3308,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 )
         {
@@ -3311,10 +3318,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()))

Reply via email to