Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
21 : #include <canvas/debug.hxx>
22 : #include <tools/diagnose_ex.h>
23 : #include <canvas/verbosetrace.hxx>
24 :
25 : #include "drawshapesubsetting.hxx"
26 : #include "subsettableshapemanager.hxx"
27 : #include "eventqueue.hxx"
28 : #include "eventmultiplexer.hxx"
29 : #include "intrinsicanimationactivity.hxx"
30 : #include "intrinsicanimationeventhandler.hxx"
31 :
32 : #include <boost/noncopyable.hpp>
33 : #include <boost/enable_shared_from_this.hpp>
34 : #include <boost/weak_ptr.hpp>
35 :
36 : namespace slideshow
37 : {
38 : namespace internal
39 : {
40 : /** Activity for intrinsic shape animations
41 :
42 : This is an Activity interface implementation for intrinsic
43 : shape animations. Intrinsic shape animations are
44 : animations directly within a shape, e.g. drawing layer
45 : animations, or GIF animations.
46 : */
47 0 : class IntrinsicAnimationActivity : public Activity,
48 : public boost::enable_shared_from_this<IntrinsicAnimationActivity>,
49 : private boost::noncopyable
50 : {
51 : public:
52 : /** Create an IntrinsicAnimationActivity.
53 :
54 : @param rContext
55 : Common slideshow objects
56 :
57 : @param rDrawShape
58 : Shape to control the intrinsic animation for
59 :
60 : @param rWakeupEvent
61 : Externally generated wakeup event, to set this
62 : activity to sleep during inter-frame intervals. Must
63 : come from the outside, since wakeup event and this
64 : object have mutual references to each other.
65 :
66 : @param rTimeouts
67 : Vector of timeout values, to wait before the next
68 : frame is shown.
69 : */
70 : IntrinsicAnimationActivity( const SlideShowContext& rContext,
71 : const DrawShapeSharedPtr& rDrawShape,
72 : const WakeupEventSharedPtr& rWakeupEvent,
73 : const ::std::vector<double>& rTimeouts,
74 : ::std::size_t nNumLoops,
75 : CycleMode eCycleMode );
76 :
77 : virtual void dispose() SAL_OVERRIDE;
78 : virtual double calcTimeLag() const SAL_OVERRIDE;
79 : virtual bool perform() SAL_OVERRIDE;
80 : virtual bool isActive() const SAL_OVERRIDE;
81 : virtual void dequeued() SAL_OVERRIDE;
82 : virtual void end() SAL_OVERRIDE;
83 :
84 : bool enableAnimations();
85 :
86 : private:
87 : SlideShowContext maContext;
88 : boost::weak_ptr<DrawShape> mpDrawShape;
89 : WakeupEventSharedPtr mpWakeupEvent;
90 : IntrinsicAnimationEventHandlerSharedPtr mpListener;
91 : ::std::vector<double> maTimeouts;
92 : CycleMode meCycleMode;
93 : ::std::size_t mnCurrIndex;
94 : ::std::size_t mnNumLoops;
95 : ::std::size_t mnLoopCount;
96 : bool mbIsActive;
97 : };
98 :
99 :
100 :
101 0 : class IntrinsicAnimationListener : public IntrinsicAnimationEventHandler,
102 : private boost::noncopyable
103 : {
104 : public:
105 0 : explicit IntrinsicAnimationListener( IntrinsicAnimationActivity& rActivity ) :
106 0 : mrActivity( rActivity )
107 0 : {}
108 :
109 : private:
110 :
111 0 : virtual bool enableAnimations() SAL_OVERRIDE { return mrActivity.enableAnimations(); }
112 0 : virtual bool disableAnimations() SAL_OVERRIDE { mrActivity.end(); return true; }
113 :
114 : IntrinsicAnimationActivity& mrActivity;
115 : };
116 :
117 :
118 :
119 0 : IntrinsicAnimationActivity::IntrinsicAnimationActivity( const SlideShowContext& rContext,
120 : const DrawShapeSharedPtr& rDrawShape,
121 : const WakeupEventSharedPtr& rWakeupEvent,
122 : const ::std::vector<double>& rTimeouts,
123 : ::std::size_t nNumLoops,
124 : CycleMode eCycleMode ) :
125 : maContext( rContext ),
126 : mpDrawShape( rDrawShape ),
127 : mpWakeupEvent( rWakeupEvent ),
128 0 : mpListener( new IntrinsicAnimationListener(*this) ),
129 : maTimeouts( rTimeouts ),
130 : meCycleMode( eCycleMode ),
131 : mnCurrIndex(0),
132 : mnNumLoops(nNumLoops),
133 : mnLoopCount(0),
134 0 : mbIsActive(false)
135 : {
136 0 : ENSURE_OR_THROW( rContext.mpSubsettableShapeManager,
137 : "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid shape manager" );
138 0 : ENSURE_OR_THROW( rDrawShape,
139 : "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid draw shape" );
140 0 : ENSURE_OR_THROW( rWakeupEvent,
141 : "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid wakeup event" );
142 0 : ENSURE_OR_THROW( !rTimeouts.empty(),
143 : "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Empty timeout vector" );
144 :
145 0 : maContext.mpSubsettableShapeManager->addIntrinsicAnimationHandler(
146 0 : mpListener );
147 0 : }
148 :
149 0 : void IntrinsicAnimationActivity::dispose()
150 : {
151 0 : end();
152 :
153 0 : if( mpWakeupEvent )
154 0 : mpWakeupEvent->dispose();
155 :
156 0 : maContext.dispose();
157 0 : mpDrawShape.reset();
158 0 : mpWakeupEvent.reset();
159 0 : maTimeouts.clear();
160 0 : mnCurrIndex = 0;
161 :
162 0 : maContext.mpSubsettableShapeManager->removeIntrinsicAnimationHandler(
163 0 : mpListener );
164 0 : }
165 :
166 0 : double IntrinsicAnimationActivity::calcTimeLag() const
167 : {
168 0 : return 0.0;
169 : }
170 :
171 0 : bool IntrinsicAnimationActivity::perform()
172 : {
173 0 : if( !isActive() )
174 0 : return false;
175 :
176 0 : DrawShapeSharedPtr pDrawShape( mpDrawShape.lock() );
177 0 : if( !pDrawShape || !mpWakeupEvent )
178 : {
179 : // event or draw shape vanished, no sense living on ->
180 : // commit suicide.
181 0 : dispose();
182 0 : return false;
183 : }
184 :
185 : // mnNumLoops == 0 means infinite looping
186 0 : if( mnNumLoops != 0 &&
187 0 : mnLoopCount >= mnNumLoops )
188 : {
189 : // #i55294# After finishing the loops, display the first frame
190 0 : pDrawShape->setIntrinsicAnimationFrame( 0 );
191 0 : maContext.mpSubsettableShapeManager->notifyShapeUpdate( pDrawShape );
192 :
193 0 : end();
194 :
195 0 : return false;
196 : }
197 :
198 0 : ::std::size_t nNewIndex = 0;
199 0 : const ::std::size_t nNumFrames(maTimeouts.size());
200 0 : switch( meCycleMode )
201 : {
202 : case CYCLE_LOOP:
203 : {
204 0 : pDrawShape->setIntrinsicAnimationFrame( mnCurrIndex );
205 :
206 0 : mpWakeupEvent->start();
207 0 : mpWakeupEvent->setNextTimeout( maTimeouts[mnCurrIndex] );
208 :
209 0 : mnLoopCount += (mnCurrIndex + 1) / nNumFrames;
210 0 : nNewIndex = (mnCurrIndex + 1) % nNumFrames;
211 0 : break;
212 : }
213 :
214 : case CYCLE_PINGPONGLOOP:
215 : {
216 0 : ::std::size_t nTrueIndex( mnCurrIndex < nNumFrames ?
217 : mnCurrIndex :
218 0 : 2*nNumFrames - mnCurrIndex - 1 );
219 0 : pDrawShape->setIntrinsicAnimationFrame( nTrueIndex );
220 :
221 0 : mpWakeupEvent->start();
222 0 : mpWakeupEvent->setNextTimeout( maTimeouts[nTrueIndex] );
223 :
224 0 : mnLoopCount += (mnCurrIndex + 1) / (2*nNumFrames);
225 0 : nNewIndex = (mnCurrIndex + 1) % 2*nNumFrames;
226 0 : break;
227 : }
228 : }
229 :
230 0 : maContext.mrEventQueue.addEvent( mpWakeupEvent );
231 0 : maContext.mpSubsettableShapeManager->notifyShapeUpdate( pDrawShape );
232 0 : mnCurrIndex = nNewIndex;
233 :
234 0 : return false; // don't reinsert, WakeupEvent will perform
235 : // that after the given timeout
236 : }
237 :
238 0 : bool IntrinsicAnimationActivity::isActive() const
239 : {
240 0 : return mbIsActive;
241 : }
242 :
243 0 : void IntrinsicAnimationActivity::dequeued()
244 : {
245 : // not used here
246 0 : }
247 :
248 0 : void IntrinsicAnimationActivity::end()
249 : {
250 : // there is no dedicated end state, just become inactive:
251 0 : mbIsActive = false;
252 0 : }
253 :
254 0 : bool IntrinsicAnimationActivity::enableAnimations()
255 : {
256 0 : mbIsActive = true;
257 : return maContext.mrActivitiesQueue.addActivity(
258 0 : shared_from_this() );
259 : }
260 :
261 :
262 :
263 0 : ActivitySharedPtr createIntrinsicAnimationActivity(
264 : const SlideShowContext& rContext,
265 : const DrawShapeSharedPtr& rDrawShape,
266 : const WakeupEventSharedPtr& rWakeupEvent,
267 : const ::std::vector<double>& rTimeouts,
268 : ::std::size_t nNumLoops,
269 : CycleMode eCycleMode )
270 : {
271 : return ActivitySharedPtr(
272 : new IntrinsicAnimationActivity(rContext,
273 : rDrawShape,
274 : rWakeupEvent,
275 : rTimeouts,
276 : nNumLoops,
277 0 : eCycleMode) );
278 : }
279 : }
280 3 : }
281 :
282 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|