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