blob: 132de8b7f7dafc5dc69f5464c026f92426f1cba4 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_slideshow.hxx"
// must be first
#include <canvas/debug.hxx>
#include <tools/diagnose_ex.h>
#include <canvas/verbosetrace.hxx>
#include <animationfactory.hxx>
#include <attributemap.hxx>
#include <com/sun/star/animations/AnimationAdditiveMode.hpp>
#include <com/sun/star/animations/AnimationTransformType.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/awt/FontSlant.hpp>
#include <com/sun/star/awt/FontUnderline.hpp>
#include <com/sun/star/awt/FontWeight.hpp>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <functional>
using namespace ::com::sun::star;
namespace slideshow
{
namespace internal
{
namespace
{
// attention, there is a similar implementation of Animation in
// transitions/transitionfactory.cxx
template< typename ValueT > class TupleAnimation : public PairAnimation
{
public:
TupleAnimation( const ShapeManagerSharedPtr& rShapeManager,
int nFlags,
bool (ShapeAttributeLayer::*pIs1stValid)() const,
bool (ShapeAttributeLayer::*pIs2ndValid)() const,
const ValueT& rDefaultValue,
const ::basegfx::B2DSize& rReferenceSize,
double (ShapeAttributeLayer::*pGet1stValue)() const,
double (ShapeAttributeLayer::*pGet2ndValue)() const,
void (ShapeAttributeLayer::*pSetValue)( const ValueT& ) ) :
mpShape(),
mpAttrLayer(),
mpShapeManager( rShapeManager ),
mpIs1stValidFunc(pIs1stValid),
mpIs2ndValidFunc(pIs2ndValid),
mpGet1stValueFunc(pGet1stValue),
mpGet2ndValueFunc(pGet2ndValue),
mpSetValueFunc(pSetValue),
mnFlags( nFlags ),
maReferenceSize( rReferenceSize ),
maDefaultValue( rDefaultValue ),
mbAnimationStarted( false )
{
ENSURE_OR_THROW( rShapeManager,
"TupleAnimation::TupleAnimation(): Invalid ShapeManager" );
ENSURE_OR_THROW( pIs1stValid && pIs2ndValid && pGet1stValue && pGet2ndValue && pSetValue,
"TupleAnimation::TupleAnimation(): One of the method pointers is NULL" );
}
~TupleAnimation()
{
end_();
}
// Animation interface
// -------------------
virtual void prefetch( const AnimatableShapeSharedPtr&,
const ShapeAttributeLayerSharedPtr& )
{}
virtual void start( const AnimatableShapeSharedPtr& rShape,
const ShapeAttributeLayerSharedPtr& rAttrLayer )
{
OSL_ENSURE( !mpShape,
"TupleAnimation::start(): Shape already set" );
OSL_ENSURE( !mpAttrLayer,
"TupleAnimation::start(): Attribute layer already set" );
mpShape = rShape;
mpAttrLayer = rAttrLayer;
ENSURE_OR_THROW( rShape,
"TupleAnimation::start(): Invalid shape" );
ENSURE_OR_THROW( rAttrLayer,
"TupleAnimation::start(): Invalid attribute layer" );
if( !mbAnimationStarted )
{
mbAnimationStarted = true;
if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
mpShapeManager->enterAnimationMode( mpShape );
}
}
virtual void end() { end_(); }
void end_()
{
if( mbAnimationStarted )
{
mbAnimationStarted = false;
if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
mpShapeManager->leaveAnimationMode( mpShape );
if( mpShape->isContentChanged() )
mpShapeManager->notifyShapeUpdate( mpShape );
}
}
// PairAnimation interface
// -----------------------
virtual bool operator()( const ::basegfx::B2DTuple& rValue )
{
ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
"TupleAnimation::operator(): Invalid ShapeAttributeLayer" );
ValueT aValue( rValue.getX(),
rValue.getY() );
// Activitis get values from the expression parser,
// which returns _relative_ sizes/positions.
// Convert back relative to reference coordinate system
aValue *= maReferenceSize;
((*mpAttrLayer).*mpSetValueFunc)( aValue );
if( mpShape->isContentChanged() )
mpShapeManager->notifyShapeUpdate( mpShape );
return true;
}
virtual ::basegfx::B2DTuple getUnderlyingValue() const
{
ENSURE_OR_THROW( mpAttrLayer,
"TupleAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
::basegfx::B2DTuple aRetVal;
// deviated from the (*shared_ptr).*mpFuncPtr
// notation here, since gcc does not seem to parse
// that as a member function call anymore.
aRetVal.setX( (mpAttrLayer.get()->*mpIs1stValidFunc)() ?
(mpAttrLayer.get()->*mpGet1stValueFunc)() :
maDefaultValue.getX() );
aRetVal.setY( (mpAttrLayer.get()->*mpIs2ndValidFunc)() ?
(mpAttrLayer.get()->*mpGet2ndValueFunc)() :
maDefaultValue.getY() );
// Activities get values from the expression
// parser, which returns _relative_
// sizes/positions. Convert start value to the
// same coordinate space (i.e. relative to given
// reference size).
aRetVal /= maReferenceSize;
return aRetVal;
}
private:
AnimatableShapeSharedPtr mpShape;
ShapeAttributeLayerSharedPtr mpAttrLayer;
ShapeManagerSharedPtr mpShapeManager;
bool (ShapeAttributeLayer::*mpIs1stValidFunc)() const;
bool (ShapeAttributeLayer::*mpIs2ndValidFunc)() const;
double (ShapeAttributeLayer::*mpGet1stValueFunc)() const;
double (ShapeAttributeLayer::*mpGet2ndValueFunc)() const;
void (ShapeAttributeLayer::*mpSetValueFunc)( const ValueT& );
const int mnFlags;
const ::basegfx::B2DSize maReferenceSize;
const ValueT maDefaultValue;
bool mbAnimationStarted;
};
class PathAnimation : public NumberAnimation
{
public:
PathAnimation( const ::rtl::OUString& rSVGDPath,
sal_Int16 nAdditive,
const ShapeManagerSharedPtr& rShapeManager,
const ::basegfx::B2DVector& rSlideSize,
int nFlags ) :
maPathPoly(),
mpShape(),
mpAttrLayer(),
mpShapeManager( rShapeManager ),
maPageSize( rSlideSize ),
maShapeOrig(),
mnFlags( nFlags ),
mbAnimationStarted( false ),
mnAdditive( nAdditive )
{
ENSURE_OR_THROW( rShapeManager,
"PathAnimation::PathAnimation(): Invalid ShapeManager" );
::basegfx::B2DPolyPolygon aPolyPoly;
ENSURE_OR_THROW( ::basegfx::tools::importFromSvgD( aPolyPoly, rSVGDPath, false, 0 ),
"PathAnimation::PathAnimation(): failed to parse SVG:d path" );
ENSURE_OR_THROW( aPolyPoly.count() == 1,
"PathAnimation::PathAnimation(): motion path consists of multiple/zero polygon(s)" );
// TODO(F2): Since getPositionRelative() currently
// cannot handle beziers, have to subdivide.
// AW: Should be no longer necessary; getPositionRelative is now bezier-safe
maPathPoly = ::basegfx::tools::adaptiveSubdivideByAngle(aPolyPoly.getB2DPolygon(0) );
}
~PathAnimation()
{
end_();
}
// Animation interface
// -------------------
virtual void prefetch( const AnimatableShapeSharedPtr&,
const ShapeAttributeLayerSharedPtr& )
{}
virtual void start( const AnimatableShapeSharedPtr& rShape,
const ShapeAttributeLayerSharedPtr& rAttrLayer )
{
OSL_ENSURE( !mpShape,
"PathAnimation::start(): Shape already set" );
OSL_ENSURE( !mpAttrLayer,
"PathAnimation::start(): Attribute layer already set" );
mpShape = rShape;
mpAttrLayer = rAttrLayer;
ENSURE_OR_THROW( rShape,
"PathAnimation::start(): Invalid shape" );
ENSURE_OR_THROW( rAttrLayer,
"PathAnimation::start(): Invalid attribute layer" );
// TODO(F1): Check whether _shape_ bounds are correct here.
// Theoretically, our AttrLayer is way down the stack, and
// we only have to consider _that_ value, not the one from
// the top of the stack as returned by Shape::getBounds()
if( mnAdditive == animations::AnimationAdditiveMode::SUM )
maShapeOrig = mpShape->getBounds().getCenter();
else
maShapeOrig = mpShape->getDomBounds().getCenter();
if( !mbAnimationStarted )
{
mbAnimationStarted = true;
if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
mpShapeManager->enterAnimationMode( mpShape );
}
}
virtual void end() { end_(); }
void end_()
{
if( mbAnimationStarted )
{
mbAnimationStarted = false;
if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
mpShapeManager->leaveAnimationMode( mpShape );
if( mpShape->isContentChanged() )
mpShapeManager->notifyShapeUpdate( mpShape );
}
}
// NumberAnimation interface
// -----------------------
virtual bool operator()( double nValue )
{
ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
"PathAnimation::operator(): Invalid ShapeAttributeLayer" );
::basegfx::B2DPoint rOutPos = ::basegfx::tools::getPositionRelative( maPathPoly,
nValue );
// TODO(F1): Determine whether the path is
// absolute, or shape-relative.
// interpret path as page-relative. Scale up with page size
rOutPos *= maPageSize;
// TODO(F1): Determine whether the path origin is
// absolute, or shape-relative.
// interpret path as shape-originated. Offset to shape position
rOutPos += maShapeOrig;
mpAttrLayer->setPosition( rOutPos );
if( mpShape->isContentChanged() )
mpShapeManager->notifyShapeUpdate( mpShape );
return true;
}
virtual double getUnderlyingValue() const
{
ENSURE_OR_THROW( mpAttrLayer,
"PathAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
return 0.0; // though this should be used in concert with
// ActivitiesFactory::createSimpleActivity, better
// explicitely name our start value.
// Permissible range for operator() above is [0,1]
}
private:
::basegfx::B2DPolygon maPathPoly;
AnimatableShapeSharedPtr mpShape;
ShapeAttributeLayerSharedPtr mpAttrLayer;
ShapeManagerSharedPtr mpShapeManager;
const ::basegfx::B2DSize maPageSize;
::basegfx::B2DPoint maShapeOrig;
const int mnFlags;
bool mbAnimationStarted;
sal_Int16 mnAdditive;
};
/** GenericAnimation template
This template makes heavy use of SFINAE, only one of
the operator()() methods will compile for each of the
base classes.
Note that we omit the virtual keyword on the
operator()() overrides and getUnderlyingValue() methods on
purpose; those that actually do override baseclass
virtual methods inherit the property, and the others
won't increase our vtable. What's more, having all
those methods in the vtable actually creates POIs for
them, which breaks the whole SFINAE concept (IOW, this
template won't compile any longer).
@tpl AnimationBase
Type of animation to generate (determines the
interface GenericAnimation will implement). Must be
one of NumberAnimation, ColorAnimation,
StringAnimation, PairAnimation or BoolAnimation.
@tpl ModifierFunctor
Type of a functor object, which can optionally be used to
modify the getter/setter values.
*/
template< typename AnimationBase, typename ModifierFunctor > class GenericAnimation : public AnimationBase
{
public:
typedef typename AnimationBase::ValueType ValueT;
/** Create generic animation
@param pIsValid
Function pointer to one of the is*Valid
methods. Used to either take the given getter
method, or the given default value for the start value.
@param rDefaultValue
Default value, to take as the start value if
is*Valid returns false.
@param pGetValue
Getter method, to fetch start value if valid.
@param pSetValue
Setter method. This one puts the current animation
value to the ShapeAttributeLayer.
@param rGetterModifier
Modifies up values retrieved from the pGetValue method.
Must provide operator()( const ValueT& ) method.
@param rSetterModifier
Modifies up values before passing them to the pSetValue method.
Must provide operator()( const ValueT& ) method.
*/
GenericAnimation( const ShapeManagerSharedPtr& rShapeManager,
int nFlags,
bool (ShapeAttributeLayer::*pIsValid)() const,
const ValueT& rDefaultValue,
ValueT (ShapeAttributeLayer::*pGetValue)() const,
void (ShapeAttributeLayer::*pSetValue)( const ValueT& ),
const ModifierFunctor& rGetterModifier,
const ModifierFunctor& rSetterModifier ) :
mpShape(),
mpAttrLayer(),
mpShapeManager( rShapeManager ),
mpIsValidFunc(pIsValid),
mpGetValueFunc(pGetValue),
mpSetValueFunc(pSetValue),
maGetterModifier( rGetterModifier ),
maSetterModifier( rSetterModifier ),
mnFlags( nFlags ),
maDefaultValue(rDefaultValue),
mbAnimationStarted( false )
{
ENSURE_OR_THROW( rShapeManager,
"GenericAnimation::GenericAnimation(): Invalid ShapeManager" );
ENSURE_OR_THROW( pIsValid && pGetValue && pSetValue,
"GenericAnimation::GenericAnimation(): One of the method pointers is NULL" );
}
~GenericAnimation()
{
end_();
}
// Animation interface
// -------------------
virtual void prefetch( const AnimatableShapeSharedPtr&,
const ShapeAttributeLayerSharedPtr& )
{}
virtual void start( const AnimatableShapeSharedPtr& rShape,
const ShapeAttributeLayerSharedPtr& rAttrLayer )
{
OSL_ENSURE( !mpShape,
"GenericAnimation::start(): Shape already set" );
OSL_ENSURE( !mpAttrLayer,
"GenericAnimation::start(): Attribute layer already set" );
mpShape = rShape;
mpAttrLayer = rAttrLayer;
ENSURE_OR_THROW( rShape,
"GenericAnimation::start(): Invalid shape" );
ENSURE_OR_THROW( rAttrLayer,
"GenericAnimation::start(): Invalid attribute layer" );
// only start animation once per repeated start() call,
// and only if sprites should be used for display
if( !mbAnimationStarted )
{
mbAnimationStarted = true;
if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
mpShapeManager->enterAnimationMode( mpShape );
}
}
virtual void end() { end_(); }
void end_()
{
// TODO(Q2): Factor out common code (most
// prominently start() and end()) into base class
// only stop animation once per repeated end() call,
// and only if sprites are used for display
if( mbAnimationStarted )
{
mbAnimationStarted = false;
if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
mpShapeManager->leaveAnimationMode( mpShape );
// Attention, this notifyShapeUpdate() is
// somewhat delicate here. Calling it
// unconditional (i.e. not guarded by
// mbAnimationStarted) will lead to shapes
// snapping back to their original state just
// before the slide ends. Not calling it at
// all might swallow final animation
// states. The current implementation relies
// on the fact that end() is either called by
// the Activity (then, the last animation
// state has been set, and corresponds to the
// shape's hold state), or by the animation
// node (then, it's a forced end, and we
// _have_ to snap back).
//
// To reiterate: normally, we're called from
// the Activity first, thus the
// notifyShapeUpdate() below will update to
// the last activity value.
// force shape update, activity might have changed
// state in the last round.
if( mpShape->isContentChanged() )
mpShapeManager->notifyShapeUpdate( mpShape );
}
}
// Derived Animation interface
// ---------------------------
/** For by-reference interfaces (B2DTuple, OUString)
*/
bool operator()( const ValueT& x )
{
ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
"GenericAnimation::operator(): Invalid ShapeAttributeLayer" );
((*mpAttrLayer).*mpSetValueFunc)( maSetterModifier( x ) );
if( mpShape->isContentChanged() )
mpShapeManager->notifyShapeUpdate( mpShape );
return true;
}
/** For by-value interfaces (bool, double)
*/
bool operator()( ValueT x )
{
ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
"GenericAnimation::operator(): Invalid ShapeAttributeLayer" );
((*mpAttrLayer).*mpSetValueFunc)( maSetterModifier( x ) );
if( mpShape->isContentChanged() )
mpShapeManager->notifyShapeUpdate( mpShape );
return true;
}
ValueT getUnderlyingValue() const
{
ENSURE_OR_THROW( mpAttrLayer,
"GenericAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
// deviated from the (*shared_ptr).*mpFuncPtr
// notation here, since gcc does not seem to parse
// that as a member function call anymore.
if( (mpAttrLayer.get()->*mpIsValidFunc)() )
return maGetterModifier( ((*mpAttrLayer).*mpGetValueFunc)() );
else
return maDefaultValue;
}
private:
AnimatableShapeSharedPtr mpShape;
ShapeAttributeLayerSharedPtr mpAttrLayer;
ShapeManagerSharedPtr mpShapeManager;
bool (ShapeAttributeLayer::*mpIsValidFunc)() const;
ValueT (ShapeAttributeLayer::*mpGetValueFunc)() const;
void (ShapeAttributeLayer::*mpSetValueFunc)( const ValueT& );
ModifierFunctor maGetterModifier;
ModifierFunctor maSetterModifier;
const int mnFlags;
const ValueT maDefaultValue;
bool mbAnimationStarted;
};
/** Function template wrapper around GenericAnimation template
@tpl AnimationBase
Type of animation to generate (determines the
interface GenericAnimation will implement).
*/
template< typename AnimationBase > ::boost::shared_ptr< AnimationBase >
makeGenericAnimation( const ShapeManagerSharedPtr& rShapeManager,
int nFlags,
bool (ShapeAttributeLayer::*pIsValid)() const,
const typename AnimationBase::ValueType& rDefaultValue,
typename AnimationBase::ValueType (ShapeAttributeLayer::*pGetValue)() const,
void (ShapeAttributeLayer::*pSetValue)( const typename AnimationBase::ValueType& ) )
{
return ::boost::shared_ptr< AnimationBase >(
new GenericAnimation< AnimationBase,
::std::identity< typename AnimationBase::ValueType > >(
rShapeManager,
nFlags,
pIsValid,
rDefaultValue,
pGetValue,
pSetValue,
// no modification necessary, use identity functor here
std::identity< typename AnimationBase::ValueType >(),
std::identity< typename AnimationBase::ValueType >()));
}
class Scaler
{
public:
Scaler( double nScale ) :
mnScale( nScale )
{
}
double operator()( double nVal ) const
{
return mnScale * nVal;
}
private:
double mnScale;
};
/** Overload for NumberAnimations which need scaling (width,height,x,y currently)
*/
NumberAnimationSharedPtr makeGenericAnimation( const ShapeManagerSharedPtr& rShapeManager,
int nFlags,
bool (ShapeAttributeLayer::*pIsValid)() const,
double nDefaultValue,
double (ShapeAttributeLayer::*pGetValue)() const,
void (ShapeAttributeLayer::*pSetValue)( const double& ),
double nScaleValue )
{
return NumberAnimationSharedPtr(
new GenericAnimation< NumberAnimation, Scaler >( rShapeManager,
nFlags,
pIsValid,
nDefaultValue / nScaleValue,
pGetValue,
pSetValue,
Scaler( 1.0/nScaleValue ),
Scaler( nScaleValue ) ) );
}
uno::Any getShapeDefault( const AnimatableShapeSharedPtr& rShape,
const ::rtl::OUString& rPropertyName )
{
uno::Reference< drawing::XShape > xShape( rShape->getXShape() );
if( !xShape.is() )
return uno::Any(); // no regular shape, no defaults available
// extract relevant value from XShape's PropertySet
uno::Reference< beans::XPropertySet > xPropSet( xShape,
uno::UNO_QUERY );
ENSURE_OR_THROW( xPropSet.is(),
"getShapeDefault(): Cannot query property set from shape" );
return xPropSet->getPropertyValue( rPropertyName );
}
template< typename ValueType > ValueType getDefault( const AnimatableShapeSharedPtr& rShape,
const ::rtl::OUString& rPropertyName )
{
const uno::Any& rAny( getShapeDefault( rShape,
rPropertyName ) );
if( !rAny.hasValue() )
{
OSL_ENSURE( false, "getDefault(): cannot get requested shape property" );
OSL_TRACE( "getDefault(): cannot get '%s' shape property",
::rtl::OUStringToOString( rPropertyName,
RTL_TEXTENCODING_ASCII_US ).getStr() );
return ValueType();
}
else
{
ValueType aValue = ValueType();
if( !(rAny >>= aValue) )
{
OSL_ENSURE( false, "getDefault(): cannot extract requested shape property" );
OSL_TRACE( "getDefault(): cannot extract '%s' shape property",
::rtl::OUStringToOString( rPropertyName,
RTL_TEXTENCODING_ASCII_US ).getStr() );
return ValueType();
}
return aValue;
}
}
template<> RGBColor getDefault< RGBColor >( const AnimatableShapeSharedPtr& rShape,
const ::rtl::OUString& rPropertyName )
{
const uno::Any& rAny( getShapeDefault( rShape,
rPropertyName ) );
if( !rAny.hasValue() )
{
OSL_ENSURE( false, "getDefault(): cannot get requested shape color property" );
OSL_TRACE( "getDefault(): cannot get '%s' shape color property",
::rtl::OUStringToOString( rPropertyName,
RTL_TEXTENCODING_ASCII_US ).getStr() );
return RGBColor();
}
else
{
sal_Int32 nValue = 0;
if( !(rAny >>= nValue) )
{
OSL_ENSURE( false, "getDefault(): cannot extract requested shape color property" );
OSL_TRACE( "getDefault(): cannot extract '%s' shape color property",
::rtl::OUStringToOString( rPropertyName,
RTL_TEXTENCODING_ASCII_US ).getStr() );
return RGBColor();
}
// convert from 0xAARRGGBB API color to 0xRRGGBB00
// canvas color
return RGBColor( (nValue << 8U) & 0xFFFFFF00U );
}
}
}
AnimationFactory::AttributeClass AnimationFactory::classifyAttributeName( const ::rtl::OUString& rAttrName )
{
// ATTENTION: When changing this map, also the create*PropertyAnimation() methods must
// be checked and possibly adapted in their switch statements
// TODO(Q2): Since this map must be coherent with the various switch statements
// in the create*PropertyAnimation methods, try to unify into a single method or table
switch( mapAttributeName( rAttrName ) )
{
default:
// FALLTHROUGH intended
case ATTRIBUTE_INVALID:
return CLASS_UNKNOWN_PROPERTY;
case ATTRIBUTE_CHAR_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_DIMCOLOR:
// FALLTHROUGH intended
case ATTRIBUTE_FILL_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_LINE_COLOR:
return CLASS_COLOR_PROPERTY;
case ATTRIBUTE_CHAR_FONT_NAME:
return CLASS_STRING_PROPERTY;
case ATTRIBUTE_VISIBILITY:
return CLASS_BOOL_PROPERTY;
case ATTRIBUTE_CHAR_HEIGHT:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_WEIGHT:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_ROTATION:
// FALLTHROUGH intended
case ATTRIBUTE_HEIGHT:
// FALLTHROUGH intended
case ATTRIBUTE_OPACITY:
// FALLTHROUGH intended
case ATTRIBUTE_ROTATE:
// FALLTHROUGH intended
case ATTRIBUTE_SKEW_X:
// FALLTHROUGH intended
case ATTRIBUTE_SKEW_Y:
// FALLTHROUGH intended
case ATTRIBUTE_WIDTH:
// FALLTHROUGH intended
case ATTRIBUTE_POS_X:
// FALLTHROUGH intended
case ATTRIBUTE_POS_Y:
return CLASS_NUMBER_PROPERTY;
case ATTRIBUTE_CHAR_UNDERLINE:
// FALLTHROUGH intended
case ATTRIBUTE_FILL_STYLE:
// FALLTHROUGH intended
case ATTRIBUTE_LINE_STYLE:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_POSTURE:
return CLASS_ENUM_PROPERTY;
}
}
NumberAnimationSharedPtr AnimationFactory::createNumberPropertyAnimation( const ::rtl::OUString& rAttrName,
const AnimatableShapeSharedPtr& rShape,
const ShapeManagerSharedPtr& rShapeManager,
const ::basegfx::B2DVector& rSlideSize,
int nFlags )
{
// ATTENTION: When changing this map, also the classifyAttributeName() method must
// be checked and possibly adapted in their switch statement
switch( mapAttributeName( rAttrName ) )
{
default:
// FALLTHROUGH intended
case ATTRIBUTE_INVALID:
ENSURE_OR_THROW( false,
"AnimationFactory::createNumberPropertyAnimation(): Unknown attribute" );
break;
case ATTRIBUTE_CHAR_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_FONT_NAME:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_POSTURE:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_UNDERLINE:
// FALLTHROUGH intended
case ATTRIBUTE_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_DIMCOLOR:
// FALLTHROUGH intended
case ATTRIBUTE_FILL_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_FILL_STYLE:
// FALLTHROUGH intended
case ATTRIBUTE_LINE_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_LINE_STYLE:
// FALLTHROUGH intended
case ATTRIBUTE_VISIBILITY:
ENSURE_OR_THROW( false,
"AnimationFactory::createNumberPropertyAnimation(): Attribute type mismatch" );
break;
case ATTRIBUTE_CHAR_HEIGHT:
return makeGenericAnimation<NumberAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isCharScaleValid,
1.0, // CharHeight is a relative attribute, thus
// default is 1.0
&ShapeAttributeLayer::getCharScale,
&ShapeAttributeLayer::setCharScale );
case ATTRIBUTE_CHAR_WEIGHT:
return makeGenericAnimation<NumberAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isCharWeightValid,
getDefault<double>( rShape, rAttrName ),
&ShapeAttributeLayer::getCharWeight,
&ShapeAttributeLayer::setCharWeight );
case ATTRIBUTE_CHAR_ROTATION:
return makeGenericAnimation<NumberAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isCharRotationAngleValid,
getDefault<double>( rShape, rAttrName ),
&ShapeAttributeLayer::getCharRotationAngle,
&ShapeAttributeLayer::setCharRotationAngle );
case ATTRIBUTE_HEIGHT:
return makeGenericAnimation( rShapeManager,
nFlags,
&ShapeAttributeLayer::isHeightValid,
// TODO(F1): Check whether _shape_ bounds are correct here.
// Theoretically, our AttrLayer is way down the stack, and
// we only have to consider _that_ value, not the one from
// the top of the stack as returned by Shape::getBounds()
rShape->getBounds().getHeight(),
&ShapeAttributeLayer::getHeight,
&ShapeAttributeLayer::setHeight,
// convert expression parser value from relative page size
rSlideSize.getY() );
case ATTRIBUTE_OPACITY:
return makeGenericAnimation<NumberAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isAlphaValid,
// TODO(F1): Provide shape default here (FillTransparency?)
1.0,
&ShapeAttributeLayer::getAlpha,
&ShapeAttributeLayer::setAlpha );
case ATTRIBUTE_ROTATE:
return makeGenericAnimation<NumberAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isRotationAngleValid,
// NOTE: Since we paint the shape as-is from metafile,
// rotation angle is always 0.0, even for rotated shapes
0.0,
&ShapeAttributeLayer::getRotationAngle,
&ShapeAttributeLayer::setRotationAngle );
case ATTRIBUTE_SKEW_X:
return makeGenericAnimation<NumberAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isShearXAngleValid,
// TODO(F1): Is there any shape property for skew?
0.0,
&ShapeAttributeLayer::getShearXAngle,
&ShapeAttributeLayer::setShearXAngle );
case ATTRIBUTE_SKEW_Y:
return makeGenericAnimation<NumberAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isShearYAngleValid,
// TODO(F1): Is there any shape property for skew?
0.0,
&ShapeAttributeLayer::getShearYAngle,
&ShapeAttributeLayer::setShearYAngle );
case ATTRIBUTE_WIDTH:
return makeGenericAnimation( rShapeManager,
nFlags,
&ShapeAttributeLayer::isWidthValid,
// TODO(F1): Check whether _shape_ bounds are correct here.
// Theoretically, our AttrLayer is way down the stack, and
// we only have to consider _that_ value, not the one from
// the top of the stack as returned by Shape::getBounds()
rShape->getBounds().getWidth(),
&ShapeAttributeLayer::getWidth,
&ShapeAttributeLayer::setWidth,
// convert expression parser value from relative page size
rSlideSize.getX() );
case ATTRIBUTE_POS_X:
return makeGenericAnimation( rShapeManager,
nFlags,
&ShapeAttributeLayer::isPosXValid,
// TODO(F1): Check whether _shape_ bounds are correct here.
// Theoretically, our AttrLayer is way down the stack, and
// we only have to consider _that_ value, not the one from
// the top of the stack as returned by Shape::getBounds()
rShape->getBounds().getCenterX(),
&ShapeAttributeLayer::getPosX,
&ShapeAttributeLayer::setPosX,
// convert expression parser value from relative page size
rSlideSize.getX() );
case ATTRIBUTE_POS_Y:
return makeGenericAnimation( rShapeManager,
nFlags,
&ShapeAttributeLayer::isPosYValid,
// TODO(F1): Check whether _shape_ bounds are correct here.
// Theoretically, our AttrLayer is way down the stack, and
// we only have to consider _that_ value, not the one from
// the top of the stack as returned by Shape::getBounds()
rShape->getBounds().getCenterY(),
&ShapeAttributeLayer::getPosY,
&ShapeAttributeLayer::setPosY,
// convert expression parser value from relative page size
rSlideSize.getY() );
}
return NumberAnimationSharedPtr();
}
EnumAnimationSharedPtr AnimationFactory::createEnumPropertyAnimation( const ::rtl::OUString& rAttrName,
const AnimatableShapeSharedPtr& rShape,
const ShapeManagerSharedPtr& rShapeManager,
const ::basegfx::B2DVector& /*rSlideSize*/,
int nFlags )
{
// ATTENTION: When changing this map, also the classifyAttributeName() method must
// be checked and possibly adapted in their switch statement
switch( mapAttributeName( rAttrName ) )
{
default:
// FALLTHROUGH intended
case ATTRIBUTE_INVALID:
ENSURE_OR_THROW( false,
"AnimationFactory::createEnumPropertyAnimation(): Unknown attribute" );
break;
case ATTRIBUTE_CHAR_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_FONT_NAME:
// FALLTHROUGH intended
case ATTRIBUTE_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_DIMCOLOR:
// FALLTHROUGH intended
case ATTRIBUTE_FILL_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_LINE_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_VISIBILITY:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_HEIGHT:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_WEIGHT:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_ROTATION:
// FALLTHROUGH intended
case ATTRIBUTE_HEIGHT:
// FALLTHROUGH intended
case ATTRIBUTE_OPACITY:
// FALLTHROUGH intended
case ATTRIBUTE_ROTATE:
// FALLTHROUGH intended
case ATTRIBUTE_SKEW_X:
// FALLTHROUGH intended
case ATTRIBUTE_SKEW_Y:
// FALLTHROUGH intended
case ATTRIBUTE_WIDTH:
// FALLTHROUGH intended
case ATTRIBUTE_POS_X:
// FALLTHROUGH intended
case ATTRIBUTE_POS_Y:
ENSURE_OR_THROW( false,
"AnimationFactory::createEnumPropertyAnimation(): Attribute type mismatch" );
break;
case ATTRIBUTE_FILL_STYLE:
return makeGenericAnimation<EnumAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isFillStyleValid,
sal::static_int_cast<sal_Int16>(
getDefault<drawing::FillStyle>( rShape, rAttrName )),
&ShapeAttributeLayer::getFillStyle,
&ShapeAttributeLayer::setFillStyle );
case ATTRIBUTE_LINE_STYLE:
return makeGenericAnimation<EnumAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isLineStyleValid,
sal::static_int_cast<sal_Int16>(
getDefault<drawing::LineStyle>( rShape, rAttrName )),
&ShapeAttributeLayer::getLineStyle,
&ShapeAttributeLayer::setLineStyle );
case ATTRIBUTE_CHAR_POSTURE:
return makeGenericAnimation<EnumAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isCharPostureValid,
sal::static_int_cast<sal_Int16>(
getDefault<awt::FontSlant>( rShape, rAttrName )),
&ShapeAttributeLayer::getCharPosture,
&ShapeAttributeLayer::setCharPosture );
case ATTRIBUTE_CHAR_UNDERLINE:
return makeGenericAnimation<EnumAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isUnderlineModeValid,
getDefault<sal_Int16>( rShape, rAttrName ),
&ShapeAttributeLayer::getUnderlineMode,
&ShapeAttributeLayer::setUnderlineMode );
}
return EnumAnimationSharedPtr();
}
ColorAnimationSharedPtr AnimationFactory::createColorPropertyAnimation( const ::rtl::OUString& rAttrName,
const AnimatableShapeSharedPtr& rShape,
const ShapeManagerSharedPtr& rShapeManager,
const ::basegfx::B2DVector& /*rSlideSize*/,
int nFlags )
{
// ATTENTION: When changing this map, also the classifyAttributeName() method must
// be checked and possibly adapted in their switch statement
switch( mapAttributeName( rAttrName ) )
{
default:
// FALLTHROUGH intended
case ATTRIBUTE_INVALID:
ENSURE_OR_THROW( false,
"AnimationFactory::createColorPropertyAnimation(): Unknown attribute" );
break;
case ATTRIBUTE_CHAR_FONT_NAME:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_HEIGHT:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_POSTURE:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_ROTATION:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_UNDERLINE:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_WEIGHT:
// FALLTHROUGH intended
case ATTRIBUTE_FILL_STYLE:
// FALLTHROUGH intended
case ATTRIBUTE_HEIGHT:
// FALLTHROUGH intended
case ATTRIBUTE_LINE_STYLE:
// FALLTHROUGH intended
case ATTRIBUTE_OPACITY:
// FALLTHROUGH intended
case ATTRIBUTE_ROTATE:
// FALLTHROUGH intended
case ATTRIBUTE_SKEW_X:
// FALLTHROUGH intended
case ATTRIBUTE_SKEW_Y:
// FALLTHROUGH intended
case ATTRIBUTE_VISIBILITY:
// FALLTHROUGH intended
case ATTRIBUTE_WIDTH:
// FALLTHROUGH intended
case ATTRIBUTE_POS_X:
// FALLTHROUGH intended
case ATTRIBUTE_POS_Y:
ENSURE_OR_THROW( false,
"AnimationFactory::createColorPropertyAnimation(): Attribute type mismatch" );
break;
case ATTRIBUTE_CHAR_COLOR:
return makeGenericAnimation<ColorAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isCharColorValid,
getDefault<RGBColor>( rShape, rAttrName ),
&ShapeAttributeLayer::getCharColor,
&ShapeAttributeLayer::setCharColor );
case ATTRIBUTE_COLOR:
// TODO(F2): This is just mapped to fill color to make it work
return makeGenericAnimation<ColorAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isFillColorValid,
getDefault<RGBColor>( rShape, rAttrName ),
&ShapeAttributeLayer::getFillColor,
&ShapeAttributeLayer::setFillColor );
case ATTRIBUTE_DIMCOLOR:
return makeGenericAnimation<ColorAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isDimColorValid,
getDefault<RGBColor>( rShape, rAttrName ),
&ShapeAttributeLayer::getDimColor,
&ShapeAttributeLayer::setDimColor );
case ATTRIBUTE_FILL_COLOR:
return makeGenericAnimation<ColorAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isFillColorValid,
getDefault<RGBColor>( rShape, rAttrName ),
&ShapeAttributeLayer::getFillColor,
&ShapeAttributeLayer::setFillColor );
case ATTRIBUTE_LINE_COLOR:
return makeGenericAnimation<ColorAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isLineColorValid,
getDefault<RGBColor>( rShape, rAttrName ),
&ShapeAttributeLayer::getLineColor,
&ShapeAttributeLayer::setLineColor );
}
return ColorAnimationSharedPtr();
}
PairAnimationSharedPtr AnimationFactory::createPairPropertyAnimation( const AnimatableShapeSharedPtr& rShape,
const ShapeManagerSharedPtr& rShapeManager,
const ::basegfx::B2DVector& rSlideSize,
sal_Int16 nTransformType,
int nFlags )
{
const ::basegfx::B2DRectangle& rBounds( rShape->getBounds() );
switch( nTransformType )
{
case animations::AnimationTransformType::SCALE:
return PairAnimationSharedPtr(
new TupleAnimation< ::basegfx::B2DSize >(
rShapeManager,
nFlags,
&ShapeAttributeLayer::isWidthValid,
&ShapeAttributeLayer::isHeightValid,
// TODO(F1): Check whether _shape_ bounds are correct here.
// Theoretically, our AttrLayer is way down the stack, and
// we only have to consider _that_ value, not the one from
// the top of the stack as returned by Shape::getBounds()
rBounds.getRange(),
rBounds.getRange(),
&ShapeAttributeLayer::getWidth,
&ShapeAttributeLayer::getHeight,
&ShapeAttributeLayer::setSize ) );
case animations::AnimationTransformType::TRANSLATE:
return PairAnimationSharedPtr(
new TupleAnimation< ::basegfx::B2DPoint >(
rShapeManager,
nFlags,
&ShapeAttributeLayer::isPosXValid,
&ShapeAttributeLayer::isPosYValid,
// TODO(F1): Check whether _shape_ bounds are correct here.
// Theoretically, our AttrLayer is way down the stack, and
// we only have to consider _that_ value, not the one from
// the top of the stack as returned by Shape::getBounds()
rBounds.getCenter(),
rSlideSize,
&ShapeAttributeLayer::getPosX,
&ShapeAttributeLayer::getPosY,
&ShapeAttributeLayer::setPosition ) );
default:
ENSURE_OR_THROW( false,
"AnimationFactory::createPairPropertyAnimation(): Attribute type mismatch" );
break;
}
return PairAnimationSharedPtr();
}
StringAnimationSharedPtr AnimationFactory::createStringPropertyAnimation( const ::rtl::OUString& rAttrName,
const AnimatableShapeSharedPtr& rShape,
const ShapeManagerSharedPtr& rShapeManager,
const ::basegfx::B2DVector& /*rSlideSize*/,
int nFlags )
{
// ATTENTION: When changing this map, also the classifyAttributeName() method must
// be checked and possibly adapted in their switch statement
switch( mapAttributeName( rAttrName ) )
{
default:
// FALLTHROUGH intended
case ATTRIBUTE_INVALID:
ENSURE_OR_THROW( false,
"AnimationFactory::createStringPropertyAnimation(): Unknown attribute" );
break;
case ATTRIBUTE_CHAR_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_HEIGHT:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_ROTATION:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_UNDERLINE:
// FALLTHROUGH intended
case ATTRIBUTE_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_DIMCOLOR:
// FALLTHROUGH intended
case ATTRIBUTE_FILL_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_HEIGHT:
// FALLTHROUGH intended
case ATTRIBUTE_LINE_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_OPACITY:
// FALLTHROUGH intended
case ATTRIBUTE_ROTATE:
// FALLTHROUGH intended
case ATTRIBUTE_SKEW_X:
// FALLTHROUGH intended
case ATTRIBUTE_SKEW_Y:
// FALLTHROUGH intended
case ATTRIBUTE_VISIBILITY:
// FALLTHROUGH intended
case ATTRIBUTE_WIDTH:
// FALLTHROUGH intended
case ATTRIBUTE_POS_X:
// FALLTHROUGH intended
case ATTRIBUTE_POS_Y:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_POSTURE:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_WEIGHT:
// FALLTHROUGH intended
case ATTRIBUTE_FILL_STYLE:
// FALLTHROUGH intended
case ATTRIBUTE_LINE_STYLE:
ENSURE_OR_THROW( false,
"AnimationFactory::createStringPropertyAnimation(): Attribute type mismatch" );
break;
case ATTRIBUTE_CHAR_FONT_NAME:
return makeGenericAnimation<StringAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isFontFamilyValid,
getDefault< ::rtl::OUString >( rShape, rAttrName ),
&ShapeAttributeLayer::getFontFamily,
&ShapeAttributeLayer::setFontFamily );
}
return StringAnimationSharedPtr();
}
BoolAnimationSharedPtr AnimationFactory::createBoolPropertyAnimation( const ::rtl::OUString& rAttrName,
const AnimatableShapeSharedPtr& /*rShape*/,
const ShapeManagerSharedPtr& rShapeManager,
const ::basegfx::B2DVector& /*rSlideSize*/,
int nFlags )
{
// ATTENTION: When changing this map, also the classifyAttributeName() method must
// be checked and possibly adapted in their switch statement
switch( mapAttributeName( rAttrName ) )
{
default:
// FALLTHROUGH intended
case ATTRIBUTE_INVALID:
ENSURE_OR_THROW( false,
"AnimationFactory::createBoolPropertyAnimation(): Unknown attribute" );
break;
case ATTRIBUTE_CHAR_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_FONT_NAME:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_HEIGHT:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_POSTURE:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_ROTATION:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_WEIGHT:
// FALLTHROUGH intended
case ATTRIBUTE_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_DIMCOLOR:
// FALLTHROUGH intended
case ATTRIBUTE_FILL_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_FILL_STYLE:
// FALLTHROUGH intended
case ATTRIBUTE_HEIGHT:
// FALLTHROUGH intended
case ATTRIBUTE_LINE_COLOR:
// FALLTHROUGH intended
case ATTRIBUTE_LINE_STYLE:
// FALLTHROUGH intended
case ATTRIBUTE_OPACITY:
// FALLTHROUGH intended
case ATTRIBUTE_ROTATE:
// FALLTHROUGH intended
case ATTRIBUTE_SKEW_X:
// FALLTHROUGH intended
case ATTRIBUTE_SKEW_Y:
// FALLTHROUGH intended
case ATTRIBUTE_WIDTH:
// FALLTHROUGH intended
case ATTRIBUTE_POS_X:
// FALLTHROUGH intended
case ATTRIBUTE_POS_Y:
// FALLTHROUGH intended
case ATTRIBUTE_CHAR_UNDERLINE:
ENSURE_OR_THROW( false,
"AnimationFactory::createBoolPropertyAnimation(): Attribute type mismatch" );
break;
case ATTRIBUTE_VISIBILITY:
return makeGenericAnimation<BoolAnimation>( rShapeManager,
nFlags,
&ShapeAttributeLayer::isVisibilityValid,
// TODO(F1): Is there a corresponding shape property?
true,
&ShapeAttributeLayer::getVisibility,
&ShapeAttributeLayer::setVisibility );
}
return BoolAnimationSharedPtr();
}
NumberAnimationSharedPtr AnimationFactory::createPathMotionAnimation( const ::rtl::OUString& rSVGDPath,
sal_Int16 nAdditive,
const AnimatableShapeSharedPtr& /*rShape*/,
const ShapeManagerSharedPtr& rShapeManager,
const ::basegfx::B2DVector& rSlideSize,
int nFlags )
{
return NumberAnimationSharedPtr(
new PathAnimation( rSVGDPath, nAdditive,
rShapeManager,
rSlideSize,
nFlags ) );
}
}
}