1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_slideshow.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir // must be first 32*cdf0e10cSrcweir #include <canvas/debug.hxx> 33*cdf0e10cSrcweir #include <canvas/verbosetrace.hxx> 34*cdf0e10cSrcweir 35*cdf0e10cSrcweir #include <simplecontinuousactivitybase.hxx> 36*cdf0e10cSrcweir 37*cdf0e10cSrcweir 38*cdf0e10cSrcweir namespace slideshow 39*cdf0e10cSrcweir { 40*cdf0e10cSrcweir namespace internal 41*cdf0e10cSrcweir { 42*cdf0e10cSrcweir SimpleContinuousActivityBase::SimpleContinuousActivityBase( 43*cdf0e10cSrcweir const ActivityParameters& rParms ) : 44*cdf0e10cSrcweir ActivityBase( rParms ), 45*cdf0e10cSrcweir maTimer( rParms.mrActivitiesQueue.getTimer() ), 46*cdf0e10cSrcweir mnMinSimpleDuration( rParms.mnMinDuration ), 47*cdf0e10cSrcweir mnMinNumberOfFrames( rParms.mnMinNumberOfFrames ), 48*cdf0e10cSrcweir mnCurrPerformCalls( 0 ) 49*cdf0e10cSrcweir { 50*cdf0e10cSrcweir } 51*cdf0e10cSrcweir 52*cdf0e10cSrcweir void SimpleContinuousActivityBase::startAnimation() 53*cdf0e10cSrcweir { 54*cdf0e10cSrcweir // init timer. We measure animation time only when we're 55*cdf0e10cSrcweir // actually started. 56*cdf0e10cSrcweir maTimer.reset(); 57*cdf0e10cSrcweir } 58*cdf0e10cSrcweir 59*cdf0e10cSrcweir double SimpleContinuousActivityBase::calcTimeLag() const 60*cdf0e10cSrcweir { 61*cdf0e10cSrcweir ActivityBase::calcTimeLag(); 62*cdf0e10cSrcweir if (! isActive()) 63*cdf0e10cSrcweir return 0.0; 64*cdf0e10cSrcweir 65*cdf0e10cSrcweir // retrieve locally elapsed time 66*cdf0e10cSrcweir const double nCurrElapsedTime( maTimer.getElapsedTime() ); 67*cdf0e10cSrcweir 68*cdf0e10cSrcweir // log time 69*cdf0e10cSrcweir VERBOSE_TRACE( "SimpleContinuousActivityBase::calcTimeLag(): " 70*cdf0e10cSrcweir "next step is based on time: %f", nCurrElapsedTime ); 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir // go to great length to ensure a proper animation 73*cdf0e10cSrcweir // run. Since we don't know how often we will be called 74*cdf0e10cSrcweir // here, try to spread the animator calls uniquely over 75*cdf0e10cSrcweir // the [0,1] parameter range. Be aware of the fact that 76*cdf0e10cSrcweir // perform will be called at least mnMinNumberOfTurns 77*cdf0e10cSrcweir // times. 78*cdf0e10cSrcweir 79*cdf0e10cSrcweir // fraction of time elapsed 80*cdf0e10cSrcweir const double nFractionElapsedTime( 81*cdf0e10cSrcweir nCurrElapsedTime / mnMinSimpleDuration ); 82*cdf0e10cSrcweir 83*cdf0e10cSrcweir // fraction of minimum calls performed 84*cdf0e10cSrcweir const double nFractionRequiredCalls( 85*cdf0e10cSrcweir double(mnCurrPerformCalls) / mnMinNumberOfFrames ); 86*cdf0e10cSrcweir 87*cdf0e10cSrcweir // okay, so now, the decision is easy: 88*cdf0e10cSrcweir // 89*cdf0e10cSrcweir // If the fraction of time elapsed is smaller than the 90*cdf0e10cSrcweir // number of calls required to be performed, then we calc 91*cdf0e10cSrcweir // the position on the animation range according to 92*cdf0e10cSrcweir // elapsed time. That is, we're so to say ahead of time. 93*cdf0e10cSrcweir // 94*cdf0e10cSrcweir // In contrary, if the fraction of time elapsed is larger, 95*cdf0e10cSrcweir // then we're lagging, and we thus calc the position on 96*cdf0e10cSrcweir // the animation time line according to the fraction of 97*cdf0e10cSrcweir // calls performed. Thus, the animation is forced to slow 98*cdf0e10cSrcweir // down, and take the required minimal number of steps, 99*cdf0e10cSrcweir // sufficiently equally distributed across the animation 100*cdf0e10cSrcweir // time line. 101*cdf0e10cSrcweir if( nFractionElapsedTime < nFractionRequiredCalls ) 102*cdf0e10cSrcweir { 103*cdf0e10cSrcweir VERBOSE_TRACE( "SimpleContinuousActivityBase::calcTimeLag(): " 104*cdf0e10cSrcweir "t=%f is based on time", nFractionElapsedTime ); 105*cdf0e10cSrcweir return 0.0; 106*cdf0e10cSrcweir } 107*cdf0e10cSrcweir else 108*cdf0e10cSrcweir { 109*cdf0e10cSrcweir VERBOSE_TRACE( "SimpleContinuousActivityBase::perform(): " 110*cdf0e10cSrcweir "t=%f is based on number of calls", 111*cdf0e10cSrcweir nFractionRequiredCalls ); 112*cdf0e10cSrcweir 113*cdf0e10cSrcweir // lag global time, so all other animations lag, too: 114*cdf0e10cSrcweir return ((nFractionElapsedTime - nFractionRequiredCalls) 115*cdf0e10cSrcweir * mnMinSimpleDuration); 116*cdf0e10cSrcweir } 117*cdf0e10cSrcweir } 118*cdf0e10cSrcweir 119*cdf0e10cSrcweir bool SimpleContinuousActivityBase::perform() 120*cdf0e10cSrcweir { 121*cdf0e10cSrcweir // call base class, for start() calls and end handling 122*cdf0e10cSrcweir if( !ActivityBase::perform() ) 123*cdf0e10cSrcweir return false; // done, we're ended 124*cdf0e10cSrcweir 125*cdf0e10cSrcweir 126*cdf0e10cSrcweir // get relative animation position 127*cdf0e10cSrcweir // =============================== 128*cdf0e10cSrcweir 129*cdf0e10cSrcweir const double nCurrElapsedTime( maTimer.getElapsedTime() ); 130*cdf0e10cSrcweir double nT( nCurrElapsedTime / mnMinSimpleDuration ); 131*cdf0e10cSrcweir 132*cdf0e10cSrcweir 133*cdf0e10cSrcweir // one of the stop criteria reached? 134*cdf0e10cSrcweir // ================================= 135*cdf0e10cSrcweir 136*cdf0e10cSrcweir // will be set to true below, if one of the termination criteria 137*cdf0e10cSrcweir // matched. 138*cdf0e10cSrcweir bool bActivityEnding( false ); 139*cdf0e10cSrcweir 140*cdf0e10cSrcweir if( isRepeatCountValid() ) 141*cdf0e10cSrcweir { 142*cdf0e10cSrcweir // Finite duration 143*cdf0e10cSrcweir // =============== 144*cdf0e10cSrcweir 145*cdf0e10cSrcweir // When we've autoreverse on, the repeat count 146*cdf0e10cSrcweir // doubles 147*cdf0e10cSrcweir const double nRepeatCount( getRepeatCount() ); 148*cdf0e10cSrcweir const double nEffectiveRepeat( isAutoReverse() ? 149*cdf0e10cSrcweir 2.0*nRepeatCount : 150*cdf0e10cSrcweir nRepeatCount ); 151*cdf0e10cSrcweir 152*cdf0e10cSrcweir // time (or frame count) elapsed? 153*cdf0e10cSrcweir if( nEffectiveRepeat <= nT ) 154*cdf0e10cSrcweir { 155*cdf0e10cSrcweir // okee. done for now. Will not exit right here, 156*cdf0e10cSrcweir // to give animation the chance to render the last 157*cdf0e10cSrcweir // frame below 158*cdf0e10cSrcweir bActivityEnding = true; 159*cdf0e10cSrcweir 160*cdf0e10cSrcweir // clamp animation to max permissible value 161*cdf0e10cSrcweir nT = nEffectiveRepeat; 162*cdf0e10cSrcweir } 163*cdf0e10cSrcweir } 164*cdf0e10cSrcweir 165*cdf0e10cSrcweir 166*cdf0e10cSrcweir // need to do auto-reverse? 167*cdf0e10cSrcweir // ======================== 168*cdf0e10cSrcweir 169*cdf0e10cSrcweir double nRepeats; 170*cdf0e10cSrcweir double nRelativeSimpleTime; 171*cdf0e10cSrcweir 172*cdf0e10cSrcweir // TODO(Q3): Refactor this mess 173*cdf0e10cSrcweir if( isAutoReverse() ) 174*cdf0e10cSrcweir { 175*cdf0e10cSrcweir // divert active duration into repeat and 176*cdf0e10cSrcweir // fractional part. 177*cdf0e10cSrcweir const double nFractionalActiveDuration( modf(nT, &nRepeats) ); 178*cdf0e10cSrcweir 179*cdf0e10cSrcweir // for auto-reverse, map ranges [1,2), [3,4), ... 180*cdf0e10cSrcweir // to ranges [0,1), [1,2), etc. 181*cdf0e10cSrcweir if( ((int)nRepeats) % 2 ) 182*cdf0e10cSrcweir { 183*cdf0e10cSrcweir // we're in an odd range, reverse sweep 184*cdf0e10cSrcweir nRelativeSimpleTime = 1.0 - nFractionalActiveDuration; 185*cdf0e10cSrcweir } 186*cdf0e10cSrcweir else 187*cdf0e10cSrcweir { 188*cdf0e10cSrcweir // we're in an even range, pass on as is 189*cdf0e10cSrcweir nRelativeSimpleTime = nFractionalActiveDuration; 190*cdf0e10cSrcweir } 191*cdf0e10cSrcweir 192*cdf0e10cSrcweir // effective repeat count for autoreverse is half of 193*cdf0e10cSrcweir // the input time's value (each run of an autoreverse 194*cdf0e10cSrcweir // cycle is half of a repeat) 195*cdf0e10cSrcweir nRepeats /= 2; 196*cdf0e10cSrcweir } 197*cdf0e10cSrcweir else 198*cdf0e10cSrcweir { 199*cdf0e10cSrcweir // determine repeat 200*cdf0e10cSrcweir // ================ 201*cdf0e10cSrcweir 202*cdf0e10cSrcweir // calc simple time and number of repeats from nT 203*cdf0e10cSrcweir // Now, that's easy, since the fractional part of 204*cdf0e10cSrcweir // nT gives the relative simple time, and the 205*cdf0e10cSrcweir // integer part the number of full repeats: 206*cdf0e10cSrcweir nRelativeSimpleTime = modf(nT, &nRepeats); 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir // clamp repeats to max permissible value (maRepeats.getValue() - 1.0) 209*cdf0e10cSrcweir if( isRepeatCountValid() && 210*cdf0e10cSrcweir nRepeats >= getRepeatCount() ) 211*cdf0e10cSrcweir { 212*cdf0e10cSrcweir // Note that this code here only gets 213*cdf0e10cSrcweir // triggered if maRepeats.getValue() is an 214*cdf0e10cSrcweir // _integer_. Otherwise, nRepeats will never 215*cdf0e10cSrcweir // reach nor exceed 216*cdf0e10cSrcweir // maRepeats.getValue(). Thus, the code below 217*cdf0e10cSrcweir // does not need to handle cases of fractional 218*cdf0e10cSrcweir // repeats, and can always assume that a full 219*cdf0e10cSrcweir // animation run has ended (with 220*cdf0e10cSrcweir // nRelativeSimpleTime=1.0 for 221*cdf0e10cSrcweir // non-autoreversed activities). 222*cdf0e10cSrcweir 223*cdf0e10cSrcweir // with modf, nRelativeSimpleTime will never 224*cdf0e10cSrcweir // become 1.0, since nRepeats is incremented and 225*cdf0e10cSrcweir // nRelativeSimpleTime set to 0.0 then. 226*cdf0e10cSrcweir // 227*cdf0e10cSrcweir // For the animation to reach its final value, 228*cdf0e10cSrcweir // nRepeats must although become 229*cdf0e10cSrcweir // maRepeats.getValue()-1.0, and 230*cdf0e10cSrcweir // nRelativeSimpleTime=1.0. 231*cdf0e10cSrcweir nRelativeSimpleTime = 1.0; 232*cdf0e10cSrcweir nRepeats -= 1.0; 233*cdf0e10cSrcweir } 234*cdf0e10cSrcweir } 235*cdf0e10cSrcweir 236*cdf0e10cSrcweir // actually perform something 237*cdf0e10cSrcweir // ========================== 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir simplePerform( nRelativeSimpleTime, 240*cdf0e10cSrcweir // nRepeats is already integer-valued 241*cdf0e10cSrcweir static_cast<sal_uInt32>( nRepeats ) ); 242*cdf0e10cSrcweir 243*cdf0e10cSrcweir 244*cdf0e10cSrcweir // delayed endActivity() call from end condition check 245*cdf0e10cSrcweir // below. Issued after the simplePerform() call above, to 246*cdf0e10cSrcweir // give animations the chance to correctly reach the 247*cdf0e10cSrcweir // animation end value, without spurious bail-outs because 248*cdf0e10cSrcweir // of isActive() returning false. 249*cdf0e10cSrcweir if( bActivityEnding ) 250*cdf0e10cSrcweir endActivity(); 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir // one more frame successfully performed 253*cdf0e10cSrcweir ++mnCurrPerformCalls; 254*cdf0e10cSrcweir 255*cdf0e10cSrcweir return isActive(); 256*cdf0e10cSrcweir } 257*cdf0e10cSrcweir } 258*cdf0e10cSrcweir } 259