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>
24 #include <tools/diagnose_ex.h>
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 
42 #include "animvariantcontext.hxx"
44 #include "conditioncontext.hxx"
46 #include "timeanimvaluecontext.hxx"
47 #include "animationtypes.hxx"
49 
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;
59 
60 namespace {
61 
62  oox::ppt::AnimationAttributeEnum getAttributeEnumByAPIName(const OUString &rAPIName)
63  {
66  while(attrConv->mpAPIName != nullptr)
67  {
68  if(rAPIName.equalsAscii(attrConv->mpAPIName))
69  {
70  eResult = attrConv->meAttribute;
71  break;
72  }
73  attrConv++;
74  }
75  return eResult;
76  }
77 
78  bool convertAnimationValueWithTimeNode(const oox::ppt::TimeNodePtr& pNode, css::uno::Any &rAny)
79  {
80  css::uno::Any aAny = pNode->getNodeProperties()[oox::ppt::NP_ATTRIBUTENAME];
81  OUString aNameList;
82  aAny >>= aNameList;
83 
84  // only get first token.
85  return oox::ppt::convertAnimationValue(getAttributeEnumByAPIName(aNameList.getToken(0, ';')), rAny);
86  }
87 
88  css::uno::Any convertPointPercent(const css::awt::Point& rPoint)
89  {
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);
95  }
96 }
97 
98 namespace oox::ppt {
99 
100  namespace {
101 
102  struct AnimColor
103  {
104  AnimColor(sal_Int16 cs, sal_Int32 o, sal_Int32 t, sal_Int32 th )
105  : colorSpace( cs ), one( o ), two( t ), three( th )
106  {
107  }
108 
109  Any get() const
110  {
111  sal_Int32 nColor;
112  Sequence< double > aHSL( 3 );
113  Any aColor;
114 
115  switch( colorSpace )
116  {
117  case AnimationColorSpace::HSL:
118  aHSL[ 0 ] = double(one) / 100000;
119  aHSL[ 1 ] = double(two) / 100000;
120  aHSL[ 2 ] = double(three) / 100000;
121  aColor <<= aHSL;
122  break;
123  case AnimationColorSpace::RGB:
124  nColor = ( ( ( one * 128 ) / 1000 ) & 0xff ) << 16
125  | ( ( ( two * 128 ) / 1000 ) & 0xff ) << 8
126  | ( ( ( three * 128 ) / 1000 ) & 0xff );
127  aColor <<= nColor;
128  break;
129  default:
130  nColor = 0;
131  aColor <<= nColor;
132  break;
133  }
134  return aColor;
135  }
136 
137  sal_Int16 colorSpace;
138  sal_Int32 one;
139  sal_Int32 two;
140  sal_Int32 three;
141  };
142 
145  class MediaNodeContext
146  : public TimeNodeContext
147  {
148  public:
149  MediaNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
150  const Reference< XFastAttributeList >& xAttribs,
151  const TimeNodePtr & pNode )
152  : TimeNodeContext( rParent, aElement, pNode )
153  , mbIsNarration( false )
154  , mbFullScrn( false )
155  , mbHideDuringShow(false)
156  {
157  AttributeList attribs( xAttribs );
158 
159  switch( aElement )
160  {
161  case PPT_TOKEN( audio ):
162  mbIsNarration = attribs.getBool( XML_isNarration, false );
163  break;
164  case PPT_TOKEN( video ):
165  mbFullScrn = attribs.getBool( XML_fullScrn, false );
166  break;
167  default:
168  break;
169  }
170  }
171 
172  virtual void onEndElement() override
173  {
174  sal_Int32 aElement = getCurrentElement();
175  if( aElement == PPT_TOKEN( audio ) )
176  {
177  mpNode->getNodeProperties()[NP_ISNARRATION] <<= mbIsNarration;
178  }
179  else if( aElement == PPT_TOKEN( video ) )
180  {
181  // TODO deal with mbFullScrn
182  }
183  else if (aElement == PPT_TOKEN(cMediaNode))
184  {
185  mpNode->getNodeProperties()[NP_HIDEDURINGSHOW] <<= mbHideDuringShow;
186  }
187  }
188 
189  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs) override
190  {
191  switch ( aElementToken )
192  {
193  case PPT_TOKEN( cTn ):
194  return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode );
195  case PPT_TOKEN( tgtEl ):
196  return new TimeTargetElementContext( *this, mpNode->getTarget() );
197  case PPT_TOKEN(cMediaNode):
198  mbHideDuringShow = !rAttribs.getBool(XML_showWhenStopped, true);
199  break;
200  default:
201  break;
202  }
203 
204  return this;
205  }
206 
207  private:
211  };
212 
215  class SetTimeNodeContext
216  : public TimeNodeContext
217  {
218  public:
219  SetTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
220  const TimeNodePtr & pNode )
221  : TimeNodeContext( rParent, aElement, pNode )
222  {
223 
224  }
225 
226  virtual ~SetTimeNodeContext() noexcept override
227  {
228  if(maTo.hasValue())
229  {
230  convertAnimationValueWithTimeNode(mpNode, maTo);
231  mpNode->setTo(maTo);
232  }
233 
234  }
235 
236  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
237  {
238  switch ( aElementToken )
239  {
240  case PPT_TOKEN( cBhvr ):
241  return new CommonBehaviorContext ( *this, mpNode );
242  case PPT_TOKEN( to ):
243  // CT_TLAnimVariant
244  return new AnimVariantContext( *this, aElementToken, maTo );
245  default:
246  break;
247  }
248 
249  return this;
250  }
251  private:
253  };
254 
257  class CmdTimeNodeContext
258  : public TimeNodeContext
259  {
260  public:
261  CmdTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
262  const Reference< XFastAttributeList >& xAttribs,
263  const TimeNodePtr & pNode )
264  : TimeNodeContext( rParent, aElement, pNode )
265  , maType(0)
266  {
267  switch ( aElement )
268  {
269  case PPT_TOKEN( cmd ):
270  msCommand = xAttribs->getOptionalValue( XML_cmd );
271  maType = xAttribs->getOptionalValueToken( XML_type, 0 );
272  break;
273  default:
274  break;
275  }
276  }
277 
278  virtual void onEndElement() override
279  {
280  if( !isCurrentElement( PPT_TOKEN( cmd ) ) )
281  return;
282 
283  try {
284  // see sd/source/filter/ppt/pptinanimations.cxx
285  // in AnimationImporter::importCommandContainer()
286  // REFACTOR?
287  // a good chunk of this code has been copied verbatim *sigh*
288  sal_Int16 nCommand = EffectCommands::CUSTOM;
289  NamedValue aParamValue;
290 
291  switch( maType )
292  {
293  case XML_verb:
294  aParamValue.Name = "Verb";
295  // TODO make sure msCommand has what we want
296  aParamValue.Value <<= msCommand.toInt32();
297  nCommand = EffectCommands::VERB;
298  break;
299  case XML_evt:
300  case XML_call:
301  if ( msCommand == "onstopaudio" )
302  {
303  nCommand = EffectCommands::STOPAUDIO;
304  }
305  else if ( msCommand == "play" )
306  {
307  nCommand = EffectCommands::PLAY;
308  }
309  else if (msCommand.startsWith("playFrom"))
310  {
311  const OUString aMediaTime( msCommand.copy( 9, msCommand.getLength() - 10 ) );
312  rtl_math_ConversionStatus eStatus;
313  double fMediaTime = ::rtl::math::stringToDouble( aMediaTime, u'.', u',', &eStatus );
314  if( eStatus == rtl_math_ConversionStatus_Ok )
315  {
316  aParamValue.Name = "MediaTime";
317  aParamValue.Value <<= fMediaTime;
318  }
319  nCommand = EffectCommands::PLAY;
320  }
321  else if ( msCommand == "togglePause" )
322  {
323  nCommand = EffectCommands::TOGGLEPAUSE;
324  }
325  else if ( msCommand == "stop" )
326  {
327  nCommand = EffectCommands::STOP;
328  }
329  break;
330  }
331  mpNode->getNodeProperties()[ NP_COMMAND ] <<= nCommand;
332  if( nCommand == EffectCommands::CUSTOM )
333  {
334  SAL_WARN("oox.ppt", "OOX: CmdTimeNodeContext::endFastElement(), unknown command!");
335  aParamValue.Name = "UserDefined";
336  aParamValue.Value <<= msCommand;
337  }
338  if( aParamValue.Value.hasValue() )
339  {
340  Sequence< NamedValue > aParamSeq( &aParamValue, 1 );
341  mpNode->getNodeProperties()[ NP_PARAMETER ] <<= aParamSeq;
342  }
343  }
344  catch( RuntimeException& )
345  {
346  TOOLS_WARN_EXCEPTION("oox.ppt", "OOX: Exception in CmdTimeNodeContext::endFastElement()" );
347  }
348  }
349 
350  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override
351  {
352  switch ( aElementToken )
353  {
354  case PPT_TOKEN( cBhvr ):
355  return new CommonBehaviorContext ( *this, mpNode );
356  default:
357  break;
358  }
359 
360  return this;
361  }
362 
363  private:
364  OUString msCommand;
365  sal_Int32 maType;
366  };
367 
370  class SequenceTimeNodeContext
371  : public TimeNodeContext
372  {
373  public:
374  SequenceTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
375  const Reference< XFastAttributeList >& xAttribs,
376  const TimeNodePtr & pNode )
377  : TimeNodeContext( rParent, aElement, pNode )
378  , mnNextAc(0)
379  , mnPrevAc(0)
380  {
381  AttributeList attribs(xAttribs);
382  mbConcurrent = attribs.getBool( XML_concurrent, false );
383  mnNextAc = xAttribs->getOptionalValueToken( XML_nextAc, 0 );
384  mnPrevAc = xAttribs->getOptionalValueToken( XML_prevAc, 0 );
385  }
386 
387  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
388  {
389  switch ( aElementToken )
390  {
391  case PPT_TOKEN( cTn ):
392  return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode );
393  case PPT_TOKEN( nextCondLst ):
394  return new CondListContext( *this, aElementToken, mpNode, mpNode->getNextCondition() );
395  case PPT_TOKEN( prevCondLst ):
396  return new CondListContext( *this, aElementToken, mpNode, mpNode->getPrevCondition() );
397  default:
398  break;
399  }
400 
401  return this;
402  }
403  private:
405  sal_Int32 mnNextAc, mnPrevAc;
406  };
407 
411  class ParallelExclTimeNodeContext
412  : public TimeNodeContext
413  {
414  public:
415  ParallelExclTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
416  const TimeNodePtr & pNode )
417  : TimeNodeContext( rParent, aElement, pNode )
418  {
419  }
420 
421  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
422  {
423  switch ( aElementToken )
424  {
425  case PPT_TOKEN( cTn ):
426  return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode );
427  default:
428  break;
429  }
430 
431  return this;
432  }
433 
434  protected:
435 
436  };
437 
439  class AnimColorContext
440  : public TimeNodeContext
441  {
442  public:
443  AnimColorContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
444  const Reference< XFastAttributeList >& xAttribs,
445  const TimeNodePtr & pNode ) noexcept
446  : TimeNodeContext( rParent, aElement, pNode )
447  , mnColorSpace( xAttribs->getOptionalValueToken( XML_clrSpc, 0 ) )
448  , mnDir( xAttribs->getOptionalValueToken( XML_dir, 0 ) )
449  , mbHasByColor( false )
450  , m_byColor( AnimationColorSpace::RGB, 0, 0, 0)
451  {
452  }
453 
454  virtual void onEndElement() override
455  {
456  //xParentNode
457  if( !isCurrentElement( mnElement ) )
458  return;
459 
460  NodePropertyMap & rProps(mpNode->getNodeProperties());
461  rProps[ NP_DIRECTION ] <<= mnDir == XML_cw;
462  rProps[ NP_COLORINTERPOLATION ] <<= mnColorSpace == XML_hsl ? AnimationColorSpace::HSL : AnimationColorSpace::RGB;
463  const GraphicHelper& rGraphicHelper = getFilter().getGraphicHelper();
464  if( maToClr.isUsed() )
465  mpNode->setTo( makeAny( maToClr.getColor( rGraphicHelper ) ) );
466  if( maFromClr.isUsed() )
467  mpNode->setFrom( makeAny( maFromClr.getColor( rGraphicHelper ) ) );
468  if( mbHasByColor )
469  mpNode->setBy( m_byColor.get() );
470  }
471 
472  virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override
473  {
474  switch ( aElementToken )
475  {
476  case PPT_TOKEN( hsl ):
477  // CT_TLByHslColorTransform
478  {
479  if( mbHasByColor )
480  {
481  m_byColor.colorSpace = AnimationColorSpace::HSL;
482  m_byColor.one = rAttribs.getInteger( XML_h, 0 );
483  m_byColor.two = rAttribs.getInteger( XML_s, 0 );
484  m_byColor.three = rAttribs.getInteger( XML_l, 0 );
485  }
486  return this;
487  }
488  case PPT_TOKEN( rgb ):
489  {
490  if( mbHasByColor )
491  {
492  // CT_TLByRgbColorTransform
493  m_byColor.colorSpace = AnimationColorSpace::RGB;
494  m_byColor.one = rAttribs.getInteger( XML_r, 0 );
495  m_byColor.two = rAttribs.getInteger( XML_g, 0 );
496  m_byColor.three = rAttribs.getInteger( XML_b, 0 );
497  }
498  return this;
499  }
500  case PPT_TOKEN( by ):
501  // CT_TLByAnimateColorTransform
502  mbHasByColor = true;
503  return this;
504  case PPT_TOKEN( cBhvr ):
505  return new CommonBehaviorContext ( *this, mpNode );
506  case PPT_TOKEN( to ):
507  // CT_Color
508  return new ColorContext( *this, maToClr );
509  case PPT_TOKEN( from ):
510  // CT_Color
511  return new ColorContext( *this, maFromClr );
512 
513  default:
514  break;
515  }
516 
517  return this;
518  }
519 
520  private:
521  sal_Int32 mnColorSpace;
522  sal_Int32 mnDir;
524  AnimColor m_byColor;
527  };
528 
530  class AnimContext
531  : public TimeNodeContext
532  {
533  public:
534  AnimContext( FragmentHandler2 const & rParent, sal_Int32 aElement,
535  const Reference< XFastAttributeList >& xAttribs,
536  const TimeNodePtr & pNode ) noexcept
537  : TimeNodeContext( rParent, aElement, pNode )
538  {
539  NodePropertyMap & aProps( pNode->getNodeProperties() );
540  sal_Int32 nCalcMode = xAttribs->getOptionalValueToken( XML_calcmode, 0 );
541  if(nCalcMode)
542  {
543  sal_Int16 nEnum = 0;
544  switch(nCalcMode)
545  {
546  case XML_discrete:
547  nEnum = AnimationCalcMode::DISCRETE;
548  break;
549  case XML_lin:
550  nEnum = AnimationCalcMode::LINEAR;
551  break;
552  case XML_fmla:
553  default:
554  // TODO what value is good ?
555  nEnum = AnimationCalcMode::DISCRETE;
556  break;
557  }
558  aProps[ NP_CALCMODE ] <<= nEnum;
559  }
560 
561  msFrom = xAttribs->getOptionalValue(XML_from);
562  msTo = xAttribs->getOptionalValue(XML_to);
563  msBy = xAttribs->getOptionalValue(XML_by);
564 
565  mnValueType = xAttribs->getOptionalValueToken( XML_valueType, 0 );
566  }
567 
568  virtual ~AnimContext() noexcept override
569  {
570  if (!msFrom.isEmpty())
571  {
572  css::uno::Any aAny;
573  aAny <<= msFrom;
574  convertAnimationValueWithTimeNode(mpNode, aAny);
575  mpNode->setFrom(aAny);
576  }
577 
578  if (!msTo.isEmpty())
579  {
580  css::uno::Any aAny;
581  aAny <<= msTo;
582  convertAnimationValueWithTimeNode(mpNode, aAny);
583  mpNode->setTo(aAny);
584  }
585 
586  if (!msBy.isEmpty())
587  {
588  css::uno::Any aAny;
589  aAny <<= msBy;
590  convertAnimationValueWithTimeNode(mpNode, aAny);
591  mpNode->setBy(aAny);
592  }
593 
594  int nKeyTimes = maTavList.size();
595  if( nKeyTimes <= 0)
596  return;
597 
598  int i=0;
599  Sequence< double > aKeyTimes( nKeyTimes );
600  Sequence< Any > aValues( nKeyTimes );
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 >>= aKeyTimes[i];
608  aValues[i] = tav.maValue;
609  convertAnimationValueWithTimeNode(mpNode, aValues[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;
616  (void)convertMeasure(sFormula);
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 ) noexcept
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( makeAny( fBy ) );
746  }
747  if(attribs.hasAttribute( XML_from ) )
748  {
749  double fFrom = attribs.getDouble( XML_from, 0.0 ) / PER_DEGREE;
750  pNode->setFrom( makeAny( fFrom ) );
751  }
752  if(attribs.hasAttribute( XML_to ) )
753  {
754  double fTo = attribs.getDouble( XML_to, 0.0 ) / PER_DEGREE;
755  pNode->setTo( makeAny( 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  const TimeNodePtr & pNode ) noexcept
965  : FragmentHandler2( rParent )
966  , mnElement( aElement )
967  , mpNode( 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: */
sal_Int32 mnValueType
bool convertMeasure(OUString &rString)
convert the measure string to LibreOffice format.
bool mbIsNarration
std::vector< TimeNodePtr > TimeNodePtrList
Definition: timenode.hxx:47
bool mbConcurrent
const sal_Int32 PER_DEGREE
sal_Int32 mnPathEditMode
virtual ~TimeNodeListContext() noexcept override
AlgAtomPtr mpNode
oox::drawingml::Color maFromClr
sal_Int32 maType
bool mbZoomContents
OUString msFrom
oox::drawingml::Color maToClr
bool convertAnimationValue(AnimationAttributeEnum eAttribute, css::uno::Any &rValue)
convert attribute values of the animation target so that LibreOffice understand.
OUString msBy
const ImplAttributeNameConversion * getAttributeConversionList()
std::array< css::uno::Any, NP_SIZE_ > NodePropertyMap
TimeAnimationValueList maTavList
sal_Int32 mnColorSpace
Any maFrom
virtual ~TimeNodeContext() noexcept override
sal_Int32 mnDir
sal_Int32 mnNextAc
Any GetTimeAnimateValueTime(const OUString &val)
#define TOOLS_WARN_EXCEPTION(area, stream)
::Color getColor(const GraphicHelper &rGraphicHelper,::Color nPhClr=API_RGB_TRANSPARENT) const
Returns the final RGB color value.
Definition: color.cxx:481
::std::vector< TimeAnimationValue > TimeAnimationValueList
bool isUsed() const
Returns true, if the color is initialized.
Definition: color.hxx:87
OUString msTo
sal_Int32 two
Any maProgress
virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 aElementToken, const AttributeList &rAttribs) override
Will be called to create a context handler for the passed element.
OUString msPtsTypes
Provides access to attribute values of an element.
sal_Int16 colorSpace
sal_Int32 mnPrevAc
bool mbFullScrn
sal_Int32 three
OUString msCommand
bool mbHideDuringShow
#define SAL_INFO(area, stream)
awt::Point GetPointPercent(const Reference< XFastAttributeList > &xAttribs)
converts the attributes from a CT_TLPoint into an awt Point with 1/1000%
::rtl::Reference< ContextHandler > ContextHandlerRef
const css::uno::Reference< css::xml::sax::XFastAttributeList > & getFastAttributeList() const
Returns the wrapped com.sun.star.xml.sax.XFastAttributeList object.
void * p
std::shared_ptr< TimeNode > TimeNodePtr
Definition: timenode.hxx:44
#define SAL_WARN(area, stream)
TimeNodeListContext(::oox::core::FragmentHandler2 const &rParent, TimeNodePtrList &aList) noexcept
TimeNodeContext(::oox::core::FragmentHandler2 const &rParent, sal_Int32 aElement, const TimeNodePtr &pNode) noexcept
sal_Int32 one
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)
bool mbHasByColor
aStr
sal_Int32 mnAngle
void set(css::uno::UnoInterfaceReference const &value)
AnimColor m_byColor
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo
css::uno::Any SAL_CALL makeAny(const SharedUNOComponent< INTERFACE, COMPONENT > &value)