Use o3tl::convert in Math
[LibreOffice.git] / slideshow / source / engine / animationfactory.cxx
blobe5a7d3b9e74c5114f68ecf02b78f88dd97876627
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <tools/diagnose_ex.h>
22 #include <sal/log.hxx>
24 #include <animationfactory.hxx>
25 #include <attributemap.hxx>
27 #include <com/sun/star/animations/AnimationAdditiveMode.hpp>
28 #include <com/sun/star/animations/AnimationTransformType.hpp>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/drawing/FillStyle.hpp>
31 #include <com/sun/star/drawing/LineStyle.hpp>
32 #include <com/sun/star/awt/FontSlant.hpp>
34 #include <basegfx/polygon/b2dpolygon.hxx>
35 #include <basegfx/polygon/b2dpolygontools.hxx>
36 #include <basegfx/polygon/b2dpolypolygontools.hxx>
38 #include <box2dtools.hxx>
40 using namespace ::com::sun::star;
43 namespace slideshow::internal
45 namespace
47 // attention, there is a similar implementation of Animation in
48 // transitions/transitionfactory.cxx
50 template< typename ValueT > class TupleAnimation : public PairAnimation
52 public:
53 TupleAnimation( const ShapeManagerSharedPtr& rShapeManager,
54 int nFlags,
55 bool (ShapeAttributeLayer::*pIs1stValid)() const,
56 bool (ShapeAttributeLayer::*pIs2ndValid)() const,
57 const ValueT& rDefaultValue,
58 const ::basegfx::B2DSize& rReferenceSize,
59 double (ShapeAttributeLayer::*pGet1stValue)() const,
60 double (ShapeAttributeLayer::*pGet2ndValue)() const,
61 void (ShapeAttributeLayer::*pSetValue)( const ValueT& ) ) :
62 mpShape(),
63 mpAttrLayer(),
64 mpShapeManager( rShapeManager ),
65 mpIs1stValidFunc(pIs1stValid),
66 mpIs2ndValidFunc(pIs2ndValid),
67 mpGet1stValueFunc(pGet1stValue),
68 mpGet2ndValueFunc(pGet2ndValue),
69 mpSetValueFunc(pSetValue),
70 mnFlags( nFlags ),
71 maReferenceSize( rReferenceSize ),
72 maDefaultValue( rDefaultValue ),
73 mbAnimationStarted( false )
75 ENSURE_OR_THROW( rShapeManager,
76 "TupleAnimation::TupleAnimation(): Invalid ShapeManager" );
77 ENSURE_OR_THROW( pIs1stValid && pIs2ndValid && pGet1stValue && pGet2ndValue && pSetValue,
78 "TupleAnimation::TupleAnimation(): One of the method pointers is NULL" );
81 virtual ~TupleAnimation() override
83 end_();
86 // Animation interface
88 virtual void prefetch() override
91 virtual void start( const AnimatableShapeSharedPtr& rShape,
92 const ShapeAttributeLayerSharedPtr& rAttrLayer ) override
94 OSL_ENSURE( !mpShape,
95 "TupleAnimation::start(): Shape already set" );
96 OSL_ENSURE( !mpAttrLayer,
97 "TupleAnimation::start(): Attribute layer already set" );
99 mpShape = rShape;
100 mpAttrLayer = rAttrLayer;
102 ENSURE_OR_THROW( rShape,
103 "TupleAnimation::start(): Invalid shape" );
104 ENSURE_OR_THROW( rAttrLayer,
105 "TupleAnimation::start(): Invalid attribute layer" );
107 if( !mbAnimationStarted )
109 mbAnimationStarted = true;
111 if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
112 mpShapeManager->enterAnimationMode( mpShape );
116 virtual void end() override { end_(); }
117 void end_()
119 if( mbAnimationStarted )
121 mbAnimationStarted = false;
123 if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
124 mpShapeManager->leaveAnimationMode( mpShape );
126 if( mpShape->isContentChanged() )
127 mpShapeManager->notifyShapeUpdate( mpShape );
131 // PairAnimation interface
134 virtual bool operator()( const ::basegfx::B2DTuple& rValue ) override
136 ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
137 "TupleAnimation::operator(): Invalid ShapeAttributeLayer" );
139 ValueT aValue( rValue.getX(),
140 rValue.getY() );
142 // Activities get values from the expression parser,
143 // which returns _relative_ sizes/positions.
144 // Convert back relative to reference coordinate system
145 aValue *= maReferenceSize;
147 ((*mpAttrLayer).*mpSetValueFunc)( aValue );
149 if( mpShape->isContentChanged() )
150 mpShapeManager->notifyShapeUpdate( mpShape );
152 return true;
155 virtual ::basegfx::B2DTuple getUnderlyingValue() const override
157 ENSURE_OR_THROW( mpAttrLayer,
158 "TupleAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
160 ::basegfx::B2DTuple aRetVal;
162 // deviated from the (*shared_ptr).*mpFuncPtr
163 // notation here, since gcc does not seem to parse
164 // that as a member function call anymore.
165 aRetVal.setX( (mpAttrLayer.get()->*mpIs1stValidFunc)() ?
166 (mpAttrLayer.get()->*mpGet1stValueFunc)() :
167 maDefaultValue.getX() );
168 aRetVal.setY( (mpAttrLayer.get()->*mpIs2ndValidFunc)() ?
169 (mpAttrLayer.get()->*mpGet2ndValueFunc)() :
170 maDefaultValue.getY() );
172 // Activities get values from the expression
173 // parser, which returns _relative_
174 // sizes/positions. Convert start value to the
175 // same coordinate space (i.e. relative to given
176 // reference size).
177 aRetVal /= maReferenceSize;
179 return aRetVal;
182 private:
183 AnimatableShapeSharedPtr mpShape;
184 ShapeAttributeLayerSharedPtr mpAttrLayer;
185 ShapeManagerSharedPtr mpShapeManager;
186 bool (ShapeAttributeLayer::*mpIs1stValidFunc)() const;
187 bool (ShapeAttributeLayer::*mpIs2ndValidFunc)() const;
188 double (ShapeAttributeLayer::*mpGet1stValueFunc)() const;
189 double (ShapeAttributeLayer::*mpGet2ndValueFunc)() const;
190 void (ShapeAttributeLayer::*mpSetValueFunc)( const ValueT& );
192 const int mnFlags;
194 const ::basegfx::B2DSize maReferenceSize;
195 const ValueT maDefaultValue;
196 bool mbAnimationStarted;
200 class PathAnimation : public NumberAnimation
202 public:
203 PathAnimation( const OUString& rSVGDPath,
204 sal_Int16 nAdditive,
205 const ShapeManagerSharedPtr& rShapeManager,
206 const ::basegfx::B2DVector& rSlideSize,
207 int nFlags,
208 const box2d::utils::Box2DWorldSharedPtr& pBox2DWorld ) :
209 maPathPoly(),
210 mpShape(),
211 mpAttrLayer(),
212 mpShapeManager( rShapeManager ),
213 maPageSize( rSlideSize ),
214 maShapeOrig(),
215 mnFlags( nFlags ),
216 mbAnimationStarted( false ),
217 mbAnimationFirstUpdate( true ),
218 mnAdditive( nAdditive ),
219 mpBox2DWorld( pBox2DWorld )
221 ENSURE_OR_THROW( rShapeManager,
222 "PathAnimation::PathAnimation(): Invalid ShapeManager" );
224 ::basegfx::B2DPolyPolygon aPolyPoly;
226 ENSURE_OR_THROW( ::basegfx::utils::importFromSvgD( aPolyPoly, rSVGDPath, false, nullptr ),
227 "PathAnimation::PathAnimation(): failed to parse SVG:d path" );
228 ENSURE_OR_THROW( aPolyPoly.count() == 1,
229 "PathAnimation::PathAnimation(): motion path consists of multiple/zero polygon(s)" );
231 maPathPoly = aPolyPoly.getB2DPolygon(0);
234 virtual ~PathAnimation() override
236 end_();
239 // Animation interface
241 virtual void prefetch() override
244 virtual void start( const AnimatableShapeSharedPtr& rShape,
245 const ShapeAttributeLayerSharedPtr& rAttrLayer ) override
247 OSL_ENSURE( !mpShape,
248 "PathAnimation::start(): Shape already set" );
249 OSL_ENSURE( !mpAttrLayer,
250 "PathAnimation::start(): Attribute layer already set" );
252 mpShape = rShape;
253 mpAttrLayer = rAttrLayer;
255 ENSURE_OR_THROW( rShape,
256 "PathAnimation::start(): Invalid shape" );
257 ENSURE_OR_THROW( rAttrLayer,
258 "PathAnimation::start(): Invalid attribute layer" );
260 // TODO(F1): Check whether _shape_ bounds are correct here.
261 // Theoretically, our AttrLayer is way down the stack, and
262 // we only have to consider _that_ value, not the one from
263 // the top of the stack as returned by Shape::getBounds()
264 if( mnAdditive == animations::AnimationAdditiveMode::SUM )
265 maShapeOrig = mpShape->getBounds().getCenter();
266 else
267 maShapeOrig = mpShape->getDomBounds().getCenter();
269 if( !mbAnimationStarted )
271 mbAnimationStarted = true;
273 if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
274 mpShapeManager->enterAnimationMode( mpShape );
278 virtual void end() override { end_(); }
279 void end_()
281 if( !mbAnimationStarted )
282 return;
284 mbAnimationStarted = false;
286 if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
287 mpShapeManager->leaveAnimationMode( mpShape );
289 if( mpShape->isContentChanged() )
290 mpShapeManager->notifyShapeUpdate( mpShape );
292 // if there is a physics animation going on report the animation ending
293 // and zero out the velocity of the shape
294 if( mpBox2DWorld->isInitialized() )
295 mpBox2DWorld->queueLinearVelocityUpdate( mpShape->getXShape(), {0,0});
298 // NumberAnimation interface
301 virtual bool operator()( double nValue ) override
303 ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
304 "PathAnimation::operator(): Invalid ShapeAttributeLayer" );
306 ::basegfx::B2DPoint rOutPos = ::basegfx::utils::getPositionRelative( maPathPoly,
307 nValue );
309 // TODO(F1): Determine whether the path is
310 // absolute, or shape-relative.
312 // interpret path as page-relative. Scale up with page size
313 rOutPos *= maPageSize;
315 // TODO(F1): Determine whether the path origin is
316 // absolute, or shape-relative.
318 // interpret path as shape-originated. Offset to shape position
320 rOutPos += maShapeOrig;
322 mpAttrLayer->setPosition( rOutPos );
324 if( mpShape->isContentChanged() )
326 mpShapeManager->notifyShapeUpdate( mpShape );
328 // if there's a physics animation going on report the change to it
329 if ( mpBox2DWorld->isInitialized() )
331 mpBox2DWorld->queueShapePathAnimationUpdate( mpShape->getXShape(),
332 mpAttrLayer,
333 mbAnimationFirstUpdate );
337 if( mbAnimationFirstUpdate ) mbAnimationFirstUpdate = false;
339 return true;
342 virtual double getUnderlyingValue() const override
344 ENSURE_OR_THROW( mpAttrLayer,
345 "PathAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
347 return 0.0; // though this should be used in concert with
348 // ActivitiesFactory::createSimpleActivity, better
349 // explicitly name our start value.
350 // Permissible range for operator() above is [0,1]
353 private:
354 ::basegfx::B2DPolygon maPathPoly;
355 AnimatableShapeSharedPtr mpShape;
356 ShapeAttributeLayerSharedPtr mpAttrLayer;
357 ShapeManagerSharedPtr mpShapeManager;
358 const ::basegfx::B2DSize maPageSize;
359 ::basegfx::B2DPoint maShapeOrig;
360 const int mnFlags;
361 bool mbAnimationStarted;
362 bool mbAnimationFirstUpdate;
363 sal_Int16 mnAdditive;
364 box2d::utils::Box2DWorldSharedPtr mpBox2DWorld;
367 class PhysicsAnimation : public NumberAnimation
369 public:
370 PhysicsAnimation( const ::box2d::utils::Box2DWorldSharedPtr& pBox2DWorld,
371 const double fDuration,
372 const ShapeManagerSharedPtr& rShapeManager,
373 const ::basegfx::B2DVector& rSlideSize,
374 const ::basegfx::B2DVector& rStartVelocity,
375 const double fDensity,
376 const double fBounciness,
377 int nFlags ) :
378 mpShape(),
379 mpAttrLayer(),
380 mpShapeManager( rShapeManager ),
381 maPageSize( rSlideSize ),
382 mnFlags( nFlags ),
383 mbAnimationStarted( false ),
384 mpBox2DBody(),
385 mpBox2DWorld( pBox2DWorld ),
386 mfDuration(fDuration),
387 maStartVelocity(rStartVelocity),
388 mfDensity(fDensity),
389 mfBounciness(fBounciness),
390 mfPreviousElapsedTime(0.00f),
391 mbIsBox2dWorldStepper(false)
393 ENSURE_OR_THROW( rShapeManager,
394 "PhysicsAnimation::PhysicsAnimation(): Invalid ShapeManager" );
397 virtual ~PhysicsAnimation() override
399 end_();
402 // Animation interface
404 virtual void prefetch() override
407 virtual void start( const AnimatableShapeSharedPtr& rShape,
408 const ShapeAttributeLayerSharedPtr& rAttrLayer ) override
410 OSL_ENSURE( !mpShape,
411 "PhysicsAnimation::start(): Shape already set" );
412 OSL_ENSURE( !mpAttrLayer,
413 "PhysicsAnimation::start(): Attribute layer already set" );
415 mpShape = rShape;
416 mpAttrLayer = rAttrLayer;
418 ENSURE_OR_THROW( rShape,
419 "PhysicsAnimation::start(): Invalid shape" );
420 ENSURE_OR_THROW( rAttrLayer,
421 "PhysicsAnimation::start(): Invalid attribute layer" );
423 if( !mbAnimationStarted )
425 mbAnimationStarted = true;
427 mpBox2DWorld->alertPhysicsAnimationStart(maPageSize, mpShapeManager);
428 mpBox2DBody = mpBox2DWorld->makeShapeDynamic( mpShape->getXShape(), maStartVelocity, mfDensity, mfBounciness );
430 if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
431 mpShapeManager->enterAnimationMode( mpShape );
435 virtual void end() override { end_(); }
436 void end_()
438 if( mbIsBox2dWorldStepper )
440 mbIsBox2dWorldStepper = false;
441 mpBox2DWorld->setHasWorldStepper(false);
444 if( !mbAnimationStarted )
445 return;
447 mbAnimationStarted = false;
449 if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
450 mpShapeManager->leaveAnimationMode( mpShape );
452 if( mpShape->isContentChanged() )
453 mpShapeManager->notifyShapeUpdate( mpShape );
455 mpBox2DWorld->alertPhysicsAnimationEnd(mpShape);
456 // if this was the only physics animation effect going on
457 // all box2d bodies were destroyed on alertPhysicsAnimationEnd
458 // except the one owned by the animation.
459 // Try to destroy the remaining body - if it is unique
460 // (it being unique means all physics animation effects have ended
461 // since otherwise mpBox2DWorld would own a copy of the shared_ptr )
462 mpBox2DBody.reset();
466 // NumberAnimation interface
469 virtual bool operator()( double nValue ) override
471 ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
472 "PhysicsAnimation::operator(): Invalid ShapeAttributeLayer" );
474 // if there are multiple physics animations going in parallel
475 // Only one of them should step the box2d world
476 if( !mpBox2DWorld->hasWorldStepper() )
478 mbIsBox2dWorldStepper = true;
479 mpBox2DWorld->setHasWorldStepper(true);
482 if( mbIsBox2dWorldStepper )
484 double fPassedTime = (mfDuration * nValue) - mfPreviousElapsedTime;
485 mfPreviousElapsedTime += mpBox2DWorld->stepAmount( fPassedTime );
488 mpAttrLayer->setPosition( mpBox2DBody->getPosition() );
489 mpAttrLayer->setRotationAngle( mpBox2DBody->getAngle() );
491 if( mpShape->isContentChanged() )
492 mpShapeManager->notifyShapeUpdate( mpShape );
494 return true;
497 virtual double getUnderlyingValue() const override
499 ENSURE_OR_THROW( mpAttrLayer,
500 "PhysicsAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
502 return 0.0;
505 private:
506 AnimatableShapeSharedPtr mpShape;
507 ShapeAttributeLayerSharedPtr mpAttrLayer;
508 ShapeManagerSharedPtr mpShapeManager;
509 const ::basegfx::B2DSize maPageSize;
510 const int mnFlags;
511 bool mbAnimationStarted;
512 box2d::utils::Box2DBodySharedPtr mpBox2DBody;
513 box2d::utils::Box2DWorldSharedPtr mpBox2DWorld;
514 double mfDuration;
515 const ::basegfx::B2DVector maStartVelocity;
516 const double mfDensity;
517 const double mfBounciness;
518 double mfPreviousElapsedTime;
519 bool mbIsBox2dWorldStepper;
522 /** GenericAnimation template
524 This template makes heavy use of SFINAE, only one of
525 the operator()() methods will compile for each of the
526 base classes.
528 Note that we omit the virtual keyword on the
529 operator()() overrides and getUnderlyingValue() methods on
530 purpose; those that actually do override baseclass
531 virtual methods inherit the property, and the others
532 won't increase our vtable. What's more, having all
533 those methods in the vtable actually creates POIs for
534 them, which breaks the whole SFINAE concept (IOW, this
535 template won't compile any longer).
537 @tpl AnimationBase
538 Type of animation to generate (determines the
539 interface GenericAnimation will implement). Must be
540 one of NumberAnimation, ColorAnimation,
541 StringAnimation, PairAnimation or BoolAnimation.
543 @tpl ModifierFunctor
544 Type of a functor object, which can optionally be used to
545 modify the getter/setter values.
547 template< typename AnimationBase, typename ModifierFunctor > class GenericAnimation : public AnimationBase
549 public:
550 typedef typename AnimationBase::ValueType ValueT;
552 /** Create generic animation
554 @param pIsValid
555 Function pointer to one of the is*Valid
556 methods. Used to either take the given getter
557 method, or the given default value for the start value.
559 @param rDefaultValue
560 Default value, to take as the start value if
561 is*Valid returns false.
563 @param pGetValue
564 Getter method, to fetch start value if valid.
566 @param pSetValue
567 Setter method. This one puts the current animation
568 value to the ShapeAttributeLayer.
570 @param rGetterModifier
571 Modifies up values retrieved from the pGetValue method.
572 Must provide operator()( const ValueT& ) method.
574 @param rSetterModifier
575 Modifies up values before passing them to the pSetValue method.
576 Must provide operator()( const ValueT& ) method.
578 GenericAnimation( const ShapeManagerSharedPtr& rShapeManager,
579 int nFlags,
580 bool (ShapeAttributeLayer::*pIsValid)() const,
581 const ValueT& rDefaultValue,
582 ValueT (ShapeAttributeLayer::*pGetValue)() const,
583 void (ShapeAttributeLayer::*pSetValue)( const ValueT& ),
584 const ModifierFunctor& rGetterModifier,
585 const ModifierFunctor& rSetterModifier,
586 const AttributeType eAttrType,
587 const box2d::utils::Box2DWorldSharedPtr& pBox2DWorld ) :
588 mpShape(),
589 mpAttrLayer(),
590 mpShapeManager( rShapeManager ),
591 mpIsValidFunc(pIsValid),
592 mpGetValueFunc(pGetValue),
593 mpSetValueFunc(pSetValue),
594 maGetterModifier( rGetterModifier ),
595 maSetterModifier( rSetterModifier ),
596 mnFlags( nFlags ),
597 maDefaultValue(rDefaultValue),
598 mbAnimationStarted( false ),
599 mbAnimationFirstUpdate( true ),
600 meAttrType( eAttrType ),
601 mpBox2DWorld ( pBox2DWorld )
603 ENSURE_OR_THROW( rShapeManager,
604 "GenericAnimation::GenericAnimation(): Invalid ShapeManager" );
605 ENSURE_OR_THROW( pIsValid && pGetValue && pSetValue,
606 "GenericAnimation::GenericAnimation(): One of the method pointers is NULL" );
609 ~GenericAnimation()
611 end();
614 // Animation interface
616 virtual void prefetch()
619 virtual void start( const AnimatableShapeSharedPtr& rShape,
620 const ShapeAttributeLayerSharedPtr& rAttrLayer )
622 OSL_ENSURE( !mpShape,
623 "GenericAnimation::start(): Shape already set" );
624 OSL_ENSURE( !mpAttrLayer,
625 "GenericAnimation::start(): Attribute layer already set" );
627 mpShape = rShape;
628 mpAttrLayer = rAttrLayer;
630 ENSURE_OR_THROW( rShape,
631 "GenericAnimation::start(): Invalid shape" );
632 ENSURE_OR_THROW( rAttrLayer,
633 "GenericAnimation::start(): Invalid attribute layer" );
635 // only start animation once per repeated start() call,
636 // and only if sprites should be used for display
637 if( !mbAnimationStarted )
639 mbAnimationStarted = true;
641 if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
642 mpShapeManager->enterAnimationMode( mpShape );
646 void end()
648 // TODO(Q2): Factor out common code (most
649 // prominently start() and end()) into base class
651 // only stop animation once per repeated end() call,
652 // and only if sprites are used for display
653 if( !mbAnimationStarted )
654 return;
656 mbAnimationStarted = false;
658 if( mpBox2DWorld && mpBox2DWorld->isInitialized() )
660 // if there's a physics animation going on report the animation ending to it
661 mpBox2DWorld->queueShapeAnimationEndUpdate( mpShape->getXShape(), meAttrType );
664 if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
665 mpShapeManager->leaveAnimationMode( mpShape );
667 // Attention, this notifyShapeUpdate() is
668 // somewhat delicate here. Calling it
669 // unconditional (i.e. not guarded by
670 // mbAnimationStarted) will lead to shapes
671 // snapping back to their original state just
672 // before the slide ends. Not calling it at
673 // all might swallow final animation
674 // states. The current implementation relies
675 // on the fact that end() is either called by
676 // the Activity (then, the last animation
677 // state has been set, and corresponds to the
678 // shape's hold state), or by the animation
679 // node (then, it's a forced end, and we
680 // _have_ to snap back).
682 // To reiterate: normally, we're called from
683 // the Activity first, thus the
684 // notifyShapeUpdate() below will update to
685 // the last activity value.
687 // force shape update, activity might have changed
688 // state in the last round.
689 if( mpShape->isContentChanged() )
690 mpShapeManager->notifyShapeUpdate( mpShape );
693 // Derived Animation interface
696 /** For by-reference interfaces (B2DTuple, OUString)
698 bool operator()( const ValueT& x )
700 ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
701 "GenericAnimation::operator(): Invalid ShapeAttributeLayer" );
703 ((*mpAttrLayer).*mpSetValueFunc)( maSetterModifier( x ) );
705 if( mpShape->isContentChanged() )
706 mpShapeManager->notifyShapeUpdate( mpShape );
708 if( mbAnimationFirstUpdate ) mbAnimationFirstUpdate = false;
710 return true;
713 /** For by-value interfaces (bool, double)
715 bool operator()( ValueT x )
717 ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
718 "GenericAnimation::operator(): Invalid ShapeAttributeLayer" );
720 ((*mpAttrLayer).*mpSetValueFunc)( maSetterModifier( x ) );
722 if( mpBox2DWorld && mpBox2DWorld->isInitialized() )
724 // if there's a physics animation going on report the change to it
725 mpBox2DWorld->queueShapeAnimationUpdate( mpShape->getXShape(), mpAttrLayer, meAttrType, mbAnimationFirstUpdate );
728 if( mpShape->isContentChanged() )
729 mpShapeManager->notifyShapeUpdate( mpShape );
731 if( mbAnimationFirstUpdate ) mbAnimationFirstUpdate = false;
733 return true;
736 ValueT getUnderlyingValue() const
738 ENSURE_OR_THROW( mpAttrLayer,
739 "GenericAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
741 // deviated from the (*shared_ptr).*mpFuncPtr
742 // notation here, since gcc does not seem to parse
743 // that as a member function call anymore.
744 if( (mpAttrLayer.get()->*mpIsValidFunc)() )
745 return maGetterModifier( ((*mpAttrLayer).*mpGetValueFunc)() );
746 else
747 return maDefaultValue;
750 private:
751 AnimatableShapeSharedPtr mpShape;
752 ShapeAttributeLayerSharedPtr mpAttrLayer;
753 ShapeManagerSharedPtr mpShapeManager;
754 bool (ShapeAttributeLayer::*mpIsValidFunc)() const;
755 ValueT (ShapeAttributeLayer::*mpGetValueFunc)() const;
756 void (ShapeAttributeLayer::*mpSetValueFunc)( const ValueT& );
758 ModifierFunctor maGetterModifier;
759 ModifierFunctor maSetterModifier;
761 const int mnFlags;
763 const ValueT maDefaultValue;
764 bool mbAnimationStarted;
765 bool mbAnimationFirstUpdate;
767 const AttributeType meAttrType;
768 const box2d::utils::Box2DWorldSharedPtr mpBox2DWorld;
771 //Current c++0x draft (apparently) has std::identity, but not operator()
772 template<typename T> struct SGI_identity
774 T& operator()(T& x) const { return x; }
775 const T& operator()(const T& x) const { return x; }
778 /** Function template wrapper around GenericAnimation template
780 @tpl AnimationBase
781 Type of animation to generate (determines the
782 interface GenericAnimation will implement).
784 template< typename AnimationBase > ::std::shared_ptr< AnimationBase >
785 makeGenericAnimation( const ShapeManagerSharedPtr& rShapeManager,
786 int nFlags,
787 bool (ShapeAttributeLayer::*pIsValid)() const,
788 const typename AnimationBase::ValueType& rDefaultValue,
789 typename AnimationBase::ValueType (ShapeAttributeLayer::*pGetValue)() const,
790 void (ShapeAttributeLayer::*pSetValue)( const typename AnimationBase::ValueType& ),
791 const AttributeType eAttrType,
792 const box2d::utils::Box2DWorldSharedPtr& pBox2DWorld )
794 return std::make_shared<GenericAnimation< AnimationBase,
795 SGI_identity< typename AnimationBase::ValueType > >>(
796 rShapeManager,
797 nFlags,
798 pIsValid,
799 rDefaultValue,
800 pGetValue,
801 pSetValue,
802 // no modification necessary, use identity functor here
803 SGI_identity< typename AnimationBase::ValueType >(),
804 SGI_identity< typename AnimationBase::ValueType >(),
805 eAttrType,
806 pBox2DWorld );
809 class Scaler
811 public:
812 explicit Scaler( double nScale ) :
813 mnScale( nScale )
817 double operator()( double nVal ) const
819 return mnScale * nVal;
822 private:
823 double mnScale;
826 /** Overload for NumberAnimations which need scaling (width,height,x,y currently)
828 NumberAnimationSharedPtr makeGenericAnimation( const ShapeManagerSharedPtr& rShapeManager,
829 int nFlags,
830 bool (ShapeAttributeLayer::*pIsValid)() const,
831 double nDefaultValue,
832 double (ShapeAttributeLayer::*pGetValue)() const,
833 void (ShapeAttributeLayer::*pSetValue)( const double& ),
834 double nScaleValue,
835 const AttributeType eAttrType,
836 const box2d::utils::Box2DWorldSharedPtr& pBox2DWorld )
838 return std::make_shared<GenericAnimation< NumberAnimation, Scaler >>( rShapeManager,
839 nFlags,
840 pIsValid,
841 nDefaultValue / nScaleValue,
842 pGetValue,
843 pSetValue,
844 Scaler( 1.0/nScaleValue ),
845 Scaler( nScaleValue ),
846 eAttrType,
847 pBox2DWorld );
851 uno::Any getShapeDefault( const AnimatableShapeSharedPtr& rShape,
852 const OUString& rPropertyName )
854 uno::Reference< drawing::XShape > xShape( rShape->getXShape() );
856 if( !xShape.is() )
857 return uno::Any(); // no regular shape, no defaults available
860 // extract relevant value from XShape's PropertySet
861 uno::Reference< beans::XPropertySet > xPropSet( xShape,
862 uno::UNO_QUERY );
864 ENSURE_OR_THROW( xPropSet.is(),
865 "getShapeDefault(): Cannot query property set from shape" );
867 return xPropSet->getPropertyValue( rPropertyName );
870 template< typename ValueType > ValueType getDefault( const AnimatableShapeSharedPtr& rShape,
871 const OUString& rPropertyName )
873 const uno::Any& rAny( getShapeDefault( rShape,
874 rPropertyName ) );
876 if( !rAny.hasValue() )
878 SAL_WARN("slideshow", "getDefault(): cannot get shape property " << rPropertyName );
879 return ValueType();
881 else
883 ValueType aValue = ValueType();
885 if( !(rAny >>= aValue) )
887 SAL_WARN("slideshow", "getDefault(): cannot extract shape property " << rPropertyName);
888 return ValueType();
891 return aValue;
895 template<> RGBColor getDefault< RGBColor >( const AnimatableShapeSharedPtr& rShape,
896 const OUString& rPropertyName )
898 const uno::Any& rAny( getShapeDefault( rShape,
899 rPropertyName ) );
901 if( !rAny.hasValue() )
903 SAL_WARN("slideshow", "getDefault(): cannot get shape color property " << rPropertyName);
904 return RGBColor();
906 else
908 sal_Int32 nValue = 0;
910 if( !(rAny >>= nValue) )
912 SAL_INFO("slideshow", "getDefault(): cannot extract shape color property " << rPropertyName);
913 return RGBColor();
916 // convert from 0xAARRGGBB API color to 0xRRGGBB00
917 // canvas color
918 return RGBColor( (nValue << 8U) & 0xFFFFFF00U );
923 AnimationFactory::AttributeClass AnimationFactory::classifyAttributeName( const OUString& rAttrName )
925 // ATTENTION: When changing this map, also the create*PropertyAnimation() methods must
926 // be checked and possibly adapted in their switch statements
928 // TODO(Q2): Since this map must be coherent with the various switch statements
929 // in the create*PropertyAnimation methods, try to unify into a single method or table
930 switch( mapAttributeName( rAttrName ) )
932 default:
933 case AttributeType::Invalid:
934 return CLASS_UNKNOWN_PROPERTY;
936 case AttributeType::CharColor:
937 case AttributeType::Color:
938 case AttributeType::DimColor:
939 case AttributeType::FillColor:
940 case AttributeType::LineColor:
941 return CLASS_COLOR_PROPERTY;
943 case AttributeType::CharFontName:
944 return CLASS_STRING_PROPERTY;
946 case AttributeType::Visibility:
947 return CLASS_BOOL_PROPERTY;
949 case AttributeType::CharHeight:
950 case AttributeType::CharWeight:
951 case AttributeType::Height:
952 case AttributeType::Opacity:
953 case AttributeType::Rotate:
954 case AttributeType::SkewX:
955 case AttributeType::SkewY:
956 case AttributeType::Width:
957 case AttributeType::PosX:
958 case AttributeType::PosY:
959 return CLASS_NUMBER_PROPERTY;
961 case AttributeType::CharUnderline:
962 case AttributeType::FillStyle:
963 case AttributeType::LineStyle:
964 case AttributeType::CharPosture:
965 return CLASS_ENUM_PROPERTY;
969 NumberAnimationSharedPtr AnimationFactory::createNumberPropertyAnimation( const OUString& rAttrName,
970 const AnimatableShapeSharedPtr& rShape,
971 const ShapeManagerSharedPtr& rShapeManager,
972 const ::basegfx::B2DVector& rSlideSize,
973 const box2d::utils::Box2DWorldSharedPtr& pBox2DWorld,
974 int nFlags )
976 // ATTENTION: When changing this map, also the classifyAttributeName() method must
977 // be checked and possibly adapted in their switch statement
978 AttributeType eAttrType = mapAttributeName(rAttrName);
979 switch( eAttrType )
981 default:
982 case AttributeType::Invalid:
983 ENSURE_OR_THROW( false,
984 "AnimationFactory::createNumberPropertyAnimation(): Unknown attribute" );
985 break;
987 case AttributeType::CharColor:
988 case AttributeType::CharFontName:
989 case AttributeType::CharPosture:
990 case AttributeType::CharUnderline:
991 case AttributeType::Color:
992 case AttributeType::DimColor:
993 case AttributeType::FillColor:
994 case AttributeType::FillStyle:
995 case AttributeType::LineColor:
996 case AttributeType::LineStyle:
997 case AttributeType::Visibility:
998 ENSURE_OR_THROW( false,
999 "AnimationFactory::createNumberPropertyAnimation(): Attribute type mismatch" );
1000 break;
1002 case AttributeType::CharHeight:
1003 return makeGenericAnimation<NumberAnimation>( rShapeManager,
1004 nFlags,
1005 &ShapeAttributeLayer::isCharScaleValid,
1006 1.0, // CharHeight is a relative attribute, thus
1007 // default is 1.0
1008 &ShapeAttributeLayer::getCharScale,
1009 &ShapeAttributeLayer::setCharScale,
1010 eAttrType,
1011 pBox2DWorld );
1013 case AttributeType::CharWeight:
1014 return makeGenericAnimation<NumberAnimation>( rShapeManager,
1015 nFlags,
1016 &ShapeAttributeLayer::isCharWeightValid,
1017 getDefault<double>( rShape, rAttrName ),
1018 &ShapeAttributeLayer::getCharWeight,
1019 &ShapeAttributeLayer::setCharWeight,
1020 eAttrType,
1021 pBox2DWorld );
1023 case AttributeType::Height:
1024 return makeGenericAnimation( rShapeManager,
1025 nFlags,
1026 &ShapeAttributeLayer::isHeightValid,
1027 // TODO(F1): Check whether _shape_ bounds are correct here.
1028 // Theoretically, our AttrLayer is way down the stack, and
1029 // we only have to consider _that_ value, not the one from
1030 // the top of the stack as returned by Shape::getBounds()
1031 rShape->getBounds().getHeight(),
1032 &ShapeAttributeLayer::getHeight,
1033 &ShapeAttributeLayer::setHeight,
1034 // convert expression parser value from relative page size
1035 rSlideSize.getY(),
1036 eAttrType,
1037 pBox2DWorld );
1039 case AttributeType::Opacity:
1040 return makeGenericAnimation<NumberAnimation>( rShapeManager,
1041 nFlags,
1042 &ShapeAttributeLayer::isAlphaValid,
1043 // TODO(F1): Provide shape default here (FillTransparency?)
1044 1.0,
1045 &ShapeAttributeLayer::getAlpha,
1046 &ShapeAttributeLayer::setAlpha,
1047 eAttrType,
1048 pBox2DWorld );
1050 case AttributeType::Rotate:
1051 return makeGenericAnimation<NumberAnimation>( rShapeManager,
1052 nFlags,
1053 &ShapeAttributeLayer::isRotationAngleValid,
1054 // NOTE: Since we paint the shape as-is from metafile,
1055 // rotation angle is always 0.0, even for rotated shapes
1056 0.0,
1057 &ShapeAttributeLayer::getRotationAngle,
1058 &ShapeAttributeLayer::setRotationAngle,
1059 eAttrType,
1060 pBox2DWorld );
1062 case AttributeType::SkewX:
1063 return makeGenericAnimation<NumberAnimation>( rShapeManager,
1064 nFlags,
1065 &ShapeAttributeLayer::isShearXAngleValid,
1066 // TODO(F1): Is there any shape property for skew?
1067 0.0,
1068 &ShapeAttributeLayer::getShearXAngle,
1069 &ShapeAttributeLayer::setShearXAngle,
1070 eAttrType,
1071 pBox2DWorld );
1073 case AttributeType::SkewY:
1074 return makeGenericAnimation<NumberAnimation>( rShapeManager,
1075 nFlags,
1076 &ShapeAttributeLayer::isShearYAngleValid,
1077 // TODO(F1): Is there any shape property for skew?
1078 0.0,
1079 &ShapeAttributeLayer::getShearYAngle,
1080 &ShapeAttributeLayer::setShearYAngle,
1081 eAttrType,
1082 pBox2DWorld );
1084 case AttributeType::Width:
1085 return makeGenericAnimation( rShapeManager,
1086 nFlags,
1087 &ShapeAttributeLayer::isWidthValid,
1088 // TODO(F1): Check whether _shape_ bounds are correct here.
1089 // Theoretically, our AttrLayer is way down the stack, and
1090 // we only have to consider _that_ value, not the one from
1091 // the top of the stack as returned by Shape::getBounds()
1092 rShape->getBounds().getWidth(),
1093 &ShapeAttributeLayer::getWidth,
1094 &ShapeAttributeLayer::setWidth,
1095 // convert expression parser value from relative page size
1096 rSlideSize.getX(),
1097 eAttrType,
1098 pBox2DWorld );
1100 case AttributeType::PosX:
1101 return makeGenericAnimation( rShapeManager,
1102 nFlags,
1103 &ShapeAttributeLayer::isPosXValid,
1104 // TODO(F1): Check whether _shape_ bounds are correct here.
1105 // Theoretically, our AttrLayer is way down the stack, and
1106 // we only have to consider _that_ value, not the one from
1107 // the top of the stack as returned by Shape::getBounds()
1108 rShape->getBounds().getCenterX(),
1109 &ShapeAttributeLayer::getPosX,
1110 &ShapeAttributeLayer::setPosX,
1111 // convert expression parser value from relative page size
1112 rSlideSize.getX(),
1113 eAttrType,
1114 pBox2DWorld );
1116 case AttributeType::PosY:
1117 return makeGenericAnimation( rShapeManager,
1118 nFlags,
1119 &ShapeAttributeLayer::isPosYValid,
1120 // TODO(F1): Check whether _shape_ bounds are correct here.
1121 // Theoretically, our AttrLayer is way down the stack, and
1122 // we only have to consider _that_ value, not the one from
1123 // the top of the stack as returned by Shape::getBounds()
1124 rShape->getBounds().getCenterY(),
1125 &ShapeAttributeLayer::getPosY,
1126 &ShapeAttributeLayer::setPosY,
1127 // convert expression parser value from relative page size
1128 rSlideSize.getY(),
1129 eAttrType,
1130 pBox2DWorld );
1133 return NumberAnimationSharedPtr();
1136 EnumAnimationSharedPtr AnimationFactory::createEnumPropertyAnimation( const OUString& rAttrName,
1137 const AnimatableShapeSharedPtr& rShape,
1138 const ShapeManagerSharedPtr& rShapeManager,
1139 const ::basegfx::B2DVector& /*rSlideSize*/,
1140 const box2d::utils::Box2DWorldSharedPtr& pBox2DWorld,
1141 int nFlags )
1143 // ATTENTION: When changing this map, also the classifyAttributeName() method must
1144 // be checked and possibly adapted in their switch statement
1145 AttributeType eAttrType = mapAttributeName( rAttrName );
1146 switch( eAttrType )
1148 default:
1149 case AttributeType::Invalid:
1150 ENSURE_OR_THROW( false,
1151 "AnimationFactory::createEnumPropertyAnimation(): Unknown attribute" );
1152 break;
1154 case AttributeType::CharColor:
1155 case AttributeType::CharFontName:
1156 case AttributeType::Color:
1157 case AttributeType::DimColor:
1158 case AttributeType::FillColor:
1159 case AttributeType::LineColor:
1160 case AttributeType::Visibility:
1161 case AttributeType::CharHeight:
1162 case AttributeType::CharWeight:
1163 case AttributeType::Height:
1164 case AttributeType::Opacity:
1165 case AttributeType::Rotate:
1166 case AttributeType::SkewX:
1167 case AttributeType::SkewY:
1168 case AttributeType::Width:
1169 case AttributeType::PosX:
1170 case AttributeType::PosY:
1171 ENSURE_OR_THROW( false,
1172 "AnimationFactory::createEnumPropertyAnimation(): Attribute type mismatch" );
1173 break;
1176 case AttributeType::FillStyle:
1177 return makeGenericAnimation<EnumAnimation>( rShapeManager,
1178 nFlags,
1179 &ShapeAttributeLayer::isFillStyleValid,
1180 sal::static_int_cast<sal_Int16>(
1181 getDefault<drawing::FillStyle>( rShape, rAttrName )),
1182 &ShapeAttributeLayer::getFillStyle,
1183 &ShapeAttributeLayer::setFillStyle,
1184 eAttrType,
1185 pBox2DWorld );
1187 case AttributeType::LineStyle:
1188 return makeGenericAnimation<EnumAnimation>( rShapeManager,
1189 nFlags,
1190 &ShapeAttributeLayer::isLineStyleValid,
1191 sal::static_int_cast<sal_Int16>(
1192 getDefault<drawing::LineStyle>( rShape, rAttrName )),
1193 &ShapeAttributeLayer::getLineStyle,
1194 &ShapeAttributeLayer::setLineStyle,
1195 eAttrType,
1196 pBox2DWorld );
1198 case AttributeType::CharPosture:
1199 return makeGenericAnimation<EnumAnimation>( rShapeManager,
1200 nFlags,
1201 &ShapeAttributeLayer::isCharPostureValid,
1202 sal::static_int_cast<sal_Int16>(
1203 getDefault<awt::FontSlant>( rShape, rAttrName )),
1204 &ShapeAttributeLayer::getCharPosture,
1205 &ShapeAttributeLayer::setCharPosture,
1206 eAttrType,
1207 pBox2DWorld );
1209 case AttributeType::CharUnderline:
1210 return makeGenericAnimation<EnumAnimation>( rShapeManager,
1211 nFlags,
1212 &ShapeAttributeLayer::isUnderlineModeValid,
1213 getDefault<sal_Int16>( rShape, rAttrName ),
1214 &ShapeAttributeLayer::getUnderlineMode,
1215 &ShapeAttributeLayer::setUnderlineMode,
1216 eAttrType,
1217 pBox2DWorld );
1220 return EnumAnimationSharedPtr();
1223 ColorAnimationSharedPtr AnimationFactory::createColorPropertyAnimation( const OUString& rAttrName,
1224 const AnimatableShapeSharedPtr& rShape,
1225 const ShapeManagerSharedPtr& rShapeManager,
1226 const ::basegfx::B2DVector& /*rSlideSize*/,
1227 const box2d::utils::Box2DWorldSharedPtr& pBox2DWorld,
1228 int nFlags )
1230 // ATTENTION: When changing this map, also the classifyAttributeName() method must
1231 // be checked and possibly adapted in their switch statement
1232 AttributeType eAttrType = mapAttributeName(rAttrName);
1233 switch( eAttrType )
1235 default:
1236 case AttributeType::Invalid:
1237 ENSURE_OR_THROW( false,
1238 "AnimationFactory::createColorPropertyAnimation(): Unknown attribute" );
1239 break;
1241 case AttributeType::CharFontName:
1242 case AttributeType::CharHeight:
1243 case AttributeType::CharPosture:
1244 case AttributeType::CharUnderline:
1245 case AttributeType::CharWeight:
1246 case AttributeType::FillStyle:
1247 case AttributeType::Height:
1248 case AttributeType::LineStyle:
1249 case AttributeType::Opacity:
1250 case AttributeType::Rotate:
1251 case AttributeType::SkewX:
1252 case AttributeType::SkewY:
1253 case AttributeType::Visibility:
1254 case AttributeType::Width:
1255 case AttributeType::PosX:
1256 case AttributeType::PosY:
1257 ENSURE_OR_THROW( false,
1258 "AnimationFactory::createColorPropertyAnimation(): Attribute type mismatch" );
1259 break;
1261 case AttributeType::CharColor:
1262 return makeGenericAnimation<ColorAnimation>( rShapeManager,
1263 nFlags,
1264 &ShapeAttributeLayer::isCharColorValid,
1265 getDefault<RGBColor>( rShape, rAttrName ),
1266 &ShapeAttributeLayer::getCharColor,
1267 &ShapeAttributeLayer::setCharColor,
1268 eAttrType,
1269 pBox2DWorld );
1271 case AttributeType::Color:
1272 // TODO(F2): This is just mapped to fill color to make it work
1273 return makeGenericAnimation<ColorAnimation>( rShapeManager,
1274 nFlags,
1275 &ShapeAttributeLayer::isFillColorValid,
1276 getDefault<RGBColor>( rShape, rAttrName ),
1277 &ShapeAttributeLayer::getFillColor,
1278 &ShapeAttributeLayer::setFillColor,
1279 eAttrType,
1280 pBox2DWorld );
1282 case AttributeType::DimColor:
1283 return makeGenericAnimation<ColorAnimation>( rShapeManager,
1284 nFlags,
1285 &ShapeAttributeLayer::isDimColorValid,
1286 getDefault<RGBColor>( rShape, rAttrName ),
1287 &ShapeAttributeLayer::getDimColor,
1288 &ShapeAttributeLayer::setDimColor,
1289 eAttrType,
1290 pBox2DWorld );
1292 case AttributeType::FillColor:
1293 return makeGenericAnimation<ColorAnimation>( rShapeManager,
1294 nFlags,
1295 &ShapeAttributeLayer::isFillColorValid,
1296 getDefault<RGBColor>( rShape, rAttrName ),
1297 &ShapeAttributeLayer::getFillColor,
1298 &ShapeAttributeLayer::setFillColor,
1299 eAttrType,
1300 pBox2DWorld );
1302 case AttributeType::LineColor:
1303 return makeGenericAnimation<ColorAnimation>( rShapeManager,
1304 nFlags,
1305 &ShapeAttributeLayer::isLineColorValid,
1306 getDefault<RGBColor>( rShape, rAttrName ),
1307 &ShapeAttributeLayer::getLineColor,
1308 &ShapeAttributeLayer::setLineColor,
1309 eAttrType,
1310 pBox2DWorld );
1313 return ColorAnimationSharedPtr();
1316 PairAnimationSharedPtr AnimationFactory::createPairPropertyAnimation( const AnimatableShapeSharedPtr& rShape,
1317 const ShapeManagerSharedPtr& rShapeManager,
1318 const ::basegfx::B2DVector& rSlideSize,
1319 sal_Int16 nTransformType,
1320 int nFlags )
1322 const ::basegfx::B2DRectangle& rBounds( rShape->getBounds() );
1324 switch( nTransformType )
1326 case animations::AnimationTransformType::SCALE:
1327 return std::make_shared<TupleAnimation< ::basegfx::B2DSize >>(
1328 rShapeManager,
1329 nFlags,
1330 &ShapeAttributeLayer::isWidthValid,
1331 &ShapeAttributeLayer::isHeightValid,
1332 // TODO(F1): Check whether _shape_ bounds are correct here.
1333 // Theoretically, our AttrLayer is way down the stack, and
1334 // we only have to consider _that_ value, not the one from
1335 // the top of the stack as returned by Shape::getBounds()
1336 rBounds.getRange(),
1337 rBounds.getRange(),
1338 &ShapeAttributeLayer::getWidth,
1339 &ShapeAttributeLayer::getHeight,
1340 &ShapeAttributeLayer::setSize );
1342 case animations::AnimationTransformType::TRANSLATE:
1343 return std::make_shared<TupleAnimation< ::basegfx::B2DPoint >>(
1344 rShapeManager,
1345 nFlags,
1346 &ShapeAttributeLayer::isPosXValid,
1347 &ShapeAttributeLayer::isPosYValid,
1348 // TODO(F1): Check whether _shape_ bounds are correct here.
1349 // Theoretically, our AttrLayer is way down the stack, and
1350 // we only have to consider _that_ value, not the one from
1351 // the top of the stack as returned by Shape::getBounds()
1352 rBounds.getCenter(),
1353 rSlideSize,
1354 &ShapeAttributeLayer::getPosX,
1355 &ShapeAttributeLayer::getPosY,
1356 &ShapeAttributeLayer::setPosition );
1358 default:
1359 ENSURE_OR_THROW( false,
1360 "AnimationFactory::createPairPropertyAnimation(): Attribute type mismatch" );
1361 break;
1364 return PairAnimationSharedPtr();
1367 StringAnimationSharedPtr AnimationFactory::createStringPropertyAnimation( const OUString& rAttrName,
1368 const AnimatableShapeSharedPtr& rShape,
1369 const ShapeManagerSharedPtr& rShapeManager,
1370 const ::basegfx::B2DVector& /*rSlideSize*/,
1371 const box2d::utils::Box2DWorldSharedPtr& pBox2DWorld,
1372 int nFlags )
1374 // ATTENTION: When changing this map, also the classifyAttributeName() method must
1375 // be checked and possibly adapted in their switch statement
1376 AttributeType eAttrType = mapAttributeName(rAttrName);
1377 switch( eAttrType )
1379 default:
1380 case AttributeType::Invalid:
1381 ENSURE_OR_THROW( false,
1382 "AnimationFactory::createStringPropertyAnimation(): Unknown attribute" );
1383 break;
1385 case AttributeType::CharColor:
1386 case AttributeType::CharHeight:
1387 case AttributeType::CharUnderline:
1388 case AttributeType::Color:
1389 case AttributeType::DimColor:
1390 case AttributeType::FillColor:
1391 case AttributeType::Height:
1392 case AttributeType::LineColor:
1393 case AttributeType::Opacity:
1394 case AttributeType::Rotate:
1395 case AttributeType::SkewX:
1396 case AttributeType::SkewY:
1397 case AttributeType::Visibility:
1398 case AttributeType::Width:
1399 case AttributeType::PosX:
1400 case AttributeType::PosY:
1401 case AttributeType::CharPosture:
1402 case AttributeType::CharWeight:
1403 case AttributeType::FillStyle:
1404 case AttributeType::LineStyle:
1405 ENSURE_OR_THROW( false,
1406 "AnimationFactory::createStringPropertyAnimation(): Attribute type mismatch" );
1407 break;
1409 case AttributeType::CharFontName:
1410 return makeGenericAnimation<StringAnimation>( rShapeManager,
1411 nFlags,
1412 &ShapeAttributeLayer::isFontFamilyValid,
1413 getDefault< OUString >( rShape, rAttrName ),
1414 &ShapeAttributeLayer::getFontFamily,
1415 &ShapeAttributeLayer::setFontFamily,
1416 eAttrType,
1417 pBox2DWorld );
1420 return StringAnimationSharedPtr();
1423 BoolAnimationSharedPtr AnimationFactory::createBoolPropertyAnimation( const OUString& rAttrName,
1424 const AnimatableShapeSharedPtr& /*rShape*/,
1425 const ShapeManagerSharedPtr& rShapeManager,
1426 const ::basegfx::B2DVector& /*rSlideSize*/,
1427 const box2d::utils::Box2DWorldSharedPtr& pBox2DWorld,
1428 int nFlags )
1430 // ATTENTION: When changing this map, also the classifyAttributeName() method must
1431 // be checked and possibly adapted in their switch statement
1432 AttributeType eAttrType = mapAttributeName(rAttrName);
1433 switch( eAttrType )
1435 default:
1436 case AttributeType::Invalid:
1437 ENSURE_OR_THROW( false,
1438 "AnimationFactory::createBoolPropertyAnimation(): Unknown attribute" );
1439 break;
1441 case AttributeType::CharColor:
1442 case AttributeType::CharFontName:
1443 case AttributeType::CharHeight:
1444 case AttributeType::CharPosture:
1445 case AttributeType::CharWeight:
1446 case AttributeType::Color:
1447 case AttributeType::DimColor:
1448 case AttributeType::FillColor:
1449 case AttributeType::FillStyle:
1450 case AttributeType::Height:
1451 case AttributeType::LineColor:
1452 case AttributeType::LineStyle:
1453 case AttributeType::Opacity:
1454 case AttributeType::Rotate:
1455 case AttributeType::SkewX:
1456 case AttributeType::SkewY:
1457 case AttributeType::Width:
1458 case AttributeType::PosX:
1459 case AttributeType::PosY:
1460 case AttributeType::CharUnderline:
1461 ENSURE_OR_THROW( false,
1462 "AnimationFactory::createBoolPropertyAnimation(): Attribute type mismatch" );
1463 break;
1465 case AttributeType::Visibility:
1466 return makeGenericAnimation<BoolAnimation>( rShapeManager,
1467 nFlags,
1468 &ShapeAttributeLayer::isVisibilityValid,
1469 // TODO(F1): Is there a corresponding shape property?
1470 true,
1471 &ShapeAttributeLayer::getVisibility,
1472 &ShapeAttributeLayer::setVisibility,
1473 eAttrType,
1474 pBox2DWorld );
1477 return BoolAnimationSharedPtr();
1480 NumberAnimationSharedPtr AnimationFactory::createPathMotionAnimation( const OUString& rSVGDPath,
1481 sal_Int16 nAdditive,
1482 const AnimatableShapeSharedPtr& /*rShape*/,
1483 const ShapeManagerSharedPtr& rShapeManager,
1484 const ::basegfx::B2DVector& rSlideSize,
1485 const box2d::utils::Box2DWorldSharedPtr& pBox2DWorld,
1486 int nFlags )
1488 return std::make_shared<PathAnimation>( rSVGDPath, nAdditive,
1489 rShapeManager,
1490 rSlideSize,
1491 nFlags,
1492 pBox2DWorld);
1495 NumberAnimationSharedPtr AnimationFactory::createPhysicsAnimation( const box2d::utils::Box2DWorldSharedPtr& pBox2DWorld,
1496 const double fDuration,
1497 const ShapeManagerSharedPtr& rShapeManager,
1498 const ::basegfx::B2DVector& rSlideSize,
1499 const ::basegfx::B2DVector& rStartVelocity,
1500 const double fDensity,
1501 const double fBounciness,
1502 int nFlags )
1504 return std::make_shared<PhysicsAnimation>( pBox2DWorld, fDuration,
1505 rShapeManager,
1506 rSlideSize,
1507 rStartVelocity,
1508 fDensity,
1509 fBounciness,
1510 nFlags );
1515 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */