1*70f497fbSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*70f497fbSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*70f497fbSAndrew Rist * or more contributor license agreements. See the NOTICE file 5*70f497fbSAndrew Rist * distributed with this work for additional information 6*70f497fbSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*70f497fbSAndrew Rist * to you under the Apache License, Version 2.0 (the 8*70f497fbSAndrew Rist * "License"); you may not use this file except in compliance 9*70f497fbSAndrew Rist * with the License. You may obtain a copy of the License at 10*70f497fbSAndrew Rist * 11*70f497fbSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*70f497fbSAndrew Rist * 13*70f497fbSAndrew Rist * Unless required by applicable law or agreed to in writing, 14*70f497fbSAndrew Rist * software distributed under the License is distributed on an 15*70f497fbSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*70f497fbSAndrew Rist * KIND, either express or implied. See the License for the 17*70f497fbSAndrew Rist * specific language governing permissions and limitations 18*70f497fbSAndrew Rist * under the License. 19*70f497fbSAndrew Rist * 20*70f497fbSAndrew Rist *************************************************************/ 21*70f497fbSAndrew Rist 22*70f497fbSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_slideshow.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir // must be first 28cdf0e10cSrcweir #include <canvas/debug.hxx> 29cdf0e10cSrcweir #include <tools/diagnose_ex.h> 30cdf0e10cSrcweir #include <canvas/verbosetrace.hxx> 31cdf0e10cSrcweir 32cdf0e10cSrcweir #include <discreteactivitybase.hxx> 33cdf0e10cSrcweir 34cdf0e10cSrcweir 35cdf0e10cSrcweir namespace slideshow 36cdf0e10cSrcweir { 37cdf0e10cSrcweir namespace internal 38cdf0e10cSrcweir { DiscreteActivityBase(const ActivityParameters & rParms)39cdf0e10cSrcweir DiscreteActivityBase::DiscreteActivityBase( const ActivityParameters& rParms ) : 40cdf0e10cSrcweir ActivityBase( rParms ), 41cdf0e10cSrcweir mpWakeupEvent( rParms.mpWakeupEvent ), 42cdf0e10cSrcweir maDiscreteTimes( rParms.maDiscreteTimes ), 43cdf0e10cSrcweir mnSimpleDuration( rParms.mnMinDuration ), 44cdf0e10cSrcweir mnCurrPerformCalls( 0 ) 45cdf0e10cSrcweir { 46cdf0e10cSrcweir ENSURE_OR_THROW( mpWakeupEvent, 47cdf0e10cSrcweir "DiscreteActivityBase::DiscreteActivityBase(): Invalid wakeup event" ); 48cdf0e10cSrcweir 49cdf0e10cSrcweir ENSURE_OR_THROW( !maDiscreteTimes.empty(), 50cdf0e10cSrcweir "DiscreteActivityBase::DiscreteActivityBase(): time vector is empty, why do you create me?" ); 51cdf0e10cSrcweir 52cdf0e10cSrcweir #ifdef DBG_UTIL 53cdf0e10cSrcweir // check parameters: rDiscreteTimes must be sorted in 54cdf0e10cSrcweir // ascending order, and contain values only from the range 55cdf0e10cSrcweir // [0,1] 56cdf0e10cSrcweir for( ::std::size_t i=1, len=maDiscreteTimes.size(); i<len; ++i ) 57cdf0e10cSrcweir { 58cdf0e10cSrcweir if( maDiscreteTimes[i] < 0.0 || 59cdf0e10cSrcweir maDiscreteTimes[i] > 1.0 || 60cdf0e10cSrcweir maDiscreteTimes[i-1] < 0.0 || 61cdf0e10cSrcweir maDiscreteTimes[i-1] > 1.0 ) 62cdf0e10cSrcweir { 63cdf0e10cSrcweir ENSURE_OR_THROW( false, "DiscreteActivityBase::DiscreteActivityBase(): time values not within [0,1] range!" ); 64cdf0e10cSrcweir } 65cdf0e10cSrcweir 66cdf0e10cSrcweir if( maDiscreteTimes[i-1] > maDiscreteTimes[i] ) 67cdf0e10cSrcweir ENSURE_OR_THROW( false, "DiscreteActivityBase::DiscreteActivityBase(): time vector is not sorted in ascending order!" ); 68cdf0e10cSrcweir } 69cdf0e10cSrcweir 70cdf0e10cSrcweir // TODO(E2): check this also in production code? 71cdf0e10cSrcweir #endif 72cdf0e10cSrcweir } 73cdf0e10cSrcweir startAnimation()74cdf0e10cSrcweir void DiscreteActivityBase::startAnimation() 75cdf0e10cSrcweir { 76cdf0e10cSrcweir // start timer on wakeup event 77cdf0e10cSrcweir mpWakeupEvent->start(); 78cdf0e10cSrcweir } 79cdf0e10cSrcweir calcFrameIndex(sal_uInt32 nCurrCalls,::std::size_t nVectorSize) const80cdf0e10cSrcweir sal_uInt32 DiscreteActivityBase::calcFrameIndex( sal_uInt32 nCurrCalls, 81cdf0e10cSrcweir ::std::size_t nVectorSize ) const 82cdf0e10cSrcweir { 83cdf0e10cSrcweir if( isAutoReverse() ) 84cdf0e10cSrcweir { 85cdf0e10cSrcweir // every full repeat run consists of one 86cdf0e10cSrcweir // forward and one backward traversal. 87cdf0e10cSrcweir sal_uInt32 nFrameIndex( nCurrCalls % (2*nVectorSize) ); 88cdf0e10cSrcweir 89cdf0e10cSrcweir // nFrameIndex values >= nVectorSize belong to 90cdf0e10cSrcweir // the backward traversal 91cdf0e10cSrcweir if( nFrameIndex >= nVectorSize ) 92cdf0e10cSrcweir nFrameIndex = 2*nVectorSize - nFrameIndex; // invert sweep 93cdf0e10cSrcweir 94cdf0e10cSrcweir return nFrameIndex; 95cdf0e10cSrcweir } 96cdf0e10cSrcweir else 97cdf0e10cSrcweir { 98cdf0e10cSrcweir return nCurrCalls % nVectorSize ; 99cdf0e10cSrcweir } 100cdf0e10cSrcweir } 101cdf0e10cSrcweir calcRepeatCount(sal_uInt32 nCurrCalls,::std::size_t nVectorSize) const102cdf0e10cSrcweir sal_uInt32 DiscreteActivityBase::calcRepeatCount( sal_uInt32 nCurrCalls, 103cdf0e10cSrcweir ::std::size_t nVectorSize ) const 104cdf0e10cSrcweir { 105cdf0e10cSrcweir if( isAutoReverse() ) 106cdf0e10cSrcweir return nCurrCalls / (2*nVectorSize); // we've got 2 cycles per repeat 107cdf0e10cSrcweir else 108cdf0e10cSrcweir return nCurrCalls / nVectorSize; 109cdf0e10cSrcweir } 110cdf0e10cSrcweir perform()111cdf0e10cSrcweir bool DiscreteActivityBase::perform() 112cdf0e10cSrcweir { 113cdf0e10cSrcweir // call base class, for start() calls and end handling 114cdf0e10cSrcweir if( !ActivityBase::perform() ) 115cdf0e10cSrcweir return false; // done, we're ended 116cdf0e10cSrcweir 117cdf0e10cSrcweir const ::std::size_t nVectorSize( maDiscreteTimes.size() ); 118cdf0e10cSrcweir 119cdf0e10cSrcweir // actually perform something 120cdf0e10cSrcweir // ========================== 121cdf0e10cSrcweir 122cdf0e10cSrcweir // TODO(Q3): Refactor this mess 123cdf0e10cSrcweir 124cdf0e10cSrcweir // call derived class with current frame index (modulo 125cdf0e10cSrcweir // vector size, to cope with repeats) 126cdf0e10cSrcweir perform( calcFrameIndex( mnCurrPerformCalls, nVectorSize ), 127cdf0e10cSrcweir calcRepeatCount( mnCurrPerformCalls, nVectorSize ) ); 128cdf0e10cSrcweir 129cdf0e10cSrcweir // calc next index 130cdf0e10cSrcweir ++mnCurrPerformCalls; 131cdf0e10cSrcweir 132cdf0e10cSrcweir // calc currently reached repeat count 133cdf0e10cSrcweir double nCurrRepeat( double(mnCurrPerformCalls) / nVectorSize ); 134cdf0e10cSrcweir 135cdf0e10cSrcweir // if auto-reverse is specified, halve the 136cdf0e10cSrcweir // effective repeat count, since we pass every 137cdf0e10cSrcweir // repeat run twice: once forward, once backward. 138cdf0e10cSrcweir if( isAutoReverse() ) 139cdf0e10cSrcweir nCurrRepeat /= 2.0; 140cdf0e10cSrcweir 141cdf0e10cSrcweir // schedule next frame, if either repeat is indefinite 142cdf0e10cSrcweir // (repeat forever), or we've not yet reached the requested 143cdf0e10cSrcweir // repeat count 144cdf0e10cSrcweir if( !isRepeatCountValid() || 145cdf0e10cSrcweir nCurrRepeat < getRepeatCount() ) 146cdf0e10cSrcweir { 147cdf0e10cSrcweir // add wake-up event to queue (modulo 148cdf0e10cSrcweir // vector size, to cope with repeats). 149cdf0e10cSrcweir 150cdf0e10cSrcweir // repeat is handled locally, only apply acceleration/deceleration. 151cdf0e10cSrcweir // Scale time vector with simple duration, offset with full repeat 152cdf0e10cSrcweir // times. 153cdf0e10cSrcweir // 154cdf0e10cSrcweir // Somewhat condensed, the argument for setNextTimeout below could 155cdf0e10cSrcweir // be written as 156cdf0e10cSrcweir // 157cdf0e10cSrcweir // mnSimpleDuration*(nFullRepeats + calcAcceleratedTime( currentRepeatTime )), 158cdf0e10cSrcweir // 159cdf0e10cSrcweir // with currentRepeatTime = maDiscreteTimes[ currentRepeatIndex ] 160cdf0e10cSrcweir // 161cdf0e10cSrcweir // Note that calcAcceleratedTime() is only applied to the current repeat's value, 162cdf0e10cSrcweir // not to the total resulting time. This is in accordance with the SMIL spec. 163cdf0e10cSrcweir // 164cdf0e10cSrcweir mpWakeupEvent->setNextTimeout( 165cdf0e10cSrcweir mnSimpleDuration*( 166cdf0e10cSrcweir calcRepeatCount( 167cdf0e10cSrcweir mnCurrPerformCalls, 168cdf0e10cSrcweir nVectorSize ) + 169cdf0e10cSrcweir calcAcceleratedTime( 170cdf0e10cSrcweir maDiscreteTimes[ 171cdf0e10cSrcweir calcFrameIndex( 172cdf0e10cSrcweir mnCurrPerformCalls, 173cdf0e10cSrcweir nVectorSize ) ] ) ) ); 174cdf0e10cSrcweir 175cdf0e10cSrcweir getEventQueue().addEvent( mpWakeupEvent ); 176cdf0e10cSrcweir } 177cdf0e10cSrcweir else 178cdf0e10cSrcweir { 179cdf0e10cSrcweir // release event reference (relation to wakeup event 180cdf0e10cSrcweir // is circular!) 181cdf0e10cSrcweir mpWakeupEvent.reset(); 182cdf0e10cSrcweir 183cdf0e10cSrcweir // done with this activity 184cdf0e10cSrcweir endActivity(); 185cdf0e10cSrcweir } 186cdf0e10cSrcweir 187cdf0e10cSrcweir return false; // remove from queue, will be added back by the wakeup event. 188cdf0e10cSrcweir } 189cdf0e10cSrcweir dispose()190cdf0e10cSrcweir void DiscreteActivityBase::dispose() 191cdf0e10cSrcweir { 192cdf0e10cSrcweir // dispose event 193cdf0e10cSrcweir if( mpWakeupEvent ) 194cdf0e10cSrcweir mpWakeupEvent->dispose(); 195cdf0e10cSrcweir 196cdf0e10cSrcweir // release references 197cdf0e10cSrcweir mpWakeupEvent.reset(); 198cdf0e10cSrcweir 199cdf0e10cSrcweir ActivityBase::dispose(); 200cdf0e10cSrcweir } 201cdf0e10cSrcweir } 202cdf0e10cSrcweir } 203