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