xref: /trunk/main/xmloff/source/draw/animationimport.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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