summaryrefslogtreecommitdiffstats
path: root/slideshow/source/engine/activities/simplecontinuousactivitybase.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--slideshow/source/engine/activities/simplecontinuousactivitybase.cxx253
1 files changed, 253 insertions, 0 deletions
diff --git a/slideshow/source/engine/activities/simplecontinuousactivitybase.cxx b/slideshow/source/engine/activities/simplecontinuousactivitybase.cxx
new file mode 100644
index 000000000..01cb3b750
--- /dev/null
+++ b/slideshow/source/engine/activities/simplecontinuousactivitybase.cxx
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+// must be first
+
+#include "simplecontinuousactivitybase.hxx"
+
+#include <sal/log.hxx>
+
+namespace slideshow::internal
+{
+ SimpleContinuousActivityBase::SimpleContinuousActivityBase(
+ const ActivityParameters& rParms ) :
+ ActivityBase( rParms ),
+ maTimer( rParms.mrActivitiesQueue.getTimer() ),
+ mnMinSimpleDuration( rParms.mnMinDuration ),
+ mnMinNumberOfFrames( rParms.mnMinNumberOfFrames ),
+ mnCurrPerformCalls( 0 )
+ {
+ }
+
+ void SimpleContinuousActivityBase::startAnimation()
+ {
+ // init timer. We measure animation time only when we're
+ // actually started.
+ maTimer.reset();
+ }
+
+ double SimpleContinuousActivityBase::calcTimeLag() const
+ {
+ ActivityBase::calcTimeLag();
+ if (! isActive())
+ return 0.0;
+
+ // retrieve locally elapsed time
+ const double nCurrElapsedTime( maTimer.getElapsedTime() );
+
+ // log time
+ SAL_INFO("slideshow.verbose", "SimpleContinuousActivityBase::calcTimeLag(): "
+ "next step is based on time: " << nCurrElapsedTime );
+
+ // go to great length to ensure a proper animation
+ // run. Since we don't know how often we will be called
+ // here, try to spread the animator calls uniquely over
+ // the [0,1] parameter range. Be aware of the fact that
+ // perform will be called at least mnMinNumberOfTurns
+ // times.
+
+ // fraction of time elapsed (clamp to 1.0 for zero-length
+ // animations)
+ const double nFractionElapsedTime(
+ mnMinSimpleDuration != 0.0 ?
+ nCurrElapsedTime / mnMinSimpleDuration :
+ 1.0 );
+
+ // fraction of minimum calls performed
+ const double nFractionRequiredCalls(
+ double(mnCurrPerformCalls) / mnMinNumberOfFrames );
+
+ // okay, so now, the decision is easy:
+
+ // If the fraction of time elapsed is smaller than the
+ // number of calls required to be performed, then we calc
+ // the position on the animation range according to
+ // elapsed time. That is, we're so to say ahead of time.
+
+ // In contrary, if the fraction of time elapsed is larger,
+ // then we're lagging, and we thus calc the position on
+ // the animation time line according to the fraction of
+ // calls performed. Thus, the animation is forced to slow
+ // down, and take the required minimal number of steps,
+ // sufficiently equally distributed across the animation
+ // time line.
+ if( nFractionElapsedTime < nFractionRequiredCalls )
+ {
+ SAL_INFO("slideshow.verbose", "SimpleContinuousActivityBase::calcTimeLag(): t=" <<
+ nFractionElapsedTime <<
+ " is based on time");
+ return 0.0;
+ }
+ else
+ {
+ SAL_INFO("slideshow.verbose", "SimpleContinuousActivityBase::perform(): t=" <<
+ nFractionRequiredCalls <<
+ " is based on number of calls");
+
+ // lag global time, so all other animations lag, too:
+ return ((nFractionElapsedTime - nFractionRequiredCalls)
+ * mnMinSimpleDuration);
+ }
+ }
+
+ bool SimpleContinuousActivityBase::perform()
+ {
+ // call base class, for start() calls and end handling
+ if( !ActivityBase::perform() )
+ return false; // done, we're ended
+
+
+ // get relative animation position
+ // ===============================
+
+ const double nCurrElapsedTime( maTimer.getElapsedTime() );
+ // clamp to 1.0 for zero animation duration
+ double nT( mnMinSimpleDuration != 0.0 ?
+ nCurrElapsedTime / mnMinSimpleDuration :
+ 1.0 );
+
+
+ // one of the stop criteria reached?
+ // =================================
+
+ // will be set to true below, if one of the termination criteria
+ // matched.
+ bool bActivityEnding( false );
+
+ if( isRepeatCountValid() )
+ {
+ // Finite duration
+ // ===============
+
+ // When we've autoreverse on, the repeat count
+ // doubles
+ const double nRepeatCount( getRepeatCount() );
+ const double nEffectiveRepeat( isAutoReverse() ?
+ 2.0*nRepeatCount :
+ nRepeatCount );
+
+ // time (or frame count) elapsed?
+ if( nEffectiveRepeat <= nT )
+ {
+ // okee. done for now. Will not exit right here,
+ // to give animation the chance to render the last
+ // frame below
+ bActivityEnding = true;
+
+ // clamp animation to max permissible value
+ nT = nEffectiveRepeat;
+ }
+ }
+
+
+ // need to do auto-reverse?
+ // ========================
+
+ double nRepeats;
+ double nRelativeSimpleTime;
+
+ // TODO(Q3): Refactor this mess
+ if( isAutoReverse() )
+ {
+ // divert active duration into repeat and
+ // fractional part.
+ const double nFractionalActiveDuration( modf(nT, &nRepeats) );
+
+ // for auto-reverse, map ranges [1,2), [3,4), ...
+ // to ranges [0,1), [1,2), etc.
+ if( static_cast<int>(nRepeats) % 2 )
+ {
+ // we're in an odd range, reverse sweep
+ nRelativeSimpleTime = 1.0 - nFractionalActiveDuration;
+ }
+ else
+ {
+ // we're in an even range, pass on as is
+ nRelativeSimpleTime = nFractionalActiveDuration;
+ }
+
+ // effective repeat count for autoreverse is half of
+ // the input time's value (each run of an autoreverse
+ // cycle is half of a repeat)
+ nRepeats /= 2;
+ }
+ else
+ {
+ // determine repeat
+ // ================
+
+ // calc simple time and number of repeats from nT
+ // Now, that's easy, since the fractional part of
+ // nT gives the relative simple time, and the
+ // integer part the number of full repeats:
+ nRelativeSimpleTime = modf(nT, &nRepeats);
+
+ // clamp repeats to max permissible value (maRepeats.getValue() - 1.0)
+ if( isRepeatCountValid() &&
+ nRepeats >= getRepeatCount() )
+ {
+ // Note that this code here only gets
+ // triggered if maRepeats.getValue() is an
+ // _integer_. Otherwise, nRepeats will never
+ // reach nor exceed
+ // maRepeats.getValue(). Thus, the code below
+ // does not need to handle cases of fractional
+ // repeats, and can always assume that a full
+ // animation run has ended (with
+ // nRelativeSimpleTime=1.0 for
+ // non-autoreversed activities).
+
+ // with modf, nRelativeSimpleTime will never
+ // become 1.0, since nRepeats is incremented and
+ // nRelativeSimpleTime set to 0.0 then.
+
+ // For the animation to reach its final value,
+ // nRepeats must although become
+ // maRepeats.getValue()-1.0, and
+ // nRelativeSimpleTime=1.0.
+ nRelativeSimpleTime = 1.0;
+ nRepeats -= 1.0;
+ }
+ }
+
+ // actually perform something
+ // ==========================
+
+ simplePerform( nRelativeSimpleTime,
+ // nRepeats is already integer-valued
+ static_cast<sal_uInt32>( nRepeats ) );
+
+
+ // delayed endActivity() call from end condition check
+ // below. Issued after the simplePerform() call above, to
+ // give animations the chance to correctly reach the
+ // animation end value, without spurious bail-outs because
+ // of isActive() returning false.
+ if( bActivityEnding )
+ endActivity();
+
+ // one more frame successfully performed
+ ++mnCurrPerformCalls;
+
+ return isActive();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */