1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_slideshow.hxx" 30 31 #include <canvas/debug.hxx> 32 #include <tools/diagnose_ex.h> 33 34 #include <comphelper/anytostring.hxx> 35 #include <cppuhelper/exc_hlp.hxx> 36 #include <basegfx/numeric/ftools.hxx> 37 #include <basegfx/matrix/b2dhommatrix.hxx> 38 #include <basegfx/polygon/b2dpolypolygontools.hxx> 39 40 #include <com/sun/star/animations/TransitionType.hpp> 41 #include <com/sun/star/animations/TransitionSubType.hpp> 42 43 #include "transitionfactory.hxx" 44 #include "transitiontools.hxx" 45 #include "parametricpolypolygonfactory.hxx" 46 #include "animationfactory.hxx" 47 #include "clippingfunctor.hxx" 48 49 #include <boost/bind.hpp> 50 51 52 using namespace ::com::sun::star; 53 54 namespace slideshow { 55 namespace internal { 56 57 /*************************************************** 58 *** *** 59 *** Shape Transition Effects *** 60 *** *** 61 ***************************************************/ 62 63 namespace { 64 65 class ClippingAnimation : public NumberAnimation 66 { 67 public: 68 ClippingAnimation( 69 const ParametricPolyPolygonSharedPtr& rPolygon, 70 const ShapeManagerSharedPtr& rShapeManager, 71 const TransitionInfo& rTransitionInfo, 72 bool bDirectionForward, 73 bool bModeIn ); 74 75 ~ClippingAnimation(); 76 77 // Animation interface 78 // ------------------- 79 virtual void prefetch( const AnimatableShapeSharedPtr& rShape, 80 const ShapeAttributeLayerSharedPtr& rAttrLayer ); 81 virtual void start( const AnimatableShapeSharedPtr& rShape, 82 const ShapeAttributeLayerSharedPtr& rAttrLayer ); 83 virtual void end(); 84 85 // NumberAnimation interface 86 // ----------------------- 87 virtual bool operator()( double nValue ); 88 virtual double getUnderlyingValue() const; 89 90 private: 91 void end_(); 92 93 AnimatableShapeSharedPtr mpShape; 94 ShapeAttributeLayerSharedPtr mpAttrLayer; 95 ShapeManagerSharedPtr mpShapeManager; 96 ClippingFunctor maClippingFunctor; 97 bool mbSpriteActive; 98 }; 99 100 ClippingAnimation::ClippingAnimation( 101 const ParametricPolyPolygonSharedPtr& rPolygon, 102 const ShapeManagerSharedPtr& rShapeManager, 103 const TransitionInfo& rTransitionInfo, 104 bool bDirectionForward, 105 bool bModeIn ) : 106 mpShape(), 107 mpAttrLayer(), 108 mpShapeManager( rShapeManager ), 109 maClippingFunctor( rPolygon, 110 rTransitionInfo, 111 bDirectionForward, 112 bModeIn ), 113 mbSpriteActive(false) 114 { 115 ENSURE_OR_THROW( 116 rShapeManager, 117 "ClippingAnimation::ClippingAnimation(): Invalid ShapeManager" ); 118 } 119 120 ClippingAnimation::~ClippingAnimation() 121 { 122 try 123 { 124 end_(); 125 } 126 catch (uno::Exception &) 127 { 128 OSL_ENSURE( false, rtl::OUStringToOString( 129 comphelper::anyToString( 130 cppu::getCaughtException() ), 131 RTL_TEXTENCODING_UTF8 ).getStr() ); 132 } 133 } 134 135 void ClippingAnimation::prefetch( const AnimatableShapeSharedPtr&, 136 const ShapeAttributeLayerSharedPtr& ) 137 { 138 } 139 140 void ClippingAnimation::start( const AnimatableShapeSharedPtr& rShape, 141 const ShapeAttributeLayerSharedPtr& rAttrLayer ) 142 { 143 OSL_ENSURE( !mpShape, 144 "ClippingAnimation::start(): Shape already set" ); 145 OSL_ENSURE( !mpAttrLayer, 146 "ClippingAnimation::start(): Attribute layer already set" ); 147 148 mpShape = rShape; 149 mpAttrLayer = rAttrLayer; 150 151 ENSURE_OR_THROW( rShape, 152 "ClippingAnimation::start(): Invalid shape" ); 153 ENSURE_OR_THROW( rAttrLayer, 154 "ClippingAnimation::start(): Invalid attribute layer" ); 155 156 mpShape = rShape; 157 mpAttrLayer = rAttrLayer; 158 159 if( !mbSpriteActive ) 160 { 161 mpShapeManager->enterAnimationMode( mpShape ); 162 mbSpriteActive = true; 163 } 164 } 165 166 void ClippingAnimation::end() 167 { 168 end_(); 169 } 170 171 void ClippingAnimation::end_() 172 { 173 if( mbSpriteActive ) 174 { 175 mbSpriteActive = false; 176 mpShapeManager->leaveAnimationMode( mpShape ); 177 178 if( mpShape->isContentChanged() ) 179 mpShapeManager->notifyShapeUpdate( mpShape ); 180 } 181 } 182 183 bool ClippingAnimation::operator()( double nValue ) 184 { 185 ENSURE_OR_RETURN_FALSE( 186 mpAttrLayer && mpShape, 187 "ClippingAnimation::operator(): Invalid ShapeAttributeLayer" ); 188 189 // set new clip 190 mpAttrLayer->setClip( maClippingFunctor( nValue, 191 mpShape->getDomBounds().getRange() ) ); 192 193 if( mpShape->isContentChanged() ) 194 mpShapeManager->notifyShapeUpdate( mpShape ); 195 196 return true; 197 } 198 199 double ClippingAnimation::getUnderlyingValue() const 200 { 201 ENSURE_OR_THROW( 202 mpAttrLayer, 203 "ClippingAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" ); 204 205 return 0.0; // though this should be used in concert with 206 // ActivitiesFactory::createSimpleActivity, better 207 // explicitely name our start value. 208 // Permissible range for operator() above is [0,1] 209 } 210 211 } // anon namespace 212 213 214 AnimationActivitySharedPtr TransitionFactory::createShapeTransition( 215 const ActivitiesFactory::CommonParameters& rParms, 216 const AnimatableShapeSharedPtr& rShape, 217 const ShapeManagerSharedPtr& rShapeManager, 218 const ::basegfx::B2DVector& rSlideSize, 219 uno::Reference< animations::XTransitionFilter > const& xTransition ) 220 { 221 return createShapeTransition( rParms, 222 rShape, 223 rShapeManager, 224 rSlideSize, 225 xTransition, 226 xTransition->getTransition(), 227 xTransition->getSubtype() ); 228 } 229 230 AnimationActivitySharedPtr TransitionFactory::createShapeTransition( 231 const ActivitiesFactory::CommonParameters& rParms, 232 const AnimatableShapeSharedPtr& rShape, 233 const ShapeManagerSharedPtr& rShapeManager, 234 const ::basegfx::B2DVector& rSlideSize, 235 ::com::sun::star::uno::Reference< 236 ::com::sun::star::animations::XTransitionFilter > const& xTransition, 237 sal_Int16 nType, 238 sal_Int16 nSubType ) 239 { 240 ENSURE_OR_THROW( 241 xTransition.is(), 242 "TransitionFactory::createShapeTransition(): Invalid XTransition" ); 243 244 const TransitionInfo* pTransitionInfo( 245 getTransitionInfo( nType, nSubType ) ); 246 247 AnimationActivitySharedPtr pGeneratedActivity; 248 if( pTransitionInfo != NULL ) 249 { 250 switch( pTransitionInfo->meTransitionClass ) 251 { 252 default: 253 case TransitionInfo::TRANSITION_INVALID: 254 OSL_ENSURE( false, 255 "TransitionFactory::createShapeTransition(): Invalid transition type. " 256 "Don't ask me for a 0 TransitionType, have no XTransitionFilter node instead!" ); 257 return AnimationActivitySharedPtr(); 258 259 260 case TransitionInfo::TRANSITION_CLIP_POLYPOLYGON: 261 { 262 // generate parametric poly-polygon 263 ParametricPolyPolygonSharedPtr pPoly( 264 ParametricPolyPolygonFactory::createClipPolyPolygon( 265 nType, nSubType ) ); 266 267 // create a clip activity from that 268 pGeneratedActivity = ActivitiesFactory::createSimpleActivity( 269 rParms, 270 NumberAnimationSharedPtr( 271 new ClippingAnimation( 272 pPoly, 273 rShapeManager, 274 *pTransitionInfo, 275 xTransition->getDirection(), 276 xTransition->getMode() ) ), 277 true ); 278 } 279 break; 280 281 case TransitionInfo::TRANSITION_SPECIAL: 282 { 283 switch( nType ) 284 { 285 case animations::TransitionType::RANDOM: 286 { 287 // select randomly one of the effects from the 288 // TransitionFactoryTable 289 290 const TransitionInfo* pRandomTransitionInfo( getRandomTransitionInfo() ); 291 292 ENSURE_OR_THROW( pRandomTransitionInfo != NULL, 293 "TransitionFactory::createShapeTransition(): Got invalid random transition info" ); 294 295 ENSURE_OR_THROW( pRandomTransitionInfo->mnTransitionType != animations::TransitionType::RANDOM, 296 "TransitionFactory::createShapeTransition(): Got random again for random input!" ); 297 298 // and recurse 299 pGeneratedActivity = createShapeTransition( rParms, 300 rShape, 301 rShapeManager, 302 rSlideSize, 303 xTransition, 304 pRandomTransitionInfo->mnTransitionType, 305 pRandomTransitionInfo->mnTransitionSubType ); 306 } 307 break; 308 309 // TODO(F3): Implement slidewipe for shape 310 case animations::TransitionType::SLIDEWIPE: 311 { 312 sal_Int16 nBarWipeSubType(0); 313 bool bDirectionForward(true); 314 315 // map slidewipe to BARWIPE, for now 316 switch( nSubType ) 317 { 318 case animations::TransitionSubType::FROMLEFT: 319 nBarWipeSubType = animations::TransitionSubType::LEFTTORIGHT; 320 bDirectionForward = true; 321 break; 322 323 case animations::TransitionSubType::FROMRIGHT: 324 nBarWipeSubType = animations::TransitionSubType::LEFTTORIGHT; 325 bDirectionForward = false; 326 break; 327 328 case animations::TransitionSubType::FROMTOP: 329 nBarWipeSubType = animations::TransitionSubType::TOPTOBOTTOM; 330 bDirectionForward = true; 331 break; 332 333 case animations::TransitionSubType::FROMBOTTOM: 334 nBarWipeSubType = animations::TransitionSubType::TOPTOBOTTOM; 335 bDirectionForward = false; 336 break; 337 338 default: 339 ENSURE_OR_THROW( false, 340 "TransitionFactory::createShapeTransition(): Unexpected subtype for SLIDEWIPE" ); 341 break; 342 } 343 344 // generate parametric poly-polygon 345 ParametricPolyPolygonSharedPtr pPoly( 346 ParametricPolyPolygonFactory::createClipPolyPolygon( 347 animations::TransitionType::BARWIPE, 348 nBarWipeSubType ) ); 349 350 // create a clip activity from that 351 pGeneratedActivity = ActivitiesFactory::createSimpleActivity( 352 rParms, 353 NumberAnimationSharedPtr( 354 new ClippingAnimation( 355 pPoly, 356 rShapeManager, 357 *getTransitionInfo( animations::TransitionType::BARWIPE, 358 nBarWipeSubType ), 359 bDirectionForward, 360 xTransition->getMode() ) ), 361 true ); 362 } 363 break; 364 365 default: 366 { 367 // TODO(F1): Check whether there's anything left, anyway, 368 // for _shape_ transitions. AFAIK, there are no special 369 // effects for shapes... 370 371 // for now, map all to fade effect 372 pGeneratedActivity = ActivitiesFactory::createSimpleActivity( 373 rParms, 374 AnimationFactory::createNumberPropertyAnimation( 375 ::rtl::OUString( 376 RTL_CONSTASCII_USTRINGPARAM("Opacity") ), 377 rShape, 378 rShapeManager, 379 rSlideSize ), 380 xTransition->getMode() ); 381 } 382 break; 383 } 384 } 385 break; 386 } 387 } 388 389 if( !pGeneratedActivity ) 390 { 391 // No animation generated, maybe no table entry for given 392 // transition? 393 OSL_TRACE( 394 "TransitionFactory::createShapeTransition(): Unknown type/subtype (%d/%d) " 395 "combination encountered", 396 xTransition->getTransition(), 397 xTransition->getSubtype() ); 398 OSL_ENSURE( 399 false, 400 "TransitionFactory::createShapeTransition(): Unknown type/subtype " 401 "combination encountered" ); 402 } 403 404 return pGeneratedActivity; 405 } 406 407 } 408 } 409