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