sd/pptx-anmiations refactor NodeContext.
Change-Id: I6439882884b3808dec91eaaede50856b0afdd278 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146293 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
parent
000d88c53a
commit
55d4dc3a6b
4 changed files with 250 additions and 182 deletions
|
@ -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 \
|
||||
|
|
188
sd/source/filter/eppt/pptx-animations-nodectx.cxx
Normal file
188
sd/source/filter/eppt/pptx-animations-nodectx.cxx
Normal file
|
@ -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 <com/sun/star/animations/AnimationNodeType.hpp>
|
||||
#include <com/sun/star/animations/XAnimate.hpp>
|
||||
#include <com/sun/star/animations/XAnimationNode.hpp>
|
||||
#include <com/sun/star/animations/XCommand.hpp>
|
||||
#include <com/sun/star/animations/XAudio.hpp>
|
||||
#include <com/sun/star/animations/XIterateContainer.hpp>
|
||||
#include <com/sun/star/drawing/XShape.hpp>
|
||||
#include <com/sun/star/container/XEnumerationAccess.hpp>
|
||||
#include <com/sun/star/container/XEnumeration.hpp>
|
||||
#include <com/sun/star/presentation/EffectNodeType.hpp>
|
||||
#include <com/sun/star/presentation/EffectPresetClass.hpp>
|
||||
#include <com/sun/star/presentation/ParagraphTarget.hpp>
|
||||
#include <com/sun/star/beans/XPropertySet.hpp>
|
||||
|
||||
#include <o3tl/any.hxx>
|
||||
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> 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<XAnimationNode>& 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<NamedValue> 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<XIterateContainer> xIterate(mxNode, UNO_QUERY);
|
||||
mbValid = xIterate.is() && (bIsIterateChild || isValidTarget(xIterate->getTarget()))
|
||||
&& !maChildNodes.empty();
|
||||
}
|
||||
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)
|
||||
{
|
||||
Reference<XAudio> xAudio(mxNode, UNO_QUERY);
|
||||
OUString sURL;
|
||||
Reference<XShape> xShape;
|
||||
mbValid = false;
|
||||
if (xAudio.is())
|
||||
{
|
||||
if (xAudio->getSource() >>= sURL)
|
||||
{
|
||||
mbValid = IsAudioURL(sURL);
|
||||
}
|
||||
else if (xAudio->getSource() >>= xShape)
|
||||
{
|
||||
Reference<XPropertySet> xShapeProps(xShape, UNO_QUERY);
|
||||
bool bHasMediaURL
|
||||
= xShapeProps->getPropertySetInfo()->hasPropertyByName("MediaURL");
|
||||
if (bHasMediaURL && (xShapeProps->getPropertyValue("MediaURL") >>= sURL))
|
||||
{
|
||||
mbValid = IsAudioURL(sURL) || IsVideoURL(sURL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
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
|
||||
= std::make_unique<NodeContext>(xChildNode, bIsMainSeq, bIsIterateChild);
|
||||
if (pChildContext->isValid())
|
||||
bValid = true;
|
||||
maChildNodes.push_back(std::move(pChildContext));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bValid;
|
||||
}
|
||||
|
||||
const Reference<XAnimationNode>& NodeContext::getNodeForCondition() const
|
||||
{
|
||||
const bool bParent
|
||||
= (mnEffectNodeType != EffectNodeType::INTERACTIVE_SEQUENCE || maChildNodes.empty());
|
||||
const Reference<XAnimationNode>& rNode = bParent ? mxNode : maChildNodes[0]->getNode();
|
||||
return rNode;
|
||||
}
|
||||
}
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
59
sd/source/filter/eppt/pptx-animations-nodectx.hxx
Normal file
59
sd/source/filter/eppt/pptx-animations-nodectx.hxx
Normal file
|
@ -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 <com/sun/star/uno/Reference.hxx>
|
||||
#include <com/sun/star/animations/XAnimationNode.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace oox::core
|
||||
{
|
||||
class NodeContext;
|
||||
|
||||
typedef std::unique_ptr<NodeContext> NodeContextPtr;
|
||||
|
||||
class NodeContext
|
||||
{
|
||||
const css::uno::Reference<css::animations::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;
|
||||
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<css::animations::XAnimationNode>& xNode,
|
||||
bool bMainSeqChild, bool bIsIterateChild);
|
||||
const css::uno::Reference<css::animations::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; };
|
||||
const css::uno::Reference<css::animations::XAnimationNode>& getNodeForCondition() const;
|
||||
};
|
||||
}
|
|
@ -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> 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<XAnimationNode>& rXNode)
|
||||
{
|
||||
|
@ -490,48 +478,6 @@ const char* convertTextAnimationType(sal_Int16 nType)
|
|||
return sType;
|
||||
}
|
||||
|
||||
class NodeContext;
|
||||
|
||||
typedef std::unique_ptr<NodeContext> NodeContextPtr;
|
||||
|
||||
class NodeContext
|
||||
{
|
||||
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;
|
||||
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<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; };
|
||||
const Reference<XAnimationNode>& getNodeForCondition() const;
|
||||
};
|
||||
|
||||
class PPTXAnimationExport
|
||||
{
|
||||
void WriteAnimationNode(const NodeContextPtr& pContext);
|
||||
|
@ -952,7 +898,7 @@ void PPTXAnimationExport::WriteAnimationNodeCommonPropsStart()
|
|||
sDuration = OString::number(static_cast<sal_Int32>(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<XAnimationNode
|
|||
return nId;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
assert(mxNode.is());
|
||||
|
||||
Sequence<NamedValue> 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<XIterateContainer> xIterate(mxNode, UNO_QUERY);
|
||||
mbValid = xIterate.is() && (bIsIterateChild || isValidTarget(xIterate->getTarget()))
|
||||
&& !maChildNodes.empty();
|
||||
}
|
||||
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)
|
||||
{
|
||||
Reference<XAudio> xAudio(mxNode, UNO_QUERY);
|
||||
OUString sURL;
|
||||
uno::Reference<drawing::XShape> xShape;
|
||||
mbValid = false;
|
||||
if (xAudio.is())
|
||||
{
|
||||
if (xAudio->getSource() >>= sURL)
|
||||
{
|
||||
mbValid = IsAudioURL(sURL);
|
||||
}
|
||||
else if (xAudio->getSource() >>= xShape)
|
||||
{
|
||||
uno::Reference<beans::XPropertySet> 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> 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();
|
||||
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
|
||||
= std::make_unique<NodeContext>(xChildNode, bIsMainSeq, bIsIterateChild);
|
||||
if (pChildContext->isValid())
|
||||
bValid = true;
|
||||
maChildNodes.push_back(std::move(pChildContext));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bValid;
|
||||
}
|
||||
|
||||
const Reference<XAnimationNode>& NodeContext::getNodeForCondition() const
|
||||
{
|
||||
const bool bParent
|
||||
= (mnEffectNodeType != EffectNodeType::INTERACTIVE_SEQUENCE || maChildNodes.empty());
|
||||
const Reference<XAnimationNode>& rNode = bParent ? mxNode : maChildNodes[0]->getNode();
|
||||
return rNode;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
|
Loading…
Reference in a new issue