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_drawinglayer.hxx" 30 31 #include <drawinglayer/animation/animationtiming.hxx> 32 #include <basegfx/numeric/ftools.hxx> 33 34 ////////////////////////////////////////////////////////////////////////////// 35 36 namespace drawinglayer 37 { 38 namespace animation 39 { 40 ////////////////////////////////////////////////////////////////////////////// 41 42 AnimationEntry::AnimationEntry() 43 { 44 } 45 46 AnimationEntry::~AnimationEntry() 47 { 48 } 49 50 ////////////////////////////////////////////////////////////////////////////// 51 52 AnimationEntryFixed::AnimationEntryFixed(double fDuration, double fState) 53 : mfDuration(fDuration), 54 mfState(fState) 55 { 56 } 57 58 AnimationEntryFixed::~AnimationEntryFixed() 59 { 60 } 61 62 AnimationEntry* AnimationEntryFixed::clone() const 63 { 64 return new AnimationEntryFixed(mfDuration, mfState); 65 } 66 67 bool AnimationEntryFixed::operator==(const AnimationEntry& rCandidate) const 68 { 69 const AnimationEntryFixed* pCompare = dynamic_cast< const AnimationEntryFixed* >(&rCandidate); 70 71 return (pCompare 72 && basegfx::fTools::equal(mfDuration, pCompare->mfDuration) 73 && basegfx::fTools::equal(mfState, pCompare->mfState)); 74 } 75 76 double AnimationEntryFixed::getDuration() const 77 { 78 return mfDuration; 79 } 80 81 double AnimationEntryFixed::getStateAtTime(double /*fTime*/) const 82 { 83 return mfState; 84 } 85 86 double AnimationEntryFixed::getNextEventTime(double fTime) const 87 { 88 if(basegfx::fTools::less(fTime, mfDuration)) 89 { 90 return mfDuration; 91 } 92 else 93 { 94 return 0.0; 95 } 96 } 97 98 ////////////////////////////////////////////////////////////////////////////// 99 100 AnimationEntryLinear::AnimationEntryLinear(double fDuration, double fFrequency, double fStart, double fStop) 101 : mfDuration(fDuration), 102 mfFrequency(fFrequency), 103 mfStart(fStart), 104 mfStop(fStop) 105 { 106 } 107 108 AnimationEntryLinear::~AnimationEntryLinear() 109 { 110 } 111 112 AnimationEntry* AnimationEntryLinear::clone() const 113 { 114 return new AnimationEntryLinear(mfDuration, mfFrequency, mfStart, mfStop); 115 } 116 117 bool AnimationEntryLinear::operator==(const AnimationEntry& rCandidate) const 118 { 119 const AnimationEntryLinear* pCompare = dynamic_cast< const AnimationEntryLinear* >(&rCandidate); 120 121 return (pCompare 122 && basegfx::fTools::equal(mfDuration, pCompare->mfDuration) 123 && basegfx::fTools::equal(mfStart, pCompare->mfStart) 124 && basegfx::fTools::equal(mfStop, pCompare->mfStop)); 125 } 126 127 double AnimationEntryLinear::getDuration() const 128 { 129 return mfDuration; 130 } 131 132 double AnimationEntryLinear::getStateAtTime(double fTime) const 133 { 134 if(basegfx::fTools::more(mfDuration, 0.0)) 135 { 136 const double fFactor(fTime / mfDuration); 137 138 if(fFactor > 1.0) 139 { 140 return mfStop; 141 } 142 else 143 { 144 return mfStart + ((mfStop - mfStart) * fFactor); 145 } 146 } 147 else 148 { 149 return mfStart; 150 } 151 } 152 153 double AnimationEntryLinear::getNextEventTime(double fTime) const 154 { 155 if(basegfx::fTools::less(fTime, mfDuration)) 156 { 157 // use the simple solution: just add the frequency. More correct (but also more 158 // complicated) would be to calculate the slice of time we are in and when this 159 // slice will end. For the animations, this makes no quality difference. 160 fTime += mfFrequency; 161 162 if(basegfx::fTools::more(fTime, mfDuration)) 163 { 164 fTime = mfDuration; 165 } 166 167 return fTime; 168 } 169 else 170 { 171 return 0.0; 172 } 173 } 174 175 ////////////////////////////////////////////////////////////////////////////// 176 177 sal_uInt32 AnimationEntryList::impGetIndexAtTime(double fTime, double &rfAddedTime) const 178 { 179 sal_uInt32 nIndex(0L); 180 181 while(nIndex < maEntries.size() && basegfx::fTools::lessOrEqual(rfAddedTime + maEntries[nIndex]->getDuration(), fTime)) 182 { 183 rfAddedTime += maEntries[nIndex++]->getDuration(); 184 } 185 186 return nIndex; 187 } 188 189 AnimationEntryList::AnimationEntryList() 190 : mfDuration(0.0) 191 { 192 } 193 194 AnimationEntryList::~AnimationEntryList() 195 { 196 for(sal_uInt32 a(0L); a < maEntries.size(); a++) 197 { 198 delete maEntries[a]; 199 } 200 } 201 202 AnimationEntry* AnimationEntryList::clone() const 203 { 204 AnimationEntryList* pNew = new AnimationEntryList(); 205 206 for(sal_uInt32 a(0L); a < maEntries.size(); a++) 207 { 208 pNew->append(*maEntries[a]); 209 } 210 211 return pNew; 212 } 213 214 bool AnimationEntryList::operator==(const AnimationEntry& rCandidate) const 215 { 216 const AnimationEntryList* pCompare = dynamic_cast< const AnimationEntryList* >(&rCandidate); 217 218 if(pCompare && mfDuration == pCompare->mfDuration) 219 { 220 for(sal_uInt32 a(0L); a < maEntries.size(); a++) 221 { 222 if(!(*maEntries[a] == *pCompare->maEntries[a])) 223 { 224 return false; 225 } 226 } 227 228 return true; 229 } 230 231 return false; 232 } 233 234 void AnimationEntryList::append(const AnimationEntry& rCandidate) 235 { 236 const double fDuration(rCandidate.getDuration()); 237 238 if(!basegfx::fTools::equalZero(fDuration)) 239 { 240 maEntries.push_back(rCandidate.clone()); 241 mfDuration += fDuration; 242 } 243 } 244 245 double AnimationEntryList::getDuration() const 246 { 247 return mfDuration; 248 } 249 250 double AnimationEntryList::getStateAtTime(double fTime) const 251 { 252 if(!basegfx::fTools::equalZero(mfDuration)) 253 { 254 double fAddedTime(0.0); 255 const sal_uInt32 nIndex(impGetIndexAtTime(fTime, fAddedTime)); 256 257 if(nIndex < maEntries.size()) 258 { 259 return maEntries[nIndex]->getStateAtTime(fTime - fAddedTime); 260 } 261 } 262 263 return 0.0; 264 } 265 266 double AnimationEntryList::getNextEventTime(double fTime) const 267 { 268 double fNewTime(0.0); 269 270 if(!basegfx::fTools::equalZero(mfDuration)) 271 { 272 double fAddedTime(0.0); 273 const sal_uInt32 nIndex(impGetIndexAtTime(fTime, fAddedTime)); 274 275 if(nIndex < maEntries.size()) 276 { 277 fNewTime = maEntries[nIndex]->getNextEventTime(fTime - fAddedTime) + fAddedTime; 278 } 279 } 280 281 return fNewTime; 282 } 283 284 ////////////////////////////////////////////////////////////////////////////// 285 286 AnimationEntryLoop::AnimationEntryLoop(sal_uInt32 nRepeat) 287 : AnimationEntryList(), 288 mnRepeat(nRepeat) 289 { 290 } 291 292 AnimationEntryLoop::~AnimationEntryLoop() 293 { 294 } 295 296 AnimationEntry* AnimationEntryLoop::clone() const 297 { 298 AnimationEntryLoop* pNew = new AnimationEntryLoop(mnRepeat); 299 300 for(sal_uInt32 a(0L); a < maEntries.size(); a++) 301 { 302 pNew->append(*maEntries[a]); 303 } 304 305 return pNew; 306 } 307 308 bool AnimationEntryLoop::operator==(const AnimationEntry& rCandidate) const 309 { 310 const AnimationEntryLoop* pCompare = dynamic_cast< const AnimationEntryLoop* >(&rCandidate); 311 312 return (pCompare 313 && mnRepeat == pCompare->mnRepeat 314 && AnimationEntryList::operator==(rCandidate)); 315 } 316 317 double AnimationEntryLoop::getDuration() const 318 { 319 return (mfDuration * (double)mnRepeat); 320 } 321 322 double AnimationEntryLoop::getStateAtTime(double fTime) const 323 { 324 if(mnRepeat && !basegfx::fTools::equalZero(mfDuration)) 325 { 326 const sal_uInt32 nCurrentLoop((sal_uInt32)(fTime / mfDuration)); 327 328 if(nCurrentLoop > mnRepeat) 329 { 330 return 1.0; 331 } 332 else 333 { 334 const double fTimeAtLoopStart((double)nCurrentLoop * mfDuration); 335 const double fRelativeTime(fTime - fTimeAtLoopStart); 336 return AnimationEntryList::getStateAtTime(fRelativeTime); 337 } 338 } 339 340 return 0.0; 341 } 342 343 double AnimationEntryLoop::getNextEventTime(double fTime) const 344 { 345 double fNewTime(0.0); 346 347 if(mnRepeat && !basegfx::fTools::equalZero(mfDuration)) 348 { 349 const sal_uInt32 nCurrentLoop((sal_uInt32)(fTime / mfDuration)); 350 351 if(nCurrentLoop <= mnRepeat) 352 { 353 const double fTimeAtLoopStart((double)nCurrentLoop * mfDuration); 354 const double fRelativeTime(fTime - fTimeAtLoopStart); 355 const double fNextEventAtLoop(AnimationEntryList::getNextEventTime(fRelativeTime)); 356 357 if(!basegfx::fTools::equalZero(fNextEventAtLoop)) 358 { 359 fNewTime = fNextEventAtLoop + fTimeAtLoopStart; 360 } 361 } 362 } 363 364 return fNewTime; 365 } 366 } // end of namespace animation 367 } // end of namespace drawinglayer 368 369 ////////////////////////////////////////////////////////////////////////////// 370 // eof 371