summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Hung <marklh9@gmail.com>2019-02-19 23:54:55 +0800
committerMark Hung <marklh9@gmail.com>2019-02-27 11:11:32 +0100
commit4076b7589a7c856beb4fe2f7f5cd784443415cd3 (patch)
treecfb9ba025fddb1a8a16565e5a56cf7f850d14297
parentUnit test for array formula and OFFSET() non-ReferenceOrRefArray, tdf#123477 (diff)
downloadcore-4076b7589a7c856beb4fe2f7f5cd784443415cd3.tar.gz
core-4076b7589a7c856beb4fe2f7f5cd784443415cd3.zip
tdf#123557 PPTX: Export timenode condition targets.
Refactor the code and reuse WriteAnimationTarget to export the target element for the condition element in stCondLst and endCondLst. Add testTdf123557 to make sure import-export-import works. As SdOOXMLExportTest2::testTdf90627 no longer produce corupt pptx that has endCondLst without Cond element, make the xpath more specific about what is testing. Update schema because drawooo:enhanced-path incluced in the test case. Change-Id: If5d64f5c23aa2652cfa72471f9f7886c7dd956eb Reviewed-on: https://gerrit.libreoffice.org/68211 Tested-by: Jenkins Reviewed-by: Mark Hung <marklh9@gmail.com>
-rw-r--r--schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng5
-rw-r--r--sd/qa/unit/data/pptx/trigger.pptxbin0 -> 32278 bytes
-rw-r--r--sd/qa/unit/export-tests-ooxml2.cxx4
-rw-r--r--sd/qa/unit/export-tests.cxx24
-rw-r--r--sd/source/filter/eppt/pptx-animations.cxx307
5 files changed, 198 insertions, 142 deletions
diff --git a/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng b/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng
index 19786f82a7e1..e5a0116bd029 100644
--- a/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng
+++ b/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng
@@ -2266,6 +2266,11 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
<rng:ref name="string"/>
</rng:attribute>
</rng:optional>
+ <rng:optional>
+ <rng:attribute name="drawooo:enhanced-path">
+ <rng:ref name="string"/>
+ </rng:attribute>
+ </rng:optional>
</rng:define>
<!-- TODO no proposal -->
diff --git a/sd/qa/unit/data/pptx/trigger.pptx b/sd/qa/unit/data/pptx/trigger.pptx
new file mode 100644
index 000000000000..fdfb397402a0
--- /dev/null
+++ b/sd/qa/unit/data/pptx/trigger.pptx
Binary files differ
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx
index 0d63f6b0f508..ae60952752fc 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -1764,8 +1764,8 @@ void SdOOXMLExportTest2::testTdf90627()
xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
xmlDocPtr pXmlDocContent = parseExport(tempFile, "ppt/slides/slide1.xml");
- // Don't export empty conditions
- assertXPath(pXmlDocContent, "/p:sld/p:timing/p:tnLst/p:par/p:cTn/p:childTnLst[1]/p:seq/p:cTn/p:childTnLst[1]/p:par[2]/p:cTn/p:childTnLst[1]/p:par/p:cTn/p:childTnLst[1]/p:par/p:cTn/p:endCondLst", 0);
+ // Don't export empty endCondLst without cond.
+ assertXPath(pXmlDocContent, "/p:sld/p:timing/p:tnLst/p:par/p:cTn/p:childTnLst[1]/p:seq/p:cTn/p:childTnLst[1]/p:par[2]/p:cTn/p:childTnLst[1]/p:par/p:cTn/p:childTnLst[1]/p:par/p:cTn/p:endCondLst[not(*)]", 0);
xDocShRef->DoClose();
}
diff --git a/sd/qa/unit/export-tests.cxx b/sd/qa/unit/export-tests.cxx
index dc2fa945194e..d7fa712c3b5a 100644
--- a/sd/qa/unit/export-tests.cxx
+++ b/sd/qa/unit/export-tests.cxx
@@ -103,6 +103,7 @@ public:
void testBulletsAsImage();
void testTdf113818();
void testTdf119629();
+ void testTdf123557();
void testTdf113822();
CPPUNIT_TEST_SUITE(SdExportTest);
@@ -132,6 +133,7 @@ public:
CPPUNIT_TEST(testBulletsAsImage);
CPPUNIT_TEST(testTdf113818);
CPPUNIT_TEST(testTdf119629);
+ CPPUNIT_TEST(testTdf123557);
CPPUNIT_TEST(testTdf113822);
CPPUNIT_TEST_SUITE_END();
@@ -153,6 +155,7 @@ public:
{ "text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0" },
{ "xlink", "http://www.w3c.org/1999/xlink" },
{ "loext", "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" },
+ { "smil", "urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" },
// user-defined
{ "foo", "http://example.com/" },
};
@@ -1160,6 +1163,27 @@ void SdExportTest::testTdf119629()
xDocShRef->DoClose();
}
+void SdExportTest::testTdf123557()
+{
+ utl::TempFile tempFile;
+ sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/pptx/trigger.pptx"), PPTX);
+ xDocShRef = saveAndReload(xDocShRef.get(), PPTX);
+ xDocShRef = saveAndReload(xDocShRef.get(), ODP, &tempFile);
+ xmlDocPtr pXmlDoc = parseExport(tempFile, "content.xml");
+
+ // Contians 2 interactive sequence and 3 triggered effects.
+ assertXPath(pXmlDoc, "//draw:page", 1);
+ assertXPath(pXmlDoc, "//draw:page/anim:par", 1);
+ assertXPath(pXmlDoc, "//draw:page"
+ "/anim:par[@presentation:node-type='timing-root']"
+ "/anim:seq[@presentation:node-type='interactive-sequence']", 2);
+ assertXPath(pXmlDoc, "//draw:page"
+ "/anim:par[@presentation:node-type='timing-root']"
+ "/anim:seq[@presentation:node-type='interactive-sequence']"
+ "/anim:par[@smil:begin]",3);
+ xDocShRef->DoClose();
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(SdExportTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/source/filter/eppt/pptx-animations.cxx b/sd/source/filter/eppt/pptx-animations.cxx
index 23a2ba7c2378..7e0967d19789 100644
--- a/sd/source/filter/eppt/pptx-animations.cxx
+++ b/sd/source/filter/eppt/pptx-animations.cxx
@@ -231,126 +231,60 @@ void WriteAnimateValues(const FSHelperPtr& pFS, const Reference<XAnimate>& rXAni
pFS->endElementNS(XML_p, XML_tavLst);
}
-void WriteAnimationCondition(const FSHelperPtr& pFS, const char* pDelay, const char* pEvent,
- double fDelay, bool bHasFDelay, sal_Int32 nToken)
+// Write condition list ( either prevCondlst or nextCondlst ) of Seq.
+void WriteAnimationCondListForSeq(const FSHelperPtr& pFS, sal_Int32 nToken)
{
- if (!(bHasFDelay || pDelay || pEvent))
- return;
+ const char* pEvent = (nToken == XML_prevCondLst) ? "onPrev" : "onNext";
pFS->startElementNS(XML_p, nToken, FSEND);
-
- if (!pEvent)
- pFS->singleElementNS(XML_p, XML_cond, XML_delay,
- bHasFDelay ? I64S(static_cast<sal_uInt32>(fDelay * 1000.0)) : pDelay,
- FSEND);
- else
- {
- pFS->startElementNS(XML_p, XML_cond, XML_delay,
- bHasFDelay ? I64S(static_cast<sal_uInt32>(fDelay * 1000.0)) : pDelay,
- XML_evt, pEvent, FSEND);
-
- pFS->startElementNS(XML_p, XML_tgtEl, FSEND);
- pFS->singleElementNS(XML_p, XML_sldTgt, FSEND);
- pFS->endElementNS(XML_p, XML_tgtEl);
-
- pFS->endElementNS(XML_p, XML_cond);
- }
-
+ pFS->startElementNS(XML_p, XML_cond, XML_evt, pEvent, FSEND);
+ pFS->startElementNS(XML_p, XML_tgtEl, FSEND);
+ pFS->singleElementNS(XML_p, XML_sldTgt, FSEND);
+ pFS->endElementNS(XML_p, XML_tgtEl);
+ pFS->endElementNS(XML_p, XML_cond);
pFS->endElementNS(XML_p, nToken);
}
-void WriteAnimationCondition(const FSHelperPtr& pFS, Any const& rAny, bool bWriteEvent,
- bool bMainSeqChild, sal_Int32 nToken)
+const char* convertEventTrigger(sal_Int16 nTrigger)
{
- bool bHasFDelay = false;
- double fDelay = 0;
- Timing eTiming;
- Event aEvent;
- Reference<XShape> xShape;
- const char* pDelay = nullptr;
const char* pEvent = nullptr;
-
- if (rAny >>= fDelay)
- bHasFDelay = true;
- else if (rAny >>= eTiming)
- {
- if (eTiming == Timing_INDEFINITE)
- pDelay = "indefinite";
- }
- else if (rAny >>= aEvent)
- {
- // TODO
-
- SAL_INFO("sd.eppt", "animation condition event: TODO");
- SAL_INFO("sd.eppt", "event offset has value: "
- << aEvent.Offset.hasValue() << " trigger: " << aEvent.Trigger
- << " source has value: " << aEvent.Source.hasValue());
- if (!bWriteEvent && aEvent.Trigger == EventTrigger::ON_NEXT && bMainSeqChild)
- pDelay = "indefinite";
- else if (bWriteEvent)
- {
- switch (aEvent.Trigger)
- {
- case EventTrigger::ON_NEXT:
- pEvent = "onNext";
- break;
- case EventTrigger::ON_PREV:
- pEvent = "onPrev";
- break;
- case EventTrigger::BEGIN_EVENT:
- pEvent = "begin";
- break;
- case EventTrigger::END_EVENT:
- pEvent = "end";
- break;
- case EventTrigger::ON_BEGIN:
- pEvent = "onBegin";
- break;
- case EventTrigger::ON_END:
- pEvent = "onEnd";
- break;
- case EventTrigger::ON_CLICK:
- pEvent = "onClick";
- break;
- case EventTrigger::ON_DBL_CLICK:
- pEvent = "onDblClick";
- break;
- case EventTrigger::ON_STOP_AUDIO:
- pEvent = "onStopAudio";
- break;
- case EventTrigger::ON_MOUSE_ENTER:
- pEvent = "onMouseOver"; // not exact?
- break;
- case EventTrigger::ON_MOUSE_LEAVE:
- pEvent = "onMouseOut";
- break;
- }
- }
-
- if (aEvent.Offset >>= fDelay)
- {
- bHasFDelay = true;
- SAL_INFO("sd.eppt", "event offset: " << fDelay);
- }
- else if (aEvent.Offset >>= eTiming)
- {
- if (eTiming == Timing_INDEFINITE)
- pDelay = "indefinite";
- SAL_INFO("sd.eppt", "event offset timing: " << static_cast<int>(eTiming));
- }
- }
- else if (rAny >>= xShape)
+ switch (nTrigger)
{
- 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;
- }
+ case EventTrigger::ON_NEXT:
+ pEvent = "onNext";
+ break;
+ case EventTrigger::ON_PREV:
+ pEvent = "onPrev";
+ break;
+ case EventTrigger::BEGIN_EVENT:
+ pEvent = "begin";
+ break;
+ case EventTrigger::END_EVENT:
+ pEvent = "end";
+ break;
+ case EventTrigger::ON_BEGIN:
+ pEvent = "onBegin";
+ break;
+ case EventTrigger::ON_END:
+ pEvent = "onEnd";
+ break;
+ case EventTrigger::ON_CLICK:
+ pEvent = "onClick";
+ break;
+ case EventTrigger::ON_DBL_CLICK:
+ pEvent = "onDblClick";
+ break;
+ case EventTrigger::ON_STOP_AUDIO:
+ pEvent = "onStopAudio";
+ break;
+ case EventTrigger::ON_MOUSE_ENTER:
+ pEvent = "onMouseOver"; // not exact?
+ break;
+ case EventTrigger::ON_MOUSE_LEAVE:
+ pEvent = "onMouseOut";
+ break;
}
-
- WriteAnimationCondition(pFS, pDelay, pEvent, fDelay, bHasFDelay, nToken);
+ return pEvent;
}
void WriteAnimationAttributeName(const FSHelperPtr& pFS, const OUString& rAttributeName)
@@ -622,8 +556,57 @@ public:
const OUString& getEffectPresetSubType() const { return msEffectPresetSubType; }
bool isValid() const { return mbValid; }
const std::vector<NodeContextPtr>& getChildNodes() const { return maChildNodes; };
+ Any getCondition(bool bBegin) const;
};
+struct Cond
+{
+ OString msDelay;
+ const char* mpEvent;
+ Reference<XShape> mxShape;
+
+ Cond(const Any& rAny, bool bIsMainSeqChild);
+
+ bool isValid() { return msDelay.getLength() || mpEvent; }
+ const char* getDelay() const { return msDelay.getLength() ? msDelay.getStr() : nullptr; }
+};
+
+Cond::Cond(const Any& rAny, bool bIsMainSeqChild)
+ : mpEvent(nullptr)
+{
+ bool bHasFDelay = false;
+ double fDelay = 0;
+ Timing eTiming;
+ Event aEvent;
+
+ if (rAny >>= eTiming)
+ {
+ if (eTiming == Timing_INDEFINITE)
+ msDelay = "indefinite";
+ }
+ else if (rAny >>= aEvent)
+ {
+ if (aEvent.Trigger == EventTrigger::ON_NEXT && bIsMainSeqChild)
+ msDelay = "indefinite";
+ else
+ {
+ mpEvent = convertEventTrigger(aEvent.Trigger);
+ aEvent.Source >>= mxShape;
+
+ if (aEvent.Offset >>= fDelay)
+ bHasFDelay = true;
+ }
+ }
+ else if (rAny >>= fDelay)
+ bHasFDelay = true;
+
+ if (bHasFDelay)
+ {
+ sal_Int32 nDelay = static_cast<sal_uInt32>(fDelay * 1000.0);
+ msDelay = OString::number(nDelay);
+ }
+}
+
class PPTXAnimationExport
{
void WriteAnimationNode(const NodeContextPtr& pContext);
@@ -634,6 +617,8 @@ class PPTXAnimationExport
void WriteAnimationNodeCommand();
void WriteAnimationNodeCommonPropsStart();
void WriteAnimationTarget(const Any& rTarget);
+ void WriteAnimationCondList(const Any& rAny, sal_Int32 nToken);
+ void WriteAnimationCond(const Cond& rCond);
bool isMainSeqChild();
const Reference<XAnimationNode>& getCurrentNode();
@@ -721,6 +706,64 @@ void PPTXAnimationExport::WriteAnimationTarget(const Any& rTarget)
mpFS->endElementNS(XML_p, XML_tgtEl);
}
+void PPTXAnimationExport::WriteAnimationCondList(const Any& rAny, sal_Int32 nToken)
+{
+ if (!rAny.hasValue())
+ return;
+
+ std::vector<Cond> aList;
+
+ bool bIsMainSeqChild = isMainSeqChild();
+
+ Sequence<Any> aCondSeq;
+ if (rAny >>= aCondSeq)
+ {
+ for (int i = 0; i < aCondSeq.getLength(); i++)
+ {
+ Cond aCond(aCondSeq[i], bIsMainSeqChild);
+ if (aCond.isValid())
+ aList.push_back(aCond);
+ }
+ }
+ else
+ {
+ Cond aCond(rAny, bIsMainSeqChild);
+ if (aCond.isValid())
+ aList.push_back(aCond);
+ }
+
+ if (aList.size() > 0)
+ {
+ mpFS->startElementNS(XML_p, nToken, FSEND);
+
+ for (const Cond& rCond : aList)
+ WriteAnimationCond(rCond);
+
+ mpFS->endElementNS(XML_p, nToken);
+ }
+}
+
+void PPTXAnimationExport::WriteAnimationCond(const Cond& rCond)
+{
+ if (rCond.mpEvent)
+ {
+ if (rCond.mxShape.is())
+ {
+ mpFS->startElementNS(XML_p, XML_cond, XML_delay, rCond.getDelay(), XML_evt,
+ rCond.mpEvent, FSEND);
+ WriteAnimationTarget(makeAny(rCond.mxShape));
+ mpFS->endElementNS(XML_p, XML_cond);
+ }
+ else
+ {
+ mpFS->singleElementNS(XML_p, XML_cond, XML_delay, rCond.getDelay(), XML_evt,
+ rCond.mpEvent, FSEND);
+ }
+ }
+ else
+ mpFS->singleElementNS(XML_p, XML_cond, XML_delay, rCond.getDelay(), FSEND);
+}
+
void PPTXAnimationExport::WriteAnimationNodeAnimate(sal_Int32 nXmlNodeType)
{
const Reference<XAnimationNode>& rXNode = getCurrentNode();
@@ -917,7 +960,6 @@ void PPTXAnimationExport::WriteAnimationNodeAnimateInside(bool bSimple, bool bWr
void PPTXAnimationExport::WriteAnimationNodeCommonPropsStart()
{
const Reference<XAnimationNode>& rXNode = getCurrentNode();
- bool bMainSeqChild = isMainSeqChild();
const char* pDuration = nullptr;
const char* pRestart = nullptr;
const char* pNodeType = nullptr;
@@ -999,33 +1041,8 @@ void PPTXAnimationExport::WriteAnimationNodeCommonPropsStart()
pFill, XML_presetClass, pPresetClass, XML_presetID, bPresetId ? I64S(nPresetId) : nullptr,
XML_presetSubtype, bPresetSubType ? I64S(nPresetSubType) : nullptr, FSEND);
- aAny = rXNode->getBegin();
- if (aAny.hasValue())
- {
- Sequence<Any> aCondSeq;
-
- if (aAny >>= aCondSeq)
- {
- for (int i = 0; i < aCondSeq.getLength(); i++)
- WriteAnimationCondition(mpFS, aCondSeq[i], false, bMainSeqChild, XML_stCondLst);
- }
- else
- WriteAnimationCondition(mpFS, aAny, false, bMainSeqChild, XML_stCondLst);
- }
-
- aAny = rXNode->getEnd();
- if (aAny.hasValue())
- {
- Sequence<Any> aCondSeq;
-
- if (aAny >>= aCondSeq)
- {
- for (int i = 0; i < aCondSeq.getLength(); i++)
- WriteAnimationCondition(mpFS, aCondSeq[i], false, bMainSeqChild, XML_endCondLst);
- }
- else
- WriteAnimationCondition(mpFS, aAny, false, bMainSeqChild, XML_endCondLst);
- }
+ WriteAnimationCondList(mpContext->getCondition(true), XML_stCondLst);
+ WriteAnimationCondList(mpContext->getCondition(false), XML_endCondLst);
if (rXNode->getType() == AnimationNodeType::ITERATE)
{
@@ -1063,8 +1080,8 @@ void PPTXAnimationExport::WriteAnimationNodeSeq()
WriteAnimationNodeCommonPropsStart();
- WriteAnimationCondition(mpFS, nullptr, "onPrev", 0, true, XML_prevCondLst);
- WriteAnimationCondition(mpFS, nullptr, "onNext", 0, true, XML_nextCondLst);
+ WriteAnimationCondListForSeq(mpFS, XML_prevCondLst);
+ WriteAnimationCondListForSeq(mpFS, XML_nextCondLst);
mpFS->endElementNS(XML_p, XML_seq);
}
@@ -1298,4 +1315,14 @@ bool NodeContext::initChildNodes()
}
return bValid;
}
+
+Any NodeContext::getCondition(bool bBegin) const
+{
+ const bool bParent
+ = (mnEffectNodeType != EffectNodeType::INTERACTIVE_SEQUENCE || maChildNodes.empty());
+ const Reference<XAnimationNode>& rNode = bParent ? mxNode : maChildNodes[0]->getNode();
+
+ return bBegin ? rNode->getBegin() : rNode->getEnd();
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */