1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <drawinglayer/animation/animationtiming.hxx>
23 #include <basegfx/numeric/ftools.hxx>
25 namespace drawinglayer::animation
29 AnimationEntry::AnimationEntry()
33 AnimationEntry::~AnimationEntry()
38 AnimationEntryFixed::AnimationEntryFixed(double fDuration
, double fState
)
39 : mfDuration(fDuration
),
44 AnimationEntryFixed::~AnimationEntryFixed()
48 std::unique_ptr
<AnimationEntry
> AnimationEntryFixed::clone() const
50 return std::make_unique
<AnimationEntryFixed
>(mfDuration
, mfState
);
53 bool AnimationEntryFixed::operator==(const AnimationEntry
& rCandidate
) const
55 const AnimationEntryFixed
* pCompare
= dynamic_cast< const AnimationEntryFixed
* >(&rCandidate
);
58 && basegfx::fTools::equal(mfDuration
, pCompare
->mfDuration
)
59 && basegfx::fTools::equal(mfState
, pCompare
->mfState
));
62 double AnimationEntryFixed::getDuration() const
67 double AnimationEntryFixed::getStateAtTime(double /*fTime*/) const
72 double AnimationEntryFixed::getNextEventTime(double fTime
) const
74 if(basegfx::fTools::less(fTime
, mfDuration
))
85 AnimationEntryLinear::AnimationEntryLinear(double fDuration
, double fFrequency
, double fStart
, double fStop
)
86 : mfDuration(fDuration
),
87 mfFrequency(fFrequency
),
93 AnimationEntryLinear::~AnimationEntryLinear()
97 std::unique_ptr
<AnimationEntry
> AnimationEntryLinear::clone() const
99 return std::make_unique
<AnimationEntryLinear
>(mfDuration
, mfFrequency
, mfStart
, mfStop
);
102 bool AnimationEntryLinear::operator==(const AnimationEntry
& rCandidate
) const
104 const AnimationEntryLinear
* pCompare
= dynamic_cast< const AnimationEntryLinear
* >(&rCandidate
);
107 && basegfx::fTools::equal(mfDuration
, pCompare
->mfDuration
)
108 && basegfx::fTools::equal(mfStart
, pCompare
->mfStart
)
109 && basegfx::fTools::equal(mfStop
, pCompare
->mfStop
));
112 double AnimationEntryLinear::getDuration() const
117 double AnimationEntryLinear::getStateAtTime(double fTime
) const
119 if(basegfx::fTools::more(mfDuration
, 0.0))
121 const double fFactor(fTime
/ mfDuration
);
129 return mfStart
+ ((mfStop
- mfStart
) * fFactor
);
138 double AnimationEntryLinear::getNextEventTime(double fTime
) const
140 if(basegfx::fTools::less(fTime
, mfDuration
))
142 // use the simple solution: just add the frequency. More correct (but also more
143 // complicated) would be to calculate the slice of time we are in and when this
144 // slice will end. For the animations, this makes no quality difference.
145 fTime
+= mfFrequency
;
147 if(basegfx::fTools::more(fTime
, mfDuration
))
161 AnimationEntryList::Entries::size_type
AnimationEntryList::impGetIndexAtTime(double fTime
, double &rfAddedTime
) const
163 Entries::size_type
nIndex(0);
165 while(nIndex
< maEntries
.size() && basegfx::fTools::lessOrEqual(rfAddedTime
+ maEntries
[nIndex
]->getDuration(), fTime
))
167 rfAddedTime
+= maEntries
[nIndex
++]->getDuration();
173 AnimationEntryList::AnimationEntryList()
178 AnimationEntryList::~AnimationEntryList()
182 std::unique_ptr
<AnimationEntry
> AnimationEntryList::clone() const
184 std::unique_ptr
<AnimationEntryList
> pNew(std::make_unique
<AnimationEntryList
>());
186 for(const auto &i
: maEntries
)
194 bool AnimationEntryList::operator==(const AnimationEntry
& rCandidate
) const
196 const AnimationEntryList
* pCompare
= dynamic_cast< const AnimationEntryList
* >(&rCandidate
);
198 if(pCompare
&& mfDuration
== pCompare
->mfDuration
)
200 for(size_t a(0); a
< maEntries
.size(); a
++)
202 if(!(*maEntries
[a
] == *pCompare
->maEntries
[a
]))
214 void AnimationEntryList::append(const AnimationEntry
& rCandidate
)
216 const double fDuration(rCandidate
.getDuration());
218 if(!basegfx::fTools::equalZero(fDuration
))
220 maEntries
.push_back(rCandidate
.clone());
221 mfDuration
+= fDuration
;
225 double AnimationEntryList::getDuration() const
230 double AnimationEntryList::getStateAtTime(double fTime
) const
232 if(!basegfx::fTools::equalZero(mfDuration
))
234 double fAddedTime(0.0);
235 const auto nIndex(impGetIndexAtTime(fTime
, fAddedTime
));
237 if(nIndex
< maEntries
.size())
239 return maEntries
[nIndex
]->getStateAtTime(fTime
- fAddedTime
);
246 double AnimationEntryList::getNextEventTime(double fTime
) const
248 double fNewTime(0.0);
250 if(!basegfx::fTools::equalZero(mfDuration
))
252 double fAddedTime(0.0);
253 const auto nIndex(impGetIndexAtTime(fTime
, fAddedTime
));
255 if(nIndex
< maEntries
.size())
257 fNewTime
= maEntries
[nIndex
]->getNextEventTime(fTime
- fAddedTime
) + fAddedTime
;
265 AnimationEntryLoop::AnimationEntryLoop(sal_uInt32 nRepeat
)
270 AnimationEntryLoop::~AnimationEntryLoop()
274 std::unique_ptr
<AnimationEntry
> AnimationEntryLoop::clone() const
276 std::unique_ptr
<AnimationEntryLoop
> pNew(std::make_unique
<AnimationEntryLoop
>(mnRepeat
));
278 for(const auto &i
: maEntries
)
286 bool AnimationEntryLoop::operator==(const AnimationEntry
& rCandidate
) const
288 const AnimationEntryLoop
* pCompare
= dynamic_cast< const AnimationEntryLoop
* >(&rCandidate
);
291 && mnRepeat
== pCompare
->mnRepeat
292 && AnimationEntryList::operator==(rCandidate
));
295 double AnimationEntryLoop::getDuration() const
297 return (mfDuration
* static_cast<double>(mnRepeat
));
300 double AnimationEntryLoop::getStateAtTime(double fTime
) const
302 if(mnRepeat
&& !basegfx::fTools::equalZero(mfDuration
))
304 const sal_uInt32
nCurrentLoop(static_cast<sal_uInt32
>(fTime
/ mfDuration
));
306 if(nCurrentLoop
> mnRepeat
)
312 const double fTimeAtLoopStart(static_cast<double>(nCurrentLoop
) * mfDuration
);
313 const double fRelativeTime(fTime
- fTimeAtLoopStart
);
314 return AnimationEntryList::getStateAtTime(fRelativeTime
);
321 double AnimationEntryLoop::getNextEventTime(double fTime
) const
323 double fNewTime(0.0);
325 if(mnRepeat
&& !basegfx::fTools::equalZero(mfDuration
))
327 const sal_uInt32
nCurrentLoop(static_cast<sal_uInt32
>(fTime
/ mfDuration
));
329 if(nCurrentLoop
<= mnRepeat
)
331 const double fTimeAtLoopStart(static_cast<double>(nCurrentLoop
) * mfDuration
);
332 const double fRelativeTime(fTime
- fTimeAtLoopStart
);
333 const double fNextEventAtLoop(AnimationEntryList::getNextEventTime(fRelativeTime
));
335 if(!basegfx::fTools::equalZero(fNextEventAtLoop
))
337 fNewTime
= fNextEventAtLoop
+ fTimeAtLoopStart
;
344 } // end of namespace
346 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */