1*b1cdbd2cSJim Jagielski /************************************************************** 2*b1cdbd2cSJim Jagielski * 3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski * distributed with this work for additional information 6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski * 11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski * 13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski * under the License. 19*b1cdbd2cSJim Jagielski * 20*b1cdbd2cSJim Jagielski *************************************************************/ 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski 23*b1cdbd2cSJim Jagielski 24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove 25*b1cdbd2cSJim Jagielski #include "precompiled_slideshow.hxx" 26*b1cdbd2cSJim Jagielski 27*b1cdbd2cSJim Jagielski // must be first 28*b1cdbd2cSJim Jagielski #include <canvas/debug.hxx> 29*b1cdbd2cSJim Jagielski #include <tools/diagnose_ex.h> 30*b1cdbd2cSJim Jagielski #include <canvas/verbosetrace.hxx> 31*b1cdbd2cSJim Jagielski #include <canvas/canvastools.hxx> 32*b1cdbd2cSJim Jagielski 33*b1cdbd2cSJim Jagielski #include <activitybase.hxx> 34*b1cdbd2cSJim Jagielski 35*b1cdbd2cSJim Jagielski 36*b1cdbd2cSJim Jagielski namespace slideshow 37*b1cdbd2cSJim Jagielski { 38*b1cdbd2cSJim Jagielski namespace internal 39*b1cdbd2cSJim Jagielski { 40*b1cdbd2cSJim Jagielski // TODO(P1): Elide some virtual function calls, by templifying this 41*b1cdbd2cSJim Jagielski // static hierarchy 42*b1cdbd2cSJim Jagielski ActivityBase(const ActivityParameters & rParms)43*b1cdbd2cSJim Jagielski ActivityBase::ActivityBase( const ActivityParameters& rParms ) : 44*b1cdbd2cSJim Jagielski mpEndEvent( rParms.mrEndEvent ), 45*b1cdbd2cSJim Jagielski mrEventQueue( rParms.mrEventQueue ), 46*b1cdbd2cSJim Jagielski mpShape(), 47*b1cdbd2cSJim Jagielski mpAttributeLayer(), 48*b1cdbd2cSJim Jagielski maRepeats( rParms.mrRepeats ), 49*b1cdbd2cSJim Jagielski mnAccelerationFraction( rParms.mnAccelerationFraction ), 50*b1cdbd2cSJim Jagielski mnDecelerationFraction( rParms.mnDecelerationFraction ), 51*b1cdbd2cSJim Jagielski mbAutoReverse( rParms.mbAutoReverse ), 52*b1cdbd2cSJim Jagielski mbFirstPerformCall( true ), 53*b1cdbd2cSJim Jagielski mbIsActive( true ) {} 54*b1cdbd2cSJim Jagielski dispose()55*b1cdbd2cSJim Jagielski void ActivityBase::dispose() 56*b1cdbd2cSJim Jagielski { 57*b1cdbd2cSJim Jagielski // deactivate 58*b1cdbd2cSJim Jagielski mbIsActive = false; 59*b1cdbd2cSJim Jagielski 60*b1cdbd2cSJim Jagielski // dispose event 61*b1cdbd2cSJim Jagielski if( mpEndEvent ) 62*b1cdbd2cSJim Jagielski mpEndEvent->dispose(); 63*b1cdbd2cSJim Jagielski 64*b1cdbd2cSJim Jagielski // release references 65*b1cdbd2cSJim Jagielski mpEndEvent.reset(); 66*b1cdbd2cSJim Jagielski mpShape.reset(); 67*b1cdbd2cSJim Jagielski mpAttributeLayer.reset(); 68*b1cdbd2cSJim Jagielski } 69*b1cdbd2cSJim Jagielski calcTimeLag() const70*b1cdbd2cSJim Jagielski double ActivityBase::calcTimeLag() const 71*b1cdbd2cSJim Jagielski { 72*b1cdbd2cSJim Jagielski // TODO(Q1): implement different init process! 73*b1cdbd2cSJim Jagielski if (isActive() && mbFirstPerformCall) 74*b1cdbd2cSJim Jagielski { 75*b1cdbd2cSJim Jagielski mbFirstPerformCall = false; 76*b1cdbd2cSJim Jagielski 77*b1cdbd2cSJim Jagielski // notify derived classes that we're 78*b1cdbd2cSJim Jagielski // starting now 79*b1cdbd2cSJim Jagielski const_cast<ActivityBase *>(this)->startAnimation(); 80*b1cdbd2cSJim Jagielski } 81*b1cdbd2cSJim Jagielski return 0.0; 82*b1cdbd2cSJim Jagielski } 83*b1cdbd2cSJim Jagielski perform()84*b1cdbd2cSJim Jagielski bool ActivityBase::perform() 85*b1cdbd2cSJim Jagielski { 86*b1cdbd2cSJim Jagielski // still active? 87*b1cdbd2cSJim Jagielski if( !isActive() ) 88*b1cdbd2cSJim Jagielski return false; // no, early exit. 89*b1cdbd2cSJim Jagielski 90*b1cdbd2cSJim Jagielski OSL_ASSERT( ! mbFirstPerformCall ); 91*b1cdbd2cSJim Jagielski 92*b1cdbd2cSJim Jagielski return true; 93*b1cdbd2cSJim Jagielski } 94*b1cdbd2cSJim Jagielski isActive() const95*b1cdbd2cSJim Jagielski bool ActivityBase::isActive() const 96*b1cdbd2cSJim Jagielski { 97*b1cdbd2cSJim Jagielski return mbIsActive; 98*b1cdbd2cSJim Jagielski } 99*b1cdbd2cSJim Jagielski setTargets(const AnimatableShapeSharedPtr & rShape,const ShapeAttributeLayerSharedPtr & rAttrLayer)100*b1cdbd2cSJim Jagielski void ActivityBase::setTargets( const AnimatableShapeSharedPtr& rShape, 101*b1cdbd2cSJim Jagielski const ShapeAttributeLayerSharedPtr& rAttrLayer ) 102*b1cdbd2cSJim Jagielski { 103*b1cdbd2cSJim Jagielski ENSURE_OR_THROW( rShape, 104*b1cdbd2cSJim Jagielski "ActivityBase::setTargets(): Invalid shape" ); 105*b1cdbd2cSJim Jagielski ENSURE_OR_THROW( rAttrLayer, 106*b1cdbd2cSJim Jagielski "ActivityBase::setTargets(): Invalid attribute layer" ); 107*b1cdbd2cSJim Jagielski 108*b1cdbd2cSJim Jagielski mpShape = rShape; 109*b1cdbd2cSJim Jagielski mpAttributeLayer = rAttrLayer; 110*b1cdbd2cSJim Jagielski } 111*b1cdbd2cSJim Jagielski endActivity()112*b1cdbd2cSJim Jagielski void ActivityBase::endActivity() 113*b1cdbd2cSJim Jagielski { 114*b1cdbd2cSJim Jagielski // this is a regular activity end 115*b1cdbd2cSJim Jagielski mbIsActive = false; 116*b1cdbd2cSJim Jagielski 117*b1cdbd2cSJim Jagielski // Activity is ending, queue event, then 118*b1cdbd2cSJim Jagielski if( mpEndEvent ) 119*b1cdbd2cSJim Jagielski mrEventQueue.addEvent( mpEndEvent ); 120*b1cdbd2cSJim Jagielski 121*b1cdbd2cSJim Jagielski // release references 122*b1cdbd2cSJim Jagielski mpEndEvent.reset(); 123*b1cdbd2cSJim Jagielski } 124*b1cdbd2cSJim Jagielski dequeued()125*b1cdbd2cSJim Jagielski void ActivityBase::dequeued() 126*b1cdbd2cSJim Jagielski { 127*b1cdbd2cSJim Jagielski // xxx todo: 128*b1cdbd2cSJim Jagielski // // ignored here, if we're still active. Discrete 129*b1cdbd2cSJim Jagielski // // activities are dequeued after every perform() call, 130*b1cdbd2cSJim Jagielski // // thus, the call is only significant when isActive() == 131*b1cdbd2cSJim Jagielski // // false. 132*b1cdbd2cSJim Jagielski if( !isActive() ) 133*b1cdbd2cSJim Jagielski endAnimation(); 134*b1cdbd2cSJim Jagielski } 135*b1cdbd2cSJim Jagielski end()136*b1cdbd2cSJim Jagielski void ActivityBase::end() 137*b1cdbd2cSJim Jagielski { 138*b1cdbd2cSJim Jagielski if (!isActive() || isDisposed()) 139*b1cdbd2cSJim Jagielski return; 140*b1cdbd2cSJim Jagielski // assure animation is started: 141*b1cdbd2cSJim Jagielski if (mbFirstPerformCall) { 142*b1cdbd2cSJim Jagielski mbFirstPerformCall = false; 143*b1cdbd2cSJim Jagielski // notify derived classes that we're starting now 144*b1cdbd2cSJim Jagielski this->startAnimation(); 145*b1cdbd2cSJim Jagielski } 146*b1cdbd2cSJim Jagielski 147*b1cdbd2cSJim Jagielski performEnd(); // calling private virtual 148*b1cdbd2cSJim Jagielski endAnimation(); 149*b1cdbd2cSJim Jagielski endActivity(); 150*b1cdbd2cSJim Jagielski } 151*b1cdbd2cSJim Jagielski calcAcceleratedTime(double nT) const152*b1cdbd2cSJim Jagielski double ActivityBase::calcAcceleratedTime( double nT ) const 153*b1cdbd2cSJim Jagielski { 154*b1cdbd2cSJim Jagielski // Handle acceleration/deceleration 155*b1cdbd2cSJim Jagielski // ================================ 156*b1cdbd2cSJim Jagielski 157*b1cdbd2cSJim Jagielski // clamp nT to permissible [0,1] range 158*b1cdbd2cSJim Jagielski nT = ::basegfx::clamp( nT, 0.0, 1.0 ); 159*b1cdbd2cSJim Jagielski 160*b1cdbd2cSJim Jagielski // take acceleration/deceleration into account. if the sum 161*b1cdbd2cSJim Jagielski // of mnAccelerationFraction and mnDecelerationFraction 162*b1cdbd2cSJim Jagielski // exceeds 1.0, ignore both (that's according to SMIL spec) 163*b1cdbd2cSJim Jagielski if( (mnAccelerationFraction > 0.0 || 164*b1cdbd2cSJim Jagielski mnDecelerationFraction > 0.0) && 165*b1cdbd2cSJim Jagielski mnAccelerationFraction + mnDecelerationFraction <= 1.0 ) 166*b1cdbd2cSJim Jagielski { 167*b1cdbd2cSJim Jagielski /* 168*b1cdbd2cSJim Jagielski // calc accelerated/decelerated time. 169*b1cdbd2cSJim Jagielski // 170*b1cdbd2cSJim Jagielski // We have three intervals: 171*b1cdbd2cSJim Jagielski // 1 [0,a] 172*b1cdbd2cSJim Jagielski // 2 [a,d] 173*b1cdbd2cSJim Jagielski // 3 [d,1] (with a and d being acceleration/deceleration 174*b1cdbd2cSJim Jagielski // fraction, resp.) 175*b1cdbd2cSJim Jagielski // 176*b1cdbd2cSJim Jagielski // The change rate during interval 1 is constantly 177*b1cdbd2cSJim Jagielski // increasing, reaching 1 at a. It then stays at 1, 178*b1cdbd2cSJim Jagielski // starting a linear decrease at d, ending with 0 at 179*b1cdbd2cSJim Jagielski // time 1. The integral of this function is the 180*b1cdbd2cSJim Jagielski // required new time nT'. 181*b1cdbd2cSJim Jagielski // 182*b1cdbd2cSJim Jagielski // As we arbitrarily assumed 1 as the upper value of 183*b1cdbd2cSJim Jagielski // the change rate, the integral must be normalized to 184*b1cdbd2cSJim Jagielski // reach nT'=1 at the end of the interval. This 185*b1cdbd2cSJim Jagielski // normalization constant is: 186*b1cdbd2cSJim Jagielski // 187*b1cdbd2cSJim Jagielski // c = 1 - 0.5a - 0.5d 188*b1cdbd2cSJim Jagielski // 189*b1cdbd2cSJim Jagielski // The integral itself then amounts to: 190*b1cdbd2cSJim Jagielski // 191*b1cdbd2cSJim Jagielski // 0.5 nT^2 / a + (nT-a) + (nT - 0.5 nT^2 / d) 192*b1cdbd2cSJim Jagielski // 193*b1cdbd2cSJim Jagielski // (where each of the three summands correspond to the 194*b1cdbd2cSJim Jagielski // three intervals above, and are applied only if nT 195*b1cdbd2cSJim Jagielski // has reached the corresponding interval) 196*b1cdbd2cSJim Jagielski // 197*b1cdbd2cSJim Jagielski // The graph of the change rate is a trapezoid: 198*b1cdbd2cSJim Jagielski // 199*b1cdbd2cSJim Jagielski // | 200*b1cdbd2cSJim Jagielski // 1| /--------------\ 201*b1cdbd2cSJim Jagielski // | / \ 202*b1cdbd2cSJim Jagielski // | / \ 203*b1cdbd2cSJim Jagielski // | / \ 204*b1cdbd2cSJim Jagielski // ----------------------------- 205*b1cdbd2cSJim Jagielski // 0 a d 1 206*b1cdbd2cSJim Jagielski // 207*b1cdbd2cSJim Jagielski //*/ 208*b1cdbd2cSJim Jagielski const double nC( 1.0 - 0.5*mnAccelerationFraction - 0.5*mnDecelerationFraction ); 209*b1cdbd2cSJim Jagielski 210*b1cdbd2cSJim Jagielski // this variable accumulates the new time value 211*b1cdbd2cSJim Jagielski double nTPrime(0.0); 212*b1cdbd2cSJim Jagielski 213*b1cdbd2cSJim Jagielski if( nT < mnAccelerationFraction ) 214*b1cdbd2cSJim Jagielski { 215*b1cdbd2cSJim Jagielski nTPrime += 0.5*nT*nT/mnAccelerationFraction; // partial first interval 216*b1cdbd2cSJim Jagielski } 217*b1cdbd2cSJim Jagielski else 218*b1cdbd2cSJim Jagielski { 219*b1cdbd2cSJim Jagielski nTPrime += 0.5*mnAccelerationFraction; // full first interval 220*b1cdbd2cSJim Jagielski 221*b1cdbd2cSJim Jagielski if( nT <= 1.0-mnDecelerationFraction ) 222*b1cdbd2cSJim Jagielski { 223*b1cdbd2cSJim Jagielski nTPrime += nT-mnAccelerationFraction; // partial second interval 224*b1cdbd2cSJim Jagielski } 225*b1cdbd2cSJim Jagielski else 226*b1cdbd2cSJim Jagielski { 227*b1cdbd2cSJim Jagielski nTPrime += 1.0 - mnAccelerationFraction - mnDecelerationFraction; // full second interval 228*b1cdbd2cSJim Jagielski 229*b1cdbd2cSJim Jagielski const double nTRelative( nT - 1.0 + mnDecelerationFraction ); 230*b1cdbd2cSJim Jagielski 231*b1cdbd2cSJim Jagielski nTPrime += nTRelative - 0.5*nTRelative*nTRelative / mnDecelerationFraction; 232*b1cdbd2cSJim Jagielski } 233*b1cdbd2cSJim Jagielski } 234*b1cdbd2cSJim Jagielski 235*b1cdbd2cSJim Jagielski // normalize, and assign to work variable 236*b1cdbd2cSJim Jagielski nT = nTPrime / nC; 237*b1cdbd2cSJim Jagielski } 238*b1cdbd2cSJim Jagielski 239*b1cdbd2cSJim Jagielski return nT; 240*b1cdbd2cSJim Jagielski } 241*b1cdbd2cSJim Jagielski } 242*b1cdbd2cSJim Jagielski } 243