Bump version to 24.04.3.4
[LibreOffice.git] / oox / source / ppt / timenodelistcontext.cxx
blob50d5c032f61257cf2a427aded6084d0666b061cc
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 <comphelper/diagnose_ex.hxx>
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>
41 #include <o3tl/string_view.hxx>
42 #include <utility>
44 #include "animvariantcontext.hxx"
45 #include "commonbehaviorcontext.hxx"
46 #include "conditioncontext.hxx"
47 #include "commontimenodecontext.hxx"
48 #include "timeanimvaluecontext.hxx"
49 #include "animationtypes.hxx"
50 #include "timetargetelementcontext.hxx"
52 using namespace ::oox::core;
53 using namespace ::oox::drawingml;
54 using namespace ::com::sun::star;
55 using namespace ::com::sun::star::uno;
56 using namespace ::com::sun::star::lang;
57 using namespace ::com::sun::star::animations;
58 using namespace ::com::sun::star::presentation;
59 using namespace ::com::sun::star::xml::sax;
60 using ::com::sun::star::beans::NamedValue;
62 namespace {
64 oox::ppt::AnimationAttributeEnum getAttributeEnumByAPIName(std::u16string_view rAPIName)
66 oox::ppt::AnimationAttributeEnum eResult = oox::ppt::AnimationAttributeEnum::UNKNOWN;
67 const oox::ppt::ImplAttributeNameConversion *attrConv = oox::ppt::getAttributeConversionList();
68 while(attrConv->mpAPIName != nullptr)
70 if(o3tl::equalsAscii(rAPIName, attrConv->mpAPIName))
72 eResult = attrConv->meAttribute;
73 break;
75 attrConv++;
77 return eResult;
80 bool convertAnimationValueWithTimeNode(const oox::ppt::TimeNodePtr& pNode, css::uno::Any &rAny)
82 css::uno::Any aAny = pNode->getNodeProperties()[oox::ppt::NP_ATTRIBUTENAME];
83 OUString aNameList;
84 aAny >>= aNameList;
86 // only get first token.
87 return oox::ppt::convertAnimationValue(getAttributeEnumByAPIName(o3tl::getToken(aNameList, 0, ';')), rAny);
90 css::uno::Any convertPointPercent(const css::awt::Point& rPoint)
92 css::animations::ValuePair aPair;
93 // rPoint.X and rPoint.Y are in 1000th of a percent, but we only need ratio.
94 aPair.First <<= static_cast<double>(rPoint.X) / 100000.0;
95 aPair.Second <<= static_cast<double>(rPoint.Y) / 100000.0;
96 return Any(aPair);
100 namespace oox::ppt {
102 namespace {
104 struct AnimColor
106 AnimColor(sal_Int16 cs, sal_Int32 o, sal_Int32 t, sal_Int32 th )
107 : colorSpace( cs ), one( o ), two( t ), three( th )
111 Any get() const
113 sal_Int32 nColor;
114 Any aColor;
116 switch( colorSpace )
118 case AnimationColorSpace::HSL:
119 aColor <<= Sequence< double >{ one / 100000.0, two / 100000.0, three / 100000.0 };
120 break;
121 case AnimationColorSpace::RGB:
122 nColor = ( ( ( one * 128 ) / 1000 ) & 0xff ) << 16
123 | ( ( ( two * 128 ) / 1000 ) & 0xff ) << 8
124 | ( ( ( three * 128 ) / 1000 ) & 0xff );
125 aColor <<= nColor;
126 break;
127 default:
128 nColor = 0;
129 aColor <<= nColor;
130 break;
132 return aColor;
135 sal_Int16 colorSpace;
136 sal_Int32 one;
137 sal_Int32 two;
138 sal_Int32 three;
141 /** CT_TLMediaNodeAudio
142 CT_TLMediaNodeVideo */
143 class MediaNodeContext
144 : public TimeNodeContext
146 public:
147 MediaNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
148 const Reference< XFastAttributeList >& xAttribs,
149 const TimeNodePtr & pNode )
150 : TimeNodeContext( rParent, aElement, pNode )
151 , mbIsNarration( false )
152 , mbFullScrn( false )
153 , mbHideDuringShow(false)
155 AttributeList attribs( xAttribs );
157 switch( aElement )
159 case PPT_TOKEN( audio ):
160 mbIsNarration = attribs.getBool( XML_isNarration, false );
161 break;
162 case PPT_TOKEN( video ):
163 mbFullScrn = attribs.getBool( XML_fullScrn, false );
164 break;
165 default:
166 break;
170 virtual void onEndElement() override
172 sal_Int32 aElement = getCurrentElement();
173 if( aElement == PPT_TOKEN( audio ) )
175 mpNode->getNodeProperties()[NP_ISNARRATION] <<= mbIsNarration;
177 else if( aElement == PPT_TOKEN( video ) )
179 // TODO deal with mbFullScrn
181 else if (aElement == PPT_TOKEN(cMediaNode))
183 mpNode->getNodeProperties()[NP_HIDEDURINGSHOW] <<= mbHideDuringShow;
187 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs) override
189 switch ( aElementToken )
191 case PPT_TOKEN( cTn ):
192 return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode );
193 case PPT_TOKEN( tgtEl ):
194 return new TimeTargetElementContext( *this, mpNode->getTarget() );
195 case PPT_TOKEN(cMediaNode):
196 mbHideDuringShow = !rAttribs.getBool(XML_showWhenStopped, true);
197 break;
198 default:
199 break;
202 return this;
205 private:
206 bool mbIsNarration;
207 bool mbFullScrn;
208 bool mbHideDuringShow;
211 /** CT_TLSetBehavior
213 class SetTimeNodeContext
214 : public TimeNodeContext
216 public:
217 SetTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
218 const TimeNodePtr & pNode )
219 : TimeNodeContext( rParent, aElement, pNode )
224 virtual ~SetTimeNodeContext() noexcept override
226 if(maTo.hasValue())
228 convertAnimationValueWithTimeNode(mpNode, maTo);
229 mpNode->setTo(maTo);
234 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
236 switch ( aElementToken )
238 case PPT_TOKEN( cBhvr ):
239 return new CommonBehaviorContext ( *this, mpNode );
240 case PPT_TOKEN( to ):
241 // CT_TLAnimVariant
242 return new AnimVariantContext( *this, aElementToken, maTo );
243 default:
244 break;
247 return this;
249 private:
250 Any maTo;
253 /** CT_TLCommandBehavior
255 class CmdTimeNodeContext
256 : public TimeNodeContext
258 public:
259 CmdTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
260 const Reference< XFastAttributeList >& xAttribs,
261 const TimeNodePtr & pNode )
262 : TimeNodeContext( rParent, aElement, pNode )
263 , maType(0)
265 switch ( aElement )
267 case PPT_TOKEN( cmd ):
268 msCommand = xAttribs->getOptionalValue( XML_cmd );
269 maType = xAttribs->getOptionalValueToken( XML_type, 0 );
270 break;
271 default:
272 break;
276 virtual void onEndElement() override
278 if( !isCurrentElement( PPT_TOKEN( cmd ) ) )
279 return;
281 try {
282 // see sd/source/filter/ppt/pptinanimations.cxx
283 // in AnimationImporter::importCommandContainer()
284 // REFACTOR?
285 // a good chunk of this code has been copied verbatim *sigh*
286 sal_Int16 nCommand = EffectCommands::CUSTOM;
287 NamedValue aParamValue;
289 switch( maType )
291 case XML_verb:
292 aParamValue.Name = "Verb";
293 // TODO make sure msCommand has what we want
294 aParamValue.Value <<= msCommand.toInt32();
295 nCommand = EffectCommands::VERB;
296 break;
297 case XML_evt:
298 case XML_call:
299 if ( msCommand == "onstopaudio" )
301 nCommand = EffectCommands::STOPAUDIO;
303 else if ( msCommand == "play" )
305 nCommand = EffectCommands::PLAY;
307 else if (msCommand.startsWith("playFrom"))
309 std::u16string_view aMediaTime( msCommand.subView( 9, msCommand.getLength() - 10 ) );
310 rtl_math_ConversionStatus eStatus;
311 double fMediaTime = ::rtl::math::stringToDouble( aMediaTime, u'.', u',', &eStatus );
312 if( eStatus == rtl_math_ConversionStatus_Ok )
314 aParamValue.Name = "MediaTime";
315 aParamValue.Value <<= fMediaTime;
317 nCommand = EffectCommands::PLAY;
319 else if ( msCommand == "togglePause" )
321 nCommand = EffectCommands::TOGGLEPAUSE;
323 else if ( msCommand == "stop" )
325 nCommand = EffectCommands::STOP;
327 break;
329 mpNode->getNodeProperties()[ NP_COMMAND ] <<= nCommand;
330 if( nCommand == EffectCommands::CUSTOM )
332 SAL_WARN("oox.ppt", "OOX: CmdTimeNodeContext::endFastElement(), unknown command!");
333 aParamValue.Name = "UserDefined";
334 aParamValue.Value <<= msCommand;
336 if( aParamValue.Value.hasValue() )
338 Sequence< NamedValue > aParamSeq( &aParamValue, 1 );
339 mpNode->getNodeProperties()[ NP_PARAMETER ] <<= aParamSeq;
342 catch( RuntimeException& )
344 TOOLS_WARN_EXCEPTION("oox.ppt", "OOX: Exception in CmdTimeNodeContext::endFastElement()" );
348 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
350 switch ( aElementToken )
352 case PPT_TOKEN( cBhvr ):
353 return new CommonBehaviorContext ( *this, mpNode );
354 default:
355 break;
358 return this;
361 private:
362 OUString msCommand;
363 sal_Int32 maType;
366 /** CT_TLTimeNodeSequence
368 class SequenceTimeNodeContext
369 : public TimeNodeContext
371 public:
372 SequenceTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
373 const Reference< XFastAttributeList >& xAttribs,
374 const TimeNodePtr & pNode )
375 : TimeNodeContext( rParent, aElement, pNode )
376 , mnNextAc(0)
377 , mnPrevAc(0)
379 AttributeList attribs(xAttribs);
380 mbConcurrent = attribs.getBool( XML_concurrent, false );
381 mnNextAc = xAttribs->getOptionalValueToken( XML_nextAc, 0 );
382 mnPrevAc = xAttribs->getOptionalValueToken( XML_prevAc, 0 );
385 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
387 switch ( aElementToken )
389 case PPT_TOKEN( cTn ):
390 return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode );
391 case PPT_TOKEN( nextCondLst ):
392 return new CondListContext( *this, aElementToken, mpNode, mpNode->getNextCondition() );
393 case PPT_TOKEN( prevCondLst ):
394 return new CondListContext( *this, aElementToken, mpNode, mpNode->getPrevCondition() );
395 default:
396 break;
399 return this;
401 private:
402 bool mbConcurrent;
403 sal_Int32 mnNextAc, mnPrevAc;
406 /** CT_TLTimeNodeParallel
407 * CT_TLTimeNodeExclusive
409 class ParallelExclTimeNodeContext
410 : public TimeNodeContext
412 public:
413 ParallelExclTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
414 const TimeNodePtr & pNode )
415 : TimeNodeContext( rParent, aElement, pNode )
419 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
421 switch ( aElementToken )
423 case PPT_TOKEN( cTn ):
424 return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode );
425 default:
426 break;
429 return this;
432 protected:
436 /** CT_TLAnimateColorBehavior */
437 class AnimColorContext
438 : public TimeNodeContext
440 public:
441 AnimColorContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
442 const Reference< XFastAttributeList >& xAttribs,
443 const TimeNodePtr & pNode ) noexcept
444 : TimeNodeContext( rParent, aElement, pNode )
445 , mnColorSpace( xAttribs->getOptionalValueToken( XML_clrSpc, 0 ) )
446 , mnDir( xAttribs->getOptionalValueToken( XML_dir, 0 ) )
447 , mbHasByColor( false )
448 , m_byColor( AnimationColorSpace::RGB, 0, 0, 0)
452 virtual void onEndElement() override
454 //xParentNode
455 if( !isCurrentElement( mnElement ) )
456 return;
458 NodePropertyMap & rProps(mpNode->getNodeProperties());
459 rProps[ NP_DIRECTION ] <<= mnDir == XML_cw;
460 rProps[ NP_COLORINTERPOLATION ] <<= mnColorSpace == XML_hsl ? AnimationColorSpace::HSL : AnimationColorSpace::RGB;
461 const GraphicHelper& rGraphicHelper = getFilter().getGraphicHelper();
462 if( maToClr.isUsed() )
463 mpNode->setTo( Any( maToClr.getColor( rGraphicHelper ) ) );
464 if( maFromClr.isUsed() )
465 mpNode->setFrom( Any( maFromClr.getColor( rGraphicHelper ) ) );
466 if( mbHasByColor )
467 mpNode->setBy( m_byColor.get() );
470 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
472 switch ( aElementToken )
474 case PPT_TOKEN( hsl ):
475 // CT_TLByHslColorTransform
477 if( mbHasByColor )
479 m_byColor.colorSpace = AnimationColorSpace::HSL;
480 m_byColor.one = rAttribs.getInteger( XML_h, 0 );
481 m_byColor.two = rAttribs.getInteger( XML_s, 0 );
482 m_byColor.three = rAttribs.getInteger( XML_l, 0 );
484 return this;
486 case PPT_TOKEN( rgb ):
488 if( mbHasByColor )
490 // CT_TLByRgbColorTransform
491 m_byColor.colorSpace = AnimationColorSpace::RGB;
492 m_byColor.one = rAttribs.getInteger( XML_r, 0 );
493 m_byColor.two = rAttribs.getInteger( XML_g, 0 );
494 m_byColor.three = rAttribs.getInteger( XML_b, 0 );
496 return this;
498 case PPT_TOKEN( by ):
499 // CT_TLByAnimateColorTransform
500 mbHasByColor = true;
501 return this;
502 case PPT_TOKEN( cBhvr ):
503 return new CommonBehaviorContext ( *this, mpNode );
504 case PPT_TOKEN( to ):
505 // CT_Color
506 return new ColorContext( *this, maToClr );
507 case PPT_TOKEN( from ):
508 // CT_Color
509 return new ColorContext( *this, maFromClr );
511 default:
512 break;
515 return this;
518 private:
519 sal_Int32 mnColorSpace;
520 sal_Int32 mnDir;
521 bool mbHasByColor;
522 AnimColor m_byColor;
523 oox::drawingml::Color maToClr;
524 oox::drawingml::Color maFromClr;
527 /** CT_TLAnimateBehavior */
528 class AnimContext
529 : public TimeNodeContext
531 public:
532 AnimContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
533 const Reference< XFastAttributeList >& xAttribs,
534 const TimeNodePtr & pNode ) noexcept
535 : TimeNodeContext( rParent, aElement, pNode )
537 NodePropertyMap & aProps( pNode->getNodeProperties() );
538 sal_Int32 nCalcMode = xAttribs->getOptionalValueToken( XML_calcmode, 0 );
539 if(nCalcMode)
541 sal_Int16 nEnum = 0;
542 switch(nCalcMode)
544 case XML_discrete:
545 nEnum = AnimationCalcMode::DISCRETE;
546 break;
547 case XML_lin:
548 nEnum = AnimationCalcMode::LINEAR;
549 break;
550 case XML_fmla:
551 default:
552 // TODO what value is good ?
553 nEnum = AnimationCalcMode::DISCRETE;
554 break;
556 aProps[ NP_CALCMODE ] <<= nEnum;
559 msFrom = xAttribs->getOptionalValue(XML_from);
560 msTo = xAttribs->getOptionalValue(XML_to);
561 msBy = xAttribs->getOptionalValue(XML_by);
563 mnValueType = xAttribs->getOptionalValueToken( XML_valueType, 0 );
566 virtual ~AnimContext() noexcept override
568 if (!msFrom.isEmpty())
570 css::uno::Any aAny;
571 aAny <<= msFrom;
572 convertAnimationValueWithTimeNode(mpNode, aAny);
573 mpNode->setFrom(aAny);
576 if (!msTo.isEmpty())
578 css::uno::Any aAny;
579 aAny <<= msTo;
580 convertAnimationValueWithTimeNode(mpNode, aAny);
581 mpNode->setTo(aAny);
584 if (!msBy.isEmpty())
586 css::uno::Any aAny;
587 aAny <<= msBy;
588 convertAnimationValueWithTimeNode(mpNode, aAny);
589 mpNode->setBy(aAny);
592 int nKeyTimes = maTavList.size();
593 if( nKeyTimes <= 0)
594 return;
596 int i=0;
597 Sequence< double > aKeyTimes( nKeyTimes );
598 auto pKeyTimes = aKeyTimes.getArray();
599 Sequence< Any > aValues( nKeyTimes );
600 auto pValues = aValues.getArray();
602 NodePropertyMap & aProps( mpNode->getNodeProperties() );
603 for (auto const& tav : maTavList)
605 // TODO what to do if it is Timing_INFINITE ?
606 Any aTime = GetTimeAnimateValueTime( tav.msTime );
607 aTime >>= pKeyTimes[i];
608 pValues[i] = tav.maValue;
609 convertAnimationValueWithTimeNode(mpNode, pValues[i]);
611 // Examine pptx documents and find that only the first tav
612 // has the formula set. The formula can be used for the whole.
613 if (!tav.msFormula.isEmpty())
615 OUString sFormula = tav.msFormula;
616 (void)convertMeasure(sFormula);
617 aProps[NP_FORMULA] <<= sFormula;
620 ++i;
622 aProps[ NP_VALUES ] <<= aValues;
623 aProps[ NP_KEYTIMES ] <<= aKeyTimes;
626 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
628 switch ( aElementToken )
630 case PPT_TOKEN( cBhvr ):
631 return new CommonBehaviorContext ( *this, mpNode );
632 case PPT_TOKEN( tavLst ):
633 return new TimeAnimValueListContext ( *this, maTavList );
634 default:
635 break;
638 return this;
640 private:
641 sal_Int32 mnValueType;
642 TimeAnimationValueList maTavList;
643 OUString msFrom;
644 OUString msTo;
645 OUString msBy;
648 /** CT_TLAnimateScaleBehavior */
649 class AnimScaleContext
650 : public TimeNodeContext
652 public:
653 AnimScaleContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
654 const Reference< XFastAttributeList >& xAttribs,
655 const TimeNodePtr & pNode )
656 : TimeNodeContext( rParent, aElement, pNode )
657 , mbZoomContents( false )
659 AttributeList attribs( xAttribs );
660 // TODO what to do with mbZoomContents
661 mbZoomContents = attribs.getBool( XML_zoomContents, false );
662 pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
663 <<= sal_Int16(AnimationTransformType::SCALE);
666 virtual void onEndElement() override
668 if( !isCurrentElement( mnElement ) )
669 return;
671 if( maTo.hasValue() )
673 mpNode->setTo( maTo );
675 if( maBy.hasValue() )
677 mpNode->setBy( maBy );
679 if( maFrom.hasValue() )
681 mpNode->setFrom( maFrom );
685 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
687 switch ( aElementToken )
689 case PPT_TOKEN( cBhvr ):
690 return new CommonBehaviorContext ( *this, mpNode );
691 case PPT_TOKEN( to ):
693 // CT_TLPoint
694 maTo = convertPointPercent(GetPointPercent(rAttribs.getFastAttributeList()));
695 return this;
697 case PPT_TOKEN( from ):
699 // CT_TLPoint
700 maFrom = convertPointPercent(GetPointPercent(rAttribs.getFastAttributeList()));
701 return this;
703 case PPT_TOKEN( by ):
705 // CT_TLPoint
706 css::awt::Point aPoint = GetPointPercent(rAttribs.getFastAttributeList());
707 // We got ending values instead of offset values, so subtract 100% from them.
708 aPoint.X -= 100000;
709 aPoint.Y -= 100000;
710 maBy = convertPointPercent(aPoint);
711 return this;
713 default:
714 break;
717 return this;
719 private:
720 Any maBy;
721 Any maFrom;
722 Any maTo;
723 bool mbZoomContents;
726 /** CT_TLAnimateRotationBehavior */
727 class AnimRotContext
728 : public TimeNodeContext
730 public:
731 AnimRotContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
732 const Reference< XFastAttributeList >& xAttribs,
733 const TimeNodePtr & pNode ) noexcept
734 : TimeNodeContext( rParent, aElement, pNode )
736 AttributeList attribs( xAttribs );
738 pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
739 <<= sal_Int16(AnimationTransformType::ROTATE);
740 // see also DFF_msofbtAnimateRotationData in
741 // sd/source/filter/ppt/pptinanimations.cxx
742 if(attribs.hasAttribute( XML_by ) )
744 double fBy = attribs.getDouble( XML_by, 0.0 ) / PER_DEGREE; //1 PowerPoint-angle-unit = 1/60000 degree
745 pNode->setBy( Any( fBy ) );
747 if(attribs.hasAttribute( XML_from ) )
749 double fFrom = attribs.getDouble( XML_from, 0.0 ) / PER_DEGREE;
750 pNode->setFrom( Any( fFrom ) );
752 if(attribs.hasAttribute( XML_to ) )
754 double fTo = attribs.getDouble( XML_to, 0.0 ) / PER_DEGREE;
755 pNode->setTo( Any( fTo ) );
759 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
761 switch ( aElementToken )
763 case PPT_TOKEN( cBhvr ):
764 return new CommonBehaviorContext ( *this, mpNode );
765 default:
766 break;
769 return this;
773 /** CT_TLAnimateMotionBehavior */
774 class AnimMotionContext
775 : public TimeNodeContext
777 public:
778 AnimMotionContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
779 const Reference< XFastAttributeList >& xAttribs,
780 const TimeNodePtr & pNode ) noexcept
781 : TimeNodeContext( rParent, aElement, pNode )
783 pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
784 <<= sal_Int16(AnimationTransformType::TRANSLATE);
786 AttributeList attribs( xAttribs );
787 sal_Int32 nOrigin = xAttribs->getOptionalValueToken( XML_origin, 0 );
788 if( nOrigin != 0 )
790 switch(nOrigin)
792 case XML_layout:
793 case XML_parent:
794 break;
796 // TODO
799 OUString aStr = xAttribs->getOptionalValue( XML_path );
800 // E can appear inside a number, so we only check for its presence at the end
801 aStr = aStr.trim();
802 if (aStr.endsWith("E"))
803 aStr = aStr.copy(0, aStr.getLength() - 1);
804 aStr = aStr.trim();
805 pNode->getNodeProperties()[ NP_PATH ] <<= aStr;
806 mnPathEditMode = xAttribs->getOptionalValueToken( XML_pathEditMode, 0 );
807 msPtsTypes = xAttribs->getOptionalValue( XML_ptsTypes );
808 mnAngle = attribs.getInteger( XML_rAng, 0 );
809 // TODO make sure the units are right. Likely not.
812 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
814 switch ( aElementToken )
816 case PPT_TOKEN( cBhvr ):
817 return new CommonBehaviorContext ( *this, mpNode );
818 case PPT_TOKEN( to ):
820 // CT_TLPoint
821 awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() );
822 Any rAny;
823 rAny <<= p.X;
824 rAny <<= p.Y;
825 mpNode->setTo( rAny );
826 return this;
828 case PPT_TOKEN( from ):
830 // CT_TLPoint
831 awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() );
832 Any rAny;
833 rAny <<= p.X;
834 rAny <<= p.Y;
835 mpNode->setFrom( rAny );
836 return this;
838 case PPT_TOKEN( by ):
840 // CT_TLPoint
841 awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() );
842 Any rAny;
843 rAny <<= p.X;
844 rAny <<= p.Y;
845 mpNode->setBy( rAny );
846 return this;
848 case PPT_TOKEN( rCtr ):
850 // CT_TLPoint
851 awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() );
852 // TODO push
853 (void)p;
854 return this;
856 default:
857 break;
860 return this;
862 private:
863 OUString msPtsTypes;
864 sal_Int32 mnPathEditMode;
865 sal_Int32 mnAngle;
868 /** CT_TLAnimateEffectBehavior */
869 class AnimEffectContext
870 : public TimeNodeContext
872 public:
873 AnimEffectContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
874 const Reference< XFastAttributeList >& xAttribs,
875 const TimeNodePtr & pNode ) noexcept
876 : TimeNodeContext( rParent, aElement, pNode )
878 sal_Int32 nDir = xAttribs->getOptionalValueToken( XML_transition, 0 );
879 OUString sFilter = xAttribs->getOptionalValue( XML_filter );
880 // TODO
881 // OUString sPrList = xAttribs->getOptionalValue( XML_prLst );
883 if( !sFilter.isEmpty() )
885 SlideTransition aFilter( sFilter );
886 aFilter.setMode( nDir != XML_out );
887 pNode->setTransitionFilter( aFilter );
891 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
893 switch ( aElementToken )
895 case PPT_TOKEN( cBhvr ):
896 return new CommonBehaviorContext ( *this, mpNode );
897 case PPT_TOKEN( progress ):
898 return new AnimVariantContext( *this, aElementToken, maProgress );
899 // TODO handle it.
900 default:
901 break;
904 return this;
906 private:
907 Any maProgress;
912 rtl::Reference<TimeNodeContext> TimeNodeContext::makeContext(
913 FragmentHandler2 const & rParent, sal_Int32 aElement,
914 const Reference< XFastAttributeList >& xAttribs,
915 const TimeNodePtr & pNode )
917 rtl::Reference<TimeNodeContext> pCtx;
918 switch( aElement )
920 case PPT_TOKEN( animClr ):
921 pCtx = new AnimColorContext( rParent, aElement, xAttribs, pNode );
922 break;
923 case PPT_TOKEN( par ):
924 pCtx = new ParallelExclTimeNodeContext( rParent, aElement, pNode );
925 break;
926 case PPT_TOKEN( seq ):
927 pCtx = new SequenceTimeNodeContext( rParent, aElement, xAttribs, pNode );
928 break;
929 case PPT_TOKEN( excl ):
930 pCtx = new ParallelExclTimeNodeContext( rParent, aElement, pNode );
931 break;
932 case PPT_TOKEN( anim ):
933 pCtx = new AnimContext ( rParent, aElement, xAttribs, pNode );
934 break;
935 case PPT_TOKEN( animEffect ):
936 pCtx = new AnimEffectContext( rParent, aElement, xAttribs, pNode );
937 break;
938 case PPT_TOKEN( animMotion ):
939 pCtx = new AnimMotionContext( rParent, aElement, xAttribs, pNode );
940 break;
941 case PPT_TOKEN( animRot ):
942 pCtx = new AnimRotContext( rParent, aElement, xAttribs, pNode );
943 break;
944 case PPT_TOKEN( animScale ):
945 pCtx = new AnimScaleContext( rParent, aElement, xAttribs, pNode );
946 break;
947 case PPT_TOKEN( cmd ):
948 pCtx = new CmdTimeNodeContext( rParent, aElement, xAttribs, pNode );
949 break;
950 case PPT_TOKEN( set ):
951 pCtx = new SetTimeNodeContext( rParent, aElement, pNode );
952 break;
953 case PPT_TOKEN( audio ):
954 case PPT_TOKEN( video ):
955 pCtx = new MediaNodeContext( rParent, aElement, xAttribs, pNode );
956 break;
957 default:
958 break;
960 return pCtx;
963 TimeNodeContext::TimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
964 TimeNodePtr pNode ) noexcept
965 : FragmentHandler2( rParent )
966 , mnElement( aElement )
967 , mpNode(std::move( pNode ))
971 TimeNodeContext::~TimeNodeContext( ) noexcept
976 TimeNodeListContext::TimeNodeListContext( FragmentHandler2 const & rParent, TimeNodePtrList & aList )
977 noexcept
978 : FragmentHandler2( rParent )
979 , maList( aList )
983 TimeNodeListContext::~TimeNodeListContext( ) noexcept
987 ::oox::core::ContextHandlerRef TimeNodeListContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
989 sal_Int16 nNodeType;
991 switch( aElementToken )
993 case PPT_TOKEN( par ):
994 nNodeType = AnimationNodeType::PAR;
995 break;
996 case PPT_TOKEN( seq ):
997 nNodeType = AnimationNodeType::SEQ;
998 break;
999 case PPT_TOKEN( excl ):
1000 // TODO pick the right type. We choose parallel for now as
1001 // there does not seem to be an "Exclusive"
1002 nNodeType = AnimationNodeType::PAR;
1003 break;
1004 case PPT_TOKEN( anim ):
1005 nNodeType = AnimationNodeType::ANIMATE;
1006 break;
1007 case PPT_TOKEN( animClr ):
1008 nNodeType = AnimationNodeType::ANIMATECOLOR;
1009 break;
1010 case PPT_TOKEN( animEffect ):
1011 nNodeType = AnimationNodeType::TRANSITIONFILTER;
1012 break;
1013 case PPT_TOKEN( animMotion ):
1014 nNodeType = AnimationNodeType::ANIMATEMOTION;
1015 break;
1016 case PPT_TOKEN( animRot ):
1017 case PPT_TOKEN( animScale ):
1018 nNodeType = AnimationNodeType::ANIMATETRANSFORM;
1019 break;
1020 case PPT_TOKEN( cmd ):
1021 nNodeType = AnimationNodeType::COMMAND;
1022 break;
1023 case PPT_TOKEN( set ):
1024 nNodeType = AnimationNodeType::SET;
1025 break;
1026 case PPT_TOKEN( audio ):
1027 nNodeType = AnimationNodeType::AUDIO;
1028 break;
1029 case PPT_TOKEN( video ):
1030 nNodeType = AnimationNodeType::AUDIO;
1031 SAL_WARN("oox.ppt", "OOX: video requested, gave Audio instead" );
1032 break;
1034 default:
1035 nNodeType = AnimationNodeType::CUSTOM;
1036 SAL_INFO("oox.ppt", "unhandled token " << aElementToken);
1037 break;
1040 TimeNodePtr pNode = std::make_shared<TimeNode>(nNodeType);
1041 maList.push_back( pNode );
1042 rtl::Reference<FragmentHandler2> pContext = TimeNodeContext::makeContext( *this, aElementToken, rAttribs.getFastAttributeList(), pNode );
1044 return pContext ? pContext : this;
1049 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */