LibreOffice Module oox (master) 1
timenodelistcontext.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
21
22#include <rtl/math.hxx>
23#include <sal/log.hxx>
25
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>
33
39#include <oox/token/namespaces.hxx>
40#include <oox/token/tokens.hxx>
41#include <o3tl/string_view.hxx>
42#include <utility>
43
46#include "conditioncontext.hxx"
49#include "animationtypes.hxx"
51
52using namespace ::oox::core;
53using namespace ::oox::drawingml;
54using namespace ::com::sun::star;
55using namespace ::com::sun::star::uno;
56using namespace ::com::sun::star::lang;
57using namespace ::com::sun::star::animations;
58using namespace ::com::sun::star::presentation;
59using namespace ::com::sun::star::xml::sax;
60using ::com::sun::star::beans::NamedValue;
61
62namespace {
63
64 oox::ppt::AnimationAttributeEnum getAttributeEnumByAPIName(std::u16string_view rAPIName)
65 {
68 while(attrConv->mpAPIName != nullptr)
69 {
70 if(o3tl::equalsAscii(rAPIName, attrConv->mpAPIName))
71 {
72 eResult = attrConv->meAttribute;
73 break;
74 }
75 attrConv++;
76 }
77 return eResult;
78 }
79
80 bool convertAnimationValueWithTimeNode(const oox::ppt::TimeNodePtr& pNode, css::uno::Any &rAny)
81 {
82 css::uno::Any aAny = pNode->getNodeProperties()[oox::ppt::NP_ATTRIBUTENAME];
83 OUString aNameList;
84 aAny >>= aNameList;
85
86 // only get first token.
87 return oox::ppt::convertAnimationValue(getAttributeEnumByAPIName(o3tl::getToken(aNameList, 0, ';')), rAny);
88 }
89
90 css::uno::Any convertPointPercent(const css::awt::Point& rPoint)
91 {
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);
97 }
98}
99
100namespace oox::ppt {
101
102 namespace {
103
104 struct AnimColor
105 {
106 AnimColor(sal_Int16 cs, sal_Int32 o, sal_Int32 t, sal_Int32 th )
107 : colorSpace( cs ), one( o ), two( t ), three( th )
108 {
109 }
110
111 Any get() const
112 {
113 sal_Int32 nColor;
114 Any aColor;
115
116 switch( colorSpace )
117 {
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;
131 }
132 return aColor;
133 }
134
135 sal_Int16 colorSpace;
136 sal_Int32 one;
137 sal_Int32 two;
138 sal_Int32 three;
139 };
140
143 class MediaNodeContext
144 : public TimeNodeContext
145 {
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)
154 {
155 AttributeList attribs( xAttribs );
156
157 switch( aElement )
158 {
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;
167 }
168 }
169
170 virtual void onEndElement() override
171 {
172 sal_Int32 aElement = getCurrentElement();
173 if( aElement == PPT_TOKEN( audio ) )
174 {
175 mpNode->getNodeProperties()[NP_ISNARRATION] <<= mbIsNarration;
176 }
177 else if( aElement == PPT_TOKEN( video ) )
178 {
179 // TODO deal with mbFullScrn
180 }
181 else if (aElement == PPT_TOKEN(cMediaNode))
182 {
183 mpNode->getNodeProperties()[NP_HIDEDURINGSHOW] <<= mbHideDuringShow;
184 }
185 }
186
187 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs) override
188 {
189 switch ( aElementToken )
190 {
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;
200 }
201
202 return this;
203 }
204
205 private:
209 };
210
213 class SetTimeNodeContext
214 : public TimeNodeContext
215 {
216 public:
217 SetTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
218 const TimeNodePtr & pNode )
219 : TimeNodeContext( rParent, aElement, pNode )
220 {
221
222 }
223
224 virtual ~SetTimeNodeContext() noexcept override
225 {
226 if(maTo.hasValue())
227 {
228 convertAnimationValueWithTimeNode(mpNode, maTo);
229 mpNode->setTo(maTo);
230 }
231
232 }
233
234 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
235 {
236 switch ( aElementToken )
237 {
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;
245 }
246
247 return this;
248 }
249 private:
251 };
252
255 class CmdTimeNodeContext
256 : public TimeNodeContext
257 {
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)
264 {
265 switch ( aElement )
266 {
267 case PPT_TOKEN( cmd ):
268 msCommand = xAttribs->getOptionalValue( XML_cmd );
269 maType = xAttribs->getOptionalValueToken( XML_type, 0 );
270 break;
271 default:
272 break;
273 }
274 }
275
276 virtual void onEndElement() override
277 {
278 if( !isCurrentElement( PPT_TOKEN( cmd ) ) )
279 return;
280
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;
288
289 switch( maType )
290 {
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" )
300 {
301 nCommand = EffectCommands::STOPAUDIO;
302 }
303 else if ( msCommand == "play" )
304 {
305 nCommand = EffectCommands::PLAY;
306 }
307 else if (msCommand.startsWith("playFrom"))
308 {
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 )
313 {
314 aParamValue.Name = "MediaTime";
315 aParamValue.Value <<= fMediaTime;
316 }
317 nCommand = EffectCommands::PLAY;
318 }
319 else if ( msCommand == "togglePause" )
320 {
321 nCommand = EffectCommands::TOGGLEPAUSE;
322 }
323 else if ( msCommand == "stop" )
324 {
325 nCommand = EffectCommands::STOP;
326 }
327 break;
328 }
329 mpNode->getNodeProperties()[ NP_COMMAND ] <<= nCommand;
330 if( nCommand == EffectCommands::CUSTOM )
331 {
332 SAL_WARN("oox.ppt", "OOX: CmdTimeNodeContext::endFastElement(), unknown command!");
333 aParamValue.Name = "UserDefined";
334 aParamValue.Value <<= msCommand;
335 }
336 if( aParamValue.Value.hasValue() )
337 {
338 Sequence< NamedValue > aParamSeq( &aParamValue, 1 );
339 mpNode->getNodeProperties()[ NP_PARAMETER ] <<= aParamSeq;
340 }
341 }
342 catch( RuntimeException& )
343 {
344 TOOLS_WARN_EXCEPTION("oox.ppt", "OOX: Exception in CmdTimeNodeContext::endFastElement()" );
345 }
346 }
347
348 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
349 {
350 switch ( aElementToken )
351 {
352 case PPT_TOKEN( cBhvr ):
353 return new CommonBehaviorContext ( *this, mpNode );
354 default:
355 break;
356 }
357
358 return this;
359 }
360
361 private:
362 OUString msCommand;
363 sal_Int32 maType;
364 };
365
368 class SequenceTimeNodeContext
369 : public TimeNodeContext
370 {
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)
378 {
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 );
383 }
384
385 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
386 {
387 switch ( aElementToken )
388 {
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;
397 }
398
399 return this;
400 }
401 private:
403 sal_Int32 mnNextAc, mnPrevAc;
404 };
405
409 class ParallelExclTimeNodeContext
410 : public TimeNodeContext
411 {
412 public:
413 ParallelExclTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
414 const TimeNodePtr & pNode )
415 : TimeNodeContext( rParent, aElement, pNode )
416 {
417 }
418
419 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
420 {
421 switch ( aElementToken )
422 {
423 case PPT_TOKEN( cTn ):
424 return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode );
425 default:
426 break;
427 }
428
429 return this;
430 }
431
432 protected:
433
434 };
435
437 class AnimColorContext
438 : public TimeNodeContext
439 {
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)
449 {
450 }
451
452 virtual void onEndElement() override
453 {
454 //xParentNode
455 if( !isCurrentElement( mnElement ) )
456 return;
457
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() );
468 }
469
470 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
471 {
472 switch ( aElementToken )
473 {
474 case PPT_TOKEN( hsl ):
475 // CT_TLByHslColorTransform
476 {
477 if( mbHasByColor )
478 {
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 );
483 }
484 return this;
485 }
486 case PPT_TOKEN( rgb ):
487 {
488 if( mbHasByColor )
489 {
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 );
495 }
496 return this;
497 }
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 );
510
511 default:
512 break;
513 }
514
515 return this;
516 }
517
518 private:
519 sal_Int32 mnColorSpace;
520 sal_Int32 mnDir;
522 AnimColor m_byColor;
525 };
526
528 class AnimContext
529 : public TimeNodeContext
530 {
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 )
536 {
537 NodePropertyMap & aProps( pNode->getNodeProperties() );
538 sal_Int32 nCalcMode = xAttribs->getOptionalValueToken( XML_calcmode, 0 );
539 if(nCalcMode)
540 {
541 sal_Int16 nEnum = 0;
542 switch(nCalcMode)
543 {
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;
555 }
556 aProps[ NP_CALCMODE ] <<= nEnum;
557 }
558
559 msFrom = xAttribs->getOptionalValue(XML_from);
560 msTo = xAttribs->getOptionalValue(XML_to);
561 msBy = xAttribs->getOptionalValue(XML_by);
562
563 mnValueType = xAttribs->getOptionalValueToken( XML_valueType, 0 );
564 }
565
566 virtual ~AnimContext() noexcept override
567 {
568 if (!msFrom.isEmpty())
569 {
570 css::uno::Any aAny;
571 aAny <<= msFrom;
572 convertAnimationValueWithTimeNode(mpNode, aAny);
573 mpNode->setFrom(aAny);
574 }
575
576 if (!msTo.isEmpty())
577 {
578 css::uno::Any aAny;
579 aAny <<= msTo;
580 convertAnimationValueWithTimeNode(mpNode, aAny);
581 mpNode->setTo(aAny);
582 }
583
584 if (!msBy.isEmpty())
585 {
586 css::uno::Any aAny;
587 aAny <<= msBy;
588 convertAnimationValueWithTimeNode(mpNode, aAny);
589 mpNode->setBy(aAny);
590 }
591
592 int nKeyTimes = maTavList.size();
593 if( nKeyTimes <= 0)
594 return;
595
596 int i=0;
597 Sequence< double > aKeyTimes( nKeyTimes );
598 auto pKeyTimes = aKeyTimes.getArray();
599 Sequence< Any > aValues( nKeyTimes );
600 auto pValues = aValues.getArray();
601
602 NodePropertyMap & aProps( mpNode->getNodeProperties() );
603 for (auto const& tav : maTavList)
604 {
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]);
610
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())
614 {
615 OUString sFormula = tav.msFormula;
617 aProps[NP_FORMULA] <<= sFormula;
618 }
619
620 ++i;
621 }
622 aProps[ NP_VALUES ] <<= aValues;
623 aProps[ NP_KEYTIMES ] <<= aKeyTimes;
624 }
625
626 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
627 {
628 switch ( aElementToken )
629 {
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;
636 }
637
638 return this;
639 }
640 private:
641 sal_Int32 mnValueType;
643 OUString msFrom;
644 OUString msTo;
645 OUString msBy;
646 };
647
649 class AnimScaleContext
650 : public TimeNodeContext
651 {
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 )
658 {
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);
664 }
665
666 virtual void onEndElement() override
667 {
668 if( !isCurrentElement( mnElement ) )
669 return;
670
671 if( maTo.hasValue() )
672 {
673 mpNode->setTo( maTo );
674 }
675 if( maBy.hasValue() )
676 {
677 mpNode->setBy( maBy );
678 }
679 if( maFrom.hasValue() )
680 {
681 mpNode->setFrom( maFrom );
682 }
683 }
684
685 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
686 {
687 switch ( aElementToken )
688 {
689 case PPT_TOKEN( cBhvr ):
690 return new CommonBehaviorContext ( *this, mpNode );
691 case PPT_TOKEN( to ):
692 {
693 // CT_TLPoint
694 maTo = convertPointPercent(GetPointPercent(rAttribs.getFastAttributeList()));
695 return this;
696 }
697 case PPT_TOKEN( from ):
698 {
699 // CT_TLPoint
700 maFrom = convertPointPercent(GetPointPercent(rAttribs.getFastAttributeList()));
701 return this;
702 }
703 case PPT_TOKEN( by ):
704 {
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;
712 }
713 default:
714 break;
715 }
716
717 return this;
718 }
719 private:
722 Any maTo;
724 };
725
727 class AnimRotContext
728 : public TimeNodeContext
729 {
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 )
735 {
736 AttributeList attribs( xAttribs );
737
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 ) )
743 {
744 double fBy = attribs.getDouble( XML_by, 0.0 ) / PER_DEGREE; //1 PowerPoint-angle-unit = 1/60000 degree
745 pNode->setBy( Any( fBy ) );
746 }
747 if(attribs.hasAttribute( XML_from ) )
748 {
749 double fFrom = attribs.getDouble( XML_from, 0.0 ) / PER_DEGREE;
750 pNode->setFrom( Any( fFrom ) );
751 }
752 if(attribs.hasAttribute( XML_to ) )
753 {
754 double fTo = attribs.getDouble( XML_to, 0.0 ) / PER_DEGREE;
755 pNode->setTo( Any( fTo ) );
756 }
757 }
758
759 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
760 {
761 switch ( aElementToken )
762 {
763 case PPT_TOKEN( cBhvr ):
764 return new CommonBehaviorContext ( *this, mpNode );
765 default:
766 break;
767 }
768
769 return this;
770 }
771 };
772
774 class AnimMotionContext
775 : public TimeNodeContext
776 {
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 )
782 {
783 pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
784 <<= sal_Int16(AnimationTransformType::TRANSLATE);
785
786 AttributeList attribs( xAttribs );
787 sal_Int32 nOrigin = xAttribs->getOptionalValueToken( XML_origin, 0 );
788 if( nOrigin != 0 )
789 {
790 switch(nOrigin)
791 {
792 case XML_layout:
793 case XML_parent:
794 break;
795 }
796 // TODO
797 }
798
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.
810 }
811
812 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
813 {
814 switch ( aElementToken )
815 {
816 case PPT_TOKEN( cBhvr ):
817 return new CommonBehaviorContext ( *this, mpNode );
818 case PPT_TOKEN( to ):
819 {
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;
827 }
828 case PPT_TOKEN( from ):
829 {
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;
837 }
838 case PPT_TOKEN( by ):
839 {
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;
847 }
848 case PPT_TOKEN( rCtr ):
849 {
850 // CT_TLPoint
851 awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() );
852 // TODO push
853 (void)p;
854 return this;
855 }
856 default:
857 break;
858 }
859
860 return this;
861 }
862 private:
863 OUString msPtsTypes;
864 sal_Int32 mnPathEditMode;
865 sal_Int32 mnAngle;
866 };
867
869 class AnimEffectContext
870 : public TimeNodeContext
871 {
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 )
877 {
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 );
882
883 if( !sFilter.isEmpty() )
884 {
885 SlideTransition aFilter( sFilter );
886 aFilter.setMode( nDir != XML_out );
887 pNode->setTransitionFilter( aFilter );
888 }
889 }
890
891 virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
892 {
893 switch ( aElementToken )
894 {
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;
902 }
903
904 return this;
905 }
906 private:
908 };
909
910 }
911
913 FragmentHandler2 const & rParent, sal_Int32 aElement,
914 const Reference< XFastAttributeList >& xAttribs,
915 const TimeNodePtr & pNode )
916 {
918 switch( aElement )
919 {
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;
959 }
960 return pCtx;
961 }
962
963 TimeNodeContext::TimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
964 TimeNodePtr pNode ) noexcept
965 : FragmentHandler2( rParent )
966 , mnElement( aElement )
967 , mpNode(std::move( pNode ))
968 {
969 }
970
972 {
973
974 }
975
976 TimeNodeListContext::TimeNodeListContext( FragmentHandler2 const & rParent, TimeNodePtrList & aList )
977 noexcept
978 : FragmentHandler2( rParent )
979 , maList( aList )
980 {
981 }
982
984 {
985 }
986
988 {
989 sal_Int16 nNodeType;
990
991 switch( aElementToken )
992 {
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;
1033
1034 default:
1035 nNodeType = AnimationNodeType::CUSTOM;
1036 SAL_INFO("oox.ppt", "unhandled token " << aElementToken);
1037 break;
1038 }
1039
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 );
1043
1044 return pContext ? pContext : this;
1045 }
1046
1047}
1048
1049/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const PropertyValue * pValues
XPropertyListType t
Provides access to attribute values of an element.
const css::uno::Reference< css::xml::sax::XFastAttributeList > & getFastAttributeList() const
Returns the wrapped com.sun.star.xml.sax.XFastAttributeList object.
bool isUsed() const
Returns true, if the color is initialized.
Definition: color.hxx:87
::Color getColor(const GraphicHelper &rGraphicHelper, ::Color nPhClr=API_RGB_TRANSPARENT) const
Returns the final RGB color value.
Definition: color.cxx:531
TimeNodeContext(::oox::core::FragmentHandler2 const &rParent, sal_Int32 aElement, TimeNodePtr pNode) noexcept
static rtl::Reference< TimeNodeContext > makeContext(::oox::core::FragmentHandler2 const &rParent, sal_Int32 aElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttribs, const TimeNodePtr &pNode)
virtual ~TimeNodeContext() noexcept override
virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 aElementToken, const AttributeList &rAttribs) override
Will be called to create a context handler for the passed element.
TimeNodeListContext(::oox::core::FragmentHandler2 const &rParent, TimeNodePtrList &aList) noexcept
virtual ~TimeNodeListContext() noexcept override
#define TOOLS_WARN_EXCEPTION(area, stream)
OString sFormula
Definition: drawingml.cxx:4093
void * p
AlgAtomPtr mpNode
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
aStr
void set(css::uno::UnoInterfaceReference const &value)
bool equalsAscii(std::u16string_view s1, const char *s2)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
::rtl::Reference< ContextHandler > ContextHandlerRef
awt::Point GetPointPercent(const Reference< XFastAttributeList > &xAttribs)
converts the attributes from a CT_TLPoint into an awt Point with 1/1000%
const sal_Int32 PER_DEGREE
std::shared_ptr< TimeNode > TimeNodePtr
Definition: timenode.hxx:44
bool convertMeasure(OUString &rString)
convert the measure string to LibreOffice format.
const ImplAttributeNameConversion * getAttributeConversionList()
::std::vector< TimeAnimationValue > TimeAnimationValueList
bool convertAnimationValue(AnimationAttributeEnum eAttribute, css::uno::Any &rValue)
convert attribute values of the animation target so that LibreOffice understand.
Any GetTimeAnimateValueTime(const OUString &val)
std::vector< TimeNodePtr > TimeNodePtrList
Definition: timenode.hxx:47
std::array< css::uno::Any, NP_SIZE_ > NodePropertyMap
XML_type
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
OUString msPtsTypes
bool mbConcurrent
sal_Int32 maType
oox::drawingml::Color maFromClr
Any maProgress
OUString msBy
sal_Int32 two
sal_Int32 three
sal_Int32 mnPrevAc
Any maFrom
sal_Int16 colorSpace
sal_Int32 mnNextAc
sal_Int32 mnValueType
oox::drawingml::Color maToClr
sal_Int32 mnAngle
OUString msTo
sal_Int32 mnPathEditMode
bool mbIsNarration
sal_Int32 one
AnimColor m_byColor
bool mbHideDuringShow
OUString msCommand
OUString msFrom
sal_Int32 mnColorSpace
TimeAnimationValueList maTavList
bool mbFullScrn
bool mbZoomContents
bool mbHasByColor
sal_Int32 mnDir