[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-5.3' - include/oox oox/CppunitTest_oox_tokenmap.mk oox/Library_oox.mk oox/source sd/qa sd/source

Jan Holesovsky kendy at collabora.com
Thu Sep 7 08:28:44 UTC 2017


 include/oox/export/drawingml.hxx         |    4 +
 oox/CppunitTest_oox_tokenmap.mk          |    1 
 oox/Library_oox.mk                       |    3 
 oox/source/export/drawingml.cxx          |   98 +++++++++++++++++++++++++++++++
 oox/source/export/shapes.cxx             |   42 +++++++++++--
 oox/source/ppt/timenode.cxx              |    6 +
 sd/qa/unit/data/pptx/tdf106867.pptx      |binary
 sd/qa/unit/export-tests-ooxml2.cxx       |   33 ++++++++++
 sd/source/filter/eppt/epptooxml.hxx      |    1 
 sd/source/filter/eppt/pptx-epptooxml.cxx |   56 +++++++++++++++++
 10 files changed, 235 insertions(+), 9 deletions(-)

New commits:
commit 50f8e0e479e70fca3620da192e5a2cc4ca12bc2c
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Tue Sep 5 16:53:14 2017 +0200

    tdf#106867: Export videos in PPTX.
    
    Contains also:
    
    tdf#106867: Implement pptx export of AnimationNodeType::COMMAND.
    tdf#106867: Import target for commands in PPTX.
    tdf#106867: Write also the extended markup to fully support embedded videos.
    tdf#106867: Unit test for the export of embedded videos.
    
    Change-Id: I7f4f389a72aa7ecef65d87f07bb69ba8f3374a14
    Reviewed-on: https://gerrit.libreoffice.org/42017
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index d9216d2c6bf4..fc2c4b8bd28e 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -134,6 +134,10 @@ protected:
 
     /// If bRelPathToMedia is true add "../" to image folder path while adding the image relationship
     OUString WriteImage( const OUString& rURL, bool bRelPathToMedia = false);
+
+    /// Output the media (including copying a video from vnd.sun.star.Package: to the output if necessary).
+    void WriteMediaNonVisualProperties(const css::uno::Reference<css::drawing::XShape>& xShape);
+
     void WriteStyleProperties( sal_Int32 nTokenId, const css::uno::Sequence< css::beans::PropertyValue >& aProperties );
 
     const char* GetComponentDir();
diff --git a/oox/CppunitTest_oox_tokenmap.mk b/oox/CppunitTest_oox_tokenmap.mk
index 1e903a25a368..e71bcf6ba6bc 100644
--- a/oox/CppunitTest_oox_tokenmap.mk
+++ b/oox/CppunitTest_oox_tokenmap.mk
@@ -35,6 +35,7 @@ endif
 endif
 
 $(eval $(call gb_CppunitTest_use_libraries,oox_tokenmap,\
+    avmedia \
     basegfx \
     comphelper \
     cppu \
diff --git a/oox/Library_oox.mk b/oox/Library_oox.mk
index fcd7215c23a4..e44015aaa595 100644
--- a/oox/Library_oox.mk
+++ b/oox/Library_oox.mk
@@ -38,6 +38,7 @@ $(eval $(call gb_Library_use_api,oox,\
 ))
 
 $(eval $(call gb_Library_use_libraries,oox,\
+    avmedia \
     basegfx \
     comphelper \
     cppu \
@@ -47,7 +48,7 @@ $(eval $(call gb_Library_use_libraries,oox,\
     drawinglayer \
     msfilter \
     sal \
-	i18nlangtag \
+    i18nlangtag \
     sax \
     sfx \
     svl \
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index bb90a48eb96d..3e9cc01e9ed7 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -41,6 +41,7 @@
 #include <com/sun/star/beans/XPropertySetInfo.hpp>
 #include <com/sun/star/container/XEnumerationAccess.hpp>
 #include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/document/XStorageBasedDocument.hpp>
 #include <com/sun/star/drawing/BitmapMode.hpp>
 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
@@ -56,6 +57,7 @@
 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
 #include <com/sun/star/drawing/XShape.hpp>
 #include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
 #include <com/sun/star/i18n/ScriptType.hpp>
 #include <com/sun/star/io/XOutputStream.hpp>
 #include <com/sun/star/style/LineSpacing.hpp>
@@ -69,6 +71,8 @@
 #include <com/sun/star/text/XTextField.hpp>
 #include <com/sun/star/text/XTextRange.hpp>
 #include <com/sun/star/style/CaseMap.hpp>
+
+#include <comphelper/storagehelper.hxx>
 #include <o3tl/any.hxx>
 #include <tools/stream.hxx>
 #include <unotools/fontdefs.hxx>
@@ -87,6 +91,7 @@
 #include <editeng/flditem.hxx>
 #include <svx/sdtfsitm.hxx>
 #include <svx/svdoashp.hxx>
+#include <svx/svdomedia.hxx>
 #include <svx/unoapi.hxx>
 #include <svx/unoshape.hxx>
 
@@ -944,6 +949,99 @@ OUString DrawingML::WriteImage( const Graphic& rGraphic , bool bRelPathToMedia )
     return sRelId;
 }
 
+void DrawingML::WriteMediaNonVisualProperties(const css::uno::Reference<css::drawing::XShape>& xShape)
+{
+    SdrMediaObj* pMediaObj = dynamic_cast<SdrMediaObj*>(GetSdrObjectFromXShape(xShape));
+    if (!pMediaObj)
+        return;
+
+    // extension
+    OUString aExtension;
+    const OUString& rURL(pMediaObj->getURL());
+    int nLastDot = rURL.lastIndexOf('.');
+    if (nLastDot >= 0)
+        aExtension = rURL.copy(nLastDot);
+
+    bool bEmbed = rURL.startsWith("vnd.sun.star.Package:");
+
+    // mime type
+    OUString aMimeType(pMediaObj->getMediaProperties().getMimeType());
+    if (aMimeType == "application/vnd.sun.star.media")
+    {
+        // try to set something better
+        // TODO fix the importer to actually set the mimetype on import
+        if (aExtension.equalsIgnoreAsciiCase(".avi"))
+            aMimeType = "video/x-msvideo";
+        else if (aExtension.equalsIgnoreAsciiCase(".flv"))
+            aMimeType = "video/x-flv";
+        else if (aExtension.equalsIgnoreAsciiCase(".mp4"))
+            aMimeType = "video/mp4";
+        else if (aExtension.equalsIgnoreAsciiCase(".mov"))
+            aMimeType = "video/quicktime";
+        else if (aExtension.equalsIgnoreAsciiCase(".ogv"))
+            aMimeType = "video/ogg";
+        else if (aExtension.equalsIgnoreAsciiCase(".wmv"))
+            aMimeType = "video/x-ms-wmv";
+    }
+
+    OUString aVideoFileRelId;
+    OUString aMediaRelId;
+
+    static const OUString aVideoRelationship("http://schemas.openxmlformats.org/officeDocument/2006/relationships/video");
+    static const OUString aMediaRelationship("http://schemas.microsoft.com/office/2007/relationships/media");
+
+    if (bEmbed)
+    {
+        // copy the video stream
+        Reference<XOutputStream> xOutStream = mpFB->openFragmentStream(OUStringBuffer()
+                                                                       .appendAscii(GetComponentDir())
+                                                                       .append("/media/media")
+                                                                       .append((sal_Int32) mnImageCounter)
+                                                                       .append(aExtension)
+                                                                       .makeStringAndClear(),
+                                                                       aMimeType);
+
+        uno::Reference<io::XInputStream> xInputStream(pMediaObj->GetInputStream());
+        comphelper::OStorageHelper::CopyInputToOutput(xInputStream, xOutStream);
+
+        xOutStream->closeOutput();
+
+        // create the relation
+        OUString aPath = OUStringBuffer().appendAscii(GetRelationCompPrefix())
+                                         .append("media/media")
+                                         .append((sal_Int32) mnImageCounter++)
+                                         .append(aExtension)
+                                         .makeStringAndClear();
+        aVideoFileRelId = mpFB->addRelation(mpFS->getOutputStream(), aVideoRelationship, aPath);
+        aMediaRelId = mpFB->addRelation(mpFS->getOutputStream(), aMediaRelationship, aPath);
+    }
+    else
+    {
+        aVideoFileRelId = mpFB->addRelation(mpFS->getOutputStream(), aVideoRelationship, rURL);
+        aMediaRelId = mpFB->addRelation(mpFS->getOutputStream(), aMediaRelationship, rURL);
+    }
+
+    GetFS()->startElementNS(XML_p, XML_nvPr, FSEND);
+
+    GetFS()->singleElementNS(XML_a, XML_videoFile,
+                    FSNS(XML_r, XML_link), USS(aVideoFileRelId),
+                    FSEND);
+
+    GetFS()->startElementNS(XML_p, XML_extLst, FSEND);
+    GetFS()->startElementNS(XML_p, XML_ext,
+            XML_uri, "{DAA4B4D4-6D71-4841-9C94-3DE7FCFB9230}", // media extensions; google this ID for details
+            FSEND);
+
+    GetFS()->singleElementNS(XML_p14, XML_media,
+            bEmbed? FSNS(XML_r, XML_embed): FSNS(XML_r, XML_link), USS(aMediaRelId),
+            FSEND);
+
+    GetFS()->endElementNS(XML_p, XML_ext);
+    GetFS()->endElementNS(XML_p, XML_extLst);
+
+    GetFS()->endElementNS(XML_p, XML_nvPr);
+}
+
 OUString DrawingML::WriteBlip( const Reference< XPropertySet >& rXPropSet, const OUString& rURL, bool bRelPathToMedia, const Graphic *pGraphic )
 {
     OUString sRelId;
diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx
index 3391ae3d1ec1..767328311a69 100644
--- a/oox/source/export/shapes.cxx
+++ b/oox/source/export/shapes.cxx
@@ -58,6 +58,7 @@
 #include <com/sun/star/embed/XEmbeddedObject.hpp>
 #include <com/sun/star/embed/XEmbedPersist.hpp>
 #include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
 #include <com/sun/star/i18n/ScriptType.hpp>
 #include <com/sun/star/io/XOutputStream.hpp>
 #include <com/sun/star/style/ParagraphAdjust.hpp>
@@ -77,6 +78,7 @@
 #include <tools/stream.hxx>
 #include <tools/globname.hxx>
 #include <comphelper/classids.hxx>
+#include <comphelper/sequence.hxx>
 #include <comphelper/storagehelper.hxx>
 #include <sot/exchange.hxx>
 #include <vcl/cvtgrf.hxx>
@@ -1099,10 +1101,15 @@ void ShapeExport::WriteGraphicObjectShapePart( const Reference< XShape >& xShape
     SAL_INFO("oox.shape", "graphicObject without text");
 
     OUString sGraphicURL;
+    OUString sMediaURL;
     Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY );
-    if( !pGraphic && ( !xShapeProps.is() || !( xShapeProps->getPropertyValue( "GraphicURL" ) >>= sGraphicURL ) ) )
+
+    bool bHasGraphicURL = xShapeProps.is() && xShapeProps->getPropertySetInfo()->hasPropertyByName("GraphicURL") && (xShapeProps->getPropertyValue("GraphicURL") >>= sGraphicURL);
+    bool bHasMediaURL = xShapeProps.is() && xShapeProps->getPropertySetInfo()->hasPropertyByName("MediaURL") && (xShapeProps->getPropertyValue("MediaURL") >>= sMediaURL);
+
+    if (!pGraphic && !bHasGraphicURL && !bHasMediaURL)
     {
-        SAL_INFO("oox.shape", "no graphic URL found");
+        SAL_INFO("oox.shape", "no graphic or media URL found");
         return;
     }
 
@@ -1125,26 +1132,48 @@ void ShapeExport::WriteGraphicObjectShapePart( const Reference< XShape >& xShape
     if ( ( bHaveDesc = GetProperty( xShapeProps, "Description" ) ) )
         mAny >>= sDescr;
 
-    pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
+    pFS->startElementNS( mnXmlNamespace, XML_cNvPr,
                           XML_id,     I32S( GetNewShapeID( xShape ) ),
                           XML_name,   bHaveName ? USS( sName ) : OString( "Picture " + OString::number( mnPictureIdMax++ )).getStr(),
                           XML_descr,  bHaveDesc ? USS( sDescr ) : nullptr,
                           FSEND );
+
     // OOXTODO: //cNvPr children: XML_extLst, XML_hlinkClick, XML_hlinkHover
+    if (bHasMediaURL)
+        pFS->singleElementNS(XML_a, XML_hlinkClick,
+                             FSNS(XML_r, XML_id), "",
+                             XML_action, "ppaction://media",
+                             FSEND);
+
+    pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
 
     pFS->singleElementNS( mnXmlNamespace, XML_cNvPicPr,
                           // OOXTODO: XML_preferRelativeSize
                           FSEND );
 
-    WriteNonVisualProperties( xShape );
+    if (bHasMediaURL)
+        WriteMediaNonVisualProperties(xShape);
+    else
+        WriteNonVisualProperties(xShape);
 
     pFS->endElementNS( mnXmlNamespace, XML_nvPicPr );
 
     pFS->startElementNS( mnXmlNamespace, XML_blipFill, FSEND );
 
-    WriteBlip( xShapeProps, sGraphicURL, false, pGraphic );
+    if (pGraphic || bHasGraphicURL)
+        WriteBlip(xShapeProps, sGraphicURL, false, pGraphic);
+    else if (bHasMediaURL)
+    {
+        Reference<graphic::XGraphic> rGraphic;
+        if (xShapeProps->getPropertySetInfo()->hasPropertyByName("FallbackGraphic"))
+            xShapeProps->getPropertyValue("FallbackGraphic") >>= rGraphic;
+
+        Graphic aGraphic(rGraphic);
+        WriteBlip(xShapeProps, sMediaURL, false, &aGraphic);
+    }
 
-    WriteSrcRect( xShapeProps, sGraphicURL );
+    if (bHasGraphicURL)
+        WriteSrcRect(xShapeProps, sGraphicURL);
 
     // now we stretch always when we get pGraphic (when changing that
     // behavior, test n#780830 for regression, where the OLE sheet might get tiled
@@ -1420,6 +1449,7 @@ static const NameToConvertMapType& lcl_GetConverters()
     shape_converters[ "com.sun.star.drawing.GroupShape" ]               = &ShapeExport::WriteGroupShape;
 
     shape_converters[ "com.sun.star.presentation.GraphicObjectShape" ]  = &ShapeExport::WriteGraphicObjectShape;
+    shape_converters[ "com.sun.star.presentation.MediaShape" ]          = &ShapeExport::WriteGraphicObjectShape;
     shape_converters[ "com.sun.star.presentation.OLE2Shape" ]           = &ShapeExport::WriteOLE2Shape;
     shape_converters[ "com.sun.star.presentation.TableShape" ]          = &ShapeExport::WriteTableShape;
     shape_converters[ "com.sun.star.presentation.TextShape" ]           = &ShapeExport::WriteTextShape;
diff --git a/oox/source/ppt/timenode.cxx b/oox/source/ppt/timenode.cxx
index 2e5a02e9fabd..321a4c9297ec 100644
--- a/oox/source/ppt/timenode.cxx
+++ b/oox/source/ppt/timenode.cxx
@@ -313,8 +313,10 @@ namespace oox { namespace ppt {
                             xAnimate->setBy( aValue );
                         break;
                     case NP_TARGET:
-                        if( xAnimate.is() )
-                            xAnimate->setTarget( aValue );
+                        if (xAnimate.is())
+                            xAnimate->setTarget(aValue);
+                        if (xCommand.is())
+                            xCommand->setTarget(aValue);
                         break;
                     case NP_SUBITEM:
                         if( xAnimate.is() )
diff --git a/sd/qa/unit/data/pptx/tdf106867.pptx b/sd/qa/unit/data/pptx/tdf106867.pptx
new file mode 100644
index 000000000000..5bf16d690ef2
Binary files /dev/null and b/sd/qa/unit/data/pptx/tdf106867.pptx differ
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx
index 817cad398a13..5586564a33e5 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -105,6 +105,7 @@ public:
     void testTdf59046();
     void testTdf105739();
     void testTdf111518();
+    void testTdf106867();
 
     CPPUNIT_TEST_SUITE(SdOOXMLExportTest2);
 
@@ -133,6 +134,7 @@ public:
     CPPUNIT_TEST(testTdf59046);
     CPPUNIT_TEST(testTdf105739);
     CPPUNIT_TEST(testTdf111518);
+    CPPUNIT_TEST(testTdf106867);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -151,6 +153,7 @@ public:
             { "pic", "http://schemas.openxmlformats.org/drawingml/2006/picture" },
             { "wp", "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" },
             { "p", "http://schemas.openxmlformats.org/presentationml/2006/main" },
+            { "p14", "http://schemas.microsoft.com/office/powerpoint/2010/main" },
             { "w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main" },
             { "a14", "http://schemas.microsoft.com/office/drawing/2010/main" },
             { "wps", "http://schemas.microsoft.com/office/word/2010/wordprocessingShape" },
@@ -807,6 +810,36 @@ void SdOOXMLExportTest2::testTdf111518()
             "M -3.54167E-6 -4.81481E-6 L 0.39037 -0.00069");
 }
 
+void SdOOXMLExportTest2::testTdf106867()
+{
+    ::sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/pptx/tdf106867.pptx"), PPTX);
+    utl::TempFile tempFile;
+    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+
+    const SdrPage *pPage = GetPage(1, xDocShRef.get());
+
+    // first check that we have the media object
+    const SdrMediaObj* pMediaObj = dynamic_cast<SdrMediaObj*>(pPage->GetObj(2));
+    CPPUNIT_ASSERT_MESSAGE("no media object", pMediaObj != nullptr);
+    CPPUNIT_ASSERT_EQUAL(OUString("vnd.sun.star.Package:ppt/media/media1.avi"), pMediaObj->getURL());
+
+    xDocShRef->DoClose();
+
+    // additional checks of the output file
+    uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), tempFile.GetURL());
+    // check that the document contains the video stream
+    CPPUNIT_ASSERT(xNameAccess->hasByName("ppt/media/media1.avi"));
+
+    // both the ooxml and the extended markup
+    xmlDocPtr pXmlDocContent = parseExport(tempFile, "ppt/slides/slide1.xml");
+    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:pic/p:nvPicPr/p:nvPr/a:videoFile");
+    assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:pic/p:nvPicPr/p:nvPr/p:extLst/p:ext/p14:media");
+
+    // target the shape with the video in the command
+    assertXPath(pXmlDocContent, "/p:sld/p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:cmd/p:cBhvr/p:tgtEl/p:spTgt",
+            "spid", "42");
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest2);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/source/filter/eppt/epptooxml.hxx b/sd/source/filter/eppt/epptooxml.hxx
index 1134daf6cb7a..ebfe5d345813 100644
--- a/sd/source/filter/eppt/epptooxml.hxx
+++ b/sd/source/filter/eppt/epptooxml.hxx
@@ -108,6 +108,7 @@ protected:
     void WriteAnimationNodeAnimateInside( const ::sax_fastparser::FSHelperPtr& pFS, const css::uno::Reference< css::animations::XAnimationNode >& rXNode, bool bMainSeqChild, bool bSimple );
     void WriteAnimationNodeSeq( const ::sax_fastparser::FSHelperPtr& pFS, const css::uno::Reference< css::animations::XAnimationNode >& rXNode, sal_Int32 nXmlNodeType, bool bMainSeqChild );
     void WriteAnimationNodeEffect( const ::sax_fastparser::FSHelperPtr& pFS, const css::uno::Reference< css::animations::XAnimationNode >& rXNode, sal_Int32 nXmlNodeType, bool bMainSeqChild );
+    void WriteAnimationNodeCommand(const ::sax_fastparser::FSHelperPtr& pFS, const css::uno::Reference< css::animations::XAnimationNode >& rXNode, sal_Int32 nXmlNodeType, bool bMainSeqChild );
     void WriteAnimationNodeCommonPropsStart( const ::sax_fastparser::FSHelperPtr& pFS, const css::uno::Reference< css::animations::XAnimationNode >& rXNode, bool bSingle, bool bMainSeqChild );
     static void WriteAnimationProperty( const ::sax_fastparser::FSHelperPtr& pFS, const css::uno::Any& rAny );
     void WriteAnimationTarget( const ::sax_fastparser::FSHelperPtr& pFS, const css::uno::Any& rTarget );
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx
index 383706809c89..d4d8fe6908b4 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -49,6 +49,7 @@
 #include <com/sun/star/animations/XAnimateMotion.hpp>
 #include <com/sun/star/animations/XAnimationNode.hpp>
 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
+#include <com/sun/star/animations/XCommand.hpp>
 #include <com/sun/star/animations/XTransitionFilter.hpp>
 #include <com/sun/star/beans/Property.hpp>
 #include <com/sun/star/beans/XPropertySetInfo.hpp>
@@ -60,6 +61,7 @@
 #include <com/sun/star/office/XAnnotationEnumeration.hpp>
 #include <com/sun/star/office/XAnnotationAccess.hpp>
 #include <com/sun/star/presentation/AnimationSpeed.hpp>
+#include <com/sun/star/presentation/EffectCommands.hpp>
 #include <com/sun/star/presentation/EffectNodeType.hpp>
 #include <com/sun/star/util/DateTime.hpp>
 
@@ -309,6 +311,8 @@ ShapeExport& PowerPointShapeExport::WriteUnknownShape( const Reference< XShape >
         if( !WritePlaceholder( xShape, Subtitle, mbMaster ) )
             ShapeExport::WriteTextShape( xShape );
     }
+    else
+        SAL_WARN("sd.eppt", "unknown shape not handled: " << USS(sShapeType));
 
     return *this;
 }
@@ -1061,6 +1065,7 @@ void PowerPointExport::WriteAnimationCondition( const FSHelperPtr& pFS, Any& rAn
     double fDelay = 0;
     Timing eTiming;
     Event aEvent;
+    Reference<XShape> xShape;
     const char* pDelay = nullptr;
     const char* pEvent = nullptr;
 
@@ -1127,6 +1132,15 @@ void PowerPointExport::WriteAnimationCondition( const FSHelperPtr& pFS, Any& rAn
         SAL_INFO("sd.eppt", "event offset timing: " << eTiming);
     }
     }
+    else if (rAny >>= xShape)
+    {
+        SAL_INFO("sd.eppt", "Got the xShape: " << xShape->getShapeType());
+        if (xShape->getShapeType() == "com.sun.star.drawing.MediaShape" || xShape->getShapeType() == "com.sun.star.presentation.MediaShape")
+        {
+            // write the default
+            bHasFDelay = true;
+        }
+    }
 
     WriteAnimationCondition( pFS, pDelay, pEvent, fDelay, bHasFDelay );
 }
@@ -1358,6 +1372,41 @@ void PowerPointExport::WriteAnimationNodeEffect( const FSHelperPtr& pFS, const R
     }
 }
 
+void PowerPointExport::WriteAnimationNodeCommand(const FSHelperPtr& pFS, const Reference< XAnimationNode >& rXNode, sal_Int32, bool bMainSeqChild)
+{
+    SAL_INFO("sd.eppt", "write animation node COMMAND");
+    Reference<XCommand> xCommand(rXNode, UNO_QUERY);
+    if (xCommand.is())
+    {
+        const char* pType = "call";
+        const char* pCommand = nullptr;
+        switch (xCommand->getCommand())
+        {
+        case EffectCommands::VERB:        pType = "verb"; pCommand = "1"; /* FIXME hardcoded viewing */ break;
+        case EffectCommands::PLAY:        pCommand = "play"; break;
+        case EffectCommands::TOGGLEPAUSE: pCommand = "togglePause"; break;
+        case EffectCommands::STOP:        pCommand = "stop"; break;
+        default:
+            SAL_WARN("sd.eppt", "unknown command: " << xCommand->getCommand());
+            break;
+        }
+
+        pFS->startElementNS(XML_p, XML_cmd,
+                            XML_type, pType,
+                            XML_cmd, pCommand,
+                            FSEND);
+
+        WriteAnimationNodeAnimateInside(pFS, rXNode, bMainSeqChild, false);
+        pFS->startElementNS(XML_p, XML_cBhvr,
+                            FSEND);
+        WriteAnimationNodeCommonPropsStart(pFS, rXNode, true, bMainSeqChild);
+        WriteAnimationTarget(pFS, xCommand->getTarget());
+        pFS->endElementNS(XML_p, XML_cBhvr);
+
+        pFS->endElementNS(XML_p, XML_cmd);
+    }
+}
+
 void PowerPointExport::WriteAnimationNode( const FSHelperPtr& pFS, const Reference< XAnimationNode >& rXNode, bool bMainSeqChild )
 {
     SAL_INFO("sd.eppt", "export node type: " << rXNode->getType());
@@ -1388,6 +1437,13 @@ void PowerPointExport::WriteAnimationNode( const FSHelperPtr& pFS, const Referen
         xmlNodeType = XML_animEffect;
         pMethod = &PowerPointExport::WriteAnimationNodeEffect;
         break;
+    case AnimationNodeType::COMMAND:
+        xmlNodeType = XML_cmd;
+        pMethod = &PowerPointExport::WriteAnimationNodeCommand;
+        break;
+    default:
+        SAL_WARN("sd.eppt", "unhandled: " << rXNode->getType());
+        break;
     }
 
     if( pMethod ) {


More information about the Libreoffice-commits mailing list