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_slideshow.hxx"
30 
31 // must be first
32 #include <canvas/debug.hxx>
33 #include <tools/diagnose_ex.h>
34 #include <canvas/verbosetrace.hxx>
35 
36 #include <animationfactory.hxx>
37 #include <attributemap.hxx>
38 
39 #include <com/sun/star/animations/AnimationAdditiveMode.hpp>
40 #include <com/sun/star/animations/AnimationTransformType.hpp>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <com/sun/star/drawing/FillStyle.hpp>
43 #include <com/sun/star/drawing/LineStyle.hpp>
44 #include <com/sun/star/awt/FontSlant.hpp>
45 #include <com/sun/star/awt/FontUnderline.hpp>
46 #include <com/sun/star/awt/FontWeight.hpp>
47 
48 #include <basegfx/polygon/b2dpolygon.hxx>
49 #include <basegfx/polygon/b2dpolygontools.hxx>
50 #include <basegfx/polygon/b2dpolypolygontools.hxx>
51 
52 #include <functional>
53 
54 
55 using namespace ::com::sun::star;
56 
57 
58 namespace slideshow
59 {
60     namespace internal
61     {
62         namespace
63         {
64             // attention, there is a similar implementation of Animation in
65             // transitions/transitionfactory.cxx
66 
67             template< typename ValueT > class TupleAnimation : public PairAnimation
68             {
69             public:
70                 TupleAnimation( const ShapeManagerSharedPtr&		rShapeManager,
71                                 int									nFlags,
72                                 bool      	 (ShapeAttributeLayer::*pIs1stValid)() const,
73                                 bool      	 (ShapeAttributeLayer::*pIs2ndValid)() const,
74                                 const ValueT&						rDefaultValue,
75                                 const ::basegfx::B2DSize&			rReferenceSize,
76                                 double 	 	 (ShapeAttributeLayer::*pGet1stValue)() const,
77                                 double 	 	 (ShapeAttributeLayer::*pGet2ndValue)() const,
78                                 void      	 (ShapeAttributeLayer::*pSetValue)( const ValueT& ) ) :
79                     mpShape(),
80                     mpAttrLayer(),
81                     mpShapeManager( rShapeManager ),
82                     mpIs1stValidFunc(pIs1stValid),
83                     mpIs2ndValidFunc(pIs2ndValid),
84                     mpGet1stValueFunc(pGet1stValue),
85                     mpGet2ndValueFunc(pGet2ndValue),
86                     mpSetValueFunc(pSetValue),
87                     mnFlags( nFlags ),
88                     maReferenceSize( rReferenceSize ),
89                     maDefaultValue( rDefaultValue ),
90                     mbAnimationStarted( false )
91                 {
92                     ENSURE_OR_THROW( rShapeManager,
93                                       "TupleAnimation::TupleAnimation(): Invalid ShapeManager" );
94                     ENSURE_OR_THROW( pIs1stValid && pIs2ndValid && pGet1stValue && pGet2ndValue && pSetValue,
95                                       "TupleAnimation::TupleAnimation(): One of the method pointers is NULL" );
96                 }
97 
98                 ~TupleAnimation()
99                 {
100                     end_();
101                 }
102 
103                 // Animation interface
104                 // -------------------
105                 virtual void prefetch( const AnimatableShapeSharedPtr&,
106                                        const ShapeAttributeLayerSharedPtr& )
107                 {}
108 
109                 virtual void start( const AnimatableShapeSharedPtr& 	rShape,
110                                     const ShapeAttributeLayerSharedPtr& rAttrLayer )
111                 {
112                     OSL_ENSURE( !mpShape,
113                                 "TupleAnimation::start(): Shape already set" );
114                     OSL_ENSURE( !mpAttrLayer,
115                                 "TupleAnimation::start(): Attribute layer already set" );
116 
117                     mpShape = rShape;
118                     mpAttrLayer = rAttrLayer;
119 
120                     ENSURE_OR_THROW( rShape,
121                                       "TupleAnimation::start(): Invalid shape" );
122                     ENSURE_OR_THROW( rAttrLayer,
123                                       "TupleAnimation::start(): Invalid attribute layer" );
124 
125                     if( !mbAnimationStarted )
126                     {
127                         mbAnimationStarted = true;
128 
129                         if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
130                             mpShapeManager->enterAnimationMode( mpShape );
131                     }
132                 }
133 
134                 virtual void end() { end_(); }
135                 void end_()
136                 {
137                     if( mbAnimationStarted )
138                     {
139                         mbAnimationStarted = false;
140 
141                         if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
142                             mpShapeManager->leaveAnimationMode( mpShape );
143 
144                         if( mpShape->isContentChanged() )
145                             mpShapeManager->notifyShapeUpdate( mpShape );
146                     }
147                 }
148 
149                 // PairAnimation interface
150                 // -----------------------
151 
152                 virtual bool operator()( const ::basegfx::B2DTuple& rValue )
153                 {
154                     ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
155                                        "TupleAnimation::operator(): Invalid ShapeAttributeLayer" );
156 
157                     ValueT aValue( rValue.getX(),
158                                    rValue.getY() );
159 
160                     // Activitis get values from the expression parser,
161                     // which returns _relative_ sizes/positions.
162                     // Convert back relative to reference coordinate system
163                     aValue *= maReferenceSize;
164 
165                     ((*mpAttrLayer).*mpSetValueFunc)( aValue );
166 
167                     if( mpShape->isContentChanged() )
168                         mpShapeManager->notifyShapeUpdate( mpShape );
169 
170                     return true;
171                 }
172 
173                 virtual ::basegfx::B2DTuple getUnderlyingValue() const
174                 {
175                     ENSURE_OR_THROW( mpAttrLayer,
176                                       "TupleAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
177 
178                     ::basegfx::B2DTuple aRetVal;
179 
180                     // deviated from the (*shared_ptr).*mpFuncPtr
181                     // notation here, since gcc does not seem to parse
182                     // that as a member function call anymore.
183                     aRetVal.setX( (mpAttrLayer.get()->*mpIs1stValidFunc)() ?
184                                   (mpAttrLayer.get()->*mpGet1stValueFunc)() :
185                                   maDefaultValue.getX() );
186                     aRetVal.setY( (mpAttrLayer.get()->*mpIs2ndValidFunc)() ?
187                                   (mpAttrLayer.get()->*mpGet2ndValueFunc)() :
188                                   maDefaultValue.getY() );
189 
190                     // Activities get values from the expression
191                     // parser, which returns _relative_
192                     // sizes/positions.  Convert start value to the
193                     // same coordinate space (i.e. relative to given
194                     // reference size).
195                     aRetVal /= maReferenceSize;
196 
197                     return aRetVal;
198                 }
199 
200             private:
201                 AnimatableShapeSharedPtr		   mpShape;
202                 ShapeAttributeLayerSharedPtr	   mpAttrLayer;
203                 ShapeManagerSharedPtr			   mpShapeManager;
204                 bool 		(ShapeAttributeLayer::*mpIs1stValidFunc)() const;
205                 bool 		(ShapeAttributeLayer::*mpIs2ndValidFunc)() const;
206                 double 		(ShapeAttributeLayer::*mpGet1stValueFunc)() const;
207                 double 		(ShapeAttributeLayer::*mpGet2ndValueFunc)() const;
208                 void 		(ShapeAttributeLayer::*mpSetValueFunc)( const ValueT& );
209 
210                 const int						   mnFlags;
211 
212                 const ::basegfx::B2DSize		   maReferenceSize;
213                 const ValueT					   maDefaultValue;
214                 bool							   mbAnimationStarted;
215             };
216 
217 
218             class PathAnimation : public NumberAnimation
219             {
220             public:
221                 PathAnimation( const ::rtl::OUString&		rSVGDPath,
222                                sal_Int16                    nAdditive,
223                                const ShapeManagerSharedPtr&	rShapeManager,
224                                const ::basegfx::B2DVector&  rSlideSize,
225                                int							nFlags ) :
226                     maPathPoly(),
227                     mpShape(),
228                     mpAttrLayer(),
229                     mpShapeManager( rShapeManager ),
230                     maPageSize( rSlideSize ),
231 					maShapeOrig(),
232                     mnFlags( nFlags ),
233 					mbAnimationStarted( false ),
234 					mnAdditive( nAdditive )
235                 {
236                     ENSURE_OR_THROW( rShapeManager,
237                                       "PathAnimation::PathAnimation(): Invalid ShapeManager" );
238 
239                     ::basegfx::B2DPolyPolygon aPolyPoly;
240 
241                     ENSURE_OR_THROW( ::basegfx::tools::importFromSvgD( aPolyPoly, rSVGDPath ),
242                                       "PathAnimation::PathAnimation(): failed to parse SVG:d path" );
243                     ENSURE_OR_THROW( aPolyPoly.count() == 1,
244                                       "PathAnimation::PathAnimation(): motion path consists of multiple/zero polygon(s)" );
245 
246                     // TODO(F2): Since getPositionRelative() currently
247                     // cannot handle beziers, have to subdivide.
248                     // AW: Should be no longer necessary; getPositionRelative is now bezier-safe
249                     maPathPoly = ::basegfx::tools::adaptiveSubdivideByAngle(aPolyPoly.getB2DPolygon(0) );
250                 }
251 
252                 ~PathAnimation()
253                 {
254                     end_();
255                 }
256 
257                 // Animation interface
258                 // -------------------
259                 virtual void prefetch( const AnimatableShapeSharedPtr&,
260                                        const ShapeAttributeLayerSharedPtr& )
261                 {}
262 
263                 virtual void start( const AnimatableShapeSharedPtr& 	rShape,
264                                     const ShapeAttributeLayerSharedPtr& rAttrLayer )
265                 {
266                     OSL_ENSURE( !mpShape,
267                                 "PathAnimation::start(): Shape already set" );
268                     OSL_ENSURE( !mpAttrLayer,
269                                 "PathAnimation::start(): Attribute layer already set" );
270 
271                     mpShape = rShape;
272                     mpAttrLayer = rAttrLayer;
273 
274                     ENSURE_OR_THROW( rShape,
275                                       "PathAnimation::start(): Invalid shape" );
276                     ENSURE_OR_THROW( rAttrLayer,
277                                       "PathAnimation::start(): Invalid attribute layer" );
278 
279                     // TODO(F1): Check whether _shape_ bounds are correct here.
280                     // Theoretically, our AttrLayer is way down the stack, and
281                     // we only have to consider _that_ value, not the one from
282                     // the top of the stack as returned by Shape::getBounds()
283 					if( mnAdditive == animations::AnimationAdditiveMode::SUM )
284 						maShapeOrig = mpShape->getBounds().getCenter();
285 					else
286 						maShapeOrig = mpShape->getDomBounds().getCenter();
287 
288                     if( !mbAnimationStarted )
289                     {
290                         mbAnimationStarted = true;
291 
292                         if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
293                             mpShapeManager->enterAnimationMode( mpShape );
294                     }
295                 }
296 
297                 virtual void end() { end_(); }
298                 void end_()
299                 {
300                     if( mbAnimationStarted )
301                     {
302                         mbAnimationStarted = false;
303 
304                         if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
305                             mpShapeManager->leaveAnimationMode( mpShape );
306 
307                         if( mpShape->isContentChanged() )
308                             mpShapeManager->notifyShapeUpdate( mpShape );
309                     }
310                 }
311 
312                 // NumberAnimation interface
313                 // -----------------------
314 
315                 virtual bool operator()( double nValue )
316                 {
317                     ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
318                                        "PathAnimation::operator(): Invalid ShapeAttributeLayer" );
319 
320                     ::basegfx::B2DPoint rOutPos = ::basegfx::tools::getPositionRelative( maPathPoly,
321                                                                                          nValue );
322 
323                     // TODO(F1): Determine whether the path is
324                     // absolute, or shape-relative.
325 
326                     // interpret path as page-relative. Scale up with page size
327                     rOutPos *= maPageSize;
328 
329                     // TODO(F1): Determine whether the path origin is
330                     // absolute, or shape-relative.
331 
332                     // interpret path as shape-originated. Offset to shape position
333 
334                     rOutPos += maShapeOrig;
335 
336                     mpAttrLayer->setPosition( rOutPos );
337 
338                     if( mpShape->isContentChanged() )
339                         mpShapeManager->notifyShapeUpdate( mpShape );
340 
341                     return true;
342                 }
343 
344                 virtual double getUnderlyingValue() const
345                 {
346                     ENSURE_OR_THROW( mpAttrLayer,
347                                       "PathAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
348 
349                     return 0.0; // though this should be used in concert with
350                     			// ActivitiesFactory::createSimpleActivity, better
351                     			// explicitely name our start value.
352                     			// Permissible range for operator() above is [0,1]
353                 }
354 
355             private:
356                 ::basegfx::B2DPolygon			   maPathPoly;
357                 AnimatableShapeSharedPtr		   mpShape;
358                 ShapeAttributeLayerSharedPtr	   mpAttrLayer;
359                 ShapeManagerSharedPtr			   mpShapeManager;
360                 const ::basegfx::B2DSize		   maPageSize;
361                 ::basegfx::B2DPoint				   maShapeOrig;
362                 const int						   mnFlags;
363                 bool							   mbAnimationStarted;
364 				sal_Int16						   mnAdditive;
365             };
366 
367 
368             /** GenericAnimation template
369 
370             	This template makes heavy use of SFINAE, only one of
371             	the operator()() methods will compile for each of the
372             	base classes.
373 
374                 Note that we omit the virtual keyword on the
375                 operator()() overrides and getUnderlyingValue() methods on
376                 purpose; those that actually do override baseclass
377                 virtual methods inherit the property, and the others
378                 won't increase our vtable. What's more, having all
379                 those methods in the vtable actually creates POIs for
380                 them, which breaks the whole SFINAE concept (IOW, this
381                 template won't compile any longer).
382 
383             	@tpl AnimationBase
384                 Type of animation to generate (determines the
385                 interface GenericAnimation will implement). Must be
386                 one of NumberAnimation, ColorAnimation,
387                 StringAnimation, PairAnimation or BoolAnimation.
388 
389                 @tpl ModifierFunctor
390                 Type of a functor object, which can optionally be used to
391                 modify the getter/setter values.
392              */
393             template< typename AnimationBase, typename ModifierFunctor > class GenericAnimation : public AnimationBase
394             {
395             public:
396                 typedef typename AnimationBase::ValueType ValueT;
397 
398                 /** Create generic animation
399 
400                 	@param pIsValid
401                     Function pointer to one of the is*Valid
402                     methods. Used to either take the given getter
403                     method, or the given default value for the start value.
404 
405                     @param rDefaultValue
406                     Default value, to take as the start value if
407                     is*Valid returns false.
408 
409                     @param pGetValue
410                     Getter method, to fetch start value if valid.
411 
412                     @param pSetValue
413                     Setter method. This one puts the current animation
414                     value to the ShapeAttributeLayer.
415 
416                     @param rGetterModifier
417                     Modifies up values retrieved from the pGetValue method.
418                     Must provide operator()( const ValueT& ) method.
419 
420                     @param rSetterModifier
421                     Modifies up values before passing them to the pSetValue method.
422                     Must provide operator()( const ValueT& ) method.
423                  */
424             	GenericAnimation( const ShapeManagerSharedPtr&			rShapeManager,
425                                   int									nFlags,
426                     			  bool      	 (ShapeAttributeLayer::*pIsValid)() const,
427                                   const ValueT&				  	   		rDefaultValue,
428                                   ValueT 		 (ShapeAttributeLayer::*pGetValue)() const,
429                                   void      	 (ShapeAttributeLayer::*pSetValue)( const ValueT& ),
430                                   const ModifierFunctor&				rGetterModifier,
431                                   const ModifierFunctor&				rSetterModifier ) :
432                     mpShape(),
433                     mpAttrLayer(),
434                     mpShapeManager( rShapeManager ),
435                     mpIsValidFunc(pIsValid),
436                     mpGetValueFunc(pGetValue),
437                     mpSetValueFunc(pSetValue),
438                     maGetterModifier( rGetterModifier ),
439                     maSetterModifier( rSetterModifier ),
440                     mnFlags( nFlags ),
441                     maDefaultValue(rDefaultValue),
442                     mbAnimationStarted( false )
443                 {
444                     ENSURE_OR_THROW( rShapeManager,
445                                       "GenericAnimation::GenericAnimation(): Invalid ShapeManager" );
446                     ENSURE_OR_THROW( pIsValid && pGetValue && pSetValue,
447                                       "GenericAnimation::GenericAnimation(): One of the method pointers is NULL" );
448                 }
449 
450                 ~GenericAnimation()
451                 {
452                     end_();
453                 }
454 
455                 // Animation interface
456                 // -------------------
457                 virtual void prefetch( const AnimatableShapeSharedPtr&,
458                                        const ShapeAttributeLayerSharedPtr& )
459                 {}
460 
461                 virtual void start( const AnimatableShapeSharedPtr& 	rShape,
462                                     const ShapeAttributeLayerSharedPtr& rAttrLayer )
463                 {
464                     OSL_ENSURE( !mpShape,
465                                 "GenericAnimation::start(): Shape already set" );
466                     OSL_ENSURE( !mpAttrLayer,
467                                 "GenericAnimation::start(): Attribute layer already set" );
468 
469                     mpShape = rShape;
470                     mpAttrLayer = rAttrLayer;
471 
472                     ENSURE_OR_THROW( rShape,
473                                       "GenericAnimation::start(): Invalid shape" );
474                     ENSURE_OR_THROW( rAttrLayer,
475                                       "GenericAnimation::start(): Invalid attribute layer" );
476 
477                     // only start animation once per repeated start() call,
478                     // and only if sprites should be used for display
479                     if( !mbAnimationStarted )
480                     {
481                         mbAnimationStarted = true;
482 
483                         if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
484                             mpShapeManager->enterAnimationMode( mpShape );
485                     }
486                 }
487 
488                 virtual void end() { end_(); }
489                 void end_()
490                 {
491                     // TODO(Q2): Factor out common code (most
492                     // prominently start() and end()) into base class
493 
494                     // only stop animation once per repeated end() call,
495                     // and only if sprites are used for display
496                     if( mbAnimationStarted )
497                     {
498                         mbAnimationStarted = false;
499 
500                         if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
501                             mpShapeManager->leaveAnimationMode( mpShape );
502 
503                         // Attention, this notifyShapeUpdate() is
504                         // somewhat delicate here. Calling it
505                         // unconditional (i.e. not guarded by
506                         // mbAnimationStarted) will lead to shapes
507                         // snapping back to their original state just
508                         // before the slide ends. Not calling it at
509                         // all might swallow final animation
510                         // states. The current implementation relies
511                         // on the fact that end() is either called by
512                         // the Activity (then, the last animation
513                         // state has been set, and corresponds to the
514                         // shape's hold state), or by the animation
515                         // node (then, it's a forced end, and we
516                         // _have_ to snap back).
517                         //
518                         // To reiterate: normally, we're called from
519                         // the Activity first, thus the
520                         // notifyShapeUpdate() below will update to
521                         // the last activity value.
522 
523                         // force shape update, activity might have changed
524                         // state in the last round.
525                         if( mpShape->isContentChanged() )
526                             mpShapeManager->notifyShapeUpdate( mpShape );
527                     }
528                 }
529 
530                 // Derived Animation interface
531                 // ---------------------------
532 
533                 /** For by-reference interfaces (B2DTuple, OUString)
534                  */
535                 bool operator()( const ValueT& x )
536                 {
537                     ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
538                                        "GenericAnimation::operator(): Invalid ShapeAttributeLayer" );
539 
540                     ((*mpAttrLayer).*mpSetValueFunc)( maSetterModifier( x ) );
541 
542                     if( mpShape->isContentChanged() )
543                         mpShapeManager->notifyShapeUpdate( mpShape );
544 
545                     return true;
546                 }
547 
548                 /** For by-value interfaces (bool, double)
549                  */
550                 bool operator()( ValueT x )
551                 {
552                     ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
553                                        "GenericAnimation::operator(): Invalid ShapeAttributeLayer" );
554 
555                     ((*mpAttrLayer).*mpSetValueFunc)( maSetterModifier( x ) );
556 
557                     if( mpShape->isContentChanged() )
558                         mpShapeManager->notifyShapeUpdate( mpShape );
559 
560                     return true;
561                 }
562 
563                 ValueT getUnderlyingValue() const
564                 {
565                     ENSURE_OR_THROW( mpAttrLayer,
566                                       "GenericAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
567 
568                     // deviated from the (*shared_ptr).*mpFuncPtr
569                     // notation here, since gcc does not seem to parse
570                     // that as a member function call anymore.
571                     if( (mpAttrLayer.get()->*mpIsValidFunc)() )
572                         return maGetterModifier( ((*mpAttrLayer).*mpGetValueFunc)() );
573                     else
574                         return maDefaultValue;
575                 }
576 
577             private:
578                 AnimatableShapeSharedPtr		   mpShape;
579                 ShapeAttributeLayerSharedPtr	   mpAttrLayer;
580                 ShapeManagerSharedPtr			   mpShapeManager;
581                 bool 		(ShapeAttributeLayer::*mpIsValidFunc)() const;
582                 ValueT	 	(ShapeAttributeLayer::*mpGetValueFunc)() const;
583                 void 		(ShapeAttributeLayer::*mpSetValueFunc)( const ValueT& );
584 
585                 ModifierFunctor					   maGetterModifier;
586                 ModifierFunctor					   maSetterModifier;
587 
588                 const int						   mnFlags;
589 
590                 const ValueT				 	   maDefaultValue;
591                 bool							   mbAnimationStarted;
592             };
593 
594             /** Function template wrapper around GenericAnimation template
595 
596             	@tpl AnimationBase
597                 Type of animation to generate (determines the
598                 interface GenericAnimation will implement).
599              */
600             template< typename AnimationBase > ::boost::shared_ptr< AnimationBase >
601             	makeGenericAnimation( const ShapeManagerSharedPtr&							   rShapeManager,
602                                       int													   nFlags,
603                                       bool 								(ShapeAttributeLayer::*pIsValid)() const,
604                                       const typename AnimationBase::ValueType&				   rDefaultValue,
605                                       typename AnimationBase::ValueType (ShapeAttributeLayer::*pGetValue)() const,
606                                       void 								(ShapeAttributeLayer::*pSetValue)( const typename AnimationBase::ValueType& ) )
607             {
608                 return ::boost::shared_ptr< AnimationBase >(
609                     new GenericAnimation< AnimationBase,
610                     					  ::std::identity< typename AnimationBase::ValueType > >(
611                                               rShapeManager,
612                                               nFlags,
613                                               pIsValid,
614                                               rDefaultValue,
615                                               pGetValue,
616                                               pSetValue,
617                                               // no modification necessary, use identity functor here
618                                               ::std::identity< typename AnimationBase::ValueType >(),
619                                               ::std::identity< typename AnimationBase::ValueType >() ) );
620             }
621 
622             class Scaler
623             {
624             public:
625                 Scaler( double nScale ) :
626                     mnScale( nScale )
627                 {
628                 }
629 
630                 double operator()( double nVal ) const
631                 {
632                     return mnScale * nVal;
633                 }
634 
635             private:
636                 double mnScale;
637             };
638 
639             /** Overload for NumberAnimations which need scaling (width,height,x,y currently)
640              */
641             NumberAnimationSharedPtr makeGenericAnimation( const ShapeManagerSharedPtr&							    rShapeManager,
642                                                            int													    nFlags,
643                                                            bool 							 (ShapeAttributeLayer::*pIsValid)() const,
644                                                            double				    								nDefaultValue,
645                                                            double							 (ShapeAttributeLayer::*pGetValue)() const,
646                                                            void 							 (ShapeAttributeLayer::*pSetValue)( const double& ),
647                                                            double								 				    nScaleValue )
648             {
649                 return NumberAnimationSharedPtr(
650                     new GenericAnimation< NumberAnimation, Scaler >( rShapeManager,
651                                                                      nFlags,
652                                                                      pIsValid,
653                                                                      nDefaultValue / nScaleValue,
654                                                                      pGetValue,
655                                                                      pSetValue,
656                                                                      Scaler( 1.0/nScaleValue ),
657                                                                      Scaler( nScaleValue ) ) );
658             }
659 
660 
661             uno::Any getShapeDefault( const AnimatableShapeSharedPtr& 	rShape,
662                                       const ::rtl::OUString& 			rPropertyName )
663             {
664                 uno::Reference< drawing::XShape > xShape( rShape->getXShape() );
665 
666                 if( !xShape.is() )
667                     return uno::Any(); // no regular shape, no defaults available
668 
669 
670                 // extract relevant value from XShape's PropertySet
671                 uno::Reference< beans::XPropertySet > xPropSet( xShape,
672                                                                 uno::UNO_QUERY );
673 
674                 ENSURE_OR_THROW( xPropSet.is(),
675                                   "getShapeDefault(): Cannot query property set from shape" );
676 
677                 return xPropSet->getPropertyValue( rPropertyName );
678             }
679 
680             template< typename ValueType > ValueType getDefault( const AnimatableShapeSharedPtr& 	rShape,
681                                                                  const ::rtl::OUString& 			rPropertyName )
682             {
683                 const uno::Any& rAny( getShapeDefault( rShape,
684                                                        rPropertyName ) );
685 
686                 if( !rAny.hasValue() )
687                 {
688                     OSL_ENSURE( false, "getDefault(): cannot get requested shape property" );
689                     OSL_TRACE( "getDefault(): cannot get '%s' shape property",
690                                ::rtl::OUStringToOString( rPropertyName,
691                                                          RTL_TEXTENCODING_ASCII_US ).getStr() );
692                     return ValueType();
693                 }
694                 else
695                 {
696                     ValueType aValue = ValueType();
697 
698                     if( !(rAny >>= aValue) )
699                     {
700                         OSL_ENSURE( false, "getDefault(): cannot extract requested shape property" );
701                         OSL_TRACE( "getDefault(): cannot extract '%s' shape property",
702                                    ::rtl::OUStringToOString( rPropertyName,
703                                                              RTL_TEXTENCODING_ASCII_US ).getStr() );
704                         return ValueType();
705                     }
706 
707                     return aValue;
708                 }
709             }
710 
711             template<> RGBColor getDefault< RGBColor >( const AnimatableShapeSharedPtr& rShape,
712                                                         const ::rtl::OUString& 			rPropertyName )
713             {
714                 const uno::Any& rAny( getShapeDefault( rShape,
715                                                        rPropertyName ) );
716 
717                 if( !rAny.hasValue() )
718                 {
719                     OSL_ENSURE( false, "getDefault(): cannot get requested shape color property" );
720                     OSL_TRACE( "getDefault(): cannot get '%s' shape color property",
721                                ::rtl::OUStringToOString( rPropertyName,
722                                                          RTL_TEXTENCODING_ASCII_US ).getStr() );
723                     return RGBColor();
724                 }
725                 else
726                 {
727                     sal_Int32 nValue = 0;
728 
729                     if( !(rAny >>= nValue) )
730                     {
731                         OSL_ENSURE( false, "getDefault(): cannot extract requested shape color property" );
732                         OSL_TRACE( "getDefault(): cannot extract '%s' shape color property",
733                                    ::rtl::OUStringToOString( rPropertyName,
734                                                              RTL_TEXTENCODING_ASCII_US ).getStr() );
735                         return RGBColor();
736                     }
737 
738                     // convert from 0xAARRGGBB API color to 0xRRGGBB00
739                     // canvas color
740                     return RGBColor( (nValue << 8U) & 0xFFFFFF00U );
741                 }
742             }
743         }
744 
745         AnimationFactory::AttributeClass AnimationFactory::classifyAttributeName( const ::rtl::OUString& rAttrName )
746         {
747             // ATTENTION: When changing this map, also the create*PropertyAnimation() methods must
748             // be checked and possibly adapted in their switch statements
749 
750             // TODO(Q2): Since this map must be coherent with the various switch statements
751             // in the create*PropertyAnimation methods, try to unify into a single method or table
752             switch( mapAttributeName( rAttrName ) )
753             {
754                 default:
755                     // FALLTHROUGH intended
756                 case ATTRIBUTE_INVALID:
757                     return CLASS_UNKNOWN_PROPERTY;
758 
759                 case ATTRIBUTE_CHAR_COLOR:
760                     // FALLTHROUGH intended
761                 case ATTRIBUTE_COLOR:
762                     // FALLTHROUGH intended
763                 case ATTRIBUTE_DIMCOLOR:
764                     // FALLTHROUGH intended
765                 case ATTRIBUTE_FILL_COLOR:
766                     // FALLTHROUGH intended
767                 case ATTRIBUTE_LINE_COLOR:
768                     return CLASS_COLOR_PROPERTY;
769 
770                 case ATTRIBUTE_CHAR_FONT_NAME:
771                     return CLASS_STRING_PROPERTY;
772 
773                 case ATTRIBUTE_VISIBILITY:
774                     return CLASS_BOOL_PROPERTY;
775 
776                 case ATTRIBUTE_CHAR_HEIGHT:
777                     // FALLTHROUGH intended
778                 case ATTRIBUTE_CHAR_WEIGHT:
779                     // FALLTHROUGH intended
780                 case ATTRIBUTE_CHAR_ROTATION:
781                     // FALLTHROUGH intended
782                 case ATTRIBUTE_HEIGHT:
783                     // FALLTHROUGH intended
784                 case ATTRIBUTE_OPACITY:
785                     // FALLTHROUGH intended
786                 case ATTRIBUTE_ROTATE:
787                     // FALLTHROUGH intended
788                 case ATTRIBUTE_SKEW_X:
789                     // FALLTHROUGH intended
790                 case ATTRIBUTE_SKEW_Y:
791                     // FALLTHROUGH intended
792                 case ATTRIBUTE_WIDTH:
793                     // FALLTHROUGH intended
794                 case ATTRIBUTE_POS_X:
795                     // FALLTHROUGH intended
796                 case ATTRIBUTE_POS_Y:
797                     return CLASS_NUMBER_PROPERTY;
798 
799                 case ATTRIBUTE_CHAR_UNDERLINE:
800                     // FALLTHROUGH intended
801                 case ATTRIBUTE_FILL_STYLE:
802                     // FALLTHROUGH intended
803                 case ATTRIBUTE_LINE_STYLE:
804                     // FALLTHROUGH intended
805                 case ATTRIBUTE_CHAR_POSTURE:
806                     return CLASS_ENUM_PROPERTY;
807             }
808         }
809 
810         NumberAnimationSharedPtr AnimationFactory::createNumberPropertyAnimation( const ::rtl::OUString&				rAttrName,
811                                                                                   const AnimatableShapeSharedPtr&		rShape,
812                                                                                   const ShapeManagerSharedPtr&			rShapeManager,
813                                                                                   const ::basegfx::B2DVector&           rSlideSize,
814                                                                                   int									nFlags )
815         {
816             // ATTENTION: When changing this map, also the classifyAttributeName() method must
817             // be checked and possibly adapted in their switch statement
818             switch( mapAttributeName( rAttrName ) )
819             {
820                 default:
821                     // FALLTHROUGH intended
822                 case ATTRIBUTE_INVALID:
823                     ENSURE_OR_THROW( false,
824                                       "AnimationFactory::createNumberPropertyAnimation(): Unknown attribute" );
825                     break;
826 
827                 case ATTRIBUTE_CHAR_COLOR:
828                     // FALLTHROUGH intended
829                 case ATTRIBUTE_CHAR_FONT_NAME:
830                     // FALLTHROUGH intended
831                 case ATTRIBUTE_CHAR_POSTURE:
832                     // FALLTHROUGH intended
833                 case ATTRIBUTE_CHAR_UNDERLINE:
834                     // FALLTHROUGH intended
835                 case ATTRIBUTE_COLOR:
836                     // FALLTHROUGH intended
837                 case ATTRIBUTE_DIMCOLOR:
838                     // FALLTHROUGH intended
839                 case ATTRIBUTE_FILL_COLOR:
840                     // FALLTHROUGH intended
841                 case ATTRIBUTE_FILL_STYLE:
842                     // FALLTHROUGH intended
843                 case ATTRIBUTE_LINE_COLOR:
844                     // FALLTHROUGH intended
845                 case ATTRIBUTE_LINE_STYLE:
846                     // FALLTHROUGH intended
847                 case ATTRIBUTE_VISIBILITY:
848                     ENSURE_OR_THROW( false,
849                                       "AnimationFactory::createNumberPropertyAnimation(): Attribute type mismatch" );
850                     break;
851 
852                 case ATTRIBUTE_CHAR_HEIGHT:
853                     return makeGenericAnimation<NumberAnimation>( rShapeManager,
854                                                                   nFlags,
855                                                                   &ShapeAttributeLayer::isCharScaleValid,
856                                                                   1.0, // CharHeight is a relative attribute, thus
857                                                                   	   // default is 1.0
858                                                                   &ShapeAttributeLayer::getCharScale,
859                                                                   &ShapeAttributeLayer::setCharScale );
860 
861                 case ATTRIBUTE_CHAR_WEIGHT:
862                     return makeGenericAnimation<NumberAnimation>( rShapeManager,
863                                                                   nFlags,
864                                                                   &ShapeAttributeLayer::isCharWeightValid,
865                                                                   getDefault<double>( rShape, rAttrName ),
866                                                                   &ShapeAttributeLayer::getCharWeight,
867                                                                   &ShapeAttributeLayer::setCharWeight );
868 
869                 case ATTRIBUTE_CHAR_ROTATION:
870                     return makeGenericAnimation<NumberAnimation>( rShapeManager,
871                                                                   nFlags,
872                                                                   &ShapeAttributeLayer::isCharRotationAngleValid,
873                                                                   getDefault<double>( rShape, rAttrName ),
874                                                                   &ShapeAttributeLayer::getCharRotationAngle,
875                                                                   &ShapeAttributeLayer::setCharRotationAngle );
876 
877                 case ATTRIBUTE_HEIGHT:
878                     return makeGenericAnimation( rShapeManager,
879                                                  nFlags,
880                                                  &ShapeAttributeLayer::isHeightValid,
881                                                  // TODO(F1): Check whether _shape_ bounds are correct here.
882                                                  // Theoretically, our AttrLayer is way down the stack, and
883                                                  // we only have to consider _that_ value, not the one from
884                                                  // the top of the stack as returned by Shape::getBounds()
885                                                  rShape->getBounds().getHeight(),
886                                                  &ShapeAttributeLayer::getHeight,
887                                                  &ShapeAttributeLayer::setHeight,
888                                                  // convert expression parser value from relative page size
889                                                  rSlideSize.getY() );
890 
891                 case ATTRIBUTE_OPACITY:
892                     return makeGenericAnimation<NumberAnimation>( rShapeManager,
893                                                                   nFlags,
894                                                                   &ShapeAttributeLayer::isAlphaValid,
895                                                                   // TODO(F1): Provide shape default here (FillTransparency?)
896                                                                   1.0,
897                                                                   &ShapeAttributeLayer::getAlpha,
898                                                                   &ShapeAttributeLayer::setAlpha );
899 
900                 case ATTRIBUTE_ROTATE:
901                     return makeGenericAnimation<NumberAnimation>( rShapeManager,
902                                                                   nFlags,
903                                                                   &ShapeAttributeLayer::isRotationAngleValid,
904                                                                   // NOTE: Since we paint the shape as-is from metafile,
905                                                                   // rotation angle is always 0.0, even for rotated shapes
906                                                                   0.0,
907                                                                   &ShapeAttributeLayer::getRotationAngle,
908                                                                   &ShapeAttributeLayer::setRotationAngle );
909 
910                 case ATTRIBUTE_SKEW_X:
911                     return makeGenericAnimation<NumberAnimation>( rShapeManager,
912                                                                   nFlags,
913                                                                   &ShapeAttributeLayer::isShearXAngleValid,
914                                                                   // TODO(F1): Is there any shape property for skew?
915                                                                   0.0,
916                                                                   &ShapeAttributeLayer::getShearXAngle,
917                                                                   &ShapeAttributeLayer::setShearXAngle );
918 
919                 case ATTRIBUTE_SKEW_Y:
920                     return makeGenericAnimation<NumberAnimation>( rShapeManager,
921                                                                   nFlags,
922                                                                   &ShapeAttributeLayer::isShearYAngleValid,
923                                                                   // TODO(F1): Is there any shape property for skew?
924                                                                   0.0,
925                                                                   &ShapeAttributeLayer::getShearYAngle,
926                                                                   &ShapeAttributeLayer::setShearYAngle );
927 
928                 case ATTRIBUTE_WIDTH:
929                     return makeGenericAnimation( rShapeManager,
930                                                  nFlags,
931                                                  &ShapeAttributeLayer::isWidthValid,
932                                                  // TODO(F1): Check whether _shape_ bounds are correct here.
933                                                  // Theoretically, our AttrLayer is way down the stack, and
934                                                  // we only have to consider _that_ value, not the one from
935                                                  // the top of the stack as returned by Shape::getBounds()
936                                                  rShape->getBounds().getWidth(),
937                                                  &ShapeAttributeLayer::getWidth,
938                                                  &ShapeAttributeLayer::setWidth,
939                                                  // convert expression parser value from relative page size
940                                                  rSlideSize.getX() );
941 
942                 case ATTRIBUTE_POS_X:
943                     return makeGenericAnimation( rShapeManager,
944                                                  nFlags,
945                                                  &ShapeAttributeLayer::isPosXValid,
946                                                  // TODO(F1): Check whether _shape_ bounds are correct here.
947                                                  // Theoretically, our AttrLayer is way down the stack, and
948                                                  // we only have to consider _that_ value, not the one from
949                                                  // the top of the stack as returned by Shape::getBounds()
950                                                  rShape->getBounds().getCenterX(),
951                                                  &ShapeAttributeLayer::getPosX,
952                                                  &ShapeAttributeLayer::setPosX,
953                                                  // convert expression parser value from relative page size
954                                                  rSlideSize.getX() );
955 
956                 case ATTRIBUTE_POS_Y:
957                     return makeGenericAnimation( rShapeManager,
958                                                  nFlags,
959                                                  &ShapeAttributeLayer::isPosYValid,
960                                                  // TODO(F1): Check whether _shape_ bounds are correct here.
961                                                  // Theoretically, our AttrLayer is way down the stack, and
962                                                  // we only have to consider _that_ value, not the one from
963                                                  // the top of the stack as returned by Shape::getBounds()
964                                                  rShape->getBounds().getCenterY(),
965                                                  &ShapeAttributeLayer::getPosY,
966                                                  &ShapeAttributeLayer::setPosY,
967                                                  // convert expression parser value from relative page size
968                                                  rSlideSize.getY() );
969             }
970 
971             return NumberAnimationSharedPtr();
972         }
973 
974         EnumAnimationSharedPtr AnimationFactory::createEnumPropertyAnimation( const ::rtl::OUString&				rAttrName,
975                                                                               const AnimatableShapeSharedPtr&		rShape,
976                                                                               const ShapeManagerSharedPtr&			rShapeManager,
977                                                                               const ::basegfx::B2DVector&           /*rSlideSize*/,
978                                                                               int									nFlags )
979         {
980             // ATTENTION: When changing this map, also the classifyAttributeName() method must
981             // be checked and possibly adapted in their switch statement
982             switch( mapAttributeName( rAttrName ) )
983             {
984                 default:
985                     // FALLTHROUGH intended
986                 case ATTRIBUTE_INVALID:
987                     ENSURE_OR_THROW( false,
988                                       "AnimationFactory::createEnumPropertyAnimation(): Unknown attribute" );
989                     break;
990 
991                 case ATTRIBUTE_CHAR_COLOR:
992                     // FALLTHROUGH intended
993                 case ATTRIBUTE_CHAR_FONT_NAME:
994                     // FALLTHROUGH intended
995                 case ATTRIBUTE_COLOR:
996                     // FALLTHROUGH intended
997                 case ATTRIBUTE_DIMCOLOR:
998                     // FALLTHROUGH intended
999                 case ATTRIBUTE_FILL_COLOR:
1000                     // FALLTHROUGH intended
1001                 case ATTRIBUTE_LINE_COLOR:
1002                     // FALLTHROUGH intended
1003                 case ATTRIBUTE_VISIBILITY:
1004                     // FALLTHROUGH intended
1005                 case ATTRIBUTE_CHAR_HEIGHT:
1006                     // FALLTHROUGH intended
1007                 case ATTRIBUTE_CHAR_WEIGHT:
1008                     // FALLTHROUGH intended
1009                 case ATTRIBUTE_CHAR_ROTATION:
1010                     // FALLTHROUGH intended
1011                 case ATTRIBUTE_HEIGHT:
1012                     // FALLTHROUGH intended
1013                 case ATTRIBUTE_OPACITY:
1014                     // FALLTHROUGH intended
1015                 case ATTRIBUTE_ROTATE:
1016                     // FALLTHROUGH intended
1017                 case ATTRIBUTE_SKEW_X:
1018                     // FALLTHROUGH intended
1019                 case ATTRIBUTE_SKEW_Y:
1020                     // FALLTHROUGH intended
1021                 case ATTRIBUTE_WIDTH:
1022                     // FALLTHROUGH intended
1023                 case ATTRIBUTE_POS_X:
1024                     // FALLTHROUGH intended
1025                 case ATTRIBUTE_POS_Y:
1026                     ENSURE_OR_THROW( false,
1027                                       "AnimationFactory::createEnumPropertyAnimation(): Attribute type mismatch" );
1028                     break;
1029 
1030 
1031                 case ATTRIBUTE_FILL_STYLE:
1032                     return makeGenericAnimation<EnumAnimation>( rShapeManager,
1033                                                                 nFlags,
1034                                                                 &ShapeAttributeLayer::isFillStyleValid,
1035                                                                 sal::static_int_cast<sal_Int16>(
1036                                                                     getDefault<drawing::FillStyle>( rShape, rAttrName )),
1037                                                                 &ShapeAttributeLayer::getFillStyle,
1038                                                                 &ShapeAttributeLayer::setFillStyle );
1039 
1040                 case ATTRIBUTE_LINE_STYLE:
1041                     return makeGenericAnimation<EnumAnimation>( rShapeManager,
1042                                                                 nFlags,
1043                                                                 &ShapeAttributeLayer::isLineStyleValid,
1044                                                                 sal::static_int_cast<sal_Int16>(
1045                                                                     getDefault<drawing::LineStyle>( rShape, rAttrName )),
1046                                                                 &ShapeAttributeLayer::getLineStyle,
1047                                                                 &ShapeAttributeLayer::setLineStyle );
1048 
1049                 case ATTRIBUTE_CHAR_POSTURE:
1050                     return makeGenericAnimation<EnumAnimation>( rShapeManager,
1051                                                                 nFlags,
1052                                                                 &ShapeAttributeLayer::isCharPostureValid,
1053                                                                 sal::static_int_cast<sal_Int16>(
1054                                                                     getDefault<awt::FontSlant>( rShape, rAttrName )),
1055                                                                 &ShapeAttributeLayer::getCharPosture,
1056                                                                 &ShapeAttributeLayer::setCharPosture );
1057 
1058                 case ATTRIBUTE_CHAR_UNDERLINE:
1059                     return makeGenericAnimation<EnumAnimation>( rShapeManager,
1060                                                                 nFlags,
1061                                                                 &ShapeAttributeLayer::isUnderlineModeValid,
1062                                                                 getDefault<sal_Int16>( rShape, rAttrName ),
1063                                                                 &ShapeAttributeLayer::getUnderlineMode,
1064                                                                 &ShapeAttributeLayer::setUnderlineMode );
1065             }
1066 
1067             return EnumAnimationSharedPtr();
1068         }
1069 
1070         ColorAnimationSharedPtr AnimationFactory::createColorPropertyAnimation( const ::rtl::OUString&				rAttrName,
1071                                                                                 const AnimatableShapeSharedPtr&		rShape,
1072                                                                                 const ShapeManagerSharedPtr&		rShapeManager,
1073                                                                                 const ::basegfx::B2DVector&         /*rSlideSize*/,
1074                                                                                 int									nFlags )
1075         {
1076             // ATTENTION: When changing this map, also the classifyAttributeName() method must
1077             // be checked and possibly adapted in their switch statement
1078             switch( mapAttributeName( rAttrName ) )
1079             {
1080                 default:
1081                     // FALLTHROUGH intended
1082                 case ATTRIBUTE_INVALID:
1083                     ENSURE_OR_THROW( false,
1084                                       "AnimationFactory::createColorPropertyAnimation(): Unknown attribute" );
1085                     break;
1086 
1087                 case ATTRIBUTE_CHAR_FONT_NAME:
1088                     // FALLTHROUGH intended
1089                 case ATTRIBUTE_CHAR_HEIGHT:
1090                     // FALLTHROUGH intended
1091                 case ATTRIBUTE_CHAR_POSTURE:
1092                     // FALLTHROUGH intended
1093                 case ATTRIBUTE_CHAR_ROTATION:
1094                     // FALLTHROUGH intended
1095                 case ATTRIBUTE_CHAR_UNDERLINE:
1096                     // FALLTHROUGH intended
1097                 case ATTRIBUTE_CHAR_WEIGHT:
1098                     // FALLTHROUGH intended
1099                 case ATTRIBUTE_FILL_STYLE:
1100                     // FALLTHROUGH intended
1101                 case ATTRIBUTE_HEIGHT:
1102                     // FALLTHROUGH intended
1103                 case ATTRIBUTE_LINE_STYLE:
1104                     // FALLTHROUGH intended
1105                 case ATTRIBUTE_OPACITY:
1106                     // FALLTHROUGH intended
1107                 case ATTRIBUTE_ROTATE:
1108                     // FALLTHROUGH intended
1109                 case ATTRIBUTE_SKEW_X:
1110                     // FALLTHROUGH intended
1111                 case ATTRIBUTE_SKEW_Y:
1112                     // FALLTHROUGH intended
1113                 case ATTRIBUTE_VISIBILITY:
1114                     // FALLTHROUGH intended
1115                 case ATTRIBUTE_WIDTH:
1116                     // FALLTHROUGH intended
1117                 case ATTRIBUTE_POS_X:
1118                     // FALLTHROUGH intended
1119                 case ATTRIBUTE_POS_Y:
1120                     ENSURE_OR_THROW( false,
1121                                       "AnimationFactory::createColorPropertyAnimation(): Attribute type mismatch" );
1122                     break;
1123 
1124                 case ATTRIBUTE_CHAR_COLOR:
1125                     return makeGenericAnimation<ColorAnimation>( rShapeManager,
1126                                                                  nFlags,
1127                                                                  &ShapeAttributeLayer::isCharColorValid,
1128                                                                  getDefault<RGBColor>( rShape, rAttrName ),
1129                                                                  &ShapeAttributeLayer::getCharColor,
1130                                                                  &ShapeAttributeLayer::setCharColor );
1131 
1132                 case ATTRIBUTE_COLOR:
1133                     // TODO(F2): This is just mapped to fill color to make it work
1134                     return makeGenericAnimation<ColorAnimation>( rShapeManager,
1135                                                                  nFlags,
1136                                                                  &ShapeAttributeLayer::isFillColorValid,
1137                                                                  getDefault<RGBColor>( rShape, rAttrName ),
1138                                                                  &ShapeAttributeLayer::getFillColor,
1139                                                                  &ShapeAttributeLayer::setFillColor );
1140 
1141                 case ATTRIBUTE_DIMCOLOR:
1142                     return makeGenericAnimation<ColorAnimation>( rShapeManager,
1143                                                                  nFlags,
1144                                                                  &ShapeAttributeLayer::isDimColorValid,
1145                                                                  getDefault<RGBColor>( rShape, rAttrName ),
1146                                                                  &ShapeAttributeLayer::getDimColor,
1147                                                                  &ShapeAttributeLayer::setDimColor );
1148 
1149                 case ATTRIBUTE_FILL_COLOR:
1150                     return makeGenericAnimation<ColorAnimation>( rShapeManager,
1151                                                                  nFlags,
1152                                                                  &ShapeAttributeLayer::isFillColorValid,
1153                                                                  getDefault<RGBColor>( rShape, rAttrName ),
1154                                                                  &ShapeAttributeLayer::getFillColor,
1155                                                                  &ShapeAttributeLayer::setFillColor );
1156 
1157                 case ATTRIBUTE_LINE_COLOR:
1158                     return makeGenericAnimation<ColorAnimation>( rShapeManager,
1159                                                                  nFlags,
1160                                                                  &ShapeAttributeLayer::isLineColorValid,
1161                                                                  getDefault<RGBColor>( rShape, rAttrName ),
1162                                                                  &ShapeAttributeLayer::getLineColor,
1163                                                                  &ShapeAttributeLayer::setLineColor );
1164             }
1165 
1166             return ColorAnimationSharedPtr();
1167         }
1168 
1169         PairAnimationSharedPtr AnimationFactory::createPairPropertyAnimation( const AnimatableShapeSharedPtr&		rShape,
1170                                                                               const ShapeManagerSharedPtr&			rShapeManager,
1171                                                                               const ::basegfx::B2DVector&           rSlideSize,
1172                                                                               sal_Int16								nTransformType,
1173                                                                               int									nFlags )
1174         {
1175             const ::basegfx::B2DRectangle& rBounds( rShape->getBounds() );
1176 
1177             switch( nTransformType )
1178             {
1179                 case animations::AnimationTransformType::SCALE:
1180                     return PairAnimationSharedPtr(
1181                         new TupleAnimation< ::basegfx::B2DSize >(
1182                             rShapeManager,
1183                             nFlags,
1184                             &ShapeAttributeLayer::isWidthValid,
1185                             &ShapeAttributeLayer::isHeightValid,
1186                             // TODO(F1): Check whether _shape_ bounds are correct here.
1187                             // Theoretically, our AttrLayer is way down the stack, and
1188                             // we only have to consider _that_ value, not the one from
1189                             // the top of the stack as returned by Shape::getBounds()
1190                             rBounds.getRange(),
1191                             rBounds.getRange(),
1192                             &ShapeAttributeLayer::getWidth,
1193                             &ShapeAttributeLayer::getHeight,
1194                             &ShapeAttributeLayer::setSize ) );
1195 
1196                 case animations::AnimationTransformType::TRANSLATE:
1197                     return PairAnimationSharedPtr(
1198                         new TupleAnimation< ::basegfx::B2DPoint >(
1199                             rShapeManager,
1200                             nFlags,
1201                             &ShapeAttributeLayer::isPosXValid,
1202                             &ShapeAttributeLayer::isPosYValid,
1203                             // TODO(F1): Check whether _shape_ bounds are correct here.
1204                             // Theoretically, our AttrLayer is way down the stack, and
1205                             // we only have to consider _that_ value, not the one from
1206                             // the top of the stack as returned by Shape::getBounds()
1207                             rBounds.getCenter(),
1208                             rSlideSize,
1209                             &ShapeAttributeLayer::getPosX,
1210                             &ShapeAttributeLayer::getPosY,
1211                             &ShapeAttributeLayer::setPosition ) );
1212 
1213                 default:
1214                     ENSURE_OR_THROW( false,
1215                                       "AnimationFactory::createPairPropertyAnimation(): Attribute type mismatch" );
1216                     break;
1217             }
1218 
1219             return PairAnimationSharedPtr();
1220         }
1221 
1222         StringAnimationSharedPtr AnimationFactory::createStringPropertyAnimation( const ::rtl::OUString&				rAttrName,
1223                                                                                   const AnimatableShapeSharedPtr&		rShape,
1224                                                                                   const ShapeManagerSharedPtr&			rShapeManager,
1225                                                                                   const ::basegfx::B2DVector&           /*rSlideSize*/,
1226                                                                                   int									nFlags )
1227         {
1228             // ATTENTION: When changing this map, also the classifyAttributeName() method must
1229             // be checked and possibly adapted in their switch statement
1230             switch( mapAttributeName( rAttrName ) )
1231             {
1232                 default:
1233                     // FALLTHROUGH intended
1234                 case ATTRIBUTE_INVALID:
1235                     ENSURE_OR_THROW( false,
1236                                       "AnimationFactory::createStringPropertyAnimation(): Unknown attribute" );
1237                     break;
1238 
1239                 case ATTRIBUTE_CHAR_COLOR:
1240                     // FALLTHROUGH intended
1241                 case ATTRIBUTE_CHAR_HEIGHT:
1242                     // FALLTHROUGH intended
1243                 case ATTRIBUTE_CHAR_ROTATION:
1244                     // FALLTHROUGH intended
1245                 case ATTRIBUTE_CHAR_UNDERLINE:
1246                     // FALLTHROUGH intended
1247                 case ATTRIBUTE_COLOR:
1248                     // FALLTHROUGH intended
1249                 case ATTRIBUTE_DIMCOLOR:
1250                     // FALLTHROUGH intended
1251                 case ATTRIBUTE_FILL_COLOR:
1252                     // FALLTHROUGH intended
1253                 case ATTRIBUTE_HEIGHT:
1254                     // FALLTHROUGH intended
1255                 case ATTRIBUTE_LINE_COLOR:
1256                     // FALLTHROUGH intended
1257                 case ATTRIBUTE_OPACITY:
1258                     // FALLTHROUGH intended
1259                 case ATTRIBUTE_ROTATE:
1260                     // FALLTHROUGH intended
1261                 case ATTRIBUTE_SKEW_X:
1262                     // FALLTHROUGH intended
1263                 case ATTRIBUTE_SKEW_Y:
1264                     // FALLTHROUGH intended
1265                 case ATTRIBUTE_VISIBILITY:
1266                     // FALLTHROUGH intended
1267                 case ATTRIBUTE_WIDTH:
1268                     // FALLTHROUGH intended
1269                 case ATTRIBUTE_POS_X:
1270                     // FALLTHROUGH intended
1271                 case ATTRIBUTE_POS_Y:
1272                     // FALLTHROUGH intended
1273                 case ATTRIBUTE_CHAR_POSTURE:
1274                     // FALLTHROUGH intended
1275                 case ATTRIBUTE_CHAR_WEIGHT:
1276                     // FALLTHROUGH intended
1277                 case ATTRIBUTE_FILL_STYLE:
1278                     // FALLTHROUGH intended
1279                 case ATTRIBUTE_LINE_STYLE:
1280                     ENSURE_OR_THROW( false,
1281                                       "AnimationFactory::createStringPropertyAnimation(): Attribute type mismatch" );
1282                     break;
1283 
1284                 case ATTRIBUTE_CHAR_FONT_NAME:
1285                     return makeGenericAnimation<StringAnimation>( rShapeManager,
1286                                                                   nFlags,
1287                                                                   &ShapeAttributeLayer::isFontFamilyValid,
1288                                                                   getDefault< ::rtl::OUString >( rShape, rAttrName ),
1289                                                                   &ShapeAttributeLayer::getFontFamily,
1290                                                                   &ShapeAttributeLayer::setFontFamily );
1291             }
1292 
1293             return StringAnimationSharedPtr();
1294         }
1295 
1296         BoolAnimationSharedPtr AnimationFactory::createBoolPropertyAnimation( const ::rtl::OUString&				rAttrName,
1297                                                                               const AnimatableShapeSharedPtr&		/*rShape*/,
1298                                                                               const ShapeManagerSharedPtr&			rShapeManager,
1299                                                                               const ::basegfx::B2DVector&           /*rSlideSize*/,
1300                                                                               int									nFlags )
1301         {
1302             // ATTENTION: When changing this map, also the classifyAttributeName() method must
1303             // be checked and possibly adapted in their switch statement
1304             switch( mapAttributeName( rAttrName ) )
1305             {
1306                 default:
1307                     // FALLTHROUGH intended
1308                 case ATTRIBUTE_INVALID:
1309                     ENSURE_OR_THROW( false,
1310                                       "AnimationFactory::createBoolPropertyAnimation(): Unknown attribute" );
1311                     break;
1312 
1313                 case ATTRIBUTE_CHAR_COLOR:
1314                     // FALLTHROUGH intended
1315                 case ATTRIBUTE_CHAR_FONT_NAME:
1316                     // FALLTHROUGH intended
1317                 case ATTRIBUTE_CHAR_HEIGHT:
1318                     // FALLTHROUGH intended
1319                 case ATTRIBUTE_CHAR_POSTURE:
1320                     // FALLTHROUGH intended
1321                 case ATTRIBUTE_CHAR_ROTATION:
1322                     // FALLTHROUGH intended
1323                 case ATTRIBUTE_CHAR_WEIGHT:
1324                     // FALLTHROUGH intended
1325                 case ATTRIBUTE_COLOR:
1326                     // FALLTHROUGH intended
1327                 case ATTRIBUTE_DIMCOLOR:
1328                     // FALLTHROUGH intended
1329                 case ATTRIBUTE_FILL_COLOR:
1330                     // FALLTHROUGH intended
1331                 case ATTRIBUTE_FILL_STYLE:
1332                     // FALLTHROUGH intended
1333                 case ATTRIBUTE_HEIGHT:
1334                     // FALLTHROUGH intended
1335                 case ATTRIBUTE_LINE_COLOR:
1336                     // FALLTHROUGH intended
1337                 case ATTRIBUTE_LINE_STYLE:
1338                     // FALLTHROUGH intended
1339                 case ATTRIBUTE_OPACITY:
1340                     // FALLTHROUGH intended
1341                 case ATTRIBUTE_ROTATE:
1342                     // FALLTHROUGH intended
1343                 case ATTRIBUTE_SKEW_X:
1344                     // FALLTHROUGH intended
1345                 case ATTRIBUTE_SKEW_Y:
1346                     // FALLTHROUGH intended
1347                 case ATTRIBUTE_WIDTH:
1348                     // FALLTHROUGH intended
1349                 case ATTRIBUTE_POS_X:
1350                     // FALLTHROUGH intended
1351                 case ATTRIBUTE_POS_Y:
1352                     // FALLTHROUGH intended
1353                 case ATTRIBUTE_CHAR_UNDERLINE:
1354                     ENSURE_OR_THROW( false,
1355                                       "AnimationFactory::createBoolPropertyAnimation(): Attribute type mismatch" );
1356                     break;
1357 
1358                 case ATTRIBUTE_VISIBILITY:
1359                     return makeGenericAnimation<BoolAnimation>( rShapeManager,
1360                                                                 nFlags,
1361                                                                 &ShapeAttributeLayer::isVisibilityValid,
1362                                                                 // TODO(F1): Is there a corresponding shape property?
1363                                                                 true,
1364                                                                 &ShapeAttributeLayer::getVisibility,
1365                                                                 &ShapeAttributeLayer::setVisibility );
1366             }
1367 
1368             return BoolAnimationSharedPtr();
1369         }
1370 
1371         NumberAnimationSharedPtr AnimationFactory::createPathMotionAnimation( const ::rtl::OUString&			rSVGDPath,
1372 																			  sal_Int16							nAdditive,
1373                                                                               const AnimatableShapeSharedPtr&	/*rShape*/,
1374                                                                               const ShapeManagerSharedPtr&		rShapeManager,
1375                                                                               const ::basegfx::B2DVector&       rSlideSize,
1376                                                                               int								nFlags )
1377         {
1378             return NumberAnimationSharedPtr(
1379                 new PathAnimation( rSVGDPath, nAdditive,
1380                                    rShapeManager,
1381                                    rSlideSize,
1382                                    nFlags ) );
1383         }
1384 
1385     }
1386 }
1387