diff options
-rw-r--r-- | sd/qa/filter/eppt/data/video-loop.pptx | bin | 0 -> 46545 bytes | |||
-rw-r--r-- | sd/qa/filter/eppt/eppt.cxx | 26 | ||||
-rw-r--r-- | sd/source/filter/eppt/pptx-animations.cxx | 47 |
3 files changed, 65 insertions, 8 deletions
diff --git a/sd/qa/filter/eppt/data/video-loop.pptx b/sd/qa/filter/eppt/data/video-loop.pptx Binary files differnew file mode 100644 index 000000000000..4cb7e20b7428 --- /dev/null +++ b/sd/qa/filter/eppt/data/video-loop.pptx diff --git a/sd/qa/filter/eppt/eppt.cxx b/sd/qa/filter/eppt/eppt.cxx index 1e8e2c7e1491..151b9cfce27a 100644 --- a/sd/qa/filter/eppt/eppt.cxx +++ b/sd/qa/filter/eppt/eppt.cxx @@ -125,6 +125,32 @@ CPPUNIT_TEST_FIXTURE(Test, testThemeExport) // i.e. the RGB color was lost on export. xComponent->dispose(); } + +CPPUNIT_TEST_FIXTURE(Test, testLoopingFromAnimation) +{ + // Given a media shape that has an animation that specifies looping for the video: + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "video-loop.pptx"; + getComponent() = loadFromDesktop(aURL); + + // When exporting that to PPTX: + utl::TempFile aTempFile; + uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("Impress Office Open XML"); + aTempFile.EnableKillingFile(); + xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + validate(aTempFile.GetFileName(), test::OOXML); + + // Then make sure that the "infinite" repeat count is written: + std::unique_ptr<SvStream> pStream = parseExportStream(aTempFile, "ppt/slides/slide1.xml"); + xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); + // Without the fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 0 + // - In <>, XPath '//p:cMediaNode/p:cTn' number of nodes is incorrect + // i.e. the media node was lost on export, the video no longer looped. + assertXPath(pXmlDoc, "//p:cMediaNode/p:cTn", "repeatCount", "indefinite"); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sd/source/filter/eppt/pptx-animations.cxx b/sd/source/filter/eppt/pptx-animations.cxx index 54dab17d1972..1c901573c00a 100644 --- a/sd/source/filter/eppt/pptx-animations.cxx +++ b/sd/source/filter/eppt/pptx-animations.cxx @@ -659,6 +659,9 @@ bool IsAudioURL(const OUString& rURL) { return rURL.endsWithIgnoreAsciiCase(".wav") || rURL.endsWithIgnoreAsciiCase(".m4a"); } + +/// Returns if rURL has an extension which is a video format. +bool IsVideoURL(const OUString& rURL) { return rURL.endsWithIgnoreAsciiCase(".mp4"); } } namespace oox::core @@ -1235,6 +1238,7 @@ void PPTXAnimationExport::WriteAnimationNodeAudio() bValid = true; } + bool bVideo = false; if (!bValid) { if (xAudio->getSource() >>= xShape) @@ -1243,7 +1247,8 @@ void PPTXAnimationExport::WriteAnimationNodeAudio() bool bHasMediaURL = xShapeProps->getPropertySetInfo()->hasPropertyByName("MediaURL"); if (bHasMediaURL && (xShapeProps->getPropertyValue("MediaURL") >>= sUrl)) { - bValid = IsAudioURL(sUrl); + bVideo = IsVideoURL(sUrl); + bValid = IsAudioURL(sUrl) || bVideo; } } } @@ -1256,12 +1261,31 @@ void PPTXAnimationExport::WriteAnimationNodeAudio() mrPowerPointExport.embedEffectAudio(mpFS, sUrl, sRelId, sName); } - bool bNarration = xAudio->getNarration(); - mpFS->startElementNS(XML_p, XML_audio, XML_isNarration, bNarration ? "1" : "0"); - bool bHideDuringShow = xAudio->getHideDuringShow(); - mpFS->startElementNS(XML_p, XML_cMediaNode, XML_showWhenStopped, bHideDuringShow ? "0" : "1"); + if (bVideo) + { + mpFS->startElementNS(XML_p, XML_video); + mpFS->startElementNS(XML_p, XML_cMediaNode); + } + else + { + bool bNarration = xAudio->getNarration(); + mpFS->startElementNS(XML_p, XML_audio, XML_isNarration, bNarration ? "1" : "0"); + bool bHideDuringShow = xAudio->getHideDuringShow(); + mpFS->startElementNS(XML_p, XML_cMediaNode, XML_showWhenStopped, + bHideDuringShow ? "0" : "1"); + } - mpFS->startElementNS(XML_p, XML_cTn); + animations::Timing eTiming{}; + bool bLooping + = (xAudio->getRepeatCount() >>= eTiming) && eTiming == animations::Timing_INDEFINITE; + if (bVideo && bLooping) + { + mpFS->startElementNS(XML_p, XML_cTn, XML_repeatCount, "indefinite"); + } + else + { + mpFS->startElementNS(XML_p, XML_cTn); + } WriteAnimationCondList(mpContext->getCondition(true), XML_stCondLst); WriteAnimationCondList(mpContext->getCondition(false), XML_endCondLst); mpFS->endElementNS(XML_p, XML_cTn); @@ -1281,7 +1305,14 @@ void PPTXAnimationExport::WriteAnimationNodeAudio() mpFS->endElementNS(XML_p, XML_tgtEl); mpFS->endElementNS(XML_p, XML_cMediaNode); - mpFS->endElementNS(XML_p, XML_audio); + if (bVideo) + { + mpFS->endElementNS(XML_p, XML_video); + } + else + { + mpFS->endElementNS(XML_p, XML_audio); + } } void PPTXAnimationExport::WriteAnimationNode(const NodeContextPtr& pContext) @@ -1456,7 +1487,7 @@ void NodeContext::initValid(bool bHasValidChild, bool bIsIterateChild) = xShapeProps->getPropertySetInfo()->hasPropertyByName("MediaURL"); if (bHasMediaURL && (xShapeProps->getPropertyValue("MediaURL") >>= sURL)) { - mbValid = IsAudioURL(sURL); + mbValid = IsAudioURL(sURL) || IsVideoURL(sURL); } } } |