From 55d4dc3a6b955e54ee73bc81807552a3b4d4a279 Mon Sep 17 00:00:00 2001 From: Mark Hung Date: Fri, 27 Jan 2023 23:34:49 +0800 Subject: [PATCH] sd/pptx-anmiations refactor NodeContext. Change-Id: I6439882884b3808dec91eaaede50856b0afdd278 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146293 Tested-by: Jenkins Reviewed-by: Noel Grandin --- sd/Library_sd.mk | 1 + .../filter/eppt/pptx-animations-nodectx.cxx | 188 ++++++++++++++++++ .../filter/eppt/pptx-animations-nodectx.hxx | 59 ++++++ sd/source/filter/eppt/pptx-animations.cxx | 184 +---------------- 4 files changed, 250 insertions(+), 182 deletions(-) create mode 100644 sd/source/filter/eppt/pptx-animations-nodectx.cxx create mode 100644 sd/source/filter/eppt/pptx-animations-nodectx.hxx diff --git a/sd/Library_sd.mk b/sd/Library_sd.mk index 297c2bc23654..4ffb86b7d461 100644 --- a/sd/Library_sd.mk +++ b/sd/Library_sd.mk @@ -188,6 +188,7 @@ $(eval $(call gb_Library_add_exception_objects,sd,\ sd/source/filter/eppt/pptx-epptooxml \ sd/source/filter/eppt/pptx-animations \ sd/source/filter/eppt/pptx-animations-cond \ + sd/source/filter/eppt/pptx-animations-nodectx \ sd/source/filter/eppt/pptx-grouptable \ sd/source/filter/eppt/pptx-stylesheet \ sd/source/filter/eppt/pptx-text \ diff --git a/sd/source/filter/eppt/pptx-animations-nodectx.cxx b/sd/source/filter/eppt/pptx-animations-nodectx.cxx new file mode 100644 index 000000000000..0d5cabd49343 --- /dev/null +++ b/sd/source/filter/eppt/pptx-animations-nodectx.cxx @@ -0,0 +1,188 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "pptx-animations-nodectx.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +using ::com::sun::star::beans::NamedValue; +using ::com::sun::star::beans::XPropertySet; +using ::com::sun::star::drawing::XShape; + +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::presentation; +using namespace ::com::sun::star::uno; + +namespace oox::core +{ +namespace +{ +bool isValidTarget(const Any& rTarget) +{ + Reference xShape; + + if ((rTarget >>= xShape) && xShape.is()) + return true; + + ParagraphTarget aParagraphTarget; + + return (rTarget >>= aParagraphTarget) && aParagraphTarget.Shape.is(); +} + +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"); } +} + +NodeContext::NodeContext(const Reference& xNode, bool bMainSeqChild, + bool bIsIterateChild) + : mxNode(xNode) + , mbMainSeqChild(bMainSeqChild) + , mbValid(true) + , mnEffectNodeType(-1) + , mnEffectPresetClass(css::presentation::EffectPresetClass::CUSTOM) +{ + assert(xNode.is()); + + initUserData(); + + initValid(initChildNodes(), bIsIterateChild); +} + +void NodeContext::initUserData() +{ + assert(mxNode.is()); + + Sequence aUserData = mxNode->getUserData(); + for (const NamedValue& rProp : aUserData) + { + if (rProp.Name == "node-type") + { + rProp.Value >>= mnEffectNodeType; + } + else if (rProp.Name == "preset-class") + { + rProp.Value >>= mnEffectPresetClass; + } + else if (rProp.Name == "preset-id") + { + rProp.Value >>= msEffectPresetId; + } + else if (rProp.Name == "preset-sub-type") + { + rProp.Value >>= msEffectPresetSubType; + } + } +} + +void NodeContext::initValid(bool bHasValidChild, bool bIsIterateChild) +{ + sal_Int16 nType = mxNode->getType(); + + if (nType == AnimationNodeType::ITERATE) + { + Reference xIterate(mxNode, UNO_QUERY); + mbValid = xIterate.is() && (bIsIterateChild || isValidTarget(xIterate->getTarget())) + && !maChildNodes.empty(); + } + else if (nType == AnimationNodeType::COMMAND) + { + Reference 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) + { + Reference xAudio(mxNode, UNO_QUERY); + OUString sURL; + Reference xShape; + mbValid = false; + if (xAudio.is()) + { + if (xAudio->getSource() >>= sURL) + { + mbValid = IsAudioURL(sURL); + } + else if (xAudio->getSource() >>= xShape) + { + Reference xShapeProps(xShape, UNO_QUERY); + bool bHasMediaURL + = xShapeProps->getPropertySetInfo()->hasPropertyByName("MediaURL"); + if (bHasMediaURL && (xShapeProps->getPropertyValue("MediaURL") >>= sURL)) + { + mbValid = IsAudioURL(sURL) || IsVideoURL(sURL); + } + } + } + } + else + { + Reference xAnimate(mxNode, UNO_QUERY); + mbValid = xAnimate.is() && (bIsIterateChild || isValidTarget(xAnimate->getTarget())); + } +} + +bool NodeContext::initChildNodes() +{ + bool bValid = false; + Reference xEnumerationAccess(mxNode, UNO_QUERY); + if (xEnumerationAccess.is()) + { + Reference xEnumeration = xEnumerationAccess->createEnumeration(); + bool bIsMainSeq = mnEffectNodeType == EffectNodeType::MAIN_SEQUENCE; + bool bIsIterateChild = mxNode->getType() == AnimationNodeType::ITERATE; + if (xEnumeration.is()) + { + while (xEnumeration->hasMoreElements()) + { + Reference xChildNode(xEnumeration->nextElement(), UNO_QUERY); + if (xChildNode.is()) + { + auto pChildContext + = std::make_unique(xChildNode, bIsMainSeq, bIsIterateChild); + if (pChildContext->isValid()) + bValid = true; + maChildNodes.push_back(std::move(pChildContext)); + } + } + } + } + return bValid; +} + +const Reference& NodeContext::getNodeForCondition() const +{ + const bool bParent + = (mnEffectNodeType != EffectNodeType::INTERACTIVE_SEQUENCE || maChildNodes.empty()); + const Reference& rNode = bParent ? mxNode : maChildNodes[0]->getNode(); + return rNode; +} +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/filter/eppt/pptx-animations-nodectx.hxx b/sd/source/filter/eppt/pptx-animations-nodectx.hxx new file mode 100644 index 000000000000..46a97c5a40cc --- /dev/null +++ b/sd/source/filter/eppt/pptx-animations-nodectx.hxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include +#include +#include + +namespace oox::core +{ +class NodeContext; + +typedef std::unique_ptr NodeContextPtr; + +class NodeContext +{ + const css::uno::Reference mxNode; + const bool mbMainSeqChild; + + std::vector 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; + OUString msEffectPresetId; + OUString msEffectPresetSubType; + + /// constructor helper for initializing user data. + 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 css::uno::Reference& xNode, + bool bMainSeqChild, bool bIsIterateChild); + const css::uno::Reference& 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& getChildNodes() const { return maChildNodes; }; + const css::uno::Reference& getNodeForCondition() const; +}; +} diff --git a/sd/source/filter/eppt/pptx-animations.cxx b/sd/source/filter/eppt/pptx-animations.cxx index 77b4ea2282a7..bfe1079885e9 100644 --- a/sd/source/filter/eppt/pptx-animations.cxx +++ b/sd/source/filter/eppt/pptx-animations.cxx @@ -60,7 +60,7 @@ #include "pptexanimations.hxx" #include "pptx-animations.hxx" #include "pptx-animations-cond.hxx" -#include "../ppt/pptanimations.hxx" +#include "pptx-animations-nodectx.hxx" using namespace ::com::sun::star; using namespace ::com::sun::star::animations; @@ -307,18 +307,6 @@ void WriteAnimationAttributeName(const FSHelperPtr& pFS, const OUString& rAttrib pFS->endElementNS(XML_p, XML_attrNameLst); } -bool isValidTarget(const Any& rTarget) -{ - Reference xShape; - - if ((rTarget >>= xShape) && xShape.is()) - return true; - - ParagraphTarget aParagraphTarget; - - return (rTarget >>= aParagraphTarget) && aParagraphTarget.Shape.is(); -} - /// extract ooxml node type from a XAnimationNode. sal_Int32 extractNodeType(const Reference& rXNode) { @@ -490,48 +478,6 @@ const char* convertTextAnimationType(sal_Int16 nType) return sType; } -class NodeContext; - -typedef std::unique_ptr NodeContextPtr; - -class NodeContext -{ - const Reference mxNode; - const bool mbMainSeqChild; - - std::vector 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; - OUString msEffectPresetId; - OUString msEffectPresetSubType; - - /// constructor helper for initializing user data. - 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& xNode, bool bMainSeqChild, bool bIsIterateChild); - const Reference& 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& getChildNodes() const { return maChildNodes; }; - const Reference& getNodeForCondition() const; -}; - class PPTXAnimationExport { void WriteAnimationNode(const NodeContextPtr& pContext); @@ -952,7 +898,7 @@ void PPTXAnimationExport::WriteAnimationNodeCommonPropsStart() sDuration = OString::number(static_cast(fDuration * 1000.0)); sal_uInt32 nPresetClass = mpContext->getEffectPresetClass(); - if (nPresetClass != DFF_ANIM_PRESS_CLASS_USER_DEFINED) + if (nPresetClass != EffectPresetClass::CUSTOM) pPresetClass = convertEffectPresetClass(nPresetClass); sal_uInt32 nPresetId = 0; @@ -1317,130 +1263,4 @@ sal_Int32 PPTXAnimationExport::GetAnimationNodeId(const Reference& 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() -{ - assert(mxNode.is()); - - Sequence aUserData = mxNode->getUserData(); - const Any* aIndexedData[DFF_ANIM_PROPERTY_ID_COUNT]; - AnimationExporter::GetUserData(aUserData, aIndexedData, sizeof(aIndexedData)); - - const Any* pAny = aIndexedData[DFF_ANIM_NODE_TYPE]; - if (pAny) - *pAny >>= mnEffectNodeType; - - pAny = aIndexedData[DFF_ANIM_PRESET_CLASS]; - if (pAny) - *pAny >>= mnEffectPresetClass; - - pAny = aIndexedData[DFF_ANIM_PRESET_ID]; - if (pAny) - *pAny >>= msEffectPresetId; - - pAny = aIndexedData[DFF_ANIM_PRESET_SUB_TYPE]; - if (pAny) - *pAny >>= msEffectPresetSubType; -} - -void NodeContext::initValid(bool bHasValidChild, bool bIsIterateChild) -{ - sal_Int16 nType = mxNode->getType(); - - if (nType == AnimationNodeType::ITERATE) - { - Reference xIterate(mxNode, UNO_QUERY); - mbValid = xIterate.is() && (bIsIterateChild || isValidTarget(xIterate->getTarget())) - && !maChildNodes.empty(); - } - else if (nType == AnimationNodeType::COMMAND) - { - Reference 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) - { - Reference xAudio(mxNode, UNO_QUERY); - OUString sURL; - uno::Reference xShape; - mbValid = false; - if (xAudio.is()) - { - if (xAudio->getSource() >>= sURL) - { - mbValid = IsAudioURL(sURL); - } - else if (xAudio->getSource() >>= xShape) - { - uno::Reference xShapeProps(xShape, uno::UNO_QUERY); - bool bHasMediaURL - = xShapeProps->getPropertySetInfo()->hasPropertyByName("MediaURL"); - if (bHasMediaURL && (xShapeProps->getPropertyValue("MediaURL") >>= sURL)) - { - mbValid = IsAudioURL(sURL) || IsVideoURL(sURL); - } - } - } - } - else - { - Reference xAnimate(mxNode, UNO_QUERY); - mbValid = xAnimate.is() && (bIsIterateChild || isValidTarget(xAnimate->getTarget())); - } -} - -bool NodeContext::initChildNodes() -{ - bool bValid = false; - Reference xEnumerationAccess(mxNode, UNO_QUERY); - if (xEnumerationAccess.is()) - { - Reference xEnumeration = xEnumerationAccess->createEnumeration(); - bool bIsMainSeq = mnEffectNodeType == EffectNodeType::MAIN_SEQUENCE; - bool bIsIterateChild = mxNode->getType() == AnimationNodeType::ITERATE; - if (xEnumeration.is()) - { - while (xEnumeration->hasMoreElements()) - { - Reference xChildNode(xEnumeration->nextElement(), UNO_QUERY); - if (xChildNode.is()) - { - auto pChildContext - = std::make_unique(xChildNode, bIsMainSeq, bIsIterateChild); - if (pChildContext->isValid()) - bValid = true; - maChildNodes.push_back(std::move(pChildContext)); - } - } - } - } - return bValid; -} - -const Reference& NodeContext::getNodeForCondition() const -{ - const bool bParent - = (mnEffectNodeType != EffectNodeType::INTERACTIVE_SEQUENCE || maChildNodes.empty()); - const Reference& rNode = bParent ? mxNode : maChildNodes[0]->getNode(); - return rNode; -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */