Prepare for removal of non-const operator[] from Sequence in oox
[LibreOffice.git] / oox / source / ppt / timenodelistcontext.cxx
blob5a6535e314c5eff2066a75d7fa9e6214027fd0e6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <oox/ppt/timenodelistcontext.hxx>
22 #include <rtl/math.hxx>
23 #include <sal/log.hxx>
24 #include <tools/diagnose_ex.h>
26 #include <com/sun/star/animations/AnimationTransformType.hpp>
27 #include <com/sun/star/animations/AnimationCalcMode.hpp>
28 #include <com/sun/star/animations/AnimationColorSpace.hpp>
29 #include <com/sun/star/animations/AnimationNodeType.hpp>
30 #include <com/sun/star/animations/ValuePair.hpp>
31 #include <com/sun/star/presentation/EffectCommands.hpp>
32 #include <com/sun/star/beans/NamedValue.hpp>
34 #include <oox/helper/attributelist.hxx>
35 #include <oox/core/xmlfilterbase.hxx>
36 #include <oox/drawingml/drawingmltypes.hxx>
37 #include <drawingml/colorchoicecontext.hxx>
38 #include <oox/ppt/slidetransition.hxx>
39 #include <oox/token/namespaces.hxx>
40 #include <oox/token/tokens.hxx>
42 #include "animvariantcontext.hxx"
43 #include "commonbehaviorcontext.hxx"
44 #include "conditioncontext.hxx"
45 #include "commontimenodecontext.hxx"
46 #include "timeanimvaluecontext.hxx"
47 #include "animationtypes.hxx"
48 #include "timetargetelementcontext.hxx"
50 using namespace ::oox::core;
51 using namespace ::oox::drawingml;
52 using namespace ::com::sun::star;
53 using namespace ::com::sun::star::uno;
54 using namespace ::com::sun::star::lang;
55 using namespace ::com::sun::star::animations;
56 using namespace ::com::sun::star::presentation;
57 using namespace ::com::sun::star::xml::sax;
58 using ::com::sun::star::beans::NamedValue;
60 namespace {
62 oox::ppt::AnimationAttributeEnum getAttributeEnumByAPIName(const OUString &rAPIName)
64 oox::ppt::AnimationAttributeEnum eResult = oox::ppt::AnimationAttributeEnum::UNKNOWN;
65 const oox::ppt::ImplAttributeNameConversion *attrConv = oox::ppt::getAttributeConversionList();
66 while(attrConv->mpAPIName != nullptr)
68 if(rAPIName.equalsAscii(attrConv->mpAPIName))
70 eResult = attrConv->meAttribute;
71 break;
73 attrConv++;
75 return eResult;
78 bool convertAnimationValueWithTimeNode(const oox::ppt::TimeNodePtr& pNode, css::uno::Any &rAny)
80 css::uno::Any aAny = pNode->getNodeProperties()[oox::ppt::NP_ATTRIBUTENAME];
81 OUString aNameList;
82 aAny >>= aNameList;
84 // only get first token.
85 return oox::ppt::convertAnimationValue(getAttributeEnumByAPIName(aNameList.getToken(0, ';')), rAny);
88 css::uno::Any convertPointPercent(const css::awt::Point& rPoint)
90 css::animations::ValuePair aPair;
91 // rPoint.X and rPoint.Y are in 1000th of a percent, but we only need ratio.
92 aPair.First <<= static_cast<double>(rPoint.X) / 100000.0;
93 aPair.Second <<= static_cast<double>(rPoint.Y) / 100000.0;
94 return makeAny(aPair);
98 namespace oox::ppt {
100 namespace {
102 struct AnimColor
104 AnimColor(sal_Int16 cs, sal_Int32 o, sal_Int32 t, sal_Int32 th )
105 : colorSpace( cs ), one( o ), two( t ), three( th )
109 Any get() const
111 sal_Int32 nColor;
112 Any aColor;
114 switch( colorSpace )
116 case AnimationColorSpace::HSL:
117 aColor <<= Sequence< double >{ one / 100000.0, two / 100000.0, three / 100000.0 };
118 break;
119 case AnimationColorSpace::RGB:
120 nColor = ( ( ( one * 128 ) / 1000 ) & 0xff ) << 16
121 | ( ( ( two * 128 ) / 1000 ) & 0xff ) << 8
122 | ( ( ( three * 128 ) / 1000 ) & 0xff );
123 aColor <<= nColor;
124 break;
125 default:
126 nColor = 0;
127 aColor <<= nColor;
128 break;
130 return aColor;
133 sal_Int16 colorSpace;
134 sal_Int32 one;
135 sal_Int32 two;
136 sal_Int32 three;
139 /** CT_TLMediaNodeAudio
140 CT_TLMediaNodeVideo */
141 class MediaNodeContext
142 : public TimeNodeContext
144 public:
145 MediaNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
146 const Reference< XFastAttributeList >& xAttribs,
147 const TimeNodePtr & pNode )
148 : TimeNodeContext( rParent, aElement, pNode )
149 , mbIsNarration( false )
150 , mbFullScrn( false )
151 , mbHideDuringShow(false)
153 AttributeList attribs( xAttribs );
155 switch( aElement )
157 case PPT_TOKEN( audio ):
158 mbIsNarration = attribs.getBool( XML_isNarration, false );
159 break;
160 case PPT_TOKEN( video ):
161 mbFullScrn = attribs.getBool( XML_fullScrn, false );
162 break;
163 default:
164 break;
168 virtual void onEndElement() override
170 sal_Int32 aElement = getCurrentElement();
171 if( aElement == PPT_TOKEN( audio ) )
173 mpNode->getNodeProperties()[NP_ISNARRATION] <<= mbIsNarration;
175 else if( aElement == PPT_TOKEN( video ) )
177 // TODO deal with mbFullScrn
179 else if (aElement == PPT_TOKEN(cMediaNode))
181 mpNode->getNodeProperties()[NP_HIDEDURINGSHOW] <<= mbHideDuringShow;
185 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs) override
187 switch ( aElementToken )
189 case PPT_TOKEN( cTn ):
190 return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode );
191 case PPT_TOKEN( tgtEl ):
192 return new TimeTargetElementContext( *this, mpNode->getTarget() );
193 case PPT_TOKEN(cMediaNode):
194 mbHideDuringShow = !rAttribs.getBool(XML_showWhenStopped, true);
195 break;
196 default:
197 break;
200 return this;
203 private:
204 bool mbIsNarration;
205 bool mbFullScrn;
206 bool mbHideDuringShow;
209 /** CT_TLSetBehavior
211 class SetTimeNodeContext
212 : public TimeNodeContext
214 public:
215 SetTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
216 const TimeNodePtr & pNode )
217 : TimeNodeContext( rParent, aElement, pNode )
222 virtual ~SetTimeNodeContext() noexcept override
224 if(maTo.hasValue())
226 convertAnimationValueWithTimeNode(mpNode, maTo);
227 mpNode->setTo(maTo);
232 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
234 switch ( aElementToken )
236 case PPT_TOKEN( cBhvr ):
237 return new CommonBehaviorContext ( *this, mpNode );
238 case PPT_TOKEN( to ):
239 // CT_TLAnimVariant
240 return new AnimVariantContext( *this, aElementToken, maTo );
241 default:
242 break;
245 return this;
247 private:
248 Any maTo;
251 /** CT_TLCommandBehavior
253 class CmdTimeNodeContext
254 : public TimeNodeContext
256 public:
257 CmdTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
258 const Reference< XFastAttributeList >& xAttribs,
259 const TimeNodePtr & pNode )
260 : TimeNodeContext( rParent, aElement, pNode )
261 , maType(0)
263 switch ( aElement )
265 case PPT_TOKEN( cmd ):
266 msCommand = xAttribs->getOptionalValue( XML_cmd );
267 maType = xAttribs->getOptionalValueToken( XML_type, 0 );
268 break;
269 default:
270 break;
274 virtual void onEndElement() override
276 if( !isCurrentElement( PPT_TOKEN( cmd ) ) )
277 return;
279 try {
280 // see sd/source/filter/ppt/pptinanimations.cxx
281 // in AnimationImporter::importCommandContainer()
282 // REFACTOR?
283 // a good chunk of this code has been copied verbatim *sigh*
284 sal_Int16 nCommand = EffectCommands::CUSTOM;
285 NamedValue aParamValue;
287 switch( maType )
289 case XML_verb:
290 aParamValue.Name = "Verb";
291 // TODO make sure msCommand has what we want
292 aParamValue.Value <<= msCommand.toInt32();
293 nCommand = EffectCommands::VERB;
294 break;
295 case XML_evt:
296 case XML_call:
297 if ( msCommand == "onstopaudio" )
299 nCommand = EffectCommands::STOPAUDIO;
301 else if ( msCommand == "play" )
303 nCommand = EffectCommands::PLAY;
305 else if (msCommand.startsWith("playFrom"))
307 const OUString aMediaTime( msCommand.copy( 9, msCommand.getLength() - 10 ) );
308 rtl_math_ConversionStatus eStatus;
309 double fMediaTime = ::rtl::math::stringToDouble( aMediaTime, u'.', u',', &eStatus );
310 if( eStatus == rtl_math_ConversionStatus_Ok )
312 aParamValue.Name = "MediaTime";
313 aParamValue.Value <<= fMediaTime;
315 nCommand = EffectCommands::PLAY;
317 else if ( msCommand == "togglePause" )
319 nCommand = EffectCommands::TOGGLEPAUSE;
321 else if ( msCommand == "stop" )
323 nCommand = EffectCommands::STOP;
325 break;
327 mpNode->getNodeProperties()[ NP_COMMAND ] <<= nCommand;
328 if( nCommand == EffectCommands::CUSTOM )
330 SAL_WARN("oox.ppt", "OOX: CmdTimeNodeContext::endFastElement(), unknown command!");
331 aParamValue.Name = "UserDefined";
332 aParamValue.Value <<= msCommand;
334 if( aParamValue.Value.hasValue() )
336 Sequence< NamedValue > aParamSeq( &aParamValue, 1 );
337 mpNode->getNodeProperties()[ NP_PARAMETER ] <<= aParamSeq;
340 catch( RuntimeException& )
342 TOOLS_WARN_EXCEPTION("oox.ppt", "OOX: Exception in CmdTimeNodeContext::endFastElement()" );
346 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
348 switch ( aElementToken )
350 case PPT_TOKEN( cBhvr ):
351 return new CommonBehaviorContext ( *this, mpNode );
352 default:
353 break;
356 return this;
359 private:
360 OUString msCommand;
361 sal_Int32 maType;
364 /** CT_TLTimeNodeSequence
366 class SequenceTimeNodeContext
367 : public TimeNodeContext
369 public:
370 SequenceTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
371 const Reference< XFastAttributeList >& xAttribs,
372 const TimeNodePtr & pNode )
373 : TimeNodeContext( rParent, aElement, pNode )
374 , mnNextAc(0)
375 , mnPrevAc(0)
377 AttributeList attribs(xAttribs);
378 mbConcurrent = attribs.getBool( XML_concurrent, false );
379 mnNextAc = xAttribs->getOptionalValueToken( XML_nextAc, 0 );
380 mnPrevAc = xAttribs->getOptionalValueToken( XML_prevAc, 0 );
383 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
385 switch ( aElementToken )
387 case PPT_TOKEN( cTn ):
388 return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode );
389 case PPT_TOKEN( nextCondLst ):
390 return new CondListContext( *this, aElementToken, mpNode, mpNode->getNextCondition() );
391 case PPT_TOKEN( prevCondLst ):
392 return new CondListContext( *this, aElementToken, mpNode, mpNode->getPrevCondition() );
393 default:
394 break;
397 return this;
399 private:
400 bool mbConcurrent;
401 sal_Int32 mnNextAc, mnPrevAc;
404 /** CT_TLTimeNodeParallel
405 * CT_TLTimeNodeExclusive
407 class ParallelExclTimeNodeContext
408 : public TimeNodeContext
410 public:
411 ParallelExclTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
412 const TimeNodePtr & pNode )
413 : TimeNodeContext( rParent, aElement, pNode )
417 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
419 switch ( aElementToken )
421 case PPT_TOKEN( cTn ):
422 return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode );
423 default:
424 break;
427 return this;
430 protected:
434 /** CT_TLAnimateColorBehavior */
435 class AnimColorContext
436 : public TimeNodeContext
438 public:
439 AnimColorContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
440 const Reference< XFastAttributeList >& xAttribs,
441 const TimeNodePtr & pNode ) noexcept
442 : TimeNodeContext( rParent, aElement, pNode )
443 , mnColorSpace( xAttribs->getOptionalValueToken( XML_clrSpc, 0 ) )
444 , mnDir( xAttribs->getOptionalValueToken( XML_dir, 0 ) )
445 , mbHasByColor( false )
446 , m_byColor( AnimationColorSpace::RGB, 0, 0, 0)
450 virtual void onEndElement() override
452 //xParentNode
453 if( !isCurrentElement( mnElement ) )
454 return;
456 NodePropertyMap & rProps(mpNode->getNodeProperties());
457 rProps[ NP_DIRECTION ] <<= mnDir == XML_cw;
458 rProps[ NP_COLORINTERPOLATION ] <<= mnColorSpace == XML_hsl ? AnimationColorSpace::HSL : AnimationColorSpace::RGB;
459 const GraphicHelper& rGraphicHelper = getFilter().getGraphicHelper();
460 if( maToClr.isUsed() )
461 mpNode->setTo( makeAny( maToClr.getColor( rGraphicHelper ) ) );
462 if( maFromClr.isUsed() )
463 mpNode->setFrom( makeAny( maFromClr.getColor( rGraphicHelper ) ) );
464 if( mbHasByColor )
465 mpNode->setBy( m_byColor.get() );
468 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
470 switch ( aElementToken )
472 case PPT_TOKEN( hsl ):
473 // CT_TLByHslColorTransform
475 if( mbHasByColor )
477 m_byColor.colorSpace = AnimationColorSpace::HSL;
478 m_byColor.one = rAttribs.getInteger( XML_h, 0 );
479 m_byColor.two = rAttribs.getInteger( XML_s, 0 );
480 m_byColor.three = rAttribs.getInteger( XML_l, 0 );
482 return this;
484 case PPT_TOKEN( rgb ):
486 if( mbHasByColor )
488 // CT_TLByRgbColorTransform
489 m_byColor.colorSpace = AnimationColorSpace::RGB;
490 m_byColor.one = rAttribs.getInteger( XML_r, 0 );
491 m_byColor.two = rAttribs.getInteger( XML_g, 0 );
492 m_byColor.three = rAttribs.getInteger( XML_b, 0 );
494 return this;
496 case PPT_TOKEN( by ):
497 // CT_TLByAnimateColorTransform
498 mbHasByColor = true;
499 return this;
500 case PPT_TOKEN( cBhvr ):
501 return new CommonBehaviorContext ( *this, mpNode );
502 case PPT_TOKEN( to ):
503 // CT_Color
504 return new ColorContext( *this, maToClr );
505 case PPT_TOKEN( from ):
506 // CT_Color
507 return new ColorContext( *this, maFromClr );
509 default:
510 break;
513 return this;
516 private:
517 sal_Int32 mnColorSpace;
518 sal_Int32 mnDir;
519 bool mbHasByColor;
520 AnimColor m_byColor;
521 oox::drawingml::Color maToClr;
522 oox::drawingml::Color maFromClr;
525 /** CT_TLAnimateBehavior */
526 class AnimContext
527 : public TimeNodeContext
529 public:
530 AnimContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
531 const Reference< XFastAttributeList >& xAttribs,
532 const TimeNodePtr & pNode ) noexcept
533 : TimeNodeContext( rParent, aElement, pNode )
535 NodePropertyMap & aProps( pNode->getNodeProperties() );
536 sal_Int32 nCalcMode = xAttribs->getOptionalValueToken( XML_calcmode, 0 );
537 if(nCalcMode)
539 sal_Int16 nEnum = 0;
540 switch(nCalcMode)
542 case XML_discrete:
543 nEnum = AnimationCalcMode::DISCRETE;
544 break;
545 case XML_lin:
546 nEnum = AnimationCalcMode::LINEAR;
547 break;
548 case XML_fmla:
549 default:
550 // TODO what value is good ?
551 nEnum = AnimationCalcMode::DISCRETE;
552 break;
554 aProps[ NP_CALCMODE ] <<= nEnum;
557 msFrom = xAttribs->getOptionalValue(XML_from);
558 msTo = xAttribs->getOptionalValue(XML_to);
559 msBy = xAttribs->getOptionalValue(XML_by);
561 mnValueType = xAttribs->getOptionalValueToken( XML_valueType, 0 );
564 virtual ~AnimContext() noexcept override
566 if (!msFrom.isEmpty())
568 css::uno::Any aAny;
569 aAny <<= msFrom;
570 convertAnimationValueWithTimeNode(mpNode, aAny);
571 mpNode->setFrom(aAny);
574 if (!msTo.isEmpty())
576 css::uno::Any aAny;
577 aAny <<= msTo;
578 convertAnimationValueWithTimeNode(mpNode, aAny);
579 mpNode->setTo(aAny);
582 if (!msBy.isEmpty())
584 css::uno::Any aAny;
585 aAny <<= msBy;
586 convertAnimationValueWithTimeNode(mpNode, aAny);
587 mpNode->setBy(aAny);
590 int nKeyTimes = maTavList.size();
591 if( nKeyTimes <= 0)
592 return;
594 int i=0;
595 Sequence< double > aKeyTimes( nKeyTimes );
596 auto pKeyTimes = aKeyTimes.getArray();
597 Sequence< Any > aValues( nKeyTimes );
598 auto pValues = aValues.getArray();
600 NodePropertyMap & aProps( mpNode->getNodeProperties() );
601 for (auto const& tav : maTavList)
603 // TODO what to do if it is Timing_INFINITE ?
604 Any aTime = GetTimeAnimateValueTime( tav.msTime );
605 aTime >>= pKeyTimes[i];
606 pValues[i] = tav.maValue;
607 convertAnimationValueWithTimeNode(mpNode, pValues[i]);
609 // Examine pptx documents and find that only the first tav
610 // has the formula set. The formula can be used for the whole.
611 if (!tav.msFormula.isEmpty())
613 OUString sFormula = tav.msFormula;
614 (void)convertMeasure(sFormula);
615 aProps[NP_FORMULA] <<= sFormula;
618 ++i;
620 aProps[ NP_VALUES ] <<= aValues;
621 aProps[ NP_KEYTIMES ] <<= aKeyTimes;
624 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
626 switch ( aElementToken )
628 case PPT_TOKEN( cBhvr ):
629 return new CommonBehaviorContext ( *this, mpNode );
630 case PPT_TOKEN( tavLst ):
631 return new TimeAnimValueListContext ( *this, maTavList );
632 default:
633 break;
636 return this;
638 private:
639 sal_Int32 mnValueType;
640 TimeAnimationValueList maTavList;
641 OUString msFrom;
642 OUString msTo;
643 OUString msBy;
646 /** CT_TLAnimateScaleBehavior */
647 class AnimScaleContext
648 : public TimeNodeContext
650 public:
651 AnimScaleContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
652 const Reference< XFastAttributeList >& xAttribs,
653 const TimeNodePtr & pNode ) noexcept
654 : TimeNodeContext( rParent, aElement, pNode )
655 , mbZoomContents( false )
657 AttributeList attribs( xAttribs );
658 // TODO what to do with mbZoomContents
659 mbZoomContents = attribs.getBool( XML_zoomContents, false );
660 pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
661 <<= sal_Int16(AnimationTransformType::SCALE);
664 virtual void onEndElement() override
666 if( !isCurrentElement( mnElement ) )
667 return;
669 if( maTo.hasValue() )
671 mpNode->setTo( maTo );
673 if( maBy.hasValue() )
675 mpNode->setBy( maBy );
677 if( maFrom.hasValue() )
679 mpNode->setFrom( maFrom );
683 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
685 switch ( aElementToken )
687 case PPT_TOKEN( cBhvr ):
688 return new CommonBehaviorContext ( *this, mpNode );
689 case PPT_TOKEN( to ):
691 // CT_TLPoint
692 maTo = convertPointPercent(GetPointPercent(rAttribs.getFastAttributeList()));
693 return this;
695 case PPT_TOKEN( from ):
697 // CT_TLPoint
698 maFrom = convertPointPercent(GetPointPercent(rAttribs.getFastAttributeList()));
699 return this;
701 case PPT_TOKEN( by ):
703 // CT_TLPoint
704 css::awt::Point aPoint = GetPointPercent(rAttribs.getFastAttributeList());
705 // We got ending values instead of offset values, so subtract 100% from them.
706 aPoint.X -= 100000;
707 aPoint.Y -= 100000;
708 maBy = convertPointPercent(aPoint);
709 return this;
711 default:
712 break;
715 return this;
717 private:
718 Any maBy;
719 Any maFrom;
720 Any maTo;
721 bool mbZoomContents;
724 /** CT_TLAnimateRotationBehavior */
725 class AnimRotContext
726 : public TimeNodeContext
728 public:
729 AnimRotContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
730 const Reference< XFastAttributeList >& xAttribs,
731 const TimeNodePtr & pNode ) noexcept
732 : TimeNodeContext( rParent, aElement, pNode )
734 AttributeList attribs( xAttribs );
736 pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
737 <<= sal_Int16(AnimationTransformType::ROTATE);
738 // see also DFF_msofbtAnimateRotationData in
739 // sd/source/filter/ppt/pptinanimations.cxx
740 if(attribs.hasAttribute( XML_by ) )
742 double fBy = attribs.getDouble( XML_by, 0.0 ) / PER_DEGREE; //1 PowerPoint-angle-unit = 1/60000 degree
743 pNode->setBy( makeAny( fBy ) );
745 if(attribs.hasAttribute( XML_from ) )
747 double fFrom = attribs.getDouble( XML_from, 0.0 ) / PER_DEGREE;
748 pNode->setFrom( makeAny( fFrom ) );
750 if(attribs.hasAttribute( XML_to ) )
752 double fTo = attribs.getDouble( XML_to, 0.0 ) / PER_DEGREE;
753 pNode->setTo( makeAny( fTo ) );
757 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
759 switch ( aElementToken )
761 case PPT_TOKEN( cBhvr ):
762 return new CommonBehaviorContext ( *this, mpNode );
763 default:
764 break;
767 return this;
771 /** CT_TLAnimateMotionBehavior */
772 class AnimMotionContext
773 : public TimeNodeContext
775 public:
776 AnimMotionContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
777 const Reference< XFastAttributeList >& xAttribs,
778 const TimeNodePtr & pNode ) noexcept
779 : TimeNodeContext( rParent, aElement, pNode )
781 pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
782 <<= sal_Int16(AnimationTransformType::TRANSLATE);
784 AttributeList attribs( xAttribs );
785 sal_Int32 nOrigin = xAttribs->getOptionalValueToken( XML_origin, 0 );
786 if( nOrigin != 0 )
788 switch(nOrigin)
790 case XML_layout:
791 case XML_parent:
792 break;
794 // TODO
797 OUString aStr = xAttribs->getOptionalValue( XML_path );
798 // E can appear inside a number, so we only check for its presence at the end
799 aStr = aStr.trim();
800 if (aStr.endsWith("E"))
801 aStr = aStr.copy(0, aStr.getLength() - 1);
802 aStr = aStr.trim();
803 pNode->getNodeProperties()[ NP_PATH ] <<= aStr;
804 mnPathEditMode = xAttribs->getOptionalValueToken( XML_pathEditMode, 0 );
805 msPtsTypes = xAttribs->getOptionalValue( XML_ptsTypes );
806 mnAngle = attribs.getInteger( XML_rAng, 0 );
807 // TODO make sure the units are right. Likely not.
810 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
812 switch ( aElementToken )
814 case PPT_TOKEN( cBhvr ):
815 return new CommonBehaviorContext ( *this, mpNode );
816 case PPT_TOKEN( to ):
818 // CT_TLPoint
819 awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() );
820 Any rAny;
821 rAny <<= p.X;
822 rAny <<= p.Y;
823 mpNode->setTo( rAny );
824 return this;
826 case PPT_TOKEN( from ):
828 // CT_TLPoint
829 awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() );
830 Any rAny;
831 rAny <<= p.X;
832 rAny <<= p.Y;
833 mpNode->setFrom( rAny );
834 return this;
836 case PPT_TOKEN( by ):
838 // CT_TLPoint
839 awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() );
840 Any rAny;
841 rAny <<= p.X;
842 rAny <<= p.Y;
843 mpNode->setBy( rAny );
844 return this;
846 case PPT_TOKEN( rCtr ):
848 // CT_TLPoint
849 awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() );
850 // TODO push
851 (void)p;
852 return this;
854 default:
855 break;
858 return this;
860 private:
861 OUString msPtsTypes;
862 sal_Int32 mnPathEditMode;
863 sal_Int32 mnAngle;
866 /** CT_TLAnimateEffectBehavior */
867 class AnimEffectContext
868 : public TimeNodeContext
870 public:
871 AnimEffectContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
872 const Reference< XFastAttributeList >& xAttribs,
873 const TimeNodePtr & pNode ) noexcept
874 : TimeNodeContext( rParent, aElement, pNode )
876 sal_Int32 nDir = xAttribs->getOptionalValueToken( XML_transition, 0 );
877 OUString sFilter = xAttribs->getOptionalValue( XML_filter );
878 // TODO
879 // OUString sPrList = xAttribs->getOptionalValue( XML_prLst );
881 if( !sFilter.isEmpty() )
883 SlideTransition aFilter( sFilter );
884 aFilter.setMode( nDir != XML_out );
885 pNode->setTransitionFilter( aFilter );
889 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
891 switch ( aElementToken )
893 case PPT_TOKEN( cBhvr ):
894 return new CommonBehaviorContext ( *this, mpNode );
895 case PPT_TOKEN( progress ):
896 return new AnimVariantContext( *this, aElementToken, maProgress );
897 // TODO handle it.
898 default:
899 break;
902 return this;
904 private:
905 Any maProgress;
910 rtl::Reference<TimeNodeContext> TimeNodeContext::makeContext(
911 FragmentHandler2 const & rParent, sal_Int32 aElement,
912 const Reference< XFastAttributeList >& xAttribs,
913 const TimeNodePtr & pNode )
915 rtl::Reference<TimeNodeContext> pCtx;
916 switch( aElement )
918 case PPT_TOKEN( animClr ):
919 pCtx = new AnimColorContext( rParent, aElement, xAttribs, pNode );
920 break;
921 case PPT_TOKEN( par ):
922 pCtx = new ParallelExclTimeNodeContext( rParent, aElement, pNode );
923 break;
924 case PPT_TOKEN( seq ):
925 pCtx = new SequenceTimeNodeContext( rParent, aElement, xAttribs, pNode );
926 break;
927 case PPT_TOKEN( excl ):
928 pCtx = new ParallelExclTimeNodeContext( rParent, aElement, pNode );
929 break;
930 case PPT_TOKEN( anim ):
931 pCtx = new AnimContext ( rParent, aElement, xAttribs, pNode );
932 break;
933 case PPT_TOKEN( animEffect ):
934 pCtx = new AnimEffectContext( rParent, aElement, xAttribs, pNode );
935 break;
936 case PPT_TOKEN( animMotion ):
937 pCtx = new AnimMotionContext( rParent, aElement, xAttribs, pNode );
938 break;
939 case PPT_TOKEN( animRot ):
940 pCtx = new AnimRotContext( rParent, aElement, xAttribs, pNode );
941 break;
942 case PPT_TOKEN( animScale ):
943 pCtx = new AnimScaleContext( rParent, aElement, xAttribs, pNode );
944 break;
945 case PPT_TOKEN( cmd ):
946 pCtx = new CmdTimeNodeContext( rParent, aElement, xAttribs, pNode );
947 break;
948 case PPT_TOKEN( set ):
949 pCtx = new SetTimeNodeContext( rParent, aElement, pNode );
950 break;
951 case PPT_TOKEN( audio ):
952 case PPT_TOKEN( video ):
953 pCtx = new MediaNodeContext( rParent, aElement, xAttribs, pNode );
954 break;
955 default:
956 break;
958 return pCtx;
961 TimeNodeContext::TimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
962 const TimeNodePtr & pNode ) noexcept
963 : FragmentHandler2( rParent )
964 , mnElement( aElement )
965 , mpNode( pNode )
969 TimeNodeContext::~TimeNodeContext( ) noexcept
974 TimeNodeListContext::TimeNodeListContext( FragmentHandler2 const & rParent, TimeNodePtrList & aList )
975 noexcept
976 : FragmentHandler2( rParent )
977 , maList( aList )
981 TimeNodeListContext::~TimeNodeListContext( ) noexcept
985 ::oox::core::ContextHandlerRef TimeNodeListContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
987 sal_Int16 nNodeType;
989 switch( aElementToken )
991 case PPT_TOKEN( par ):
992 nNodeType = AnimationNodeType::PAR;
993 break;
994 case PPT_TOKEN( seq ):
995 nNodeType = AnimationNodeType::SEQ;
996 break;
997 case PPT_TOKEN( excl ):
998 // TODO pick the right type. We choose parallel for now as
999 // there does not seem to be an "Exclusive"
1000 nNodeType = AnimationNodeType::PAR;
1001 break;
1002 case PPT_TOKEN( anim ):
1003 nNodeType = AnimationNodeType::ANIMATE;
1004 break;
1005 case PPT_TOKEN( animClr ):
1006 nNodeType = AnimationNodeType::ANIMATECOLOR;
1007 break;
1008 case PPT_TOKEN( animEffect ):
1009 nNodeType = AnimationNodeType::TRANSITIONFILTER;
1010 break;
1011 case PPT_TOKEN( animMotion ):
1012 nNodeType = AnimationNodeType::ANIMATEMOTION;
1013 break;
1014 case PPT_TOKEN( animRot ):
1015 case PPT_TOKEN( animScale ):
1016 nNodeType = AnimationNodeType::ANIMATETRANSFORM;
1017 break;
1018 case PPT_TOKEN( cmd ):
1019 nNodeType = AnimationNodeType::COMMAND;
1020 break;
1021 case PPT_TOKEN( set ):
1022 nNodeType = AnimationNodeType::SET;
1023 break;
1024 case PPT_TOKEN( audio ):
1025 nNodeType = AnimationNodeType::AUDIO;
1026 break;
1027 case PPT_TOKEN( video ):
1028 nNodeType = AnimationNodeType::AUDIO;
1029 SAL_WARN("oox.ppt", "OOX: video requested, gave Audio instead" );
1030 break;
1032 default:
1033 nNodeType = AnimationNodeType::CUSTOM;
1034 SAL_INFO("oox.ppt", "unhandled token " << aElementToken);
1035 break;
1038 TimeNodePtr pNode = std::make_shared<TimeNode>(nNodeType);
1039 maList.push_back( pNode );
1040 rtl::Reference<FragmentHandler2> pContext = TimeNodeContext::makeContext( *this, aElementToken, rAttribs.getFastAttributeList(), pNode );
1042 return pContext ? pContext : this;
1047 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */