170f497fbSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 370f497fbSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 470f497fbSAndrew Rist * or more contributor license agreements. See the NOTICE file 570f497fbSAndrew Rist * distributed with this work for additional information 670f497fbSAndrew Rist * regarding copyright ownership. The ASF licenses this file 770f497fbSAndrew Rist * to you under the Apache License, Version 2.0 (the 870f497fbSAndrew Rist * "License"); you may not use this file except in compliance 970f497fbSAndrew Rist * with the License. You may obtain a copy of the License at 1070f497fbSAndrew Rist * 1170f497fbSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 1270f497fbSAndrew Rist * 1370f497fbSAndrew Rist * Unless required by applicable law or agreed to in writing, 1470f497fbSAndrew Rist * software distributed under the License is distributed on an 1570f497fbSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1670f497fbSAndrew Rist * KIND, either express or implied. See the License for the 1770f497fbSAndrew Rist * specific language governing permissions and limitations 1870f497fbSAndrew Rist * under the License. 1970f497fbSAndrew Rist * 2070f497fbSAndrew Rist *************************************************************/ 2170f497fbSAndrew Rist 2270f497fbSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_slideshow.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <canvas/debug.hxx> 28cdf0e10cSrcweir #include <tools/diagnose_ex.h> 29cdf0e10cSrcweir #include <canvas/verbosetrace.hxx> 30cdf0e10cSrcweir 31cdf0e10cSrcweir #include "drawshapesubsetting.hxx" 32cdf0e10cSrcweir #include "subsettableshapemanager.hxx" 33cdf0e10cSrcweir #include "eventqueue.hxx" 34cdf0e10cSrcweir #include "eventmultiplexer.hxx" 35cdf0e10cSrcweir #include "intrinsicanimationactivity.hxx" 36cdf0e10cSrcweir #include "intrinsicanimationeventhandler.hxx" 37cdf0e10cSrcweir 38cdf0e10cSrcweir #include <boost/noncopyable.hpp> 39cdf0e10cSrcweir #include <boost/enable_shared_from_this.hpp> 40cdf0e10cSrcweir #include <boost/weak_ptr.hpp> 41cdf0e10cSrcweir 42cdf0e10cSrcweir namespace slideshow 43cdf0e10cSrcweir { 44cdf0e10cSrcweir namespace internal 45cdf0e10cSrcweir { 46cdf0e10cSrcweir /** Activity for intrinsic shape animations 47cdf0e10cSrcweir 48cdf0e10cSrcweir This is an Activity interface implementation for intrinsic 49cdf0e10cSrcweir shape animations. Intrinsic shape animations are 50cdf0e10cSrcweir animations directly within a shape, e.g. drawing layer 51cdf0e10cSrcweir animations, or GIF animations. 52cdf0e10cSrcweir */ 53cdf0e10cSrcweir class IntrinsicAnimationActivity : public Activity, 54cdf0e10cSrcweir public boost::enable_shared_from_this<IntrinsicAnimationActivity>, 55cdf0e10cSrcweir private boost::noncopyable 56cdf0e10cSrcweir { 57cdf0e10cSrcweir public: 58cdf0e10cSrcweir /** Create an IntrinsicAnimationActivity. 59cdf0e10cSrcweir 60cdf0e10cSrcweir @param rContext 61cdf0e10cSrcweir Common slideshow objects 62cdf0e10cSrcweir 63cdf0e10cSrcweir @param rDrawShape 64cdf0e10cSrcweir Shape to control the intrinsic animation for 65cdf0e10cSrcweir 66cdf0e10cSrcweir @param rWakeupEvent 67cdf0e10cSrcweir Externally generated wakeup event, to set this 68cdf0e10cSrcweir activity to sleep during inter-frame intervals. Must 69*86e1cf34SPedro Giffuni come from the outside, since wakeup event and this 70cdf0e10cSrcweir object have mutual references to each other. 71cdf0e10cSrcweir 72cdf0e10cSrcweir @param rTimeouts 73cdf0e10cSrcweir Vector of timeout values, to wait before the next 74cdf0e10cSrcweir frame is shown. 75cdf0e10cSrcweir */ 76cdf0e10cSrcweir IntrinsicAnimationActivity( const SlideShowContext& rContext, 77cdf0e10cSrcweir const DrawShapeSharedPtr& rDrawShape, 78cdf0e10cSrcweir const WakeupEventSharedPtr& rWakeupEvent, 79cdf0e10cSrcweir const ::std::vector<double>& rTimeouts, 80cdf0e10cSrcweir ::std::size_t nNumLoops, 81cdf0e10cSrcweir CycleMode eCycleMode ); 82cdf0e10cSrcweir 83cdf0e10cSrcweir virtual void dispose(); 84cdf0e10cSrcweir virtual double calcTimeLag() const; 85cdf0e10cSrcweir virtual bool perform(); 86cdf0e10cSrcweir virtual bool isActive() const; 87cdf0e10cSrcweir virtual void dequeued(); 88cdf0e10cSrcweir virtual void end(); 89cdf0e10cSrcweir 90cdf0e10cSrcweir bool enableAnimations(); 91cdf0e10cSrcweir 92cdf0e10cSrcweir private: 93cdf0e10cSrcweir SlideShowContext maContext; 94cdf0e10cSrcweir boost::weak_ptr<DrawShape> mpDrawShape; 95cdf0e10cSrcweir WakeupEventSharedPtr mpWakeupEvent; 96cdf0e10cSrcweir IntrinsicAnimationEventHandlerSharedPtr mpListener; 97cdf0e10cSrcweir ::std::vector<double> maTimeouts; 98cdf0e10cSrcweir CycleMode meCycleMode; 99cdf0e10cSrcweir ::std::size_t mnCurrIndex; 100cdf0e10cSrcweir ::std::size_t mnNumLoops; 101cdf0e10cSrcweir ::std::size_t mnLoopCount; 102cdf0e10cSrcweir bool mbIsActive; 103cdf0e10cSrcweir }; 104cdf0e10cSrcweir 105cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////// 106cdf0e10cSrcweir 107cdf0e10cSrcweir class IntrinsicAnimationListener : public IntrinsicAnimationEventHandler, 108cdf0e10cSrcweir private boost::noncopyable 109cdf0e10cSrcweir { 110cdf0e10cSrcweir public: IntrinsicAnimationListener(IntrinsicAnimationActivity & rActivity)111cdf0e10cSrcweir explicit IntrinsicAnimationListener( IntrinsicAnimationActivity& rActivity ) : 112cdf0e10cSrcweir mrActivity( rActivity ) 113cdf0e10cSrcweir {} 114cdf0e10cSrcweir 115cdf0e10cSrcweir private: 116cdf0e10cSrcweir enableAnimations()117cdf0e10cSrcweir virtual bool enableAnimations() { return mrActivity.enableAnimations(); } disableAnimations()118cdf0e10cSrcweir virtual bool disableAnimations() { mrActivity.end(); return true; } 119cdf0e10cSrcweir 120cdf0e10cSrcweir IntrinsicAnimationActivity& mrActivity; 121cdf0e10cSrcweir }; 122cdf0e10cSrcweir 123cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////// 124cdf0e10cSrcweir IntrinsicAnimationActivity(const SlideShowContext & rContext,const DrawShapeSharedPtr & rDrawShape,const WakeupEventSharedPtr & rWakeupEvent,const::std::vector<double> & rTimeouts,::std::size_t nNumLoops,CycleMode eCycleMode)125cdf0e10cSrcweir IntrinsicAnimationActivity::IntrinsicAnimationActivity( const SlideShowContext& rContext, 126cdf0e10cSrcweir const DrawShapeSharedPtr& rDrawShape, 127cdf0e10cSrcweir const WakeupEventSharedPtr& rWakeupEvent, 128cdf0e10cSrcweir const ::std::vector<double>& rTimeouts, 129cdf0e10cSrcweir ::std::size_t nNumLoops, 130cdf0e10cSrcweir CycleMode eCycleMode ) : 131cdf0e10cSrcweir maContext( rContext ), 132cdf0e10cSrcweir mpDrawShape( rDrawShape ), 133cdf0e10cSrcweir mpWakeupEvent( rWakeupEvent ), 134cdf0e10cSrcweir mpListener( new IntrinsicAnimationListener(*this) ), 135cdf0e10cSrcweir maTimeouts( rTimeouts ), 136cdf0e10cSrcweir meCycleMode( eCycleMode ), 137cdf0e10cSrcweir mnCurrIndex(0), 138cdf0e10cSrcweir mnNumLoops(nNumLoops), 139cdf0e10cSrcweir mnLoopCount(0), 140cdf0e10cSrcweir mbIsActive(false) 141cdf0e10cSrcweir { 142cdf0e10cSrcweir ENSURE_OR_THROW( rContext.mpSubsettableShapeManager, 143cdf0e10cSrcweir "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid shape manager" ); 144cdf0e10cSrcweir ENSURE_OR_THROW( rDrawShape, 145cdf0e10cSrcweir "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid draw shape" ); 146cdf0e10cSrcweir ENSURE_OR_THROW( rWakeupEvent, 147cdf0e10cSrcweir "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid wakeup event" ); 148cdf0e10cSrcweir ENSURE_OR_THROW( !rTimeouts.empty(), 149cdf0e10cSrcweir "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Empty timeout vector" ); 150cdf0e10cSrcweir 151cdf0e10cSrcweir maContext.mpSubsettableShapeManager->addIntrinsicAnimationHandler( 152cdf0e10cSrcweir mpListener ); 153cdf0e10cSrcweir } 154cdf0e10cSrcweir dispose()155cdf0e10cSrcweir void IntrinsicAnimationActivity::dispose() 156cdf0e10cSrcweir { 157cdf0e10cSrcweir end(); 158cdf0e10cSrcweir 159cdf0e10cSrcweir if( mpWakeupEvent ) 160cdf0e10cSrcweir mpWakeupEvent->dispose(); 161cdf0e10cSrcweir 162cdf0e10cSrcweir maContext.dispose(); 163cdf0e10cSrcweir mpDrawShape.reset(); 164cdf0e10cSrcweir mpWakeupEvent.reset(); 165cdf0e10cSrcweir maTimeouts.clear(); 166cdf0e10cSrcweir mnCurrIndex = 0; 167cdf0e10cSrcweir 168cdf0e10cSrcweir maContext.mpSubsettableShapeManager->removeIntrinsicAnimationHandler( 169cdf0e10cSrcweir mpListener ); 170cdf0e10cSrcweir } 171cdf0e10cSrcweir calcTimeLag() const172cdf0e10cSrcweir double IntrinsicAnimationActivity::calcTimeLag() const 173cdf0e10cSrcweir { 174cdf0e10cSrcweir return 0.0; 175cdf0e10cSrcweir } 176cdf0e10cSrcweir perform()177cdf0e10cSrcweir bool IntrinsicAnimationActivity::perform() 178cdf0e10cSrcweir { 179cdf0e10cSrcweir if( !isActive() ) 180cdf0e10cSrcweir return false; 181cdf0e10cSrcweir 182cdf0e10cSrcweir DrawShapeSharedPtr pDrawShape( mpDrawShape.lock() ); 183cdf0e10cSrcweir if( !pDrawShape || !mpWakeupEvent ) 184cdf0e10cSrcweir { 185cdf0e10cSrcweir // event or draw shape vanished, no sense living on -> 186cdf0e10cSrcweir // commit suicide. 187cdf0e10cSrcweir dispose(); 188cdf0e10cSrcweir return false; 189cdf0e10cSrcweir } 190cdf0e10cSrcweir 191cdf0e10cSrcweir // mnNumLoops == 0 means infinite looping 192cdf0e10cSrcweir if( mnNumLoops != 0 && 193cdf0e10cSrcweir mnLoopCount >= mnNumLoops ) 194cdf0e10cSrcweir { 195cdf0e10cSrcweir // #i55294# After finishing the loops, display the first frame 196cdf0e10cSrcweir pDrawShape->setIntrinsicAnimationFrame( 0 ); 197cdf0e10cSrcweir maContext.mpSubsettableShapeManager->notifyShapeUpdate( pDrawShape ); 198cdf0e10cSrcweir 199cdf0e10cSrcweir end(); 200cdf0e10cSrcweir 201cdf0e10cSrcweir return false; 202cdf0e10cSrcweir } 203cdf0e10cSrcweir 204cdf0e10cSrcweir ::std::size_t nNewIndex = 0; 205cdf0e10cSrcweir const ::std::size_t nNumFrames(maTimeouts.size()); 206cdf0e10cSrcweir switch( meCycleMode ) 207cdf0e10cSrcweir { 208cdf0e10cSrcweir case CYCLE_LOOP: 209cdf0e10cSrcweir { 210cdf0e10cSrcweir pDrawShape->setIntrinsicAnimationFrame( mnCurrIndex ); 211cdf0e10cSrcweir 212cdf0e10cSrcweir mpWakeupEvent->start(); 213cdf0e10cSrcweir mpWakeupEvent->setNextTimeout( maTimeouts[mnCurrIndex] ); 214cdf0e10cSrcweir 215cdf0e10cSrcweir mnLoopCount += (mnCurrIndex + 1) / nNumFrames; 216cdf0e10cSrcweir nNewIndex = (mnCurrIndex + 1) % nNumFrames; 217cdf0e10cSrcweir break; 218cdf0e10cSrcweir } 219cdf0e10cSrcweir 220cdf0e10cSrcweir case CYCLE_PINGPONGLOOP: 221cdf0e10cSrcweir { 222cdf0e10cSrcweir ::std::size_t nTrueIndex( mnCurrIndex < nNumFrames ? 223cdf0e10cSrcweir mnCurrIndex : 224cdf0e10cSrcweir 2*nNumFrames - mnCurrIndex - 1 ); 225cdf0e10cSrcweir pDrawShape->setIntrinsicAnimationFrame( nTrueIndex ); 226cdf0e10cSrcweir 227cdf0e10cSrcweir mpWakeupEvent->start(); 228cdf0e10cSrcweir mpWakeupEvent->setNextTimeout( maTimeouts[nTrueIndex] ); 229cdf0e10cSrcweir 230cdf0e10cSrcweir mnLoopCount += (mnCurrIndex + 1) / (2*nNumFrames); 231cdf0e10cSrcweir nNewIndex = (mnCurrIndex + 1) % 2*nNumFrames; 232cdf0e10cSrcweir break; 233cdf0e10cSrcweir } 234cdf0e10cSrcweir } 235cdf0e10cSrcweir 236cdf0e10cSrcweir maContext.mrEventQueue.addEvent( mpWakeupEvent ); 237cdf0e10cSrcweir maContext.mpSubsettableShapeManager->notifyShapeUpdate( pDrawShape ); 238cdf0e10cSrcweir mnCurrIndex = nNewIndex; 239cdf0e10cSrcweir 240cdf0e10cSrcweir return false; // don't reinsert, WakeupEvent will perform 241cdf0e10cSrcweir // that after the given timeout 242cdf0e10cSrcweir } 243cdf0e10cSrcweir isActive() const244cdf0e10cSrcweir bool IntrinsicAnimationActivity::isActive() const 245cdf0e10cSrcweir { 246cdf0e10cSrcweir return mbIsActive; 247cdf0e10cSrcweir } 248cdf0e10cSrcweir dequeued()249cdf0e10cSrcweir void IntrinsicAnimationActivity::dequeued() 250cdf0e10cSrcweir { 251cdf0e10cSrcweir // not used here 252cdf0e10cSrcweir } 253cdf0e10cSrcweir end()254cdf0e10cSrcweir void IntrinsicAnimationActivity::end() 255cdf0e10cSrcweir { 256cdf0e10cSrcweir // there is no dedicated end state, just become inactive: 257cdf0e10cSrcweir mbIsActive = false; 258cdf0e10cSrcweir } 259cdf0e10cSrcweir enableAnimations()260cdf0e10cSrcweir bool IntrinsicAnimationActivity::enableAnimations() 261cdf0e10cSrcweir { 262cdf0e10cSrcweir mbIsActive = true; 263cdf0e10cSrcweir return maContext.mrActivitiesQueue.addActivity( 264cdf0e10cSrcweir shared_from_this() ); 265cdf0e10cSrcweir } 266cdf0e10cSrcweir 267cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////// 268cdf0e10cSrcweir createIntrinsicAnimationActivity(const SlideShowContext & rContext,const DrawShapeSharedPtr & rDrawShape,const WakeupEventSharedPtr & rWakeupEvent,const::std::vector<double> & rTimeouts,::std::size_t nNumLoops,CycleMode eCycleMode)269cdf0e10cSrcweir ActivitySharedPtr createIntrinsicAnimationActivity( 270cdf0e10cSrcweir const SlideShowContext& rContext, 271cdf0e10cSrcweir const DrawShapeSharedPtr& rDrawShape, 272cdf0e10cSrcweir const WakeupEventSharedPtr& rWakeupEvent, 273cdf0e10cSrcweir const ::std::vector<double>& rTimeouts, 274cdf0e10cSrcweir ::std::size_t nNumLoops, 275cdf0e10cSrcweir CycleMode eCycleMode ) 276cdf0e10cSrcweir { 277cdf0e10cSrcweir return ActivitySharedPtr( 278cdf0e10cSrcweir new IntrinsicAnimationActivity(rContext, 279cdf0e10cSrcweir rDrawShape, 280cdf0e10cSrcweir rWakeupEvent, 281cdf0e10cSrcweir rTimeouts, 282cdf0e10cSrcweir nNumLoops, 283cdf0e10cSrcweir eCycleMode) ); 284cdf0e10cSrcweir } 285cdf0e10cSrcweir } 286cdf0e10cSrcweir } 287