xref: /AOO41X/main/oox/source/ppt/timenodelistcontext.cxx (revision 54628ca40d27d15cc98fe861da7fff7e60c2f7d6)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "oox/ppt/timenodelistcontext.hxx"
25 
26 #include "comphelper/anytostring.hxx"
27 #include "cppuhelper/exc_hlp.hxx"
28 #include <osl/diagnose.h>
29 #include <rtl/math.hxx>
30 
31 #include <com/sun/star/animations/XTimeContainer.hpp>
32 #include <com/sun/star/animations/XAnimationNode.hpp>
33 #include <com/sun/star/animations/XAnimateColor.hpp>
34 #include <com/sun/star/animations/XAnimateSet.hpp>
35 #include <com/sun/star/animations/XAnimateTransform.hpp>
36 #include <com/sun/star/animations/AnimationTransformType.hpp>
37 #include <com/sun/star/animations/AnimationCalcMode.hpp>
38 #include <com/sun/star/animations/AnimationColorSpace.hpp>
39 #include <com/sun/star/animations/AnimationNodeType.hpp>
40 #include <com/sun/star/animations/XCommand.hpp>
41 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
42 #include <com/sun/star/presentation/EffectCommands.hpp>
43 #include <com/sun/star/beans/NamedValue.hpp>
44 
45 #include "oox/helper/attributelist.hxx"
46 #include "oox/core/xmlfilterbase.hxx"
47 #include "oox/drawingml/drawingmltypes.hxx"
48 #include "oox/drawingml/colorchoicecontext.hxx"
49 #include "oox/ppt/slidetransition.hxx"
50 
51 #include "animvariantcontext.hxx"
52 #include "commonbehaviorcontext.hxx"
53 #include "conditioncontext.hxx"
54 #include "commontimenodecontext.hxx"
55 #include "timeanimvaluecontext.hxx"
56 #include "animationtypes.hxx"
57 
58 using namespace ::oox::core;
59 using namespace ::oox::drawingml;
60 using namespace ::com::sun::star::uno;
61 using namespace ::com::sun::star::lang;
62 using namespace ::com::sun::star::animations;
63 using namespace ::com::sun::star::presentation;
64 using namespace ::com::sun::star::xml::sax;
65 using namespace ::com::sun::star::awt;
66 using ::com::sun::star::beans::NamedValue;
67 
68 using ::rtl::OUString;
69 
70 namespace oox { namespace ppt {
71 
72     struct AnimColor
73     {
74         AnimColor(sal_Int16 cs, sal_Int32 o, sal_Int32 t, sal_Int32 th )
75             : colorSpace( cs ), one( o ), two( t ), three( th )
76             {
77             }
78 
79         sal_Int32 get()
80             {
81                 sal_Int32 nColor;
82 
83                 switch( colorSpace )
84                 {
85                 case AnimationColorSpace::HSL:
86                     nColor = ( ( ( one * 128 ) / 360 ) & 0xff ) << 16
87                         | ( ( ( two * 128 ) / 1000 ) & 0xff ) << 8
88                         | ( ( ( three * 128 ) / 1000 )  & 0xff );
89                     break;
90                 case AnimationColorSpace::RGB:
91                     nColor = ( ( ( one * 128 ) / 1000 ) & 0xff ) << 16
92                         | ( ( ( two * 128 ) / 1000 ) & 0xff ) << 8
93                         | ( ( ( three * 128 ) / 1000 )  & 0xff );
94                     break;
95                 default:
96                     nColor = 0;
97                     break;
98                 }
99                 return  nColor;
100             }
101 
102         sal_Int16 colorSpace;
103         sal_Int32 one;
104         sal_Int32 two;
105         sal_Int32 three;
106     };
107 
108 
109     /** CT_TLMediaNodeAudio
110             CT_TLMediaNodeVideo */
111     class MediaNodeContext
112         : public TimeNodeContext
113     {
114     public:
115         MediaNodeContext( ContextHandler& rParent, sal_Int32  aElement,
116                             const Reference< XFastAttributeList >& xAttribs,
117                             const TimeNodePtr & pNode )
118             : TimeNodeContext( rParent, aElement, xAttribs, pNode )
119                 , mbIsNarration( false )
120                 , mbFullScrn( false )
121             {
122                 AttributeList attribs( xAttribs );
123 
124                 switch( aElement )
125                 {
126                 case PPT_TOKEN( audio ):
127                     mbIsNarration = attribs.getBool( XML_isNarration, false );
128                     break;
129                 case PPT_TOKEN( video ):
130                     mbFullScrn = attribs.getBool( XML_fullScrn, false );
131                     break;
132                 default:
133                     break;
134                 }
135             }
136 
137         virtual void SAL_CALL endFastElement( sal_Int32 aElement )
138             throw ( SAXException, RuntimeException)
139             {
140                 if( aElement == PPT_TOKEN( audio ) )
141                 {
142                     // TODO deal with mbIsNarration
143                 }
144                 else if( aElement == PPT_TOKEN( video ) )
145                 {
146                     // TODO deal with mbFullScrn
147                 }
148             }
149 
150         virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken,
151                                                                                                                                                             const Reference< XFastAttributeList >& xAttribs )
152             throw ( SAXException, RuntimeException )
153             {
154                 Reference< XFastContextHandler > xRet;
155 
156                 switch ( aElementToken )
157                 {
158                 case PPT_TOKEN( cBhvr ):
159                     xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
160                     break;
161                 default:
162                     break;
163                 }
164 
165                 if( !xRet.is() )
166                     xRet.set( this );
167 
168                 return xRet;
169             }
170 
171     private:
172         bool mbIsNarration;
173         bool mbFullScrn;
174     };
175 
176 
177     /** CT_TLSetBehavior
178      */
179     class SetTimeNodeContext
180         : public TimeNodeContext
181     {
182     public:
183         SetTimeNodeContext( ContextHandler& rParent, sal_Int32  aElement,
184                             const Reference< XFastAttributeList >& xAttribs,
185                             const TimeNodePtr & pNode )
186             : TimeNodeContext( rParent, aElement, xAttribs, pNode )
187             {
188 
189             }
190 
191         ~SetTimeNodeContext() throw ()
192             {
193                 if( maTo.hasValue() )
194                 {
195                     // TODO
196                     // HACK !!! discard and refactor
197                     OUString aString;
198                     if( maTo >>= aString )
199                     {
200                         OSL_TRACE( "Magic conversion %s", OUSTRING_TO_CSTR( aString ) );
201                         maTo = makeAny( aString.equalsAscii( "visible" ) ? sal_True : sal_False );
202                         if( !maTo.has<sal_Bool>() )
203                             OSL_TRACE( "conversion failed" );
204                     }
205                     mpNode->setTo( maTo );
206                 }
207 
208             }
209 
210         virtual void SAL_CALL endFastElement( sal_Int32 /*aElement*/ )
211             throw ( SAXException, RuntimeException)
212             {
213             }
214 
215 
216         virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken,
217                                                                                                                                                             const Reference< XFastAttributeList >& xAttribs )
218             throw ( SAXException, RuntimeException )
219             {
220                 Reference< XFastContextHandler > xRet;
221 
222                 switch ( aElementToken )
223                 {
224                 case PPT_TOKEN( cBhvr ):
225                     xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
226                     break;
227                 case PPT_TOKEN( to ):
228                     // CT_TLAnimVariant
229                     xRet.set( new AnimVariantContext( *this, aElementToken, maTo ) );
230                     break;
231                 default:
232                     break;
233                 }
234 
235                 if( !xRet.is() )
236                     xRet.set( this );
237 
238                 return xRet;
239             }
240     private:
241         Any  maTo;
242     };
243 
244     /** CT_TLCommandBehavior
245      */
246     class CmdTimeNodeContext
247         : public TimeNodeContext
248     {
249     public:
250         CmdTimeNodeContext( ContextHandler& rParent, sal_Int32  aElement,
251                             const Reference< XFastAttributeList >& xAttribs,
252                             const TimeNodePtr & pNode )
253             : TimeNodeContext( rParent, aElement, xAttribs, pNode )
254                 , maType(0)
255             {
256                 switch ( aElement )
257                 {
258                 case PPT_TOKEN( cmd ):
259                     msCommand = xAttribs->getOptionalValue( XML_cmd );
260                     maType = xAttribs->getOptionalValueToken( XML_type, 0 );
261                     break;
262                 default:
263                     break;
264                 }
265             }
266 
267         ~CmdTimeNodeContext() throw ()
268             {
269             }
270 
271         virtual void SAL_CALL endFastElement( sal_Int32 aElement )
272             throw ( SAXException, RuntimeException)
273             {
274                 if( aElement == PPT_TOKEN( cmd ) )
275                 {
276                     try {
277                         // see sd/source/filter/ppt/pptinanimations.cxx
278                         // in AnimationImporter::importCommandContainer()
279                         // REFACTOR?
280                         // a good chunk of this code has been copied verbatim *sigh*
281                         sal_Int16 nCommand = EffectCommands::CUSTOM;
282                         NamedValue aParamValue;
283 
284                         switch( maType )
285                         {
286                         case XML_verb:
287                             aParamValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Verb"));
288                             // TODO make sure msCommand has what we want
289                             aParamValue.Value <<= msCommand.toInt32();
290                             nCommand = EffectCommands::VERB;
291                             break;
292                         case XML_evt:
293                         case XML_call:
294                             if( msCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "onstopaudio" ) ) )
295                             {
296                                 nCommand = EffectCommands::STOPAUDIO;
297                             }
298                             else if( msCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("play") ) )
299                             {
300                                 nCommand = EffectCommands::PLAY;
301                             }
302                             else if( msCommand.compareToAscii( RTL_CONSTASCII_STRINGPARAM("playFrom") ) == 0 )
303                             {
304                                 const OUString aMediaTime( msCommand.copy( 9, msCommand.getLength() - 10 ) );
305                                 rtl_math_ConversionStatus eStatus;
306                                 double fMediaTime = ::rtl::math::stringToDouble( aMediaTime, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL );
307                                 if( eStatus == rtl_math_ConversionStatus_Ok )
308                                 {
309                                     aParamValue.Name = CREATE_OUSTRING("MediaTime");
310                                     aParamValue.Value <<= fMediaTime;
311                                 }
312                                 nCommand = EffectCommands::PLAY;
313                             }
314                             else if( msCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("togglePause") ) )
315                             {
316                                 nCommand = EffectCommands::TOGGLEPAUSE;
317                             }
318                             else if( msCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("stop") ) )
319                             {
320                                 nCommand = EffectCommands::STOP;
321                             }
322                             break;
323                         }
324                         mpNode->getNodeProperties()[ NP_COMMAND ] = makeAny((sal_Int16)nCommand);
325                         if( nCommand == EffectCommands::CUSTOM )
326                         {
327                             OSL_TRACE("OOX: CmdTimeNodeContext::endFastElement(), unknown command!");
328                             aParamValue.Name = CREATE_OUSTRING("UserDefined");
329                             aParamValue.Value <<= msCommand;
330                         }
331                         if( aParamValue.Value.hasValue() )
332                         {
333                             Sequence< NamedValue > aParamSeq( &aParamValue, 1 );
334                             mpNode->getNodeProperties()[ NP_PARAMETER ] = makeAny( aParamSeq );
335                         }
336                     }
337                     catch( RuntimeException& )
338                     {
339                         OSL_TRACE( "OOX: Exception in CmdTimeNodeContext::endFastElement()" );
340                     }
341                 }
342             }
343 
344 
345         virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken,
346                                                                                                                                                             const Reference< XFastAttributeList >& xAttribs )
347             throw ( SAXException, RuntimeException )
348             {
349                 Reference< XFastContextHandler > xRet;
350 
351                 switch ( aElementToken )
352                 {
353                 case PPT_TOKEN( cBhvr ):
354                     xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
355                     break;
356                 default:
357                     break;
358                 }
359 
360                 if( !xRet.is() )
361                     xRet.set( this );
362 
363                 return xRet;
364             }
365 
366     private:
367         OUString msCommand;
368         sal_Int32 maType;
369     };
370 
371 
372     /** CT_TLTimeNodeSequence
373      */
374     class SequenceTimeNodeContext
375         : public TimeNodeContext
376     {
377     public:
378         SequenceTimeNodeContext( ContextHandler& rParent, sal_Int32  aElement,
379                                  const Reference< XFastAttributeList >& xAttribs,
380                                  const TimeNodePtr & pNode )
381             : TimeNodeContext( rParent, aElement, xAttribs, pNode )
382                 , mnNextAc(0)
383                 , mnPrevAc(0)
384             {
385                 AttributeList attribs(xAttribs);
386                 mbConcurrent = attribs.getBool( XML_concurrent, false );
387                 // ST_TLNextActionType { none, seek }
388                 mnNextAc = xAttribs->getOptionalValueToken( XML_nextAc, 0 );
389                 // ST_TLPreviousActionType { none, skipTimed }
390                 mnPrevAc = xAttribs->getOptionalValueToken( XML_prevAc, 0 );
391             }
392 
393         ~SequenceTimeNodeContext() throw()
394             {
395             }
396 
397 
398         virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken,
399                                                                                                                                                             const Reference< XFastAttributeList >& xAttribs )
400             throw ( SAXException, RuntimeException )
401             {
402                 Reference< XFastContextHandler > xRet;
403 
404                 switch ( aElementToken )
405                 {
406                 case PPT_TOKEN( cTn ):
407                     xRet.set( new CommonTimeNodeContext( *this, aElementToken, xAttribs, mpNode ) );
408                     break;
409                 case PPT_TOKEN( nextCondLst ):
410                     xRet.set( new CondListContext( *this, aElementToken, xAttribs, mpNode,
411                                                    mpNode->getNextCondition() ) );
412                     break;
413                 case PPT_TOKEN( prevCondLst ):
414                     xRet.set( new CondListContext( *this, aElementToken, xAttribs, mpNode,
415                                                    mpNode->getPrevCondition() ) );
416                     break;
417                 default:
418                     break;
419                 }
420 
421                 if( !xRet.is() )
422                     xRet.set( this );
423 
424                 return xRet;
425             }
426     private:
427         bool mbConcurrent;
428         sal_Int32 mnNextAc, mnPrevAc;
429     };
430 
431 
432     /** CT_TLTimeNodeParallel
433      *  CT_TLTimeNodeExclusive
434      */
435     class ParallelExclTimeNodeContext
436         : public TimeNodeContext
437     {
438     public:
439         ParallelExclTimeNodeContext( ContextHandler& rParent, sal_Int32  aElement,
440                                      const Reference< XFastAttributeList >& xAttribs,
441                                      const TimeNodePtr & pNode )
442             : TimeNodeContext( rParent, aElement, xAttribs, pNode )
443             {
444             }
445 
446         virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken,
447                                                                                                                                                             const Reference< XFastAttributeList >& xAttribs )
448             throw ( SAXException, RuntimeException )
449             {
450                 Reference< XFastContextHandler > xRet;
451 
452                 switch ( aElementToken )
453                 {
454                 case PPT_TOKEN( cTn ):
455                     xRet.set( new CommonTimeNodeContext( *this, aElementToken, xAttribs, mpNode ) );
456                     break;
457                 default:
458                     break;
459                 }
460 
461                 if( !xRet.is() )
462                     xRet.set( this );
463 
464                 return xRet;
465             }
466 
467     protected:
468 
469     };
470 
471 
472     /** CT_TLAnimateColorBehavior */
473     class AnimColorContext
474         : public TimeNodeContext
475     {
476     public:
477         AnimColorContext( ContextHandler& rParent, sal_Int32  aElement,
478                             const Reference< XFastAttributeList >& xAttribs,
479                             const TimeNodePtr & pNode ) throw()
480             : TimeNodeContext( rParent, aElement, xAttribs, pNode )
481                 // ST_TLAnimateColorSpace ( XML_rgb, XML_hsl }
482             , mnColorSpace( xAttribs->getOptionalValueToken( XML_clrSpc, 0 ) )
483                 // ST_TLAnimateColorDirection { XML_cw, XML_ccw }
484             , mnDir( xAttribs->getOptionalValueToken( XML_dir, 0 ) )
485             , mbHasByColor( false )
486             , m_byColor( AnimationColorSpace::RGB, 0, 0, 0)
487             {
488             }
489         ~AnimColorContext() throw()
490             {
491             }
492 
493         virtual void SAL_CALL endFastElement( sal_Int32 aElement ) throw ( SAXException, RuntimeException)
494             {
495                 //xParentNode
496                 if( aElement == mnElement )
497                 {
498                     NodePropertyMap & pProps(mpNode->getNodeProperties());
499                     pProps[ NP_DIRECTION ] = makeAny( mnDir == XML_cw );
500                     pProps[ NP_COLORINTERPOLATION ] = makeAny( mnColorSpace == XML_hsl ? AnimationColorSpace::HSL : AnimationColorSpace::RGB );
501                     const GraphicHelper& rGraphicHelper = getFilter().getGraphicHelper();
502                     if( maToClr.isUsed() )
503                         mpNode->setTo( Any( maToClr.getColor( rGraphicHelper ) ) );
504                     if( maFromClr.isUsed() )
505                         mpNode->setFrom( Any( maFromClr.getColor( rGraphicHelper ) ) );
506                     if( mbHasByColor )
507                         mpNode->setBy( Any ( m_byColor.get() ) );
508                 }
509             }
510 
511 
512         virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException )
513             {
514                 Reference< XFastContextHandler > xRet;
515 
516                 switch ( aElementToken )
517                 {
518                 case PPT_TOKEN( hsl ):
519                     // CT_TLByHslColorTransform
520                 {
521                     if( mbHasByColor )
522                     {
523                         m_byColor.colorSpace = AnimationColorSpace::HSL;
524                         m_byColor.one = xAttribs->getOptionalValue( XML_h ).toInt32( );
525                         m_byColor.two = xAttribs->getOptionalValue( XML_s ).toInt32( );
526                         m_byColor.three = xAttribs->getOptionalValue( XML_l ).toInt32( );
527                     }
528                     xRet.set(this);
529                     break;
530                 }
531                 case PPT_TOKEN( rgb ):
532                 {
533                     if( mbHasByColor )
534                     {
535                         // CT_TLByRgbColorTransform
536                         m_byColor.colorSpace = AnimationColorSpace::RGB;
537                         m_byColor.one = xAttribs->getOptionalValue( XML_r ).toInt32();
538                         m_byColor.two = xAttribs->getOptionalValue( XML_g ).toInt32();
539                         m_byColor.three = xAttribs->getOptionalValue( XML_b ).toInt32();
540                     }
541                     xRet.set(this);
542                     break;
543                 }
544                 case PPT_TOKEN( by ):
545                     // CT_TLByAnimateColorTransform
546                     mbHasByColor = true;
547                     xRet.set(this);
548                     break;
549                 case PPT_TOKEN( cBhvr ):
550                     xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
551                     break;
552                 case PPT_TOKEN( to ):
553                     // CT_Color
554                     xRet.set( new ColorContext( *this, maToClr ) );
555                     break;
556                 case PPT_TOKEN( from ):
557                     // CT_Color
558                     xRet.set( new ColorContext( *this, maFromClr ) );
559                     break;
560 
561                 default:
562                     break;
563                 }
564 
565                 if( !xRet.is() )
566                     xRet.set( this );
567 
568                 return xRet;
569             }
570 
571 
572     private:
573         sal_Int32 mnColorSpace;
574         sal_Int32 mnDir;
575         bool mbHasByColor;
576         AnimColor m_byColor;
577         oox::drawingml::Color maToClr;
578         oox::drawingml::Color maFromClr;
579     };
580 
581 
582     /** CT_TLAnimateBehavior */
583     class AnimContext
584         : public TimeNodeContext
585     {
586     public:
587         AnimContext( ContextHandler& rParent, sal_Int32  aElement,
588                      const Reference< XFastAttributeList >& xAttribs,
589                       const TimeNodePtr & pNode ) throw()
590             : TimeNodeContext( rParent, aElement, xAttribs, pNode )
591             {
592                 NodePropertyMap & aProps( pNode->getNodeProperties() );
593                 sal_Int32 nCalcMode = xAttribs->getOptionalValueToken( XML_calcmode, 0 );
594                 if(nCalcMode)
595                 {
596                     sal_Int16 nEnum = 0;
597                     switch(nCalcMode)
598                     {
599                     case XML_discrete:
600                         nEnum = AnimationCalcMode::DISCRETE;
601                         break;
602                     case XML_lin:
603                         nEnum = AnimationCalcMode::LINEAR;
604                         break;
605                     case XML_fmla:
606                     default:
607                         // TODO what value is good ?
608                         nEnum = AnimationCalcMode::DISCRETE;
609                         break;
610                     }
611                     aProps[ NP_CALCMODE ] = makeAny(nEnum);
612                 }
613                 OUString aStr;
614                 aStr = xAttribs->getOptionalValue( XML_from );
615                 if( aStr.getLength() )
616                 {
617                     pNode->setFrom( makeAny( aStr ) );
618                 }
619                 aStr = xAttribs->getOptionalValue( XML_by );
620                 if( aStr.getLength() )
621                 {
622                     pNode->setBy( makeAny( aStr ) );
623                 }
624                 aStr = xAttribs->getOptionalValue( XML_to );
625                 if( aStr.getLength() )
626                 {
627                     pNode->setTo( makeAny( aStr ) );
628                 }
629                 mnValueType = xAttribs->getOptionalValueToken( XML_valueType, 0 );
630             }
631 
632 
633         ~AnimContext() throw ()
634             {
635                 ::std::list< TimeAnimationValue >::iterator iter, end;
636                 int nKeyTimes = maTavList.size();
637                 if( nKeyTimes > 0)
638                 {
639                     int i;
640                     Sequence< double > aKeyTimes( nKeyTimes );
641                     Sequence< Any > aValues( nKeyTimes );
642 
643                     NodePropertyMap & aProps( mpNode->getNodeProperties() );
644                     end = maTavList.end();
645                     for(iter = maTavList.begin(), i=0; iter != end; iter++,i++)
646                     {
647                         // TODO what to do if it is Timing_INFINITE ?
648                         Any aTime = GetTimeAnimateValueTime( iter->msTime );
649                         aTime >>= aKeyTimes[i];
650                         aValues[i] = iter->maValue;
651 
652                         OUString aTest;
653                         iter->maValue >>= aTest;
654                         if( aTest.getLength() != 0 )
655                         {
656                             aValues[i] = iter->maValue;
657                         }
658                         else
659                         {
660                             aProps[ NP_FORMULA ] <<= iter->msFormula;
661                         }
662                     }
663                     aProps[ NP_VALUES ] <<= aValues;
664                     aProps[ NP_KEYTIMES ] <<= aKeyTimes;
665                 }
666             }
667 
668 
669         virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException )
670             {
671                 Reference< XFastContextHandler > xRet;
672 
673                 switch ( aElementToken )
674                 {
675                 case PPT_TOKEN( cBhvr ):
676                     xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
677                     break;
678                 case PPT_TOKEN( tavLst ):
679                     xRet.set( new TimeAnimValueListContext ( *this, xAttribs, maTavList ) );
680                     break;
681                 default:
682                     break;
683                 }
684 
685                 if( !xRet.is() )
686                     xRet.set( this );
687 
688                 return xRet;
689             }
690     private:
691         sal_Int32              mnValueType;
692         TimeAnimationValueList maTavList;
693     };
694 
695 
696     /** CT_TLAnimateScaleBehavior */
697     class AnimScaleContext
698         : public TimeNodeContext
699     {
700     public:
701         AnimScaleContext( ContextHandler& rParent, sal_Int32  aElement,
702                             const Reference< XFastAttributeList >& xAttribs,
703                             const TimeNodePtr & pNode ) throw()
704             : TimeNodeContext( rParent, aElement, xAttribs, pNode )
705                 , mbZoomContents( false )
706             {
707                 AttributeList attribs( xAttribs );
708                 // TODO what to do with mbZoomContents
709                 mbZoomContents = attribs.getBool( XML_zoomContents, false );
710                 pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
711                     = makeAny((sal_Int16)AnimationTransformType::SCALE);
712             }
713 
714         ~AnimScaleContext( ) throw( )
715             {
716             }
717 
718         virtual void SAL_CALL endFastElement( sal_Int32 aElement ) throw ( SAXException, RuntimeException)
719             {
720                 if( aElement == mnElement )
721                 {
722                     if( maTo.hasValue() )
723                     {
724                         mpNode->setTo( maTo );
725                     }
726                     if( maBy.hasValue() )
727                     {
728                         mpNode->setBy( maBy );
729                     }
730                     if( maFrom.hasValue() )
731                     {
732                         mpNode->setFrom( maFrom );
733                     }
734                 }
735             }
736 
737         virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken,
738                                                                                                                                                             const Reference< XFastAttributeList >& xAttribs )
739             throw ( SAXException, RuntimeException )
740             {
741                 Reference< XFastContextHandler > xRet;
742 
743                 switch ( aElementToken )
744                 {
745                 case PPT_TOKEN( cBhvr ):
746                     xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
747                     break;
748                 case PPT_TOKEN( to ):
749                 {
750                     // CT_TLPoint
751                     Point p = GetPointPercent( xAttribs );
752                     maTo <<= p.X;
753                     maTo <<= p.Y;
754                     break;
755                 }
756                 case PPT_TOKEN( from ):
757                 {
758                     // CT_TLPoint
759                     Point p = GetPointPercent( xAttribs );
760                     maFrom <<= p.X;
761                     maFrom <<= p.Y;
762                     break;
763                 }
764                 case PPT_TOKEN( by ):
765                 {
766                     // CT_TLPoint
767                     Point p = GetPointPercent( xAttribs );
768                     maBy <<= p.X;
769                     maBy <<= p.Y;
770                     break;
771                 }
772                 default:
773                     break;
774                 }
775 
776                 if( !xRet.is() )
777                     xRet.set( this );
778 
779                 return xRet;
780             }
781     private:
782         Any maBy;
783         Any maFrom;
784         Any maTo;
785         bool mbZoomContents;
786     };
787 
788 
789     /** CT_TLAnimateRotationBehavior */
790     class AnimRotContext
791         : public TimeNodeContext
792     {
793     public:
794         AnimRotContext( ContextHandler& rParent, sal_Int32  aElement,
795                         const Reference< XFastAttributeList >& xAttribs,
796                          const TimeNodePtr & pNode ) throw()
797             : TimeNodeContext( rParent, aElement, xAttribs, pNode )
798             {
799                 AttributeList attribs( xAttribs );
800 
801                 pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
802                     = makeAny((sal_Int16)AnimationTransformType::ROTATE);
803                 // TODO make sure the units are OK
804                 if(attribs.hasAttribute( XML_by ) )
805                 {
806                     sal_Int32 nBy = attribs.getInteger( XML_by, 0 );
807                     pNode->setBy( makeAny( nBy ) );
808                 }
809                 if(attribs.hasAttribute( XML_from ) )
810                 {
811                     sal_Int32 nFrom = attribs.getInteger( XML_from, 0 );
812                     pNode->setFrom( makeAny( nFrom ) );
813                 }
814                 if(attribs.hasAttribute( XML_to ) )
815                 {
816                     sal_Int32 nTo = attribs.getInteger( XML_to, 0 );
817                     pNode->setTo( makeAny( nTo ) );
818                 }
819             }
820 
821         ~AnimRotContext( ) throw( )
822             {
823             }
824 
825         virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException )
826             {
827                 Reference< XFastContextHandler > xRet;
828 
829                 switch ( aElementToken )
830                 {
831                 case PPT_TOKEN( cBhvr ):
832                     xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
833                     break;
834                 default:
835                     break;
836                 }
837 
838                 if( !xRet.is() )
839                     xRet.set( this );
840 
841                 return xRet;
842             }
843     };
844 
845 
846 
847     /** CT_TLAnimateMotionBehavior */
848     class AnimMotionContext
849         : public TimeNodeContext
850     {
851     public:
852         AnimMotionContext( ContextHandler& rParent, sal_Int32  aElement,
853                          const Reference< XFastAttributeList >& xAttribs,
854                           const TimeNodePtr & pNode ) throw()
855             : TimeNodeContext( rParent, aElement, xAttribs, pNode )
856             {
857                 pNode->getNodeProperties()[ NP_TRANSFORMTYPE ]
858                     = makeAny((sal_Int16)AnimationTransformType::TRANSLATE);
859 
860                 AttributeList attribs( xAttribs );
861                 // ST_TLAnimateMotionBehaviorOrigin { parent, layour }
862                 sal_Int32 nOrigin = xAttribs->getOptionalValueToken( XML_origin, 0 );
863                 if( nOrigin != 0 )
864                 {
865                     switch(nOrigin)
866                     {
867                     case XML_layout:
868                     case XML_parent:
869                         break;
870                     }
871                     // TODO
872                 }
873 
874                 OUString aStr = xAttribs->getOptionalValue( XML_path );
875                 aStr = aStr.replace( 'E', ' ' );
876                 aStr = aStr.trim();
877                 pNode->getNodeProperties()[ NP_PATH ] = makeAny(aStr);
878 
879                 // ST_TLAnimateMotionPathEditMode{ fixed, relative }
880                 mnPathEditMode = xAttribs->getOptionalValueToken( XML_pathEditMode, 0 );
881                 msPtsTypes = xAttribs->getOptionalValue( XML_ptsTypes );
882                 mnAngle = attribs.getInteger( XML_rAng, 0 );
883                 // TODO make sure the units are right. Likely not.
884             }
885 
886         ~AnimMotionContext( ) throw()
887             {
888             }
889 
890 
891         virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken,
892                                                                                                                                                             const Reference< XFastAttributeList >& xAttribs )
893             throw ( SAXException, RuntimeException )
894             {
895                 Reference< XFastContextHandler > xRet;
896 
897                 switch ( aElementToken )
898                 {
899                 case PPT_TOKEN( cBhvr ):
900                     xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
901                     break;
902                 case PPT_TOKEN( to ):
903                 {
904                     // CT_TLPoint
905                     Point p = GetPointPercent( xAttribs );
906                     Any rAny;
907                     rAny <<= p.X;
908                     rAny <<= p.Y;
909                     mpNode->setTo( rAny );
910                     break;
911                 }
912                 case PPT_TOKEN( from ):
913                 {
914                     // CT_TLPoint
915                     Point p = GetPointPercent( xAttribs );
916                     Any rAny;
917                     rAny <<= p.X;
918                     rAny <<= p.Y;
919                     mpNode->setFrom( rAny );
920                     break;
921                 }
922                 case PPT_TOKEN( by ):
923                 {
924                     // CT_TLPoint
925                     Point p = GetPointPercent( xAttribs );
926                     Any rAny;
927                     rAny <<= p.X;
928                     rAny <<= p.Y;
929                     mpNode->setBy( rAny );
930                     break;
931                 }
932                 case PPT_TOKEN( rCtr ):
933                 {
934                     // CT_TLPoint
935                     Point p = GetPointPercent( xAttribs );
936                     // TODO push
937                     break;
938                 }
939                 default:
940                     break;
941                 }
942 
943                 if( !xRet.is() )
944                     xRet.set( this );
945 
946                 return xRet;
947             }
948     private:
949         OUString msPtsTypes;
950         sal_Int32 mnPathEditMode;
951         sal_Int32 mnAngle;
952     };
953 
954 
955     /** CT_TLAnimateEffectBehavior */
956     class AnimEffectContext
957         : public TimeNodeContext
958     {
959     public:
960         AnimEffectContext( ContextHandler& rParent, sal_Int32  aElement,
961                              const Reference< XFastAttributeList >& xAttribs,
962                              const TimeNodePtr & pNode ) throw()
963             : TimeNodeContext( rParent, aElement, xAttribs, pNode )
964             {
965                 sal_Int32 nDir = xAttribs->getOptionalValueToken( XML_transition, 0 );
966                 OUString sFilter = xAttribs->getOptionalValue( XML_filter );
967                 // TODO
968 //              OUString sPrList = xAttribs->getOptionalValue( XML_prLst );
969 
970                 if( sFilter.getLength() )
971                 {
972                     SlideTransition aFilter( sFilter );
973                     aFilter.setMode( nDir == XML_out ? false : true );
974                     pNode->setTransitionFilter( aFilter );
975                 }
976             }
977 
978 
979         ~AnimEffectContext( ) throw()
980             {
981             }
982 
983 
984         virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException )
985             {
986                 Reference< XFastContextHandler > xRet;
987 
988                 switch ( aElementToken )
989                 {
990                 case PPT_TOKEN( cBhvr ):
991                     xRet.set( new CommonBehaviorContext ( *this, xAttribs, mpNode ) );
992                     break;
993                 case PPT_TOKEN( progress ):
994                     xRet.set( new AnimVariantContext( *this, aElementToken, maProgress ) );
995                     // TODO handle it.
996                     break;
997                 default:
998                     break;
999                 }
1000 
1001                 if( !xRet.is() )
1002                     xRet.set( this );
1003 
1004                 return xRet;
1005             }
1006     private:
1007         Any maProgress;
1008         OUString msFilter;
1009         OUString msPrList;
1010     };
1011 
1012 
1013 
1014     TimeNodeContext * TimeNodeContext::makeContext(
1015             ContextHandler& rParent, sal_Int32  aElement,
1016             const Reference< XFastAttributeList >& xAttribs,
1017             const TimeNodePtr & pNode )
1018     {
1019         TimeNodeContext *pCtx = NULL;
1020         switch( aElement )
1021         {
1022         case PPT_TOKEN( animClr ):
1023             pCtx = new AnimColorContext( rParent, aElement, xAttribs, pNode );
1024             break;
1025         case PPT_TOKEN( par ):
1026             pCtx = new ParallelExclTimeNodeContext( rParent, aElement, xAttribs, pNode );
1027             break;
1028         case PPT_TOKEN( seq ):
1029             pCtx = new SequenceTimeNodeContext( rParent, aElement, xAttribs, pNode );
1030             break;
1031         case PPT_TOKEN( excl ):
1032             pCtx = new ParallelExclTimeNodeContext( rParent, aElement, xAttribs, pNode );
1033             break;
1034         case PPT_TOKEN( anim ):
1035             pCtx = new AnimContext ( rParent, aElement, xAttribs, pNode );
1036             break;
1037         case PPT_TOKEN( animEffect ):
1038             pCtx = new AnimEffectContext( rParent, aElement, xAttribs, pNode );
1039             break;
1040         case PPT_TOKEN( animMotion ):
1041             pCtx = new AnimMotionContext( rParent, aElement, xAttribs, pNode );
1042             break;
1043         case PPT_TOKEN( animRot ):
1044             pCtx = new AnimRotContext( rParent, aElement, xAttribs, pNode );
1045             break;
1046         case PPT_TOKEN( animScale ):
1047             pCtx = new AnimScaleContext( rParent, aElement, xAttribs, pNode );
1048             break;
1049         case PPT_TOKEN( cmd ):
1050             pCtx = new CmdTimeNodeContext( rParent, aElement, xAttribs, pNode );
1051             break;
1052         case PPT_TOKEN( set ):
1053             pCtx = new SetTimeNodeContext( rParent, aElement, xAttribs, pNode );
1054             break;
1055         case PPT_TOKEN( audio ):
1056         case PPT_TOKEN( video ):
1057             pCtx = new MediaNodeContext( rParent, aElement, xAttribs, pNode );
1058             break;
1059         default:
1060             break;
1061         }
1062         return pCtx;
1063     }
1064 
1065 
1066     TimeNodeContext::TimeNodeContext( ContextHandler& rParent, sal_Int32 aElement,
1067             const Reference< XFastAttributeList >& /*xAttribs*/,
1068             const TimeNodePtr & pNode ) throw()
1069         : ContextHandler( rParent )
1070         , mnElement( aElement )
1071         , mpNode( pNode )
1072     {
1073     }
1074 
1075 
1076     TimeNodeContext::~TimeNodeContext( ) throw()
1077     {
1078 
1079     }
1080 
1081 
1082     TimeNodeListContext::TimeNodeListContext( ContextHandler& rParent, TimeNodePtrList & aList )
1083         throw()
1084         : ContextHandler( rParent )
1085             , maList( aList )
1086     {
1087     }
1088 
1089 
1090     TimeNodeListContext::~TimeNodeListContext( ) throw()
1091     {
1092     }
1093 
1094 
1095     Reference< XFastContextHandler > SAL_CALL TimeNodeListContext::createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException)
1096     {
1097         Reference< XFastContextHandler > xRet;
1098 
1099         sal_Int16 nNodeType;
1100 
1101         switch( aElementToken )
1102         {
1103         case PPT_TOKEN( par ):
1104             nNodeType = AnimationNodeType::PAR;
1105             break;
1106         case PPT_TOKEN( seq ):
1107             nNodeType = AnimationNodeType::SEQ;
1108             break;
1109         case PPT_TOKEN( excl ):
1110             // TODO pick the right type. We choose parallel for now as
1111             // there does not seem to be an "Exclusive"
1112             nNodeType = AnimationNodeType::PAR;
1113             break;
1114         case PPT_TOKEN( anim ):
1115             nNodeType = AnimationNodeType::ANIMATE;
1116             break;
1117         case PPT_TOKEN( animClr ):
1118             nNodeType = AnimationNodeType::ANIMATECOLOR;
1119             break;
1120         case PPT_TOKEN( animEffect ):
1121             nNodeType = AnimationNodeType::TRANSITIONFILTER;
1122             break;
1123         case PPT_TOKEN( animMotion ):
1124             nNodeType = AnimationNodeType::ANIMATEMOTION;
1125             break;
1126         case PPT_TOKEN( animRot ):
1127         case PPT_TOKEN( animScale ):
1128             nNodeType = AnimationNodeType::ANIMATETRANSFORM;
1129             break;
1130         case PPT_TOKEN( cmd ):
1131             nNodeType = AnimationNodeType::COMMAND;
1132             break;
1133         case PPT_TOKEN( set ):
1134             nNodeType = AnimationNodeType::SET;
1135             break;
1136         case PPT_TOKEN( audio ):
1137             nNodeType = AnimationNodeType::AUDIO;
1138             break;
1139         case PPT_TOKEN( video ):
1140             nNodeType = AnimationNodeType::AUDIO;
1141             OSL_TRACE( "OOX: video requested, gave Audio instead" );
1142             break;
1143 
1144         default:
1145             nNodeType = AnimationNodeType::CUSTOM;
1146             OSL_TRACE( "OOX: uhandled token %x", aElementToken );
1147             break;
1148         }
1149 
1150         TimeNodePtr pNode(new TimeNode(nNodeType));
1151         maList.push_back( pNode );
1152         ContextHandler * pContext = TimeNodeContext::makeContext( *this, aElementToken, xAttribs, pNode );
1153         xRet.set( pContext ? pContext : this );
1154 
1155         return xRet;
1156     }
1157 
1158 
1159 } }
1160