summaryrefslogtreecommitdiff
path: root/sd
diff options
context:
space:
mode:
authorMark Hung <marklh9@gmail.com>2018-09-01 11:11:38 +0800
committerMark Hung <marklh9@gmail.com>2018-09-07 13:11:41 +0200
commit612db6877a73e6f9b142b81697291f02c0adb95f (patch)
tree6f2d79aacd1483c230a7146bddd303dadf15e50f /sd
parentc3c43c7966e0f4c7a3b76361559d29c9335487d9 (diff)
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 <marklh9@gmail.com>
Diffstat (limited to 'sd')
-rw-r--r--sd/qa/unit/data/odp/tdf99213-target-missing.odpbin0 -> 11088 bytes
-rw-r--r--sd/qa/unit/export-tests-ooxml2.cxx15
-rw-r--r--sd/source/filter/eppt/pptx-animations.cxx143
3 files changed, 126 insertions, 32 deletions
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
--- /dev/null
+++ b/sd/qa/unit/data/odp/tdf99213-target-missing.odp
Binary files 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: */