cid#1606940 Check of thread-shared field evades lock acquisition
[LibreOffice.git] / slideshow / source / engine / activities / simplecontinuousactivitybase.cxx
blob01cb3b75007b207becf655418a0fb7821987cb30
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 // must be first
23 #include "simplecontinuousactivitybase.hxx"
25 #include <sal/log.hxx>
27 namespace slideshow::internal
29 SimpleContinuousActivityBase::SimpleContinuousActivityBase(
30 const ActivityParameters& rParms ) :
31 ActivityBase( rParms ),
32 maTimer( rParms.mrActivitiesQueue.getTimer() ),
33 mnMinSimpleDuration( rParms.mnMinDuration ),
34 mnMinNumberOfFrames( rParms.mnMinNumberOfFrames ),
35 mnCurrPerformCalls( 0 )
39 void SimpleContinuousActivityBase::startAnimation()
41 // init timer. We measure animation time only when we're
42 // actually started.
43 maTimer.reset();
46 double SimpleContinuousActivityBase::calcTimeLag() const
48 ActivityBase::calcTimeLag();
49 if (! isActive())
50 return 0.0;
52 // retrieve locally elapsed time
53 const double nCurrElapsedTime( maTimer.getElapsedTime() );
55 // log time
56 SAL_INFO("slideshow.verbose", "SimpleContinuousActivityBase::calcTimeLag(): "
57 "next step is based on time: " << nCurrElapsedTime );
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.
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 );
73 // fraction of minimum calls performed
74 const double nFractionRequiredCalls(
75 double(mnCurrPerformCalls) / mnMinNumberOfFrames );
77 // okay, so now, the decision is easy:
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.
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 )
93 SAL_INFO("slideshow.verbose", "SimpleContinuousActivityBase::calcTimeLag(): t=" <<
94 nFractionElapsedTime <<
95 " is based on time");
96 return 0.0;
98 else
100 SAL_INFO("slideshow.verbose", "SimpleContinuousActivityBase::perform(): t=" <<
101 nFractionRequiredCalls <<
102 " is based on number of calls");
104 // lag global time, so all other animations lag, too:
105 return ((nFractionElapsedTime - nFractionRequiredCalls)
106 * mnMinSimpleDuration);
110 bool SimpleContinuousActivityBase::perform()
112 // call base class, for start() calls and end handling
113 if( !ActivityBase::perform() )
114 return false; // done, we're ended
117 // get relative animation position
118 // ===============================
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 );
127 // one of the stop criteria reached?
128 // =================================
130 // will be set to true below, if one of the termination criteria
131 // matched.
132 bool bActivityEnding( false );
134 if( isRepeatCountValid() )
136 // Finite duration
137 // ===============
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 );
146 // time (or frame count) elapsed?
147 if( nEffectiveRepeat <= nT )
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;
154 // clamp animation to max permissible value
155 nT = nEffectiveRepeat;
160 // need to do auto-reverse?
161 // ========================
163 double nRepeats;
164 double nRelativeSimpleTime;
166 // TODO(Q3): Refactor this mess
167 if( isAutoReverse() )
169 // divert active duration into repeat and
170 // fractional part.
171 const double nFractionalActiveDuration( modf(nT, &nRepeats) );
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 )
177 // we're in an odd range, reverse sweep
178 nRelativeSimpleTime = 1.0 - nFractionalActiveDuration;
180 else
182 // we're in an even range, pass on as is
183 nRelativeSimpleTime = nFractionalActiveDuration;
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;
191 else
193 // determine repeat
194 // ================
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);
202 // clamp repeats to max permissible value (maRepeats.getValue() - 1.0)
203 if( isRepeatCountValid() &&
204 nRepeats >= getRepeatCount() )
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).
217 // with modf, nRelativeSimpleTime will never
218 // become 1.0, since nRepeats is incremented and
219 // nRelativeSimpleTime set to 0.0 then.
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;
230 // actually perform something
231 // ==========================
233 simplePerform( nRelativeSimpleTime,
234 // nRepeats is already integer-valued
235 static_cast<sal_uInt32>( nRepeats ) );
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();
246 // one more frame successfully performed
247 ++mnCurrPerformCalls;
249 return isActive();
253 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */