LibreOffice Module slideshow (master) 1
simplecontinuousactivitybase.cxx
Go to the documentation of this file.
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// must be first
22
24
25#include <sal/log.hxx>
26
27namespace slideshow::internal
28{
30 const ActivityParameters& rParms ) :
31 ActivityBase( rParms ),
32 maTimer( rParms.mrActivitiesQueue.getTimer() ),
33 mnMinSimpleDuration( rParms.mnMinDuration ),
34 mnMinNumberOfFrames( rParms.mnMinNumberOfFrames ),
35 mnCurrPerformCalls( 0 )
36 {
37 }
38
40 {
41 // init timer. We measure animation time only when we're
42 // actually started.
43 maTimer.reset();
44 }
45
47 {
49 if (! isActive())
50 return 0.0;
51
52 // retrieve locally elapsed time
53 const double nCurrElapsedTime( maTimer.getElapsedTime() );
54
55 // log time
56 SAL_INFO("slideshow.verbose", "SimpleContinuousActivityBase::calcTimeLag(): "
57 "next step is based on time: " << nCurrElapsedTime );
58
59 // go to great length to ensure a proper animation
60 // run. Since we don't know how often we will be called
61 // here, try to spread the animator calls uniquely over
62 // the [0,1] parameter range. Be aware of the fact that
63 // perform will be called at least mnMinNumberOfTurns
64 // times.
65
66 // fraction of time elapsed (clamp to 1.0 for zero-length
67 // animations)
68 const double nFractionElapsedTime(
69 mnMinSimpleDuration != 0.0 ?
70 nCurrElapsedTime / mnMinSimpleDuration :
71 1.0 );
72
73 // fraction of minimum calls performed
74 const double nFractionRequiredCalls(
76
77 // okay, so now, the decision is easy:
78
79 // If the fraction of time elapsed is smaller than the
80 // number of calls required to be performed, then we calc
81 // the position on the animation range according to
82 // elapsed time. That is, we're so to say ahead of time.
83
84 // In contrary, if the fraction of time elapsed is larger,
85 // then we're lagging, and we thus calc the position on
86 // the animation time line according to the fraction of
87 // calls performed. Thus, the animation is forced to slow
88 // down, and take the required minimal number of steps,
89 // sufficiently equally distributed across the animation
90 // time line.
91 if( nFractionElapsedTime < nFractionRequiredCalls )
92 {
93 SAL_INFO("slideshow.verbose", "SimpleContinuousActivityBase::calcTimeLag(): t=" <<
94 nFractionElapsedTime <<
95 " is based on time");
96 return 0.0;
97 }
98 else
99 {
100 SAL_INFO("slideshow.verbose", "SimpleContinuousActivityBase::perform(): t=" <<
101 nFractionRequiredCalls <<
102 " is based on number of calls");
103
104 // lag global time, so all other animations lag, too:
105 return ((nFractionElapsedTime - nFractionRequiredCalls)
107 }
108 }
109
111 {
112 // call base class, for start() calls and end handling
113 if( !ActivityBase::perform() )
114 return false; // done, we're ended
115
116
117 // get relative animation position
118 // ===============================
119
120 const double nCurrElapsedTime( maTimer.getElapsedTime() );
121 // clamp to 1.0 for zero animation duration
122 double nT( mnMinSimpleDuration != 0.0 ?
123 nCurrElapsedTime / mnMinSimpleDuration :
124 1.0 );
125
126
127 // one of the stop criteria reached?
128 // =================================
129
130 // will be set to true below, if one of the termination criteria
131 // matched.
132 bool bActivityEnding( false );
133
134 if( isRepeatCountValid() )
135 {
136 // Finite duration
137 // ===============
138
139 // When we've autoreverse on, the repeat count
140 // doubles
141 const double nRepeatCount( getRepeatCount() );
142 const double nEffectiveRepeat( isAutoReverse() ?
143 2.0*nRepeatCount :
144 nRepeatCount );
145
146 // time (or frame count) elapsed?
147 if( nEffectiveRepeat <= nT )
148 {
149 // okee. done for now. Will not exit right here,
150 // to give animation the chance to render the last
151 // frame below
152 bActivityEnding = true;
153
154 // clamp animation to max permissible value
155 nT = nEffectiveRepeat;
156 }
157 }
158
159
160 // need to do auto-reverse?
161 // ========================
162
163 double nRepeats;
164 double nRelativeSimpleTime;
165
166 // TODO(Q3): Refactor this mess
167 if( isAutoReverse() )
168 {
169 // divert active duration into repeat and
170 // fractional part.
171 const double nFractionalActiveDuration( modf(nT, &nRepeats) );
172
173 // for auto-reverse, map ranges [1,2), [3,4), ...
174 // to ranges [0,1), [1,2), etc.
175 if( static_cast<int>(nRepeats) % 2 )
176 {
177 // we're in an odd range, reverse sweep
178 nRelativeSimpleTime = 1.0 - nFractionalActiveDuration;
179 }
180 else
181 {
182 // we're in an even range, pass on as is
183 nRelativeSimpleTime = nFractionalActiveDuration;
184 }
185
186 // effective repeat count for autoreverse is half of
187 // the input time's value (each run of an autoreverse
188 // cycle is half of a repeat)
189 nRepeats /= 2;
190 }
191 else
192 {
193 // determine repeat
194 // ================
195
196 // calc simple time and number of repeats from nT
197 // Now, that's easy, since the fractional part of
198 // nT gives the relative simple time, and the
199 // integer part the number of full repeats:
200 nRelativeSimpleTime = modf(nT, &nRepeats);
201
202 // clamp repeats to max permissible value (maRepeats.getValue() - 1.0)
203 if( isRepeatCountValid() &&
204 nRepeats >= getRepeatCount() )
205 {
206 // Note that this code here only gets
207 // triggered if maRepeats.getValue() is an
208 // _integer_. Otherwise, nRepeats will never
209 // reach nor exceed
210 // maRepeats.getValue(). Thus, the code below
211 // does not need to handle cases of fractional
212 // repeats, and can always assume that a full
213 // animation run has ended (with
214 // nRelativeSimpleTime=1.0 for
215 // non-autoreversed activities).
216
217 // with modf, nRelativeSimpleTime will never
218 // become 1.0, since nRepeats is incremented and
219 // nRelativeSimpleTime set to 0.0 then.
220
221 // For the animation to reach its final value,
222 // nRepeats must although become
223 // maRepeats.getValue()-1.0, and
224 // nRelativeSimpleTime=1.0.
225 nRelativeSimpleTime = 1.0;
226 nRepeats -= 1.0;
227 }
228 }
229
230 // actually perform something
231 // ==========================
232
233 simplePerform( nRelativeSimpleTime,
234 // nRepeats is already integer-valued
235 static_cast<sal_uInt32>( nRepeats ) );
236
237
238 // delayed endActivity() call from end condition check
239 // below. Issued after the simplePerform() call above, to
240 // give animations the chance to correctly reach the
241 // animation end value, without spurious bail-outs because
242 // of isActive() returning false.
243 if( bActivityEnding )
244 endActivity();
245
246 // one more frame successfully performed
248
249 return isActive();
250 }
251}
252
253/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
double getElapsedTime() const
Base class for animation activities.
virtual bool perform() override
From Activity interface.
virtual bool isActive() const override
Query whether this activity is still continuing.
virtual double calcTimeLag() const override
Calculates whether the activity lags time.
void endActivity()
End this activity, in a regular way.
const double mnMinSimpleDuration
Simple duration of activity.
const sal_uInt32 mnMinNumberOfFrames
Minimal number of frames to show (see ActivityParameters)
sal_uInt32 mnCurrPerformCalls
Actual number of frames shown until now.
virtual void startAnimation() override
Hook for derived classes.
virtual void simplePerform(double nSimpleTime, sal_uInt32 nRepeatCount) const =0
Hook for derived classes.
virtual bool perform() override
From Activity interface.
virtual double calcTimeLag() const override
Calculates whether the activity lags time.
::canvas::tools::ElapsedTime maTimer
Time elapsed since activity started.
#define SAL_INFO(area, stream)
Parameter struct for animation activities.