sd/qa/unit/data/odp/tdf99213-target-missing.odp |binary
 sd/qa/unit/export-tests-ooxml2.cxx              |   15 ++
 sd/source/filter/eppt/pptx-animations.cxx       |  143 ++++++++++++++++++------
 3 files changed, 126 insertions(+), 32 deletions(-)

New commits:
commit 612db6877a73e6f9b142b81697291f02c0adb95f
Author:     Mark Hung <mark...@gmail.com>
AuthorDate: Sat Sep 1 11:11:38 2018 +0800
Commit:     Mark Hung <mark...@gmail.com>
CommitDate: Fri Sep 7 13:11:41 2018 +0200

    tdf#99213: don't export invalid child nodes.
    
    Create NodeContext for all child nodes at beginning and
    check if they are valid, either it has a valid target or
    it contains valid nodes, so that we only export valid
    node later.
    
    Change-Id: I660d99011eb57ddc79f727455fce0be8876e8b17
    Reviewed-on: https://gerrit.libreoffice.org/59892
    Tested-by: Jenkins
    Reviewed-by: Mark Hung <mark...@gmail.com>

diff --git a/sd/qa/unit/data/odp/tdf99213-target-missing.odp 
b/sd/qa/unit/data/odp/tdf99213-target-missing.odp
new file mode 100644
index 000000000000..3bc8c7260c8c
Binary files /dev/null and b/sd/qa/unit/data/odp/tdf99213-target-missing.odp 
differ
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx 
b/sd/qa/unit/export-tests-ooxml2.cxx
index 6920531af778..fa994f219d6a 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -193,6 +193,7 @@ public:
     void testTdf116350TextEffects();
     void testTdf118825();
     void testTdf119118();
+    void testTdf99213();
 
     CPPUNIT_TEST_SUITE(SdOOXMLExportTest2);
 
@@ -269,6 +270,7 @@ public:
     CPPUNIT_TEST(testTdf116350TextEffects);
     CPPUNIT_TEST(testTdf118825);
     CPPUNIT_TEST(testTdf119118);
+    CPPUNIT_TEST(testTdf99213);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -1987,6 +1989,19 @@ void SdOOXMLExportTest2::testTdf119118()
     xDocShRef->DoClose();
 }
 
+void SdOOXMLExportTest2::testTdf99213()
+{
+    ::sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc( 
"sd/qa/unit/data/odp/tdf99213-target-missing.odp" ), ODP);
+    utl::TempFile tempFile;
+    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+    xmlDocPtr pXmlDocContent = parseExport(tempFile, "ppt/slides/slide1.xml");
+    // Number of nodes with p:attrNameLst was 3, including one that missed 
tgtEl
+    assertXPath(pXmlDocContent, "//p:attrNameLst", 2);
+    // Timenode that miss its target element should be filtered.
+    assertXPath(pXmlDocContent, "//p:attrNameLst/preceding-sibling::p:tgtEl", 
2);
+    xDocShRef->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest2);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/source/filter/eppt/pptx-animations.cxx 
b/sd/source/filter/eppt/pptx-animations.cxx
index 7a64828ddfd1..b02ccdcc4cb7 100644
--- a/sd/source/filter/eppt/pptx-animations.cxx
+++ b/sd/source/filter/eppt/pptx-animations.cxx
@@ -410,6 +410,21 @@ void WriteAnimationAttributeName(const FSHelperPtr& pFS, 
const OUString& rAttrib
     pFS->endElementNS(XML_p, XML_attrNameLst);
 }
 
+bool isValidTarget(const Any& rTarget)
+{
+    Reference<XShape> xShape;
+
+    if ((rTarget >>= xShape) && xShape.is())
+        return true;
+
+    ParagraphTarget aParagraphTarget;
+
+    if ((rTarget >>= aParagraphTarget) && aParagraphTarget.Shape.is())
+        return true;
+
+    return false;
+}
+
 /// convert animation node type to corresponding ooxml element.
 sal_Int32 convertNodeType(sal_Int16 nType)
 {
@@ -575,9 +590,13 @@ typedef std::unique_ptr<NodeContext> NodeContextPtr;
 
 class NodeContext
 {
-    const Reference<XAnimationNode>& mxNode;
+    const Reference<XAnimationNode> mxNode;
     const bool mbMainSeqChild;
 
+    std::vector<NodeContextPtr> maChildNodes;
+    // if the node has valid target or contains at least one valid target.
+    bool mbValid;
+
     // Attributes initialized from mxNode->getUserData().
     sal_Int16 mnEffectNodeType;
     sal_Int16 mnEffectPresetClass;
@@ -587,14 +606,23 @@ class NodeContext
     /// constructor helper for initializing user datas.
     void initUserData();
 
+    /// constructor helper to initialize maChildNodes.
+    /// return true if at least one childnode is valid.
+    bool initChildNodes();
+
+    /// constructor helper to initialize mbValid
+    void initValid(bool bHasValidChild, bool bIsIterateChild);
+
 public:
-    NodeContext(const Reference<XAnimationNode>& xNode, bool bMainSeqChild);
+    NodeContext(const Reference<XAnimationNode>& xNode, bool bMainSeqChild, 
bool bIsIterateChild);
     const Reference<XAnimationNode>& getNode() const { return mxNode; }
     bool isMainSeqChild() const { return mbMainSeqChild; }
     sal_Int16 getEffectNodeType() const { return mnEffectNodeType; }
     sal_Int16 getEffectPresetClass() const { return mnEffectPresetClass; }
     const OUString& getEffectPresetId() const { return msEffectPresetId; }
     const OUString& getEffectPresetSubType() const { return 
msEffectPresetSubType; }
+    bool isValid() const { return mbValid; }
+    const std::vector<NodeContextPtr>& getChildNodes() const { return 
maChildNodes; };
 };
 
 class PPTXAnimationExport
@@ -1014,34 +1042,17 @@ void 
PPTXAnimationExport::WriteAnimationNodeCommonPropsStart()
         }
     }
 
-    Reference<XEnumerationAccess> xEnumerationAccess(rXNode, UNO_QUERY);
-    if (xEnumerationAccess.is())
+    const std::vector<NodeContextPtr>& aChildNodes = 
mpContext->getChildNodes();
+    if (!aChildNodes.empty())
     {
-        Reference<XEnumeration> 
xEnumeration(xEnumerationAccess->createEnumeration(), UNO_QUERY);
-        if (xEnumeration.is())
+        mpFS->startElementNS(XML_p, XML_childTnLst, FSEND);
+        for (const NodeContextPtr& pChildContext : aChildNodes)
         {
-            SAL_INFO("sd.eppt", "-----");
-
-            if (xEnumeration->hasMoreElements())
-            {
-                mpFS->startElementNS(XML_p, XML_childTnLst, FSEND);
-
-                do
-                {
-                    Reference<XAnimationNode> 
xChildNode(xEnumeration->nextElement(), UNO_QUERY);
-                    if (xChildNode.is())
-                    {
-                        WriteAnimationNode(o3tl::make_unique<NodeContext>(
-                            xChildNode, nType == 
EffectNodeType::MAIN_SEQUENCE));
-                    }
-                } while (xEnumeration->hasMoreElements());
-
-                mpFS->endElementNS(XML_p, XML_childTnLst);
-            }
-            SAL_INFO("sd.eppt", "-----");
+            if (pChildContext->isValid())
+                WriteAnimationNode(pChildContext);
         }
+        mpFS->endElementNS(XML_p, XML_childTnLst);
     }
-
     mpFS->endElementNS(XML_p, XML_cTn);
 }
 
@@ -1190,26 +1201,36 @@ void PPTXAnimationExport::WriteAnimations(const 
Reference<XDrawPage>& rXDrawPage
                                                      UNO_QUERY);
                 if (xEnumeration.is() && xEnumeration->hasMoreElements())
                 {
-                    mpFS->startElementNS(XML_p, XML_timing, FSEND);
-                    mpFS->startElementNS(XML_p, XML_tnLst, FSEND);
+                    auto pNodeContext = o3tl::make_unique<NodeContext>(xNode, 
false, false);
+                    if (pNodeContext->isValid())
+                    {
+                        mpFS->startElementNS(XML_p, XML_timing, FSEND);
+                        mpFS->startElementNS(XML_p, XML_tnLst, FSEND);
 
-                    WriteAnimationNode(o3tl::make_unique<NodeContext>(xNode, 
false));
+                        WriteAnimationNode(pNodeContext);
 
-                    mpFS->endElementNS(XML_p, XML_tnLst);
-                    mpFS->endElementNS(XML_p, XML_timing);
+                        mpFS->endElementNS(XML_p, XML_tnLst);
+                        mpFS->endElementNS(XML_p, XML_timing);
+                    }
                 }
             }
         }
     }
 }
 
-NodeContext::NodeContext(const Reference<XAnimationNode>& xNode, bool 
bMainSeqChild)
+NodeContext::NodeContext(const Reference<XAnimationNode>& xNode, bool 
bMainSeqChild,
+                         bool bIsIterateChild)
     : mxNode(xNode)
     , mbMainSeqChild(bMainSeqChild)
+    , mbValid(true)
     , mnEffectNodeType(-1)
     , mnEffectPresetClass(DFF_ANIM_PRESS_CLASS_USER_DEFINED)
 {
+    assert(xNode.is());
+
     initUserData();
+
+    initValid(initChildNodes(), bIsIterateChild);
 }
 
 void NodeContext::initUserData()
@@ -1237,4 +1258,62 @@ void NodeContext::initUserData()
         *pAny >>= msEffectPresetSubType;
 }
 
+void NodeContext::initValid(bool bHasValidChild, bool bIsIterateChild)
+{
+    sal_Int16 nType = mxNode->getType();
+
+    if (nType == AnimationNodeType::ITERATE)
+    {
+        Reference<XIterateContainer> xIterate(mxNode, UNO_QUERY);
+        mbValid = xIterate.is() && (bIsIterateChild || 
isValidTarget(xIterate->getTarget()))
+                  && maChildNodes.size();
+    }
+    else if (nType == AnimationNodeType::COMMAND)
+    {
+        Reference<XCommand> xCommand(mxNode, UNO_QUERY);
+        mbValid = xCommand.is() && (bIsIterateChild || 
isValidTarget(xCommand->getTarget()));
+    }
+    else if (nType == AnimationNodeType::PAR || nType == 
AnimationNodeType::SEQ)
+    {
+        mbValid = bHasValidChild;
+    }
+    else if (nType == AnimationNodeType::AUDIO)
+    {
+        SAL_WARN("sd.eppt", "Export AUDIO node is not supported yet.");
+        mbValid = false;
+    }
+    else
+    {
+        Reference<XAnimate> xAnimate(mxNode, UNO_QUERY);
+        mbValid = xAnimate.is() && (bIsIterateChild || 
isValidTarget(xAnimate->getTarget()));
+    }
+}
+
+bool NodeContext::initChildNodes()
+{
+    bool bValid = false;
+    Reference<XEnumerationAccess> xEnumerationAccess(mxNode, UNO_QUERY);
+    if (xEnumerationAccess.is())
+    {
+        Reference<XEnumeration> 
xEnumeration(xEnumerationAccess->createEnumeration(), UNO_QUERY);
+        bool bIsMainSeq = mnEffectNodeType == EffectNodeType::MAIN_SEQUENCE;
+        bool bIsIterateChild = mxNode->getType() == AnimationNodeType::ITERATE;
+        if (xEnumeration.is())
+        {
+            while (xEnumeration->hasMoreElements())
+            {
+                Reference<XAnimationNode> 
xChildNode(xEnumeration->nextElement(), UNO_QUERY);
+                if (xChildNode.is())
+                {
+                    auto pChildContext
+                        = o3tl::make_unique<NodeContext>(xChildNode, 
bIsMainSeq, bIsIterateChild);
+                    if (pChildContext->isValid())
+                        bValid = true;
+                    maChildNodes.push_back(std::move(pChildContext));
+                }
+            }
+        }
+    }
+    return bValid;
+}
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to