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