1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 
31 #include <tools/debug.hxx>
32 #include <tools/time.hxx>
33 #include "unointerfacetouniqueidentifiermapper.hxx"
34 #include <com/sun/star/lang/XServiceInfo.hpp>
35 #include <com/sun/star/lang/XInitialization.hpp>
36 #include <com/sun/star/animations/AnimationTransformType.hpp>
37 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
38 #include <com/sun/star/presentation/AnimationEffect.hpp>
39 #include <com/sun/star/presentation/AnimationSpeed.hpp>
40 #include <com/sun/star/animations/AnimationNodeType.hpp>
41 #include <com/sun/star/animations/XIterateContainer.hpp>
42 #include <com/sun/star/animations/XAnimateMotion.hpp>
43 #include <com/sun/star/animations/XAnimateColor.hpp>
44 #include <com/sun/star/animations/XAnimateTransform.hpp>
45 #include <com/sun/star/animations/XTransitionFilter.hpp>
46 #include <com/sun/star/animations/XCommand.hpp>
47 #include <com/sun/star/animations/XAudio.hpp>
48 #include <com/sun/star/animations/ValuePair.hpp>
49 #include <com/sun/star/animations/AnimationColorSpace.hpp>
50 #include <com/sun/star/presentation/EffectPresetClass.hpp>
51 #include <com/sun/star/animations/Timing.hpp>
52 #include <com/sun/star/animations/Event.hpp>
53 #include <com/sun/star/beans/XPropertySet.hpp>
54 #include <com/sun/star/xml/sax/XAttributeList.hpp>
55 #include <com/sun/star/text/XTextCursor.hpp>
56 #include <com/sun/star/text/XTextRangeCompare.hpp>
57 #include <com/sun/star/presentation/ParagraphTarget.hpp>
58 #include <com/sun/star/container/XEnumerationAccess.hpp>
59 #include <com/sun/star/beans/XPropertySet.hpp>
60 #include <com/sun/star/animations/EventTrigger.hpp>
61 #include <com/sun/star/presentation/EffectCommands.hpp>
62 #include <comphelper/processfactory.hxx>
63 #include <cppuhelper/implbase1.hxx>
64 
65 #include <list>
66 #include <xmloff/xmltypes.hxx>
67 #include "sdpropls.hxx"
68 #include <xmloff/xmltoken.hxx>
69 #include <xmloff/xmlimp.hxx>
70 #include "xmloff/xmlnmspe.hxx"
71 #include <xmloff/xmluconv.hxx>
72 #include <osl/mutex.hxx>
73 #include <xmloff/nmspmap.hxx>
74 #include "anim.hxx"
75 
76 #include "animations.hxx"
77 #include "animationimport.hxx"
78 
79 using ::rtl::OUString;
80 using ::rtl::OUStringBuffer;
81 
82 using namespace ::std;
83 using namespace ::cppu;
84 using namespace ::com::sun::star::beans;
85 using namespace ::com::sun::star::animations;
86 using namespace ::com::sun::star::presentation;
87 using namespace ::com::sun::star::drawing;
88 using namespace ::xmloff::token;
89 
90 using ::com::sun::star::xml::sax::XAttributeList;
91 using ::com::sun::star::uno::Any;
92 using ::com::sun::star::uno::makeAny;
93 using ::com::sun::star::uno::UNO_QUERY;
94 using ::com::sun::star::uno::UNO_QUERY_THROW;
95 using ::com::sun::star::uno::Reference;
96 using ::com::sun::star::uno::Sequence;
97 using ::com::sun::star::uno::RuntimeException;
98 using ::com::sun::star::uno::Exception;
99 using ::com::sun::star::uno::XInterface;
100 using ::com::sun::star::uno::Type;
101 using ::com::sun::star::beans::NamedValue;
102 using ::com::sun::star::text::XTextRange;
103 using ::com::sun::star::text::XTextCursor;
104 using ::com::sun::star::text::XTextRangeCompare;
105 using ::com::sun::star::container::XEnumerationAccess;
106 using ::com::sun::star::container::XEnumeration;
107 using ::com::sun::star::lang::XMultiServiceFactory;
108 using ::com::sun::star::lang::XInitialization;
109 
110 namespace xmloff
111 {
112 
113 ///////////////////////////////////////////////////////////////////////
114 
115 
116 
117 ///////////////////////////////////////////////////////////////////////
118 
119 
120 ///////////////////////////////////////////////////////////////////////
121 
122 class AnimationsImportHelperImpl
123 {
124 private:
125 	SvXMLImport& mrImport;
126 
127 	SvXMLTokenMap* mpAnimationNodeTokenMap;
128 	SvXMLTokenMap* mpAnimationNodeAttributeTokenMap;
129 
130 public:
131 	AnimationsImportHelperImpl( SvXMLImport& rImport );
132 	~AnimationsImportHelperImpl();
133 
134 	const SvXMLTokenMap& getAnimationNodeTokenMap();
135 	const SvXMLTokenMap& getAnimationNodeAttributeTokenMap();
136 
137 	Any convertValue( XMLTokenEnum eAttributeName, const OUString& rValue );
138 	Sequence< Any > convertValueSequence( XMLTokenEnum eAttributeName, const OUString& rValue );
139 
140 	Any convertTarget( const OUString& rValue );
141 	Any convertPath( const OUString& rValue );
142 	Any convertTiming( const OUString& rValue );
143 	Sequence< double > convertKeyTimes( const OUString& rValue );
144 	Sequence< TimeFilterPair > convertTimeFilter( const OUString& rValue );
145 
146 	bool convertAnimationValue( XMLTokenEnum eAttributeName, Any& rValue );
147 	const OUString mastrHSL;
148 };
149 
150 AnimationsImportHelperImpl::AnimationsImportHelperImpl( SvXMLImport& rImport )
151 :	mrImport( rImport ),
152 	mpAnimationNodeTokenMap( NULL ),
153 	mpAnimationNodeAttributeTokenMap( NULL ),
154 	mastrHSL( RTL_CONSTASCII_USTRINGPARAM( "hsl" ) )
155 {
156 }
157 
158 AnimationsImportHelperImpl::~AnimationsImportHelperImpl()
159 {
160 	delete mpAnimationNodeTokenMap;
161 	delete mpAnimationNodeAttributeTokenMap;
162 }
163 
164 const SvXMLTokenMap& AnimationsImportHelperImpl::getAnimationNodeTokenMap()
165 {
166 	if( mpAnimationNodeTokenMap == NULL )
167 	{
168 		static __FAR_DATA SvXMLTokenMapEntry aAnimationNodeTokenMap[] =
169 		{
170 			{ XML_NAMESPACE_ANIMATION,	XML_PAR,				(sal_uInt16)AnimationNodeType::PAR },
171 			{ XML_NAMESPACE_ANIMATION,	XML_SEQ,				(sal_uInt16)AnimationNodeType::SEQ },
172 			{ XML_NAMESPACE_ANIMATION,	XML_ITERATE,			(sal_uInt16)AnimationNodeType::ITERATE },
173 			{ XML_NAMESPACE_ANIMATION,	XML_ANIMATE,			(sal_uInt16)AnimationNodeType::ANIMATE },
174 			{ XML_NAMESPACE_ANIMATION,	XML_SET,				(sal_uInt16)AnimationNodeType::SET },
175 			{ XML_NAMESPACE_ANIMATION,	XML_ANIMATEMOTION,		(sal_uInt16)AnimationNodeType::ANIMATEMOTION },
176 			{ XML_NAMESPACE_ANIMATION,	XML_ANIMATECOLOR,		(sal_uInt16)AnimationNodeType::ANIMATECOLOR },
177 			{ XML_NAMESPACE_ANIMATION,	XML_ANIMATETRANSFORM,	(sal_uInt16)AnimationNodeType::ANIMATETRANSFORM },
178 			{ XML_NAMESPACE_ANIMATION,	XML_TRANSITIONFILTER,	(sal_uInt16)AnimationNodeType::TRANSITIONFILTER	},
179 			{ XML_NAMESPACE_ANIMATION,	XML_AUDIO,				(sal_uInt16)AnimationNodeType::AUDIO },
180 			{ XML_NAMESPACE_ANIMATION,	XML_COMMAND,			(sal_uInt16)AnimationNodeType::COMMAND },
181 			XML_TOKEN_MAP_END
182 		};
183 
184 		mpAnimationNodeTokenMap = new SvXMLTokenMap( aAnimationNodeTokenMap );
185 	}
186 
187 	return *mpAnimationNodeTokenMap;
188 }
189 
190 enum AnimationNodeAttributes
191 {
192 	ANA_Begin,
193 	ANA_Dur,
194 	ANA_End,
195 	ANA_Fill,
196 	ANA_FillDefault,
197 	ANA_Restart,
198 	ANA_RestartDefault,
199 	ANA_Accelerate,
200 	ANA_Decelerate,
201 	ANA_AutoReverse,
202 	ANA_RepeatCount,
203 	ANA_RepeatDur,
204 	ANA_EndSync,
205 	ANA_Node_Type,
206 	ANA_Preset_ID,
207 	ANA_Preset_Sub_Type,
208 	ANA_Preset_Class,
209 	ANA_After_Effect,
210 	ANA_Target,
211 	ANA_XLink,
212 	ANA_MasterElement,
213 	ANA_SubItem,
214 	ANA_AttributeName,
215 	ANA_Values,
216 	ANA_From,
217 	ANA_By,
218 	ANA_To,
219 	ANA_KeyTimes,
220 	ANA_CalcMode,
221 	ANA_Accumulate,
222 	ANA_AdditiveMode,
223 	ANA_KeySplines,
224 	ANA_Path,
225 	ANA_ColorSpace,
226 	ANA_ColorDirection,
227 	ANA_TransformType,
228 	ANA_TransitionType,
229 	ANA_TransitionSubType,
230 	ANA_Mode,
231 	ANA_Direction,
232 	ANA_FadeColor,
233 	ANA_IterateType,
234 	ANA_IterateInterval,
235 	ANA_Formula,
236     ANA_ANIMID,
237     ANA_XMLID,
238 	ANA_Group_Id,
239 	ANA_Command,
240 	ANA_Volume
241 };
242 
243 const SvXMLTokenMap& AnimationsImportHelperImpl::getAnimationNodeAttributeTokenMap()
244 {
245 	if( mpAnimationNodeAttributeTokenMap == NULL )
246 	{
247 		static __FAR_DATA SvXMLTokenMapEntry aAnimationNodeAttributeTokenMap[] =
248 		{
249 			{ XML_NAMESPACE_SMIL, XML_BEGIN,					(sal_uInt16)ANA_Begin },
250 			{ XML_NAMESPACE_SMIL, XML_DUR,						(sal_uInt16)ANA_Dur },
251 			{ XML_NAMESPACE_SMIL, XML_END,						(sal_uInt16)ANA_End },
252 			{ XML_NAMESPACE_SMIL, XML_FILL,						(sal_uInt16)ANA_Fill },
253 			{ XML_NAMESPACE_SMIL, XML_FILLDEFAULT,				(sal_uInt16)ANA_FillDefault },
254 			{ XML_NAMESPACE_SMIL, XML_RESTART,					(sal_uInt16)ANA_Restart },
255 			{ XML_NAMESPACE_SMIL, XML_RESTARTDEFAULT,			(sal_uInt16)ANA_RestartDefault },
256 			{ XML_NAMESPACE_SMIL, XML_ACCELERATE,				(sal_uInt16)ANA_Accelerate },
257 			{ XML_NAMESPACE_SMIL, XML_DECELERATE,				(sal_uInt16)ANA_Decelerate },
258 			{ XML_NAMESPACE_SMIL, XML_AUTOREVERSE,				(sal_uInt16)ANA_AutoReverse },
259 			{ XML_NAMESPACE_SMIL, XML_REPEATCOUNT,				(sal_uInt16)ANA_RepeatCount },
260 			{ XML_NAMESPACE_SMIL, XML_REPEATDUR,				(sal_uInt16)ANA_RepeatDur },
261 			{ XML_NAMESPACE_SMIL, XML_ENDSYNC,					(sal_uInt16)ANA_EndSync },
262 			{ XML_NAMESPACE_PRESENTATION, XML_NODE_TYPE,		(sal_uInt16)ANA_Node_Type },
263 			{ XML_NAMESPACE_PRESENTATION, XML_PRESET_ID,		(sal_uInt16)ANA_Preset_ID },
264 			{ XML_NAMESPACE_PRESENTATION, XML_PRESET_SUB_TYPE,	(sal_uInt16)ANA_Preset_Sub_Type },
265 			{ XML_NAMESPACE_PRESENTATION, XML_PRESET_CLASS,		(sal_uInt16)ANA_Preset_Class },
266 			{ XML_NAMESPACE_PRESENTATION, XML_AFTER_EFFECT,		(sal_uInt16)ANA_After_Effect },
267 			{ XML_NAMESPACE_SMIL, XML_TARGETELEMENT,			(sal_uInt16)ANA_Target },
268 			{ XML_NAMESPACE_XLINK, XML_HREF,					(sal_uInt16)ANA_XLink },
269 			{ XML_NAMESPACE_PRESENTATION, XML_MASTER_ELEMENT,	(sal_uInt16)ANA_MasterElement },
270 			{ XML_NAMESPACE_ANIMATION, XML_SUB_ITEM,			(sal_uInt16)ANA_SubItem },
271 			{ XML_NAMESPACE_SMIL, XML_ATTRIBUTENAME,			(sal_uInt16)ANA_AttributeName },
272 			{ XML_NAMESPACE_SMIL, XML_VALUES,					(sal_uInt16)ANA_Values },
273 			{ XML_NAMESPACE_SMIL, XML_FROM,						(sal_uInt16)ANA_From },
274 			{ XML_NAMESPACE_SMIL, XML_BY,						(sal_uInt16)ANA_By },
275 			{ XML_NAMESPACE_SMIL, XML_TO,						(sal_uInt16)ANA_To },
276 			{ XML_NAMESPACE_SMIL, XML_KEYTIMES,					(sal_uInt16)ANA_KeyTimes },
277 			{ XML_NAMESPACE_SMIL, XML_CALCMODE,					(sal_uInt16)ANA_CalcMode },
278 			{ XML_NAMESPACE_SMIL, XML_ACCUMULATE,				(sal_uInt16)ANA_Accumulate },
279 			{ XML_NAMESPACE_PRESENTATION, XML_ADDITIVE,			(sal_uInt16)ANA_AdditiveMode },
280 			{ XML_NAMESPACE_SMIL, XML_ADDITIVE,					(sal_uInt16)ANA_AdditiveMode },
281 			{ XML_NAMESPACE_SMIL, XML_KEYSPLINES,				(sal_uInt16)ANA_KeySplines },
282 			{ XML_NAMESPACE_SVG, XML_PATH,						(sal_uInt16)ANA_Path },
283 			{ XML_NAMESPACE_ANIMATION, XML_COLOR_INTERPOLATION,	(sal_uInt16)ANA_ColorSpace },
284 			{ XML_NAMESPACE_ANIMATION, XML_COLOR_INTERPOLATION_DIRECTION,		(sal_uInt16)ANA_ColorDirection },
285 			{ XML_NAMESPACE_SVG, XML_TYPE,						(sal_uInt16)ANA_TransformType },
286 			{ XML_NAMESPACE_SMIL, XML_TYPE,						(sal_uInt16)ANA_TransitionType },
287 			{ XML_NAMESPACE_SMIL, XML_SUBTYPE,					(sal_uInt16)ANA_TransitionSubType },
288 			{ XML_NAMESPACE_SMIL, XML_MODE,						(sal_uInt16)ANA_Mode },
289 			{ XML_NAMESPACE_SMIL, XML_DIRECTION,				(sal_uInt16)ANA_Direction },
290 			{ XML_NAMESPACE_SMIL, XML_FADECOLOR,				(sal_uInt16)ANA_FadeColor },
291 			{ XML_NAMESPACE_ANIMATION, XML_ITERATE_TYPE,		(sal_uInt16)ANA_IterateType },
292 			{ XML_NAMESPACE_ANIMATION, XML_ITERATE_INTERVAL,	(sal_uInt16)ANA_IterateInterval },
293 			{ XML_NAMESPACE_ANIMATION, XML_FORMULA,				(sal_uInt16)ANA_Formula },
294             { XML_NAMESPACE_ANIMATION, XML_ID,                  (sal_uInt16)ANA_ANIMID },
295             { XML_NAMESPACE_XML, XML_ID,                        (sal_uInt16)ANA_XMLID },
296 			{ XML_NAMESPACE_PRESENTATION, XML_GROUP_ID,			(sal_uInt16)ANA_Group_Id },
297 			{ XML_NAMESPACE_ANIMATION, XML_AUDIO_LEVEL,			(sal_uInt16)ANA_Volume },
298 			{ XML_NAMESPACE_ANIMATION, XML_COMMAND,				(sal_uInt16)ANA_Command },
299 
300 			XML_TOKEN_MAP_END
301 		};
302 
303 		mpAnimationNodeAttributeTokenMap = new SvXMLTokenMap( aAnimationNodeAttributeTokenMap );
304 	}
305 
306 	return *mpAnimationNodeAttributeTokenMap;
307 }
308 
309 static bool isDouble( const OUString& rValue )
310 {
311 	sal_Int32 nLength = rValue.getLength();
312 	const sal_Unicode * pStr = rValue.getStr();
313 	while( nLength )
314 	{
315 		if( (*pStr >= '0' && *pStr <= '9') || *pStr == '-' || *pStr == '.' || *pStr == '+' || *pStr == 'e' || *pStr == 'E' )
316 		{
317 			pStr++;
318 			nLength--;
319 		}
320 		else
321 		{
322 			return false;
323 		}
324 	}
325 
326 	return true;
327 }
328 
329 static bool isTime( const OUString& rValue )
330 {
331 	sal_Int32 nLength = rValue.getLength();
332 	const sal_Unicode * pStr;
333 	for( pStr = rValue.getStr(); nLength; pStr++, nLength-- )
334 	{
335 		if( !( (*pStr >= '0' && *pStr <= '9') || *pStr == '-' || *pStr == '.' || *pStr == '+' || *pStr == 'e' || *pStr == 'E' ) )
336 			break;
337 	}
338 
339 	// return true if this is a double (if someone forgot the 's' we silently ignore it)
340 	// or if its a double that ends with a 's' or 'S'
341 	return (nLength == 0) || ((*pStr == 's' || *pStr == 'S') && (nLength == 1));
342 }
343 
344 static sal_Int32 count_codes( const OUString& rString, sal_Unicode nCode )
345 {
346 	sal_Int32 nCount = 0;
347 	sal_Int32 fromIndex = 0;
348 
349 	while(true)
350 	{
351 		fromIndex = rString.indexOf( nCode, fromIndex );
352 		if( fromIndex == -1 )
353 			break;
354 
355 		fromIndex++;
356 		nCount++;
357 	}
358 
359 	return nCount;
360 }
361 
362 Any AnimationsImportHelperImpl::convertTarget( const OUString& rValue )
363 {
364 	try
365 	{
366 		Reference< XInterface > xRef( mrImport.getInterfaceToIdentifierMapper().getReference( rValue ) );
367 
368 		Reference< XShape > _xShape( xRef, UNO_QUERY );
369 		if( _xShape.is() )
370 			return makeAny( _xShape );
371 
372 		Reference< XTextCursor > xTextCursor( xRef, UNO_QUERY );
373 		if( xTextCursor.is() )
374 		{
375 			Reference< XTextRange > xStart( xTextCursor->getStart() ), xRange;
376 			Reference< XShape > xShape( xTextCursor->getText(), UNO_QUERY_THROW );
377 			Reference< XTextRangeCompare > xTextRangeCompare( xShape, UNO_QUERY_THROW );
378 
379 			Reference< XEnumerationAccess > xParaEnumAccess( xShape, UNO_QUERY_THROW );
380 			Reference< XEnumeration > xEnumeration( xParaEnumAccess->createEnumeration(), UNO_QUERY_THROW );
381 			sal_Int16 nParagraph = 0;
382 
383 			while( xEnumeration->hasMoreElements() )
384 			{
385 				xEnumeration->nextElement() >>= xRange;
386 
387 				// break if start of selection is prior to end of current paragraph
388 				if( xRange.is() && (xTextRangeCompare->compareRegionEnds( xStart, xRange ) >= 0 ) )
389 				{
390 					return makeAny( ParagraphTarget( xShape, nParagraph ) );
391 				}
392 
393 				nParagraph++;
394 			}
395 		}
396 	}
397 	catch( RuntimeException& )
398 	{
399 		DBG_ERROR( "xmloff::AnimationsImportImpl::convertTarget(), RuntimeException catched!" );
400 	}
401 
402 	Any aAny;
403 	return aAny;
404 }
405 
406 Any AnimationsImportHelperImpl::convertValue( XMLTokenEnum eAttributeName, const OUString& rValue )
407 {
408 	sal_Int32 nCommaPos = -1, nPos;
409 	sal_Int32 nOpenBrakets = 0;
410 	for( nPos = 0; (nPos < rValue.getLength()) && (nCommaPos == -1); nPos++ )
411 	{
412 		switch( rValue[nPos] )
413 		{
414 		case ',':
415 			if( nOpenBrakets == 0 )
416 				nCommaPos = nPos;
417 			break;
418 		case '(':
419 		case '[':
420 		case '{':
421 			nOpenBrakets++;
422 			break;
423 		case ')':
424 		case ']':
425 		case '}':
426 			nOpenBrakets--;
427 			break;
428 		}
429 	}
430 
431 	if( nCommaPos >= 0 )
432 	{
433 		ValuePair aPair;
434 		aPair.First = convertValue( eAttributeName, rValue.copy( 0, nCommaPos ) );
435 		aPair.Second = convertValue( eAttributeName, rValue.copy( nCommaPos+1, rValue.getLength() - nCommaPos - 1 ) );
436 		return makeAny( aPair );
437 	}
438 	else
439 	{
440 		Any aAny;
441 		sal_Int32 nType = XML_TYPE_STRING;
442 
443 		if( rValue.getLength() ) switch( eAttributeName )
444 		{
445 		case XML_X:
446 		case XML_Y:
447 		case XML_WIDTH:
448 		case XML_HEIGHT:
449 		case XML_TRANSLATE:
450 		{
451 			return makeAny( rValue );
452 		}
453 
454 		case XML_SCALE:
455 		case XML_SKEWY:
456 		case XML_SKEWX:
457 		case XML_OPACITY:
458 		case XML_ROTATE:			nType = XML_TYPE_DOUBLE;					break;
459 		case XML_TEXT_ROTATION_ANGLE:nType = XML_TYPE_TEXT_ROTATION_ANGLE;		break;
460 		case XML_FILL_COLOR:
461 		case XML_STROKE_COLOR:
462 		case XML_DIM:
463 		case XML_COLOR:				nType = XML_TYPE_COLOR;						break;
464 		case XML_FILL:				nType = XML_SD_TYPE_FILLSTYLE;				break;
465 		case XML_STROKE:			nType = XML_SD_TYPE_STROKE;					break;
466 		case XML_FONT_WEIGHT:		nType = XML_TYPE_TEXT_WEIGHT;				break;
467 		case XML_FONT_STYLE:		nType = XML_TYPE_TEXT_POSTURE;				break;
468 		case XML_TEXT_UNDERLINE:	nType = XML_TYPE_TEXT_UNDERLINE_STYLE;		break;
469 		case XML_FONT_SIZE:			nType = XML_TYPE_DOUBLE_PERCENT;			break;
470 		case XML_VISIBILITY:		nType = XML_SD_TYPE_PRESPAGE_VISIBILITY;	break;
471 
472 		default:
473 			if( rValue.getLength() )
474 				aAny <<= rValue;
475 			return aAny;
476 		}
477 
478 		const XMLPropertyHandler* pHandler = mrImport.GetShapeImport()->GetSdPropHdlFactory()->GetPropertyHandler( nType );
479 		if( pHandler )
480 			pHandler->importXML( rValue, aAny, mrImport.GetMM100UnitConverter() );
481 
482 		return aAny;
483 
484 /*
485 		if( rValue.getLength() == 0 )
486 		{
487 			Any aAny;
488 			return aAny;
489 		}
490 		else if( rValue.indexOf( '#' ) == 0 )
491 		{
492 			// color
493 			Color aColor;
494 			SvXMLUnitConverter::convertColor( aColor, rValue );
495 
496 			return makeAny( static_cast< sal_Int32 >( aColor.GetRGBColor() ) );
497 		}
498 		else if( rValue.indexOf( '$' ) != -1 )
499 		{
500 			// formula
501 			return makeAny( rValue );
502 		}
503 		else
504 		{
505 			if( isDouble( rValue ) )
506 			{
507 				return makeAny( rValue.toDouble() );
508 			}
509 			else
510 			{
511 				return makeAny( rValue );
512 			}
513 		}
514 */
515 	}
516 }
517 
518 Sequence< Any > AnimationsImportHelperImpl::convertValueSequence( XMLTokenEnum eAttributeName, const OUString& rValue )
519 {
520 	Sequence< Any > aValues;
521 
522 	// do we have any value at all?
523 	if( rValue.getLength() )
524 	{
525 		sal_Int32 nElements = count_codes( rValue, (sal_Unicode)';') + 1; // a non empty string has at least one value
526 
527 		// prepare the sequence
528 		aValues.realloc( nElements );
529 
530 		// fill the sequence
531 		Any* pValues = aValues.getArray();
532 		sal_Int32 nIndex, nElement;
533 		for( nIndex = 0, nElement = 0; nElements && (nIndex >= 0); nElements-- )
534 		{
535 			*pValues++ = convertValue( eAttributeName, rValue.getToken( 0, ';', nIndex ) );
536 		}
537 	}
538 
539 	return aValues;
540 }
541 
542 Any AnimationsImportHelperImpl::convertTiming( const OUString& rValue )
543 {
544 	Any aAny;
545 
546 	// do we have any value at all?
547 	if( rValue.getLength() )
548 	{
549 		// count the values
550 		sal_Int32 nElements = count_codes( rValue, (sal_Unicode)';' ) + 1; // a non empty string has at least one value
551 
552 		if( nElements == 1 )
553 		{
554 			if( IsXMLToken( rValue, XML_MEDIA ) )
555 			{
556 				aAny <<= Timing_MEDIA;
557 			}
558 			else if( IsXMLToken( rValue, XML_INDEFINITE ) )
559 			{
560 				aAny <<= Timing_INDEFINITE;
561 			}
562 			else if( isTime( rValue ) )
563 			{
564 				aAny <<= rValue.toDouble();
565 			}
566 			else
567 			{
568 				Event aEvent;
569 				aEvent.Repeat = 0;
570 				aEvent.Trigger = 0;
571 
572 				OUString aEventTrigger;
573 
574 				sal_Int32 nPos = rValue.indexOf( (sal_Unicode)'+' );
575 				if( nPos == -1 )
576 				{
577 					aEventTrigger = rValue;
578 				}
579 				else
580 				{
581 					aEventTrigger = rValue.copy( 0, nPos );
582 
583 					// convert offset
584 					aEvent.Offset <<= convertTiming( rValue.copy( nPos + 1 ) );
585 				}
586 
587 				nPos = aEventTrigger.indexOf( (sal_Unicode)'.' );
588 				if( nPos != -1 )
589 				{
590 					aEvent.Source <<= mrImport.getInterfaceToIdentifierMapper().getReference( aEventTrigger.copy( 0, nPos ) );
591 					aEventTrigger = aEventTrigger.copy( nPos + 1 );
592 				}
593 
594 				sal_uInt16 nEnum;
595 				if( SvXMLUnitConverter::convertEnum( nEnum, aEventTrigger, getAnimationsEnumMap(Animations_EnumMap_EventTrigger) ) )
596 				{
597 					aEvent.Trigger = (sal_Int16)nEnum;
598 				}
599 				else
600 				{
601 					DBG_ERROR("AnimationsImportHelperImpl::convertTiming(), unknown event trigger!");
602 				}
603 
604 				aAny <<= aEvent;
605 			}
606 		}
607 		else
608 		{
609 			// fill the sequence
610 			Sequence< Any > aValues( nElements );
611 			Any* pValues = aValues.getArray();
612 			sal_Int32 nIndex = 0;
613 			while( (nElements--) && (nIndex >= 0) )
614 				*pValues++ = convertTiming( rValue.getToken( 0, ';', nIndex ) );
615 
616 			aAny <<= aValues;
617 		}
618 	}
619 	return aAny;
620 }
621 
622 Sequence< double > AnimationsImportHelperImpl::convertKeyTimes( const OUString& rValue )
623 {
624 	sal_Int32 nElements = 0;
625 
626 	if( rValue.getLength() )
627 		nElements = count_codes( rValue, (sal_Unicode)';' ) + 1; // a non empty string has at least one value
628 
629 	Sequence< double > aKeyTimes( nElements );
630 
631 	if( nElements )
632 	{
633 		double* pValues = aKeyTimes.getArray();
634 		sal_Int32 nIndex = 0;
635 		while( (nElements--) && (nIndex >= 0) )
636 			*pValues++ = rValue.getToken( 0, ';', nIndex ).toDouble();
637 	}
638 
639 	return aKeyTimes;
640 }
641 
642 Sequence< TimeFilterPair > AnimationsImportHelperImpl::convertTimeFilter( const OUString& rValue )
643 {
644 	sal_Int32 nElements = 0;
645 
646 	if( rValue.getLength() )
647 		nElements = count_codes( rValue, (sal_Unicode)';' ) + 1; // a non empty string has at least one value
648 
649 	Sequence< TimeFilterPair > aTimeFilter( nElements );
650 
651 	if( nElements )
652 	{
653 		TimeFilterPair* pValues = aTimeFilter.getArray();
654 		sal_Int32 nIndex = 0;
655 		while( (nElements--) && (nIndex >= 0) )
656 		{
657 			const OUString aToken( rValue.getToken( 0, ';', nIndex ) );
658 
659 			sal_Int32 nPos = aToken.indexOf( ',' );
660 			if( nPos >= 0 )
661 			{
662 				pValues->Time = aToken.copy( 0, nPos ).toDouble();
663 				pValues->Progress = aToken.copy( nPos+1, aToken.getLength() - nPos - 1 ).toDouble();
664 			}
665 			pValues++;
666 		}
667 	}
668 
669 	return aTimeFilter;
670 }
671 
672 Any AnimationsImportHelperImpl::convertPath( const OUString& rValue )
673 {
674 	return makeAny( rValue );
675 }
676 
677 ///////////////////////////////////////////////////////////////////////
678 
679 TYPEINIT1( AnimationNodeContext, SvXMLImportContext );
680 
681 AnimationNodeContext::AnimationNodeContext(
682 		const Reference< XAnimationNode >& xParentNode,
683 		SvXMLImport& rImport, sal_uInt16 nPrfx,	const rtl::OUString& rLocalName,
684 		const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList,
685 		AnimationsImportHelperImpl* pHelper /* = NULL */ )
686 :	SvXMLImportContext(rImport, nPrfx, rLocalName),
687 	mpHelper( pHelper ),
688 	mbRootContext( pHelper == NULL )
689 {
690 	try
691 	{
692 		if( mbRootContext )
693 		{
694 			mpHelper = new AnimationsImportHelperImpl( rImport );
695 			mxNode = xParentNode;
696 		}
697 		else
698 		{
699 			Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
700 
701 			sal_Int16 nPresetClass = EffectPresetClass::CUSTOM;
702 
703 			const sal_Char* pServiceName = 0;
704 
705 			sal_Int16 nNodeType = (sal_Int16)mpHelper->getAnimationNodeTokenMap().Get( nPrfx, rLocalName );
706 			switch( nNodeType )
707 			{
708 			case AnimationNodeType::SEQ:				pServiceName = "com.sun.star.animations.SequenceTimeContainer"; break;
709 			case AnimationNodeType::ITERATE:			pServiceName = "com.sun.star.animations.IterateContainer"; break;
710 			case AnimationNodeType::ANIMATE:			pServiceName = "com.sun.star.animations.Animate"; break;
711 			case AnimationNodeType::SET:				pServiceName = "com.sun.star.animations.AnimateSet"; break;
712 			case AnimationNodeType::ANIMATEMOTION:		pServiceName = "com.sun.star.animations.AnimateMotion"; break;
713 			case AnimationNodeType::ANIMATECOLOR:		pServiceName = "com.sun.star.animations.AnimateColor"; break;
714 			case AnimationNodeType::ANIMATETRANSFORM:	pServiceName = "com.sun.star.animations.AnimateTransform"; break;
715 			case AnimationNodeType::TRANSITIONFILTER:	pServiceName = "com.sun.star.animations.TransitionFilter"; break;
716 			case AnimationNodeType::AUDIO:				pServiceName = "com.sun.star.animations.Audio"; break;
717 			case AnimationNodeType::COMMAND:			pServiceName = "com.sun.star.animations.Command"; break;
718 			case AnimationNodeType::PAR:
719 				{
720 					const sal_Int16 nCount = xAttrList.is() ? xAttrList->getLength() : 0;
721 					sal_Int16 nAttribute;
722 					for( nAttribute = 0; nAttribute < nCount; nAttribute++ )
723 					{
724 						OUString aLocalName;
725 						sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( xAttrList->getNameByIndex( nAttribute ), &aLocalName );
726 						if( (nPrefix == XML_NAMESPACE_PRESENTATION) && IsXMLToken( aLocalName, XML_PRESET_ID ) )
727 						{
728 							const OUString& rValue = xAttrList->getValueByIndex( nAttribute );
729 							if( rValue.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ooo-entrance-random" ) ) )
730 							{
731 								nPresetClass = EffectPresetClass::ENTRANCE;
732 							}
733 							else if( rValue.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ooo-exit-random" ) ) )
734 							{
735 								nPresetClass = EffectPresetClass::EXIT;
736 							}
737 
738 							if( nPresetClass != EffectPresetClass::CUSTOM )
739 							{
740 								pServiceName = "com.sun.star.comp.sd.RandomAnimationNode";
741 								break;
742 							}
743 						}
744 					}
745 					if( !pServiceName )
746 						pServiceName = "com.sun.star.animations.ParallelTimeContainer";
747 				}
748 				break;
749 			default:
750 				pServiceName = 0;
751 			}
752 
753 			if( pServiceName && xFactory.is() )
754 			{
755 				mxNode = Reference< XAnimationNode >( xFactory->createInstance(
756 					OUString::createFromAscii(pServiceName) ), UNO_QUERY_THROW );
757 
758 				if( nPresetClass != EffectPresetClass::CUSTOM )
759 				{
760 					Reference< XInitialization > xInit( mxNode, UNO_QUERY_THROW );
761 					const Any aAny( makeAny( nPresetClass ) );
762 					Sequence< Any > aArgs( &aAny, 1 ) ;
763 					xInit->initialize( aArgs );
764 				}
765 
766 				init_node( xAttrList );
767 
768 				Reference< XTimeContainer > xParentContainer( xParentNode, UNO_QUERY_THROW );
769 				xParentContainer->appendChild( mxNode );
770 			}
771 		}
772 	}
773 	catch( RuntimeException& )
774 	{
775 		DBG_ERROR( "xmloff::AnimationsImportImpl::AnimationsImportImpl(), RuntimeException catched!" );
776 	}
777 }
778 
779 AnimationNodeContext::~AnimationNodeContext()
780 {
781 	if( mbRootContext )
782 		delete mpHelper;
783 }
784 
785 void AnimationNodeContext::StartElement( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& )
786 {
787 	// code of StartElement is moved to init_node that is now called
788 	// in c'tor before appending this node to its parent.
789 	// This is needed for random nodes that need the correct target
790 	// set when child nodes are appended.
791 }
792 
793 void AnimationNodeContext::init_node(  const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList )
794 {
795 	if( mxNode.is() ) try
796 	{
797 		const sal_Int16 nNodeType = mxNode->getType();
798 
799 		// query for optional interfaces that are often used later
800 		Reference< XAnimate > xAnimate( mxNode, UNO_QUERY );
801 		Reference< XCommand > xCommand( mxNode, UNO_QUERY );
802 		Reference< XTransitionFilter > xTransitionFilter( mxNode, UNO_QUERY );
803 		Reference< XIterateContainer > xIter( mxNode, UNO_QUERY );
804 
805 		std::list< NamedValue > aUserData;
806 		XMLTokenEnum meAttributeName = XML_TOKEN_INVALID;
807 		OUString aFrom, aBy, aTo, aValues;
808         bool bHaveXmlId( false );
809         OUString sXmlId;
810 
811 		const sal_Int16 nCount = xAttrList.is() ? xAttrList->getLength() : 0;
812 		sal_uInt16 nEnum;
813 		sal_Int16 nAttribute;
814 		for( nAttribute = 0; nAttribute < nCount; nAttribute++ )
815 		{
816 			const OUString& rAttrName = xAttrList->getNameByIndex( nAttribute );
817 			const OUString& rValue = xAttrList->getValueByIndex( nAttribute );
818 
819 			OUString aLocalName;
820 			sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName );
821 			switch( mpHelper->getAnimationNodeAttributeTokenMap().Get( nPrefix, aLocalName ) )
822 			{
823 			case ANA_Begin:
824 			{
825 				mxNode->setBegin( mpHelper->convertTiming( rValue ) );
826 			}
827 			break;
828 			case ANA_Dur:
829 			{
830 				mxNode->setDuration( mpHelper->convertTiming( rValue ) );
831 			}
832 			break;
833 			case ANA_End:
834 			{
835 				mxNode->setEnd( mpHelper->convertTiming( rValue ) );
836 			}
837 			break;
838 			case ANA_Fill:
839 			{
840 				if( SvXMLUnitConverter::convertEnum( nEnum, rValue, getAnimationsEnumMap(Animations_EnumMap_Fill) ) )
841 					mxNode->setFill( (sal_Int16)nEnum );
842 			}
843 			break;
844 			case ANA_FillDefault:
845 			{
846 				if( SvXMLUnitConverter::convertEnum( nEnum, rValue, getAnimationsEnumMap(Animations_EnumMap_FillDefault) ) )
847 					mxNode->setFillDefault( (sal_Int16)nEnum );
848 			}
849 			break;
850 			case ANA_Restart:
851 			{
852 				if( SvXMLUnitConverter::convertEnum( nEnum, rValue, getAnimationsEnumMap(Animations_EnumMap_Restart) ) )
853 					mxNode->setRestart( (sal_Int16)nEnum );
854 			}
855 			break;
856 			case ANA_RestartDefault:
857 			{
858 				if( SvXMLUnitConverter::convertEnum( nEnum, rValue, getAnimationsEnumMap(Animations_EnumMap_RestartDefault) ) )
859 					mxNode->setRestartDefault( (sal_Int16)nEnum );
860 			}
861 			break;
862 			case ANA_Accelerate:
863 			{
864 				if( isDouble( rValue ) )
865 					mxNode->setAcceleration( rValue.toDouble() );
866 			}
867 			break;
868 			case ANA_Decelerate:
869 			{
870 				if( isDouble( rValue ) )
871 					mxNode->setDecelerate( rValue.toDouble() );
872 			}
873 			break;
874 			case ANA_AutoReverse:
875 			{
876 				sal_Bool bTemp;
877 				if( SvXMLUnitConverter::convertBool( bTemp, rValue ) )
878 					mxNode->setAutoReverse( bTemp  );
879 			}
880 			break;
881 			case ANA_RepeatCount:
882 			{
883 				mxNode->setRepeatCount( mpHelper->convertTiming( rValue ) );
884 			}
885 			break;
886 			case ANA_RepeatDur:
887 			{
888 				mxNode->setRepeatDuration( mpHelper->convertTiming( rValue ) );
889 			}
890 			break;
891 			case ANA_EndSync:
892 			{
893 				if( SvXMLUnitConverter::convertEnum( nEnum, rValue, getAnimationsEnumMap(Animations_EnumMap_Endsync) ) )
894 					mxNode->setEndSync( makeAny( (sal_Int16)nEnum ) );
895 			}
896 			break;
897 			case ANA_Node_Type:
898 			{
899 				if( SvXMLUnitConverter::convertEnum( nEnum, rValue, getAnimationsEnumMap(Animations_EnumMap_EffectNodeType) ) )
900 					aUserData.push_back( NamedValue( GetXMLToken( XML_NODE_TYPE ), makeAny( (sal_Int16)nEnum ) ) );
901 			}
902 			break;
903 			case ANA_Preset_ID:
904 			{
905 				aUserData.push_back( NamedValue( GetXMLToken( XML_PRESET_ID ), makeAny( rValue ) ) );
906 			}
907 			break;
908 			case ANA_Preset_Sub_Type:
909 			{
910 				aUserData.push_back( NamedValue( GetXMLToken( XML_PRESET_SUB_TYPE ), makeAny( rValue ) ) );
911 			}
912 			break;
913 			case ANA_Preset_Class:
914 			{
915 				if( SvXMLUnitConverter::convertEnum( nEnum, rValue, getAnimationsEnumMap(Animations_EnumMap_EffectPresetClass) ) )
916 					aUserData.push_back( NamedValue( GetXMLToken( XML_PRESET_CLASS ), makeAny( (sal_Int16)nEnum ) ) );
917 			}
918 			break;
919 			case ANA_After_Effect:
920 			{
921 				sal_Bool bTemp;
922 				if( SvXMLUnitConverter::convertBool( bTemp, rValue ) )
923 					aUserData.push_back( NamedValue( GetXMLToken( XML_AFTER_EFFECT ), makeAny( bTemp ) ) );
924 			}
925 			break;
926 			case ANA_XLink:
927 			{
928 				if( nNodeType == AnimationNodeType::AUDIO )
929 				{
930 					Reference< XAudio > xAudio( mxNode, UNO_QUERY_THROW );
931 					xAudio->setSource( makeAny( GetImport().GetAbsoluteReference( rValue ) ) );
932 					break;
933 				}
934 
935 			}
936 			// fall through intented!
937 			case ANA_Target:
938 			{
939 				{
940 					Any aTarget( mpHelper->convertTarget( rValue ) );
941 
942 					if( xAnimate.is() )
943 					{
944 						xAnimate->setTarget( aTarget );
945 					}
946 					else if( xIter.is() )
947 					{
948 						xIter->setTarget( aTarget );
949 					}
950                     else if( xCommand.is() )
951 					{
952 						xCommand->setTarget( aTarget );
953 					}
954 				}
955 			}
956 			break;
957 
958 			case ANA_Volume:
959 			{
960 				if( nNodeType == AnimationNodeType::AUDIO )
961 				{
962 					if( isDouble( rValue ) )
963 					{
964 						Reference< XAudio > xAudio( mxNode, UNO_QUERY_THROW );
965 						xAudio->setVolume( rValue.toDouble() );
966 					}
967 				}
968 			}
969 			break;
970 
971 			case ANA_MasterElement:
972 			{
973 				Reference< XAnimationNode > xMaster( GetImport().getInterfaceToIdentifierMapper().getReference( rValue ), UNO_QUERY );
974 				aUserData.push_back( NamedValue( GetXMLToken( XML_MASTER_ELEMENT ), makeAny( xMaster ) ) );
975 			}
976 			break;
977 
978 			case ANA_SubItem:
979 			{
980 				if( SvXMLUnitConverter::convertEnum( nEnum, rValue, getAnimationsEnumMap(Animations_EnumMap_SubItem) ) )
981 				{
982 					if( xAnimate.is() )
983 					{
984 						xAnimate->setSubItem( (sal_Int16)nEnum );
985 					}
986 					else if( xIter.is() )
987 					{
988 						xIter->setSubItem( (sal_Int16)nEnum );
989 					}
990 				}
991 			}
992 			break;
993 
994 			case ANA_AttributeName:
995 			{
996 				if( xAnimate.is() )
997 				{
998 					OUString aName( rValue );
999 
1000 					ImplAttributeNameConversion* p = getAnimationAttributeNamesConversionList();
1001 					while( p->mpAPIName )
1002 					{
1003 						if( IsXMLToken( aName, p->meXMLToken ) )
1004 						{
1005 							aName = OUString::createFromAscii( p->mpAPIName );
1006 							meAttributeName = p->meXMLToken;
1007 							break;
1008 						}
1009 
1010 						p++;
1011 					}
1012 
1013 					xAnimate->setAttributeName( aName );
1014 				}
1015 			}
1016 			break;
1017 
1018 			case ANA_Values:
1019 			{
1020 				aValues = rValue;
1021 			}
1022 			break;
1023 
1024 			case ANA_From:
1025 			{
1026 				aFrom = rValue;
1027 			}
1028 			break;
1029 
1030 			case ANA_By:
1031 			{
1032 				aBy = rValue;
1033 			}
1034 			break;
1035 
1036 			case ANA_To:
1037 			{
1038 				aTo = rValue;
1039 			}
1040 			break;
1041 
1042 			case ANA_KeyTimes:
1043 			{
1044 				if( xAnimate.is() )
1045 					xAnimate->setKeyTimes( mpHelper->convertKeyTimes( rValue ) );
1046 			}
1047 			break;
1048 
1049 			case ANA_Formula:
1050 			{
1051 				if( xAnimate.is() )
1052 					xAnimate->setFormula( rValue );
1053 			}
1054 			break;
1055 
1056             case ANA_ANIMID:
1057             {
1058                 if (!bHaveXmlId) { sXmlId = rValue; }
1059             }
1060             break;
1061             case ANA_XMLID:
1062             {
1063                 sXmlId = rValue;
1064                 bHaveXmlId = true;
1065             }
1066             break;
1067 
1068 			case ANA_CalcMode:
1069 			{
1070 				if( xAnimate.is() )
1071 				{
1072 					if( SvXMLUnitConverter::convertEnum( nEnum, rValue, getAnimationsEnumMap(Animations_EnumMap_CalcMode) ) )
1073 						xAnimate->setCalcMode( (sal_Int16)nEnum );
1074 				}
1075 			}
1076 			break;
1077 
1078 			case ANA_Accumulate:
1079 			{
1080 				if( xAnimate.is() )
1081 					xAnimate->setAccumulate( IsXMLToken( rValue, XML_SUM ) );
1082 			}
1083 			break;
1084 
1085 			case ANA_AdditiveMode:
1086 			{
1087 				if( xAnimate.is() )
1088 				{
1089 					if( SvXMLUnitConverter::convertEnum( nEnum, rValue, getAnimationsEnumMap(Animations_EnumMap_AdditiveMode) ) )
1090 						xAnimate->setAdditive( (sal_Int16)nEnum );
1091 				}
1092 			}
1093 			break;
1094 
1095 			case ANA_KeySplines:
1096 			{
1097 				if( xAnimate.is() )
1098 					xAnimate->setTimeFilter( mpHelper->convertTimeFilter( rValue ) );
1099 			}
1100 			break;
1101 
1102 			case ANA_Path:
1103 			{
1104 				Reference< XAnimateMotion > xAnimateMotion( mxNode, UNO_QUERY );
1105 				if( xAnimateMotion.is() )
1106 					xAnimateMotion->setPath( mpHelper->convertPath( rValue ) );
1107 			}
1108 			break;
1109 
1110 			case ANA_ColorSpace:
1111 			{
1112 				Reference< XAnimateColor > xAnimateColor( mxNode, UNO_QUERY );
1113 				if( xAnimateColor.is() )
1114 					xAnimateColor->setColorInterpolation( IsXMLToken( rValue, XML_HSL ) ? AnimationColorSpace::HSL : AnimationColorSpace::RGB );
1115 			}
1116 			break;
1117 
1118 			case ANA_ColorDirection:
1119 			{
1120 				Reference< XAnimateColor > xAnimateColor( mxNode, UNO_QUERY );
1121 				if( xAnimateColor.is() )
1122 					xAnimateColor->setDirection( IsXMLToken( rValue, XML_CLOCKWISE ) );
1123 			}
1124 			break;
1125 
1126 			case ANA_TransformType:
1127 			{
1128 				Reference< XAnimateTransform > xTransform( mxNode, UNO_QUERY );
1129 				if( xTransform.is() )
1130 				{
1131 					if( SvXMLUnitConverter::convertEnum( nEnum, rValue, getAnimationsEnumMap(Animations_EnumMap_TransformType) ) )
1132 					{
1133 						xTransform->setTransformType( (sal_Int16)nEnum );
1134 						switch( nEnum )
1135 						{
1136 						case AnimationTransformType::SCALE: meAttributeName = XML_SCALE; break;
1137 						case AnimationTransformType::ROTATE: meAttributeName = XML_ROTATE; break;
1138 						case AnimationTransformType::SKEWX: meAttributeName = XML_SKEWX; break;
1139 						case AnimationTransformType::SKEWY: meAttributeName = XML_SKEWY; break;
1140 						//case AnimationTransformType::TRANSLATE:
1141 						default:
1142 							meAttributeName = XML_TRANSLATE; break;
1143 						}
1144 					}
1145 				}
1146 			}
1147 			break;
1148 
1149 			case ANA_TransitionType:
1150 			{
1151 				if( xTransitionFilter.is() )
1152 				{
1153 					if( SvXMLUnitConverter::convertEnum( nEnum, rValue, getAnimationsEnumMap(Animations_EnumMap_TransitionType) ) )
1154 						xTransitionFilter->setTransition( (sal_Int16)nEnum );
1155 				}
1156 			}
1157 			break;
1158 
1159 			case ANA_TransitionSubType:
1160 			{
1161 				if( xTransitionFilter.is() )
1162 				{
1163 					if( SvXMLUnitConverter::convertEnum( nEnum, rValue, getAnimationsEnumMap(Animations_EnumMap_TransitionSubType) ) )
1164 						xTransitionFilter->setSubtype( (sal_Int16)nEnum );
1165 				}
1166 			}
1167 			break;
1168 
1169 			case ANA_Mode:
1170 			{
1171 				if( xTransitionFilter.is() )
1172 					xTransitionFilter->setMode( IsXMLToken( rValue, XML_IN ) );
1173 			}
1174 			break;
1175 
1176 			case ANA_Direction:
1177 			{
1178 				if( xTransitionFilter.is() )
1179 					xTransitionFilter->setDirection( IsXMLToken( rValue, XML_FORWARD ) );
1180 			}
1181 			break;
1182 
1183 			case ANA_FadeColor:
1184 			{
1185 				if( xTransitionFilter.is() )
1186 				{
1187 					Color aColor;
1188 					SvXMLUnitConverter::convertColor( aColor, rValue );
1189 					xTransitionFilter->setFadeColor( static_cast< sal_Int32 >( aColor.GetRGBColor() ) );
1190 				}
1191 			}
1192 			break;
1193 
1194 			case ANA_IterateType:
1195 			{
1196 				if( SvXMLUnitConverter::convertEnum( nEnum, rValue, getAnimationsEnumMap(Animations_EnumMap_IterateType) ) )
1197 				{
1198 					if( xIter.is() )
1199 						xIter->setIterateType( (sal_Int16)nEnum );
1200 				}
1201 			}
1202 			break;
1203 
1204 			case ANA_IterateInterval:
1205 			{
1206 				if( xIter.is() )
1207 				{
1208 					double fInterval = 0.0;
1209 					if( rValue.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("P")) )
1210 					{
1211 						::Time aTime;
1212 						sal_Int32 nSecondsFraction = 0;
1213 						if( SvXMLUnitConverter::convertTimeDuration( rValue, aTime, &nSecondsFraction ) )
1214 						{
1215 							fInterval = ((((aTime.GetHour() * 60) + aTime.GetMin()) * 60) + aTime.GetSec()) + (nSecondsFraction / 1000.0);
1216 						}
1217 					}
1218 					else
1219 					{
1220 						fInterval = rValue.toDouble();
1221 					}
1222 
1223 					xIter->setIterateInterval( fInterval );
1224 				}
1225 			}
1226 			break;
1227 
1228 			case ANA_Group_Id:
1229 			{
1230 				aUserData.push_back( NamedValue( aLocalName, makeAny( rValue.toInt32() ) ) );
1231 			}
1232 			break;
1233 
1234 			case ANA_Command:
1235 			{
1236 				if( xCommand.is() && nNodeType == AnimationNodeType::COMMAND )
1237 				{
1238 					if( SvXMLUnitConverter::convertEnum( nEnum, rValue, getAnimationsEnumMap(Animations_EnumMap_Command) ) )
1239 					{
1240 						xCommand->setCommand( (sal_Int16)nEnum );
1241 					}
1242 				}
1243 			}
1244 			break;
1245 
1246 			default:
1247 				// push all unknown attributes within the presentation namespace as user data
1248 				if( nPrefix == XML_NAMESPACE_PRESENTATION )
1249 				{
1250 					aUserData.push_back( NamedValue( aLocalName, makeAny( rValue ) ) );
1251 				}
1252 			}
1253 		}
1254 
1255         if (sXmlId.getLength())
1256         {
1257             Reference< XInterface > const xRef( mxNode, UNO_QUERY );
1258             GetImport().getInterfaceToIdentifierMapper().registerReference(
1259                 sXmlId, xRef );
1260         }
1261 
1262 		sal_Int32 nUserDataCount = aUserData.size();
1263 		if( nUserDataCount )
1264 		{
1265 			Sequence< NamedValue > aUnoUserData( nUserDataCount );
1266 			NamedValue* pData = aUnoUserData.getArray();
1267 			std::list< NamedValue >::iterator aIter( aUserData.begin() );
1268 			const std::list< NamedValue >::iterator aEnd( aUserData.end() );
1269 			while( aIter != aEnd )
1270 				*pData++ = (*aIter++);
1271 
1272 			mxNode->setUserData( aUnoUserData );
1273 		}
1274 
1275 		// convert values
1276 		if( xAnimate.is() )
1277 		{
1278 			if( aFrom.getLength() )
1279 				xAnimate->setFrom( mpHelper->convertValue( meAttributeName, aFrom ) );
1280 
1281 			if( aBy.getLength() )
1282 				xAnimate->setBy( mpHelper->convertValue( meAttributeName, aBy ) );
1283 
1284 			if( aTo.getLength() )
1285 				xAnimate->setTo( mpHelper->convertValue( meAttributeName, aTo ) );
1286 
1287 			if( aValues.getLength() )
1288 				xAnimate->setValues( mpHelper->convertValueSequence( meAttributeName, aValues ) );
1289 		}
1290 	}
1291 	catch( RuntimeException& )
1292 	{
1293 		DBG_ERROR( "xmloff::AnimationNodeContext::StartElement(), RuntimeException catched!" );
1294 	}
1295 }
1296 
1297 SvXMLImportContext * AnimationNodeContext::CreateChildContext( sal_uInt16 nPrefix, const ::rtl::OUString& rLocalName,
1298 		const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList )
1299 {
1300 	if( mxNode.is())
1301 		return new AnimationNodeContext( mxNode, GetImport(), nPrefix, rLocalName, xAttrList, mpHelper );
1302 	else
1303 		return new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
1304 }
1305 
1306 // --------------------------------------------------------------------
1307 
1308 class AnimationsImport: public SvXMLImport, public XAnimationNodeSupplier
1309 {
1310 public:
1311 	AnimationsImport( const Reference< XMultiServiceFactory > & rSMgr );
1312 	~AnimationsImport() throw ();
1313 
1314 	SvXMLImportContext* CreateContext(sal_uInt16 nPrefix, const OUString& rLocalName,	const Reference<XAttributeList>& xAttrList);
1315 
1316 	// XInterface
1317     virtual Any SAL_CALL queryInterface( const Type& aType ) throw (RuntimeException);
1318     virtual void SAL_CALL acquire() throw ();
1319     virtual void SAL_CALL release() throw ();
1320 
1321 	// XAnimationNodeSupplier
1322 	Reference< XAnimationNode > SAL_CALL getAnimationNode() throw (RuntimeException);
1323 
1324 	// XServiceInfo
1325     virtual OUString SAL_CALL getImplementationName() throw(RuntimeException);
1326     virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException);
1327     virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(RuntimeException);
1328 
1329 private:
1330 	Reference< XAnimationNode > mxRootNode;
1331 };
1332 
1333 AnimationsImport::AnimationsImport( const Reference< XMultiServiceFactory > & rSMgr )
1334 : SvXMLImport( rSMgr, true )
1335 {
1336 	// add namespaces
1337 	GetNamespaceMap().Add(
1338 		GetXMLToken(XML_NP_PRESENTATION),
1339         GetXMLToken(XML_N_PRESENTATION),
1340 		XML_NAMESPACE_PRESENTATION);
1341 
1342 	GetNamespaceMap().Add(
1343 		GetXMLToken(XML_NP_SMIL),
1344         GetXMLToken(XML_N_SMIL),
1345 		XML_NAMESPACE_SMIL);
1346 
1347 	GetNamespaceMap().Add(
1348 		GetXMLToken(XML_NP_ANIMATION),
1349         GetXMLToken(XML_N_ANIMATION),
1350 		XML_NAMESPACE_ANIMATION);
1351 
1352 	mxRootNode = Reference< XAnimationNode >::query(rSMgr->createInstance(
1353 		OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.SequenceTimeContainer"))));
1354 }
1355 
1356 AnimationsImport::~AnimationsImport() throw ()
1357 {
1358 }
1359 
1360 // XInterface
1361 Any SAL_CALL AnimationsImport::queryInterface( const Type& aType ) throw (RuntimeException)
1362 {
1363     if ( aType == ::getCppuType((Reference<XAnimationNodeSupplier> *)0) )
1364     {
1365         return makeAny( Reference<XAnimationNodeSupplier>( this ) );
1366     }
1367 	else
1368 	{
1369 		return SvXMLImport::queryInterface( aType );
1370 	}
1371 }
1372 
1373 void SAL_CALL AnimationsImport::acquire() throw ()
1374 {
1375 	SvXMLImport::acquire();
1376 }
1377 
1378 void SAL_CALL AnimationsImport::release() throw ()
1379 {
1380 	SvXMLImport::release();
1381 }
1382 
1383 SvXMLImportContext *AnimationsImport::CreateContext(sal_uInt16 nPrefix, const OUString& rLocalName,	const Reference<XAttributeList>& xAttrList)
1384 {
1385 	SvXMLImportContext* pContext = 0;
1386 
1387 	if( (XML_NAMESPACE_ANIMATION == nPrefix) && IsXMLToken( rLocalName, XML_SEQ ) )
1388 	{
1389 		 pContext = new AnimationNodeContext( mxRootNode, *this, nPrefix, rLocalName, xAttrList );
1390 	}
1391 	else
1392 	{
1393 		pContext = SvXMLImport::CreateContext(nPrefix, rLocalName, xAttrList);
1394 	}
1395 
1396 	return pContext;
1397 }
1398 
1399 // XAnimationNodeSupplier
1400 Reference< XAnimationNode > SAL_CALL AnimationsImport::getAnimationNode() throw (RuntimeException)
1401 {
1402 	return mxRootNode;
1403 }
1404 
1405 void AnimationNodeContext::postProcessRootNode( SvXMLImport& /*rImport*/, const Reference< XAnimationNode >& xRootNode, Reference< XPropertySet >& xPageProps )
1406 {
1407 	if( xRootNode.is() && xPageProps.is() ) try
1408 	{
1409 		Reference< XEnumerationAccess > xEnumerationAccess( xRootNode, UNO_QUERY_THROW );
1410 		Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
1411 		if( xEnumeration->hasMoreElements() )
1412 		{
1413 			Reference< XAnimationNode > xNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
1414 			if( xNode->getType() == AnimationNodeType::PAR )
1415 			{
1416 				Event aEvent;
1417 				if( (xNode->getBegin() >>= aEvent) && (aEvent.Trigger == EventTrigger::BEGIN_EVENT) )
1418 				{
1419 					// found transition node
1420 					Reference< XEnumerationAccess > xChildEnumerationAccess( xNode, UNO_QUERY_THROW );
1421 					Reference< XEnumeration > xChildEnumeration( xChildEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
1422 					while( xChildEnumeration->hasMoreElements() )
1423 					{
1424 						Reference< XAnimationNode > xChildNode( xChildEnumeration->nextElement(), UNO_QUERY_THROW );
1425 						switch( xChildNode->getType() )
1426 						{
1427 						case AnimationNodeType::TRANSITIONFILTER:
1428 						{
1429 							Reference< XTransitionFilter > xTransFilter( xChildNode, UNO_QUERY_THROW );
1430 
1431 
1432 							xPageProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "TransitionType" ) ), Any( xTransFilter->getTransition() ) );
1433 							xPageProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "TransitionSubtype" ) ), Any( xTransFilter->getSubtype() ) );
1434 							xPageProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "TransitionDirection" ) ), Any( xTransFilter->getDirection() ) );
1435 							xPageProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "TransitionFadeColor" ) ), Any( xTransFilter->getFadeColor() ) );
1436 
1437 							double fDuration;
1438 							if( xTransFilter->getDuration() >>= fDuration )
1439 								xPageProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "TransitionDuration" ) ), Any( fDuration ) );
1440 
1441 						}
1442 						break;
1443 
1444 						case AnimationNodeType::COMMAND:
1445 						{
1446 							Reference< XCommand > xCommand( xChildNode, UNO_QUERY_THROW );
1447 							if( xCommand->getCommand() == EffectCommands::STOPAUDIO )
1448 							{
1449 								xPageProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Sound" ) ), Any(sal_True) );
1450 							}
1451 						}
1452 						break;
1453 
1454 						case AnimationNodeType::AUDIO:
1455 						{
1456 							Reference< XAudio > xAudio( xChildNode, UNO_QUERY_THROW );
1457 							OUString sSoundURL;
1458 							if( (xAudio->getSource() >>= sSoundURL) && (sSoundURL.getLength() != 0) )
1459 							{
1460 								xPageProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Sound" ) ), Any(sSoundURL) );
1461 
1462 								Timing eTiming;
1463 								if( (xAudio->getRepeatCount() >>= eTiming) && (eTiming == Timing_INDEFINITE) )
1464 									xPageProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "LoopSound" ) ), Any( sal_True ) );
1465 							}
1466 						}
1467 						break;
1468 
1469 						}
1470 					}
1471 
1472 					Reference< XTimeContainer > xRootContainer( xRootNode, UNO_QUERY_THROW );
1473 					xRootContainer->removeChild( xNode );
1474 				}
1475 			}
1476 		}
1477 	}
1478 	catch( Exception& )
1479 	{
1480 		DBG_ERROR("xmloff::AnimationsImport::postProcessRootNode(), exception caught!");
1481 	}
1482 }
1483 
1484 } // namespace xmloff
1485 
1486 Sequence< OUString > SAL_CALL AnimationsImport_getSupportedServiceNames() throw()
1487 {
1488 	const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Xmloff.AnimationsImport" ) );
1489 	const Sequence< OUString > aSeq( &aServiceName, 1 );
1490 	return aSeq;
1491 }
1492 
1493 OUString SAL_CALL AnimationsImport_getImplementationName() throw()
1494 {
1495 	return OUString( RTL_CONSTASCII_USTRINGPARAM( "xmloff::AnimationsImport" ) );
1496 }
1497 
1498 Reference< XInterface > SAL_CALL AnimationsImport_createInstance(const Reference< XMultiServiceFactory > & rSMgr) throw( Exception )
1499 {
1500 	return (cppu::OWeakObject*)new xmloff::AnimationsImport( rSMgr );
1501 
1502 }
1503 
1504 namespace xmloff
1505 {
1506 
1507 OUString SAL_CALL AnimationsImport::getImplementationName() throw(RuntimeException)
1508 {
1509 	return AnimationsImport_getImplementationName();
1510 }
1511 
1512 sal_Bool SAL_CALL AnimationsImport::supportsService( const OUString& ServiceName ) throw(RuntimeException)
1513 {
1514 	return ServiceName.equalsAscii( "com.sun.star.comp.Xmloff.AnimationsImport" );
1515 }
1516 
1517 Sequence< OUString > SAL_CALL AnimationsImport::getSupportedServiceNames() throw(RuntimeException)
1518 {
1519 	return AnimationsImport_getSupportedServiceNames();
1520 }
1521 
1522 } // namespace xmloff
1523 
1524