1*70f497fbSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*70f497fbSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*70f497fbSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*70f497fbSAndrew Rist  * distributed with this work for additional information
6*70f497fbSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*70f497fbSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*70f497fbSAndrew Rist  * "License"); you may not use this file except in compliance
9*70f497fbSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*70f497fbSAndrew Rist  *
11*70f497fbSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*70f497fbSAndrew Rist  *
13*70f497fbSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*70f497fbSAndrew Rist  * software distributed under the License is distributed on an
15*70f497fbSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*70f497fbSAndrew Rist  * KIND, either express or implied.  See the License for the
17*70f497fbSAndrew Rist  * specific language governing permissions and limitations
18*70f497fbSAndrew Rist  * under the License.
19*70f497fbSAndrew Rist  *
20*70f497fbSAndrew Rist  *************************************************************/
21*70f497fbSAndrew Rist 
22*70f497fbSAndrew 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
69cdf0e10cSrcweir                 come frome 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:
111cdf0e10cSrcweir             explicit IntrinsicAnimationListener( IntrinsicAnimationActivity& rActivity ) :
112cdf0e10cSrcweir                 mrActivity( rActivity )
113cdf0e10cSrcweir             {}
114cdf0e10cSrcweir 
115cdf0e10cSrcweir         private:
116cdf0e10cSrcweir 
117cdf0e10cSrcweir             virtual bool enableAnimations() { return mrActivity.enableAnimations(); }
118cdf0e10cSrcweir             virtual bool disableAnimations() { mrActivity.end(); return true; }
119cdf0e10cSrcweir 
120cdf0e10cSrcweir             IntrinsicAnimationActivity& mrActivity;
121cdf0e10cSrcweir         };
122cdf0e10cSrcweir 
123cdf0e10cSrcweir         //////////////////////////////////////////////////////////////////////
124cdf0e10cSrcweir 
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 
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 
172cdf0e10cSrcweir         double IntrinsicAnimationActivity::calcTimeLag() const
173cdf0e10cSrcweir         {
174cdf0e10cSrcweir             return 0.0;
175cdf0e10cSrcweir         }
176cdf0e10cSrcweir 
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 
244cdf0e10cSrcweir         bool IntrinsicAnimationActivity::isActive() const
245cdf0e10cSrcweir         {
246cdf0e10cSrcweir             return mbIsActive;
247cdf0e10cSrcweir         }
248cdf0e10cSrcweir 
249cdf0e10cSrcweir         void IntrinsicAnimationActivity::dequeued()
250cdf0e10cSrcweir         {
251cdf0e10cSrcweir             // not used here
252cdf0e10cSrcweir         }
253cdf0e10cSrcweir 
254cdf0e10cSrcweir         void IntrinsicAnimationActivity::end()
255cdf0e10cSrcweir         {
256cdf0e10cSrcweir             // there is no dedicated end state, just become inactive:
257cdf0e10cSrcweir             mbIsActive = false;
258cdf0e10cSrcweir         }
259cdf0e10cSrcweir 
260cdf0e10cSrcweir         bool IntrinsicAnimationActivity::enableAnimations()
261cdf0e10cSrcweir         {
262cdf0e10cSrcweir             mbIsActive = true;
263cdf0e10cSrcweir             return maContext.mrActivitiesQueue.addActivity(
264cdf0e10cSrcweir                 shared_from_this() );
265cdf0e10cSrcweir         }
266cdf0e10cSrcweir 
267cdf0e10cSrcweir         //////////////////////////////////////////////////////////////////////
268cdf0e10cSrcweir 
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