xref: /trunk/main/drawinglayer/source/animation/animationtiming.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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