diff options
Diffstat (limited to '')
-rw-r--r-- | oox/source/ppt/timenodelistcontext.cxx | 1048 |
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: */ |