[Libreoffice-commits] core.git: schema/libreoffice sd/qa sd/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Wed Feb 27 10:11:58 UTC 2019


 schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng |    5 
 sd/qa/unit/data/pptx/trigger.pptx                           |binary
 sd/qa/unit/export-tests-ooxml2.cxx                          |    4 
 sd/qa/unit/export-tests.cxx                                 |   24 
 sd/source/filter/eppt/pptx-animations.cxx                   |  307 ++++++------
 5 files changed, 198 insertions(+), 142 deletions(-)

New commits:
commit 4076b7589a7c856beb4fe2f7f5cd784443415cd3
Author:     Mark Hung <marklh9 at gmail.com>
AuthorDate: Tue Feb 19 23:54:55 2019 +0800
Commit:     Mark Hung <marklh9 at gmail.com>
CommitDate: Wed Feb 27 11:11:32 2019 +0100

    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 at gmail.com>

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
Binary files /dev/null and b/sd/qa/unit/data/pptx/trigger.pptx 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: */


More information about the Libreoffice-commits mailing list