summaryrefslogtreecommitdiffstats
path: root/oox/source/ppt/timenodelistcontext.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--oox/source/ppt/timenodelistcontext.cxx1048
1 files changed, 1048 insertions, 0 deletions
diff --git a/oox/source/ppt/timenodelistcontext.cxx b/oox/source/ppt/timenodelistcontext.cxx
new file mode 100644
index 000000000..a7637432a
--- /dev/null
+++ b/oox/source/ppt/timenodelistcontext.cxx
@@ -0,0 +1,1048 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <oox/ppt/timenodelistcontext.hxx>
+
+#include <rtl/math.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <com/sun/star/animations/AnimationTransformType.hpp>
+#include <com/sun/star/animations/AnimationCalcMode.hpp>
+#include <com/sun/star/animations/AnimationColorSpace.hpp>
+#include <com/sun/star/animations/AnimationNodeType.hpp>
+#include <com/sun/star/animations/ValuePair.hpp>
+#include <com/sun/star/presentation/EffectCommands.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+
+#include <oox/helper/attributelist.hxx>
+#include <oox/core/xmlfilterbase.hxx>
+#include <oox/drawingml/drawingmltypes.hxx>
+#include <drawingml/colorchoicecontext.hxx>
+#include <oox/ppt/slidetransition.hxx>
+#include <oox/token/namespaces.hxx>
+#include <oox/token/tokens.hxx>
+#include <o3tl/string_view.hxx>
+
+#include "animvariantcontext.hxx"
+#include "commonbehaviorcontext.hxx"
+#include "conditioncontext.hxx"
+#include "commontimenodecontext.hxx"
+#include "timeanimvaluecontext.hxx"
+#include "animationtypes.hxx"
+#include "timetargetelementcontext.hxx"
+
+using namespace ::oox::core;
+using namespace ::oox::drawingml;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::animations;
+using namespace ::com::sun::star::presentation;
+using namespace ::com::sun::star::xml::sax;
+using ::com::sun::star::beans::NamedValue;
+
+namespace {
+
+ oox::ppt::AnimationAttributeEnum getAttributeEnumByAPIName(std::u16string_view rAPIName)
+ {
+ oox::ppt::AnimationAttributeEnum eResult = oox::ppt::AnimationAttributeEnum::UNKNOWN;
+ const oox::ppt::ImplAttributeNameConversion *attrConv = oox::ppt::getAttributeConversionList();
+ while(attrConv->mpAPIName != nullptr)
+ {
+ if(o3tl::equalsAscii(rAPIName, attrConv->mpAPIName))
+ {
+ eResult = attrConv->meAttribute;
+ break;
+ }
+ attrConv++;
+ }
+ return eResult;
+ }
+
+ bool convertAnimationValueWithTimeNode(const oox::ppt::TimeNodePtr& pNode, css::uno::Any &rAny)
+ {
+ css::uno::Any aAny = pNode->getNodeProperties()[oox::ppt::NP_ATTRIBUTENAME];
+ OUString aNameList;
+ aAny >>= aNameList;
+
+ // only get first token.
+ return oox::ppt::convertAnimationValue(getAttributeEnumByAPIName(o3tl::getToken(aNameList, 0, ';')), rAny);
+ }
+
+ css::uno::Any convertPointPercent(const css::awt::Point& rPoint)
+ {
+ css::animations::ValuePair aPair;
+ // rPoint.X and rPoint.Y are in 1000th of a percent, but we only need ratio.
+ aPair.First <<= static_cast<double>(rPoint.X) / 100000.0;
+ aPair.Second <<= static_cast<double>(rPoint.Y) / 100000.0;
+ return Any(aPair);
+ }
+}
+
+namespace oox::ppt {
+
+ namespace {
+
+ struct AnimColor
+ {
+ AnimColor(sal_Int16 cs, sal_Int32 o, sal_Int32 t, sal_Int32 th )
+ : colorSpace( cs ), one( o ), two( t ), three( th )
+ {
+ }
+
+ Any get() const
+ {
+ sal_Int32 nColor;
+ Any aColor;
+
+ switch( colorSpace )
+ {
+ case AnimationColorSpace::HSL:
+ aColor <<= Sequence< double >{ one / 100000.0, two / 100000.0, three / 100000.0 };
+ break;
+ case AnimationColorSpace::RGB:
+ nColor = ( ( ( one * 128 ) / 1000 ) & 0xff ) << 16
+ | ( ( ( two * 128 ) / 1000 ) & 0xff ) << 8
+ | ( ( ( three * 128 ) / 1000 ) & 0xff );
+ aColor <<= nColor;
+ break;
+ default:
+ nColor = 0;
+ aColor <<= nColor;
+ break;
+ }
+ return aColor;
+ }
+
+ sal_Int16 colorSpace;
+ sal_Int32 one;
+ sal_Int32 two;
+ sal_Int32 three;
+ };
+
+ /** CT_TLMediaNodeAudio
+ CT_TLMediaNodeVideo */
+ class MediaNodeContext
+ : public TimeNodeContext
+ {
+ public:
+ MediaNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
+ const Reference< XFastAttributeList >& xAttribs,
+ const TimeNodePtr & pNode )
+ : TimeNodeContext( rParent, aElement, pNode )
+ , mbIsNarration( false )
+ , mbFullScrn( false )
+ , mbHideDuringShow(false)
+ {
+ AttributeList attribs( xAttribs );
+
+ switch( aElement )
+ {
+ case PPT_TOKEN( audio ):
+ mbIsNarration = attribs.getBool( XML_isNarration, false );
+ break;
+ case PPT_TOKEN( video ):
+ mbFullScrn = attribs.getBool( XML_fullScrn, false );
+ break;
+ default:
+ break;
+ }
+ }
+
+ virtual void onEndElement() override
+ {
+ sal_Int32 aElement = getCurrentElement();
+ if( aElement == PPT_TOKEN( audio ) )
+ {
+ mpNode->getNodeProperties()[NP_ISNARRATION] <<= mbIsNarration;
+ }
+ else if( aElement == PPT_TOKEN( video ) )
+ {
+ // TODO deal with mbFullScrn
+ }
+ else if (aElement == PPT_TOKEN(cMediaNode))
+ {
+ mpNode->getNodeProperties()[NP_HIDEDURINGSHOW] <<= mbHideDuringShow;
+ }
+ }
+
+ virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs) override
+ {
+ switch ( aElementToken )
+ {
+ case PPT_TOKEN( cTn ):
+ return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode );
+ case PPT_TOKEN( tgtEl ):
+ return new TimeTargetElementContext( *this, mpNode->getTarget() );
+ case PPT_TOKEN(cMediaNode):
+ mbHideDuringShow = !rAttribs.getBool(XML_showWhenStopped, true);
+ break;
+ default:
+ break;
+ }
+
+ return this;
+ }
+
+ private:
+ bool mbIsNarration;
+ bool mbFullScrn;
+ bool mbHideDuringShow;
+ };
+
+ /** CT_TLSetBehavior
+ */
+ class SetTimeNodeContext
+ : public TimeNodeContext
+ {
+ public:
+ SetTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
+ const TimeNodePtr & pNode )
+ : TimeNodeContext( rParent, aElement, pNode )
+ {
+
+ }
+
+ virtual ~SetTimeNodeContext() noexcept override
+ {
+ if(maTo.hasValue())
+ {
+ convertAnimationValueWithTimeNode(mpNode, maTo);
+ mpNode->setTo(maTo);
+ }
+
+ }
+
+ virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
+ {
+ switch ( aElementToken )
+ {
+ case PPT_TOKEN( cBhvr ):
+ return new CommonBehaviorContext ( *this, mpNode );
+ case PPT_TOKEN( to ):
+ // CT_TLAnimVariant
+ return new AnimVariantContext( *this, aElementToken, maTo );
+ default:
+ break;
+ }
+
+ return this;
+ }
+ private:
+ Any maTo;
+ };
+
+ /** CT_TLCommandBehavior
+ */
+ class CmdTimeNodeContext
+ : public TimeNodeContext
+ {
+ public:
+ CmdTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
+ const Reference< XFastAttributeList >& xAttribs,
+ const TimeNodePtr & pNode )
+ : TimeNodeContext( rParent, aElement, pNode )
+ , maType(0)
+ {
+ switch ( aElement )
+ {
+ case PPT_TOKEN( cmd ):
+ msCommand = xAttribs->getOptionalValue( XML_cmd );
+ maType = xAttribs->getOptionalValueToken( XML_type, 0 );
+ break;
+ default:
+ break;
+ }
+ }
+
+ virtual void onEndElement() override
+ {
+ if( !isCurrentElement( PPT_TOKEN( cmd ) ) )
+ return;
+
+ try {
+ // see sd/source/filter/ppt/pptinanimations.cxx
+ // in AnimationImporter::importCommandContainer()
+ // REFACTOR?
+ // a good chunk of this code has been copied verbatim *sigh*
+ sal_Int16 nCommand = EffectCommands::CUSTOM;
+ NamedValue aParamValue;
+
+ switch( maType )
+ {
+ case XML_verb:
+ aParamValue.Name = "Verb";
+ // TODO make sure msCommand has what we want
+ aParamValue.Value <<= msCommand.toInt32();
+ nCommand = EffectCommands::VERB;
+ break;
+ case XML_evt:
+ case XML_call:
+ if ( msCommand == "onstopaudio" )
+ {
+ nCommand = EffectCommands::STOPAUDIO;
+ }
+ else if ( msCommand == "play" )
+ {
+ nCommand = EffectCommands::PLAY;
+ }
+ else if (msCommand.startsWith("playFrom"))
+ {
+ std::u16string_view aMediaTime( msCommand.subView( 9, msCommand.getLength() - 10 ) );
+ rtl_math_ConversionStatus eStatus;
+ double fMediaTime = ::rtl::math::stringToDouble( aMediaTime, u'.', u',', &eStatus );
+ if( eStatus == rtl_math_ConversionStatus_Ok )
+ {
+ aParamValue.Name = "MediaTime";
+ aParamValue.Value <<= fMediaTime;
+ }
+ nCommand = EffectCommands::PLAY;
+ }
+ else if ( msCommand == "togglePause" )
+ {
+ nCommand = EffectCommands::TOGGLEPAUSE;
+ }
+ else if ( msCommand == "stop" )
+ {
+ nCommand = EffectCommands::STOP;
+ }
+ break;
+ }
+ mpNode->getNodeProperties()[ NP_COMMAND ] <<= nCommand;
+ if( nCommand == EffectCommands::CUSTOM )
+ {
+ SAL_WARN("oox.ppt", "OOX: CmdTimeNodeContext::endFastElement(), unknown command!");
+ aParamValue.Name = "UserDefined";
+ aParamValue.Value <<= msCommand;
+ }
+ if( aParamValue.Value.hasValue() )
+ {
+ Sequence< NamedValue > aParamSeq( &aParamValue, 1 );
+ mpNode->getNodeProperties()[ NP_PARAMETER ] <<= aParamSeq;
+ }
+ }
+ catch( RuntimeException& )
+ {
+ TOOLS_WARN_EXCEPTION("oox.ppt", "OOX: Exception in CmdTimeNodeContext::endFastElement()" );
+ }
+ }
+
+ virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
+ {
+ switch ( aElementToken )
+ {
+ case PPT_TOKEN( cBhvr ):
+ return new CommonBehaviorContext ( *this, mpNode );
+ default:
+ break;
+ }
+
+ return this;
+ }
+
+ private:
+ OUString msCommand;
+ sal_Int32 maType;
+ };
+
+ /** CT_TLTimeNodeSequence
+ */
+ class SequenceTimeNodeContext
+ : public TimeNodeContext
+ {
+ public:
+ SequenceTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
+ const Reference< XFastAttributeList >& xAttribs,
+ const TimeNodePtr & pNode )
+ : TimeNodeContext( rParent, aElement, pNode )
+ , mnNextAc(0)
+ , mnPrevAc(0)
+ {
+ AttributeList attribs(xAttribs);
+ mbConcurrent = attribs.getBool( XML_concurrent, false );
+ mnNextAc = xAttribs->getOptionalValueToken( XML_nextAc, 0 );
+ mnPrevAc = xAttribs->getOptionalValueToken( XML_prevAc, 0 );
+ }
+
+ virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
+ {
+ switch ( aElementToken )
+ {
+ case PPT_TOKEN( cTn ):
+ return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode );
+ case PPT_TOKEN( nextCondLst ):
+ return new CondListContext( *this, aElementToken, mpNode, mpNode->getNextCondition() );
+ case PPT_TOKEN( prevCondLst ):
+ return new CondListContext( *this, aElementToken, mpNode, mpNode->getPrevCondition() );
+ default:
+ break;
+ }
+
+ return this;
+ }
+ private:
+ bool mbConcurrent;
+ sal_Int32 mnNextAc, mnPrevAc;
+ };
+
+ /** CT_TLTimeNodeParallel
+ * CT_TLTimeNodeExclusive
+ */
+ class ParallelExclTimeNodeContext
+ : public TimeNodeContext
+ {
+ public:
+ ParallelExclTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
+ const TimeNodePtr & pNode )
+ : TimeNodeContext( rParent, aElement, pNode )
+ {
+ }
+
+ virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
+ {
+ switch ( aElementToken )
+ {
+ case PPT_TOKEN( cTn ):
+ return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode );
+ default:
+ break;
+ }
+
+ return this;
+ }
+
+ protected:
+
+ };
+
+ /** CT_TLAnimateColorBehavior */
+ class AnimColorContext
+ : public TimeNodeContext
+ {
+ public:
+ AnimColorContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
+ const Reference< XFastAttributeList >& xAttribs,
+ const TimeNodePtr & pNode ) noexcept
+ : TimeNodeContext( rParent, aElement, pNode )
+ , mnColorSpace( xAttribs->getOptionalValueToken( XML_clrSpc, 0 ) )
+ , mnDir( xAttribs->getOptionalValueToken( XML_dir, 0 ) )
+ , mbHasByColor( false )
+ , m_byColor( AnimationColorSpace::RGB, 0, 0, 0)
+ {
+ }
+
+ virtual void onEndElement() override
+ {
+ //xParentNode
+ if( !isCurrentElement( mnElement ) )
+ return;
+
+ NodePropertyMap & rProps(mpNode->getNodeProperties());
+ rProps[ NP_DIRECTION ] <<= mnDir == XML_cw;
+ rProps[ NP_COLORINTERPOLATION ] <<= mnColorSpace == XML_hsl ? AnimationColorSpace::HSL : AnimationColorSpace::RGB;
+ const GraphicHelper& rGraphicHelper = getFilter().getGraphicHelper();
+ if( maToClr.isUsed() )
+ mpNode->setTo( Any( maToClr.getColor( rGraphicHelper ) ) );
+ if( maFromClr.isUsed() )
+ mpNode->setFrom( Any( maFromClr.getColor( rGraphicHelper ) ) );
+ if( mbHasByColor )
+ mpNode->setBy( m_byColor.get() );
+ }
+
+ virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
+ {
+ switch ( aElementToken )
+ {
+ case PPT_TOKEN( hsl ):
+ // CT_TLByHslColorTransform
+ {
+ if( mbHasByColor )
+ {
+ m_byColor.colorSpace = AnimationColorSpace::HSL;
+ m_byColor.one = rAttribs.getInteger( XML_h, 0 );
+ m_byColor.two = rAttribs.getInteger( XML_s, 0 );
+ m_byColor.three = rAttribs.getInteger( XML_l, 0 );
+ }
+ return this;
+ }
+ case PPT_TOKEN( rgb ):
+ {
+ if( mbHasByColor )
+ {
+ // CT_TLByRgbColorTransform
+ m_byColor.colorSpace = AnimationColorSpace::RGB;
+ m_byColor.one = rAttribs.getInteger( XML_r, 0 );
+ m_byColor.two = rAttribs.getInteger( XML_g, 0 );
+ m_byColor.three = rAttribs.getInteger( XML_b, 0 );
+ }
+ return this;
+ }
+ case PPT_TOKEN( by ):
+ // CT_TLByAnimateColorTransform
+ mbHasByColor = true;
+ return this;
+ case PPT_TOKEN( cBhvr ):
+ return new CommonBehaviorContext ( *this, mpNode );
+ case PPT_TOKEN( to ):
+ // CT_Color
+ return new ColorContext( *this, maToClr );
+ case PPT_TOKEN( from ):
+ // CT_Color
+ return new ColorContext( *this, maFromClr );
+
+ default:
+ break;
+ }
+
+ return this;
+ }
+
+ private:
+ sal_Int32 mnColorSpace;
+ sal_Int32 mnDir;
+ bool mbHasByColor;
+ AnimColor m_byColor;
+ oox::drawingml::Color maToClr;
+ oox::drawingml::Color maFromClr;
+ };
+
+ /** CT_TLAnimateBehavior */
+ class AnimContext
+ : public TimeNodeContext
+ {
+ public:
+ AnimContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
+ const Reference< XFastAttributeList >& xAttribs,
+ const TimeNodePtr & pNode ) noexcept
+ : TimeNodeContext( rParent, aElement, pNode )
+ {
+ NodePropertyMap & aProps( pNode->getNodeProperties() );
+ sal_Int32 nCalcMode = xAttribs->getOptionalValueToken( XML_calcmode, 0 );
+ if(nCalcMode)
+ {
+ sal_Int16 nEnum = 0;
+ switch(nCalcMode)
+ {
+ case XML_discrete:
+ nEnum = AnimationCalcMode::DISCRETE;
+ break;
+ case XML_lin:
+ nEnum = AnimationCalcMode::LINEAR;
+ break;
+ case XML_fmla:
+ default:
+ // TODO what value is good ?
+ nEnum = AnimationCalcMode::DISCRETE;
+ break;
+ }
+ aProps[ NP_CALCMODE ] <<= nEnum;
+ }
+
+ msFrom = xAttribs->getOptionalValue(XML_from);
+ msTo = xAttribs->getOptionalValue(XML_to);
+ msBy = xAttribs->getOptionalValue(XML_by);
+
+ mnValueType = xAttribs->getOptionalValueToken( XML_valueType, 0 );
+ }
+
+ virtual ~AnimContext() noexcept override
+ {
+ if (!msFrom.isEmpty())
+ {
+ css::uno::Any aAny;
+ aAny <<= msFrom;
+ convertAnimationValueWithTimeNode(mpNode, aAny);
+ mpNode->setFrom(aAny);
+ }
+
+ if (!msTo.isEmpty())
+ {
+ css::uno::Any aAny;
+ aAny <<= msTo;
+ convertAnimationValueWithTimeNode(mpNode, aAny);
+ mpNode->setTo(aAny);
+ }
+
+ if (!msBy.isEmpty())
+ {
+ css::uno::Any aAny;
+ aAny <<= msBy;
+ convertAnimationValueWithTimeNode(mpNode, aAny);
+ mpNode->setBy(aAny);
+ }
+
+ int nKeyTimes = maTavList.size();
+ if( nKeyTimes <= 0)
+ return;
+
+ int i=0;
+ Sequence< double > aKeyTimes( nKeyTimes );
+ auto pKeyTimes = aKeyTimes.getArray();
+ Sequence< Any > aValues( nKeyTimes );
+ auto pValues = aValues.getArray();
+
+ NodePropertyMap & aProps( mpNode->getNodeProperties() );
+ for (auto const& tav : maTavList)
+ {
+ // TODO what to do if it is Timing_INFINITE ?
+ Any aTime = GetTimeAnimateValueTime( tav.msTime );
+ aTime >>= pKeyTimes[i];
+ pValues[i] = tav.maValue;
+ convertAnimationValueWithTimeNode(mpNode, pValues[i]);
+
+ // Examine pptx documents and find that only the first tav
+ // has the formula set. The formula can be used for the whole.
+ if (!tav.msFormula.isEmpty())
+ {
+ OUString sFormula = tav.msFormula;
+ (void)convertMeasure(sFormula);
+ aProps[NP_FORMULA] <<= sFormula;
+ }
+
+ ++i;
+ }
+ aProps[ NP_VALUES ] <<= aValues;
+ aProps[ NP_KEYTIMES ] <<= aKeyTimes;
+ }
+
+ virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
+ {
+ switch ( aElementToken )
+ {
+ case PPT_TOKEN( cBhvr ):
+ return new CommonBehaviorContext ( *this, mpNode );
+ case PPT_TOKEN( tavLst ):
+ return new TimeAnimValueListContext ( *this, maTavList );
+ default:
+ break;
+ }
+
+ return this;
+ }
+ private:
+ sal_Int32 mnValueType;
+ TimeAnimationValueList maTavList;
+ OUString msFrom;
+ OUString msTo;
+ OUString msBy;
+ };
+
+ /** CT_TLAnimateScaleBehavior */
+ class AnimScaleContext
+ : public TimeNodeContext
+ {
+ public:
+ AnimScaleContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
+ const Reference< XFastAttributeList >& xAttribs,
+ const TimeNodePtr & pNode ) noexcept
+ : TimeNodeContext( rParent, aElement, pNode )
+ , mbZoomContents( false )
+ {
+ AttributeList attribs( xAttribs );
+ // TODO what to do with mbZoomContents
+ mbZoomContents = attribs.getBool( XML_zoomContents, false );
+ pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
+ <<= sal_Int16(AnimationTransformType::SCALE);
+ }
+
+ virtual void onEndElement() override
+ {
+ if( !isCurrentElement( mnElement ) )
+ return;
+
+ if( maTo.hasValue() )
+ {
+ mpNode->setTo( maTo );
+ }
+ if( maBy.hasValue() )
+ {
+ mpNode->setBy( maBy );
+ }
+ if( maFrom.hasValue() )
+ {
+ mpNode->setFrom( maFrom );
+ }
+ }
+
+ virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
+ {
+ switch ( aElementToken )
+ {
+ case PPT_TOKEN( cBhvr ):
+ return new CommonBehaviorContext ( *this, mpNode );
+ case PPT_TOKEN( to ):
+ {
+ // CT_TLPoint
+ maTo = convertPointPercent(GetPointPercent(rAttribs.getFastAttributeList()));
+ return this;
+ }
+ case PPT_TOKEN( from ):
+ {
+ // CT_TLPoint
+ maFrom = convertPointPercent(GetPointPercent(rAttribs.getFastAttributeList()));
+ return this;
+ }
+ case PPT_TOKEN( by ):
+ {
+ // CT_TLPoint
+ css::awt::Point aPoint = GetPointPercent(rAttribs.getFastAttributeList());
+ // We got ending values instead of offset values, so subtract 100% from them.
+ aPoint.X -= 100000;
+ aPoint.Y -= 100000;
+ maBy = convertPointPercent(aPoint);
+ return this;
+ }
+ default:
+ break;
+ }
+
+ return this;
+ }
+ private:
+ Any maBy;
+ Any maFrom;
+ Any maTo;
+ bool mbZoomContents;
+ };
+
+ /** CT_TLAnimateRotationBehavior */
+ class AnimRotContext
+ : public TimeNodeContext
+ {
+ public:
+ AnimRotContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
+ const Reference< XFastAttributeList >& xAttribs,
+ const TimeNodePtr & pNode ) noexcept
+ : TimeNodeContext( rParent, aElement, pNode )
+ {
+ AttributeList attribs( xAttribs );
+
+ pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
+ <<= sal_Int16(AnimationTransformType::ROTATE);
+ // see also DFF_msofbtAnimateRotationData in
+ // sd/source/filter/ppt/pptinanimations.cxx
+ if(attribs.hasAttribute( XML_by ) )
+ {
+ double fBy = attribs.getDouble( XML_by, 0.0 ) / PER_DEGREE; //1 PowerPoint-angle-unit = 1/60000 degree
+ pNode->setBy( Any( fBy ) );
+ }
+ if(attribs.hasAttribute( XML_from ) )
+ {
+ double fFrom = attribs.getDouble( XML_from, 0.0 ) / PER_DEGREE;
+ pNode->setFrom( Any( fFrom ) );
+ }
+ if(attribs.hasAttribute( XML_to ) )
+ {
+ double fTo = attribs.getDouble( XML_to, 0.0 ) / PER_DEGREE;
+ pNode->setTo( Any( fTo ) );
+ }
+ }
+
+ virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
+ {
+ switch ( aElementToken )
+ {
+ case PPT_TOKEN( cBhvr ):
+ return new CommonBehaviorContext ( *this, mpNode );
+ default:
+ break;
+ }
+
+ return this;
+ }
+ };
+
+ /** CT_TLAnimateMotionBehavior */
+ class AnimMotionContext
+ : public TimeNodeContext
+ {
+ public:
+ AnimMotionContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
+ const Reference< XFastAttributeList >& xAttribs,
+ const TimeNodePtr & pNode ) noexcept
+ : TimeNodeContext( rParent, aElement, pNode )
+ {
+ pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
+ <<= sal_Int16(AnimationTransformType::TRANSLATE);
+
+ AttributeList attribs( xAttribs );
+ sal_Int32 nOrigin = xAttribs->getOptionalValueToken( XML_origin, 0 );
+ if( nOrigin != 0 )
+ {
+ switch(nOrigin)
+ {
+ case XML_layout:
+ case XML_parent:
+ break;
+ }
+ // TODO
+ }
+
+ OUString aStr = xAttribs->getOptionalValue( XML_path );
+ // E can appear inside a number, so we only check for its presence at the end
+ aStr = aStr.trim();
+ if (aStr.endsWith("E"))
+ aStr = aStr.copy(0, aStr.getLength() - 1);
+ aStr = aStr.trim();
+ pNode->getNodeProperties()[ NP_PATH ] <<= aStr;
+ mnPathEditMode = xAttribs->getOptionalValueToken( XML_pathEditMode, 0 );
+ msPtsTypes = xAttribs->getOptionalValue( XML_ptsTypes );
+ mnAngle = attribs.getInteger( XML_rAng, 0 );
+ // TODO make sure the units are right. Likely not.
+ }
+
+ virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
+ {
+ switch ( aElementToken )
+ {
+ case PPT_TOKEN( cBhvr ):
+ return new CommonBehaviorContext ( *this, mpNode );
+ case PPT_TOKEN( to ):
+ {
+ // CT_TLPoint
+ awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() );
+ Any rAny;
+ rAny <<= p.X;
+ rAny <<= p.Y;
+ mpNode->setTo( rAny );
+ return this;
+ }
+ case PPT_TOKEN( from ):
+ {
+ // CT_TLPoint
+ awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() );
+ Any rAny;
+ rAny <<= p.X;
+ rAny <<= p.Y;
+ mpNode->setFrom( rAny );
+ return this;
+ }
+ case PPT_TOKEN( by ):
+ {
+ // CT_TLPoint
+ awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() );
+ Any rAny;
+ rAny <<= p.X;
+ rAny <<= p.Y;
+ mpNode->setBy( rAny );
+ return this;
+ }
+ case PPT_TOKEN( rCtr ):
+ {
+ // CT_TLPoint
+ awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() );
+ // TODO push
+ (void)p;
+ return this;
+ }
+ default:
+ break;
+ }
+
+ return this;
+ }
+ private:
+ OUString msPtsTypes;
+ sal_Int32 mnPathEditMode;
+ sal_Int32 mnAngle;
+ };
+
+ /** CT_TLAnimateEffectBehavior */
+ class AnimEffectContext
+ : public TimeNodeContext
+ {
+ public:
+ AnimEffectContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
+ const Reference< XFastAttributeList >& xAttribs,
+ const TimeNodePtr & pNode ) noexcept
+ : TimeNodeContext( rParent, aElement, pNode )
+ {
+ sal_Int32 nDir = xAttribs->getOptionalValueToken( XML_transition, 0 );
+ OUString sFilter = xAttribs->getOptionalValue( XML_filter );
+ // TODO
+// OUString sPrList = xAttribs->getOptionalValue( XML_prLst );
+
+ if( !sFilter.isEmpty() )
+ {
+ SlideTransition aFilter( sFilter );
+ aFilter.setMode( nDir != XML_out );
+ pNode->setTransitionFilter( aFilter );
+ }
+ }
+
+ virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
+ {
+ switch ( aElementToken )
+ {
+ case PPT_TOKEN( cBhvr ):
+ return new CommonBehaviorContext ( *this, mpNode );
+ case PPT_TOKEN( progress ):
+ return new AnimVariantContext( *this, aElementToken, maProgress );
+ // TODO handle it.
+ default:
+ break;
+ }
+
+ return this;
+ }
+ private:
+ Any maProgress;
+ };
+
+ }
+
+ rtl::Reference<TimeNodeContext> TimeNodeContext::makeContext(
+ FragmentHandler2 const & rParent, sal_Int32 aElement,
+ const Reference< XFastAttributeList >& xAttribs,
+ const TimeNodePtr & pNode )
+ {
+ rtl::Reference<TimeNodeContext> pCtx;
+ switch( aElement )
+ {
+ case PPT_TOKEN( animClr ):
+ pCtx = new AnimColorContext( rParent, aElement, xAttribs, pNode );
+ break;
+ case PPT_TOKEN( par ):
+ pCtx = new ParallelExclTimeNodeContext( rParent, aElement, pNode );
+ break;
+ case PPT_TOKEN( seq ):
+ pCtx = new SequenceTimeNodeContext( rParent, aElement, xAttribs, pNode );
+ break;
+ case PPT_TOKEN( excl ):
+ pCtx = new ParallelExclTimeNodeContext( rParent, aElement, pNode );
+ break;
+ case PPT_TOKEN( anim ):
+ pCtx = new AnimContext ( rParent, aElement, xAttribs, pNode );
+ break;
+ case PPT_TOKEN( animEffect ):
+ pCtx = new AnimEffectContext( rParent, aElement, xAttribs, pNode );
+ break;
+ case PPT_TOKEN( animMotion ):
+ pCtx = new AnimMotionContext( rParent, aElement, xAttribs, pNode );
+ break;
+ case PPT_TOKEN( animRot ):
+ pCtx = new AnimRotContext( rParent, aElement, xAttribs, pNode );
+ break;
+ case PPT_TOKEN( animScale ):
+ pCtx = new AnimScaleContext( rParent, aElement, xAttribs, pNode );
+ break;
+ case PPT_TOKEN( cmd ):
+ pCtx = new CmdTimeNodeContext( rParent, aElement, xAttribs, pNode );
+ break;
+ case PPT_TOKEN( set ):
+ pCtx = new SetTimeNodeContext( rParent, aElement, pNode );
+ break;
+ case PPT_TOKEN( audio ):
+ case PPT_TOKEN( video ):
+ pCtx = new MediaNodeContext( rParent, aElement, xAttribs, pNode );
+ break;
+ default:
+ break;
+ }
+ return pCtx;
+ }
+
+ TimeNodeContext::TimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
+ const TimeNodePtr & pNode ) noexcept
+ : FragmentHandler2( rParent )
+ , mnElement( aElement )
+ , mpNode( pNode )
+ {
+ }
+
+ TimeNodeContext::~TimeNodeContext( ) noexcept
+ {
+
+ }
+
+ TimeNodeListContext::TimeNodeListContext( FragmentHandler2 const & rParent, TimeNodePtrList & aList )
+ noexcept
+ : FragmentHandler2( rParent )
+ , maList( aList )
+ {
+ }
+
+ TimeNodeListContext::~TimeNodeListContext( ) noexcept
+ {
+ }
+
+ ::oox::core::ContextHandlerRef TimeNodeListContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
+ {
+ sal_Int16 nNodeType;
+
+ switch( aElementToken )
+ {
+ case PPT_TOKEN( par ):
+ nNodeType = AnimationNodeType::PAR;
+ break;
+ case PPT_TOKEN( seq ):
+ nNodeType = AnimationNodeType::SEQ;
+ break;
+ case PPT_TOKEN( excl ):
+ // TODO pick the right type. We choose parallel for now as
+ // there does not seem to be an "Exclusive"
+ nNodeType = AnimationNodeType::PAR;
+ break;
+ case PPT_TOKEN( anim ):
+ nNodeType = AnimationNodeType::ANIMATE;
+ break;
+ case PPT_TOKEN( animClr ):
+ nNodeType = AnimationNodeType::ANIMATECOLOR;
+ break;
+ case PPT_TOKEN( animEffect ):
+ nNodeType = AnimationNodeType::TRANSITIONFILTER;
+ break;
+ case PPT_TOKEN( animMotion ):
+ nNodeType = AnimationNodeType::ANIMATEMOTION;
+ break;
+ case PPT_TOKEN( animRot ):
+ case PPT_TOKEN( animScale ):
+ nNodeType = AnimationNodeType::ANIMATETRANSFORM;
+ break;
+ case PPT_TOKEN( cmd ):
+ nNodeType = AnimationNodeType::COMMAND;
+ break;
+ case PPT_TOKEN( set ):
+ nNodeType = AnimationNodeType::SET;
+ break;
+ case PPT_TOKEN( audio ):
+ nNodeType = AnimationNodeType::AUDIO;
+ break;
+ case PPT_TOKEN( video ):
+ nNodeType = AnimationNodeType::AUDIO;
+ SAL_WARN("oox.ppt", "OOX: video requested, gave Audio instead" );
+ break;
+
+ default:
+ nNodeType = AnimationNodeType::CUSTOM;
+ SAL_INFO("oox.ppt", "unhandled token " << aElementToken);
+ break;
+ }
+
+ TimeNodePtr pNode = std::make_shared<TimeNode>(nNodeType);
+ maList.push_back( pNode );
+ rtl::Reference<FragmentHandler2> pContext = TimeNodeContext::makeContext( *this, aElementToken, rAttribs.getFastAttributeList(), pNode );
+
+ return pContext ? pContext : this;
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */