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