| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_drawinglayer.hxx" |
| |
| #include <drawinglayer/animation/animationtiming.hxx> |
| #include <basegfx/numeric/ftools.hxx> |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| namespace drawinglayer |
| { |
| namespace animation |
| { |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| AnimationEntry::AnimationEntry() |
| { |
| } |
| |
| AnimationEntry::~AnimationEntry() |
| { |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| AnimationEntryFixed::AnimationEntryFixed(double fDuration, double fState) |
| : mfDuration(fDuration), |
| mfState(fState) |
| { |
| } |
| |
| AnimationEntryFixed::~AnimationEntryFixed() |
| { |
| } |
| |
| AnimationEntry* AnimationEntryFixed::clone() const |
| { |
| return new AnimationEntryFixed(mfDuration, mfState); |
| } |
| |
| bool AnimationEntryFixed::operator==(const AnimationEntry& rCandidate) const |
| { |
| const AnimationEntryFixed* pCompare = dynamic_cast< const AnimationEntryFixed* >(&rCandidate); |
| |
| return (pCompare |
| && basegfx::fTools::equal(mfDuration, pCompare->mfDuration) |
| && basegfx::fTools::equal(mfState, pCompare->mfState)); |
| } |
| |
| double AnimationEntryFixed::getDuration() const |
| { |
| return mfDuration; |
| } |
| |
| double AnimationEntryFixed::getStateAtTime(double /*fTime*/) const |
| { |
| return mfState; |
| } |
| |
| double AnimationEntryFixed::getNextEventTime(double fTime) const |
| { |
| if(basegfx::fTools::less(fTime, mfDuration)) |
| { |
| return mfDuration; |
| } |
| else |
| { |
| return 0.0; |
| } |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| AnimationEntryLinear::AnimationEntryLinear(double fDuration, double fFrequency, double fStart, double fStop) |
| : mfDuration(fDuration), |
| mfFrequency(fFrequency), |
| mfStart(fStart), |
| mfStop(fStop) |
| { |
| } |
| |
| AnimationEntryLinear::~AnimationEntryLinear() |
| { |
| } |
| |
| AnimationEntry* AnimationEntryLinear::clone() const |
| { |
| return new AnimationEntryLinear(mfDuration, mfFrequency, mfStart, mfStop); |
| } |
| |
| bool AnimationEntryLinear::operator==(const AnimationEntry& rCandidate) const |
| { |
| const AnimationEntryLinear* pCompare = dynamic_cast< const AnimationEntryLinear* >(&rCandidate); |
| |
| return (pCompare |
| && basegfx::fTools::equal(mfDuration, pCompare->mfDuration) |
| && basegfx::fTools::equal(mfStart, pCompare->mfStart) |
| && basegfx::fTools::equal(mfStop, pCompare->mfStop)); |
| } |
| |
| double AnimationEntryLinear::getDuration() const |
| { |
| return mfDuration; |
| } |
| |
| double AnimationEntryLinear::getStateAtTime(double fTime) const |
| { |
| if(basegfx::fTools::more(mfDuration, 0.0)) |
| { |
| const double fFactor(fTime / mfDuration); |
| |
| if(fFactor > 1.0) |
| { |
| return mfStop; |
| } |
| else |
| { |
| return mfStart + ((mfStop - mfStart) * fFactor); |
| } |
| } |
| else |
| { |
| return mfStart; |
| } |
| } |
| |
| double AnimationEntryLinear::getNextEventTime(double fTime) const |
| { |
| if(basegfx::fTools::less(fTime, mfDuration)) |
| { |
| // use the simple solution: just add the frequency. More correct (but also more |
| // complicated) would be to calculate the slice of time we are in and when this |
| // slice will end. For the animations, this makes no quality difference. |
| fTime += mfFrequency; |
| |
| if(basegfx::fTools::more(fTime, mfDuration)) |
| { |
| fTime = mfDuration; |
| } |
| |
| return fTime; |
| } |
| else |
| { |
| return 0.0; |
| } |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| sal_uInt32 AnimationEntryList::impGetIndexAtTime(double fTime, double &rfAddedTime) const |
| { |
| sal_uInt32 nIndex(0L); |
| |
| while(nIndex < maEntries.size() && basegfx::fTools::lessOrEqual(rfAddedTime + maEntries[nIndex]->getDuration(), fTime)) |
| { |
| rfAddedTime += maEntries[nIndex++]->getDuration(); |
| } |
| |
| return nIndex; |
| } |
| |
| AnimationEntryList::AnimationEntryList() |
| : mfDuration(0.0) |
| { |
| } |
| |
| AnimationEntryList::~AnimationEntryList() |
| { |
| for(sal_uInt32 a(0L); a < maEntries.size(); a++) |
| { |
| delete maEntries[a]; |
| } |
| } |
| |
| AnimationEntry* AnimationEntryList::clone() const |
| { |
| AnimationEntryList* pNew = new AnimationEntryList(); |
| |
| for(sal_uInt32 a(0L); a < maEntries.size(); a++) |
| { |
| pNew->append(*maEntries[a]); |
| } |
| |
| return pNew; |
| } |
| |
| bool AnimationEntryList::operator==(const AnimationEntry& rCandidate) const |
| { |
| const AnimationEntryList* pCompare = dynamic_cast< const AnimationEntryList* >(&rCandidate); |
| |
| if(pCompare && mfDuration == pCompare->mfDuration) |
| { |
| for(sal_uInt32 a(0L); a < maEntries.size(); a++) |
| { |
| if(!(*maEntries[a] == *pCompare->maEntries[a])) |
| { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| return false; |
| } |
| |
| void AnimationEntryList::append(const AnimationEntry& rCandidate) |
| { |
| const double fDuration(rCandidate.getDuration()); |
| |
| if(!basegfx::fTools::equalZero(fDuration)) |
| { |
| maEntries.push_back(rCandidate.clone()); |
| mfDuration += fDuration; |
| } |
| } |
| |
| double AnimationEntryList::getDuration() const |
| { |
| return mfDuration; |
| } |
| |
| double AnimationEntryList::getStateAtTime(double fTime) const |
| { |
| if(!basegfx::fTools::equalZero(mfDuration)) |
| { |
| double fAddedTime(0.0); |
| const sal_uInt32 nIndex(impGetIndexAtTime(fTime, fAddedTime)); |
| |
| if(nIndex < maEntries.size()) |
| { |
| return maEntries[nIndex]->getStateAtTime(fTime - fAddedTime); |
| } |
| } |
| |
| return 0.0; |
| } |
| |
| double AnimationEntryList::getNextEventTime(double fTime) const |
| { |
| double fNewTime(0.0); |
| |
| if(!basegfx::fTools::equalZero(mfDuration)) |
| { |
| double fAddedTime(0.0); |
| const sal_uInt32 nIndex(impGetIndexAtTime(fTime, fAddedTime)); |
| |
| if(nIndex < maEntries.size()) |
| { |
| fNewTime = maEntries[nIndex]->getNextEventTime(fTime - fAddedTime) + fAddedTime; |
| } |
| } |
| |
| return fNewTime; |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| AnimationEntryLoop::AnimationEntryLoop(sal_uInt32 nRepeat) |
| : AnimationEntryList(), |
| mnRepeat(nRepeat) |
| { |
| } |
| |
| AnimationEntryLoop::~AnimationEntryLoop() |
| { |
| } |
| |
| AnimationEntry* AnimationEntryLoop::clone() const |
| { |
| AnimationEntryLoop* pNew = new AnimationEntryLoop(mnRepeat); |
| |
| for(sal_uInt32 a(0L); a < maEntries.size(); a++) |
| { |
| pNew->append(*maEntries[a]); |
| } |
| |
| return pNew; |
| } |
| |
| bool AnimationEntryLoop::operator==(const AnimationEntry& rCandidate) const |
| { |
| const AnimationEntryLoop* pCompare = dynamic_cast< const AnimationEntryLoop* >(&rCandidate); |
| |
| return (pCompare |
| && mnRepeat == pCompare->mnRepeat |
| && AnimationEntryList::operator==(rCandidate)); |
| } |
| |
| double AnimationEntryLoop::getDuration() const |
| { |
| return (mfDuration * (double)mnRepeat); |
| } |
| |
| double AnimationEntryLoop::getStateAtTime(double fTime) const |
| { |
| if(mnRepeat && !basegfx::fTools::equalZero(mfDuration)) |
| { |
| const sal_uInt32 nCurrentLoop((sal_uInt32)(fTime / mfDuration)); |
| |
| if(nCurrentLoop > mnRepeat) |
| { |
| return 1.0; |
| } |
| else |
| { |
| const double fTimeAtLoopStart((double)nCurrentLoop * mfDuration); |
| const double fRelativeTime(fTime - fTimeAtLoopStart); |
| return AnimationEntryList::getStateAtTime(fRelativeTime); |
| } |
| } |
| |
| return 0.0; |
| } |
| |
| double AnimationEntryLoop::getNextEventTime(double fTime) const |
| { |
| double fNewTime(0.0); |
| |
| if(mnRepeat && !basegfx::fTools::equalZero(mfDuration)) |
| { |
| const sal_uInt32 nCurrentLoop((sal_uInt32)(fTime / mfDuration)); |
| |
| if(nCurrentLoop <= mnRepeat) |
| { |
| const double fTimeAtLoopStart((double)nCurrentLoop * mfDuration); |
| const double fRelativeTime(fTime - fTimeAtLoopStart); |
| const double fNextEventAtLoop(AnimationEntryList::getNextEventTime(fRelativeTime)); |
| |
| if(!basegfx::fTools::equalZero(fNextEventAtLoop)) |
| { |
| fNewTime = fNextEventAtLoop + fTimeAtLoopStart; |
| } |
| } |
| } |
| |
| return fNewTime; |
| } |
| } // end of namespace animation |
| } // end of namespace drawinglayer |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // eof |