xref: /AOO41X/main/drawinglayer/source/animation/animationtiming.cxx (revision 464702f4578bd67db020a330afd07883930c5e07)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_drawinglayer.hxx"
26 
27 #include <drawinglayer/animation/animationtiming.hxx>
28 #include <basegfx/numeric/ftools.hxx>
29 
30 //////////////////////////////////////////////////////////////////////////////
31 
32 namespace drawinglayer
33 {
34     namespace animation
35     {
36         //////////////////////////////////////////////////////////////////////////////
37 
AnimationEntry()38         AnimationEntry::AnimationEntry()
39         {
40         }
41 
~AnimationEntry()42         AnimationEntry::~AnimationEntry()
43         {
44         }
45 
46         //////////////////////////////////////////////////////////////////////////////
47 
AnimationEntryFixed(double fDuration,double fState)48         AnimationEntryFixed::AnimationEntryFixed(double fDuration, double fState)
49         :   mfDuration(fDuration),
50             mfState(fState)
51         {
52         }
53 
~AnimationEntryFixed()54         AnimationEntryFixed::~AnimationEntryFixed()
55         {
56         }
57 
clone() const58         AnimationEntry* AnimationEntryFixed::clone() const
59         {
60             return new AnimationEntryFixed(mfDuration, mfState);
61         }
62 
operator ==(const AnimationEntry & rCandidate) const63         bool AnimationEntryFixed::operator==(const AnimationEntry& rCandidate) const
64         {
65             const AnimationEntryFixed* pCompare = dynamic_cast< const AnimationEntryFixed* >(&rCandidate);
66 
67             return (pCompare
68                 && basegfx::fTools::equal(mfDuration, pCompare->mfDuration)
69                 && basegfx::fTools::equal(mfState, pCompare->mfState));
70         }
71 
getDuration() const72         double AnimationEntryFixed::getDuration() const
73         {
74             return mfDuration;
75         }
76 
getStateAtTime(double) const77         double AnimationEntryFixed::getStateAtTime(double /*fTime*/) const
78         {
79             return mfState;
80         }
81 
getNextEventTime(double fTime) const82         double AnimationEntryFixed::getNextEventTime(double fTime) const
83         {
84             if(basegfx::fTools::less(fTime, mfDuration))
85             {
86                 return mfDuration;
87             }
88             else
89             {
90                 return 0.0;
91             }
92         }
93 
94         //////////////////////////////////////////////////////////////////////////////
95 
AnimationEntryLinear(double fDuration,double fFrequency,double fStart,double fStop)96         AnimationEntryLinear::AnimationEntryLinear(double fDuration, double fFrequency, double fStart, double fStop)
97         :   mfDuration(fDuration),
98             mfFrequency(fFrequency),
99             mfStart(fStart),
100             mfStop(fStop)
101         {
102         }
103 
~AnimationEntryLinear()104         AnimationEntryLinear::~AnimationEntryLinear()
105         {
106         }
107 
clone() const108         AnimationEntry* AnimationEntryLinear::clone() const
109         {
110             return new AnimationEntryLinear(mfDuration, mfFrequency, mfStart, mfStop);
111         }
112 
operator ==(const AnimationEntry & rCandidate) const113         bool AnimationEntryLinear::operator==(const AnimationEntry& rCandidate) const
114         {
115             const AnimationEntryLinear* pCompare = dynamic_cast< const AnimationEntryLinear* >(&rCandidate);
116 
117             return (pCompare
118                 && basegfx::fTools::equal(mfDuration, pCompare->mfDuration)
119                 && basegfx::fTools::equal(mfStart, pCompare->mfStart)
120                 && basegfx::fTools::equal(mfStop, pCompare->mfStop));
121         }
122 
getDuration() const123         double AnimationEntryLinear::getDuration() const
124         {
125             return mfDuration;
126         }
127 
getStateAtTime(double fTime) const128         double AnimationEntryLinear::getStateAtTime(double fTime) const
129         {
130             if(basegfx::fTools::more(mfDuration, 0.0))
131             {
132                 const double fFactor(fTime / mfDuration);
133 
134                 if(fFactor > 1.0)
135                 {
136                     return mfStop;
137                 }
138                 else
139                 {
140                     return mfStart + ((mfStop - mfStart) * fFactor);
141                 }
142             }
143             else
144             {
145                 return mfStart;
146             }
147         }
148 
getNextEventTime(double fTime) const149         double AnimationEntryLinear::getNextEventTime(double fTime) const
150         {
151             if(basegfx::fTools::less(fTime, mfDuration))
152             {
153                 // use the simple solution: just add the frequency. More correct (but also more
154                 // complicated) would be to calculate the slice of time we are in and when this
155                 // slice will end. For the animations, this makes no quality difference.
156                 fTime += mfFrequency;
157 
158                 if(basegfx::fTools::more(fTime, mfDuration))
159                 {
160                     fTime = mfDuration;
161                 }
162 
163                 return fTime;
164             }
165             else
166             {
167                 return 0.0;
168             }
169         }
170 
171         //////////////////////////////////////////////////////////////////////////////
172 
impGetIndexAtTime(double fTime,double & rfAddedTime) const173         sal_uInt32 AnimationEntryList::impGetIndexAtTime(double fTime, double &rfAddedTime) const
174         {
175             sal_uInt32 nIndex(0L);
176 
177             while(nIndex < maEntries.size() && basegfx::fTools::lessOrEqual(rfAddedTime + maEntries[nIndex]->getDuration(), fTime))
178             {
179                 rfAddedTime += maEntries[nIndex++]->getDuration();
180             }
181 
182             return nIndex;
183         }
184 
AnimationEntryList()185         AnimationEntryList::AnimationEntryList()
186         :   mfDuration(0.0)
187         {
188         }
189 
~AnimationEntryList()190         AnimationEntryList::~AnimationEntryList()
191         {
192             for(sal_uInt32 a(0L); a < maEntries.size(); a++)
193             {
194                 delete maEntries[a];
195             }
196         }
197 
clone() const198         AnimationEntry* AnimationEntryList::clone() const
199         {
200             AnimationEntryList* pNew = new AnimationEntryList();
201 
202             for(sal_uInt32 a(0L); a < maEntries.size(); a++)
203             {
204                 pNew->append(*maEntries[a]);
205             }
206 
207             return pNew;
208         }
209 
operator ==(const AnimationEntry & rCandidate) const210         bool AnimationEntryList::operator==(const AnimationEntry& rCandidate) const
211         {
212             const AnimationEntryList* pCompare = dynamic_cast< const AnimationEntryList* >(&rCandidate);
213 
214             if(pCompare && mfDuration == pCompare->mfDuration)
215             {
216                 for(sal_uInt32 a(0L); a < maEntries.size(); a++)
217                 {
218                     if(!(*maEntries[a] == *pCompare->maEntries[a]))
219                     {
220                         return false;
221                     }
222                 }
223 
224                 return true;
225             }
226 
227             return false;
228         }
229 
append(const AnimationEntry & rCandidate)230         void AnimationEntryList::append(const AnimationEntry& rCandidate)
231         {
232             const double fDuration(rCandidate.getDuration());
233 
234             if(!basegfx::fTools::equalZero(fDuration))
235             {
236                 maEntries.push_back(rCandidate.clone());
237                 mfDuration += fDuration;
238             }
239         }
240 
getDuration() const241         double AnimationEntryList::getDuration() const
242         {
243             return mfDuration;
244         }
245 
getStateAtTime(double fTime) const246         double AnimationEntryList::getStateAtTime(double fTime) const
247         {
248             if(!basegfx::fTools::equalZero(mfDuration))
249             {
250                 double fAddedTime(0.0);
251                 const sal_uInt32 nIndex(impGetIndexAtTime(fTime, fAddedTime));
252 
253                 if(nIndex < maEntries.size())
254                 {
255                     return maEntries[nIndex]->getStateAtTime(fTime - fAddedTime);
256                 }
257             }
258 
259             return 0.0;
260         }
261 
getNextEventTime(double fTime) const262         double AnimationEntryList::getNextEventTime(double fTime) const
263         {
264             double fNewTime(0.0);
265 
266             if(!basegfx::fTools::equalZero(mfDuration))
267             {
268                 double fAddedTime(0.0);
269                 const sal_uInt32 nIndex(impGetIndexAtTime(fTime, fAddedTime));
270 
271                 if(nIndex < maEntries.size())
272                 {
273                     fNewTime = maEntries[nIndex]->getNextEventTime(fTime - fAddedTime) + fAddedTime;
274                 }
275             }
276 
277             return fNewTime;
278         }
279 
280         //////////////////////////////////////////////////////////////////////////////
281 
AnimationEntryLoop(sal_uInt32 nRepeat)282         AnimationEntryLoop::AnimationEntryLoop(sal_uInt32 nRepeat)
283         :   AnimationEntryList(),
284             mnRepeat(nRepeat)
285         {
286         }
287 
~AnimationEntryLoop()288         AnimationEntryLoop::~AnimationEntryLoop()
289         {
290         }
291 
clone() const292         AnimationEntry* AnimationEntryLoop::clone() const
293         {
294             AnimationEntryLoop* pNew = new AnimationEntryLoop(mnRepeat);
295 
296             for(sal_uInt32 a(0L); a < maEntries.size(); a++)
297             {
298                 pNew->append(*maEntries[a]);
299             }
300 
301             return pNew;
302         }
303 
operator ==(const AnimationEntry & rCandidate) const304         bool AnimationEntryLoop::operator==(const AnimationEntry& rCandidate) const
305         {
306             const AnimationEntryLoop* pCompare = dynamic_cast< const AnimationEntryLoop* >(&rCandidate);
307 
308             return (pCompare
309                 && mnRepeat == pCompare->mnRepeat
310                 && AnimationEntryList::operator==(rCandidate));
311         }
312 
getDuration() const313         double AnimationEntryLoop::getDuration() const
314         {
315             return (mfDuration * (double)mnRepeat);
316         }
317 
getStateAtTime(double fTime) const318         double AnimationEntryLoop::getStateAtTime(double fTime) const
319         {
320             if(mnRepeat && !basegfx::fTools::equalZero(mfDuration))
321             {
322                 const sal_uInt32 nCurrentLoop((sal_uInt32)(fTime / mfDuration));
323 
324                 if(nCurrentLoop > mnRepeat)
325                 {
326                     return 1.0;
327                 }
328                 else
329                 {
330                     const double fTimeAtLoopStart((double)nCurrentLoop * mfDuration);
331                     const double fRelativeTime(fTime - fTimeAtLoopStart);
332                     return AnimationEntryList::getStateAtTime(fRelativeTime);
333                 }
334             }
335 
336             return 0.0;
337         }
338 
getNextEventTime(double fTime) const339         double AnimationEntryLoop::getNextEventTime(double fTime) const
340         {
341             double fNewTime(0.0);
342 
343             if(mnRepeat && !basegfx::fTools::equalZero(mfDuration))
344             {
345                 const sal_uInt32 nCurrentLoop((sal_uInt32)(fTime / mfDuration));
346 
347                 if(nCurrentLoop <= mnRepeat)
348                 {
349                     const double fTimeAtLoopStart((double)nCurrentLoop * mfDuration);
350                     const double fRelativeTime(fTime - fTimeAtLoopStart);
351                     const double fNextEventAtLoop(AnimationEntryList::getNextEventTime(fRelativeTime));
352 
353                     if(!basegfx::fTools::equalZero(fNextEventAtLoop))
354                     {
355                         fNewTime = fNextEventAtLoop + fTimeAtLoopStart;
356                     }
357                 }
358             }
359 
360             return fNewTime;
361         }
362     } // end of namespace animation
363 } // end of namespace drawinglayer
364 
365 //////////////////////////////////////////////////////////////////////////////
366 // eof
367