1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <drawinglayer/animation/animationtiming.hxx>
32*cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
33*cdf0e10cSrcweir 
34*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
35*cdf0e10cSrcweir 
36*cdf0e10cSrcweir namespace drawinglayer
37*cdf0e10cSrcweir {
38*cdf0e10cSrcweir 	namespace animation
39*cdf0e10cSrcweir 	{
40*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////
41*cdf0e10cSrcweir 
42*cdf0e10cSrcweir 		AnimationEntry::AnimationEntry()
43*cdf0e10cSrcweir 		{
44*cdf0e10cSrcweir 		}
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir 		AnimationEntry::~AnimationEntry()
47*cdf0e10cSrcweir 		{
48*cdf0e10cSrcweir 		}
49*cdf0e10cSrcweir 
50*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////
51*cdf0e10cSrcweir 
52*cdf0e10cSrcweir 		AnimationEntryFixed::AnimationEntryFixed(double fDuration, double fState)
53*cdf0e10cSrcweir 		:	mfDuration(fDuration),
54*cdf0e10cSrcweir 			mfState(fState)
55*cdf0e10cSrcweir 		{
56*cdf0e10cSrcweir 		}
57*cdf0e10cSrcweir 
58*cdf0e10cSrcweir 		AnimationEntryFixed::~AnimationEntryFixed()
59*cdf0e10cSrcweir 		{
60*cdf0e10cSrcweir 		}
61*cdf0e10cSrcweir 
62*cdf0e10cSrcweir 		AnimationEntry* AnimationEntryFixed::clone() const
63*cdf0e10cSrcweir 		{
64*cdf0e10cSrcweir 			return new AnimationEntryFixed(mfDuration, mfState);
65*cdf0e10cSrcweir 		}
66*cdf0e10cSrcweir 
67*cdf0e10cSrcweir 		bool AnimationEntryFixed::operator==(const AnimationEntry& rCandidate) const
68*cdf0e10cSrcweir 		{
69*cdf0e10cSrcweir 			const AnimationEntryFixed* pCompare = dynamic_cast< const AnimationEntryFixed* >(&rCandidate);
70*cdf0e10cSrcweir 
71*cdf0e10cSrcweir 			return (pCompare
72*cdf0e10cSrcweir 				&& basegfx::fTools::equal(mfDuration, pCompare->mfDuration)
73*cdf0e10cSrcweir 				&& basegfx::fTools::equal(mfState, pCompare->mfState));
74*cdf0e10cSrcweir 		}
75*cdf0e10cSrcweir 
76*cdf0e10cSrcweir 		double AnimationEntryFixed::getDuration() const
77*cdf0e10cSrcweir 		{
78*cdf0e10cSrcweir 			return mfDuration;
79*cdf0e10cSrcweir 		}
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir 		double AnimationEntryFixed::getStateAtTime(double /*fTime*/) const
82*cdf0e10cSrcweir 		{
83*cdf0e10cSrcweir 			return mfState;
84*cdf0e10cSrcweir 		}
85*cdf0e10cSrcweir 
86*cdf0e10cSrcweir 		double AnimationEntryFixed::getNextEventTime(double fTime) const
87*cdf0e10cSrcweir 		{
88*cdf0e10cSrcweir 			if(basegfx::fTools::less(fTime, mfDuration))
89*cdf0e10cSrcweir 			{
90*cdf0e10cSrcweir 				return mfDuration;
91*cdf0e10cSrcweir 			}
92*cdf0e10cSrcweir 			else
93*cdf0e10cSrcweir 			{
94*cdf0e10cSrcweir 				return 0.0;
95*cdf0e10cSrcweir 			}
96*cdf0e10cSrcweir 		}
97*cdf0e10cSrcweir 
98*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////
99*cdf0e10cSrcweir 
100*cdf0e10cSrcweir 		AnimationEntryLinear::AnimationEntryLinear(double fDuration, double fFrequency, double fStart, double fStop)
101*cdf0e10cSrcweir 		:	mfDuration(fDuration),
102*cdf0e10cSrcweir 			mfFrequency(fFrequency),
103*cdf0e10cSrcweir 			mfStart(fStart),
104*cdf0e10cSrcweir 			mfStop(fStop)
105*cdf0e10cSrcweir 		{
106*cdf0e10cSrcweir 		}
107*cdf0e10cSrcweir 
108*cdf0e10cSrcweir 		AnimationEntryLinear::~AnimationEntryLinear()
109*cdf0e10cSrcweir 		{
110*cdf0e10cSrcweir 		}
111*cdf0e10cSrcweir 
112*cdf0e10cSrcweir 		AnimationEntry* AnimationEntryLinear::clone() const
113*cdf0e10cSrcweir 		{
114*cdf0e10cSrcweir 			return new AnimationEntryLinear(mfDuration, mfFrequency, mfStart, mfStop);
115*cdf0e10cSrcweir 		}
116*cdf0e10cSrcweir 
117*cdf0e10cSrcweir 		bool AnimationEntryLinear::operator==(const AnimationEntry& rCandidate) const
118*cdf0e10cSrcweir 		{
119*cdf0e10cSrcweir 			const AnimationEntryLinear* pCompare = dynamic_cast< const AnimationEntryLinear* >(&rCandidate);
120*cdf0e10cSrcweir 
121*cdf0e10cSrcweir 			return (pCompare
122*cdf0e10cSrcweir 				&& basegfx::fTools::equal(mfDuration, pCompare->mfDuration)
123*cdf0e10cSrcweir 				&& basegfx::fTools::equal(mfStart, pCompare->mfStart)
124*cdf0e10cSrcweir 				&& basegfx::fTools::equal(mfStop, pCompare->mfStop));
125*cdf0e10cSrcweir 		}
126*cdf0e10cSrcweir 
127*cdf0e10cSrcweir 		double AnimationEntryLinear::getDuration() const
128*cdf0e10cSrcweir 		{
129*cdf0e10cSrcweir 			return mfDuration;
130*cdf0e10cSrcweir 		}
131*cdf0e10cSrcweir 
132*cdf0e10cSrcweir 		double AnimationEntryLinear::getStateAtTime(double fTime) const
133*cdf0e10cSrcweir 		{
134*cdf0e10cSrcweir 			if(basegfx::fTools::more(mfDuration, 0.0))
135*cdf0e10cSrcweir 			{
136*cdf0e10cSrcweir 				const double fFactor(fTime / mfDuration);
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir 				if(fFactor > 1.0)
139*cdf0e10cSrcweir 				{
140*cdf0e10cSrcweir 					return mfStop;
141*cdf0e10cSrcweir 				}
142*cdf0e10cSrcweir 				else
143*cdf0e10cSrcweir 				{
144*cdf0e10cSrcweir 					return mfStart + ((mfStop - mfStart) * fFactor);
145*cdf0e10cSrcweir 				}
146*cdf0e10cSrcweir 			}
147*cdf0e10cSrcweir 			else
148*cdf0e10cSrcweir 			{
149*cdf0e10cSrcweir 				return mfStart;
150*cdf0e10cSrcweir 			}
151*cdf0e10cSrcweir 		}
152*cdf0e10cSrcweir 
153*cdf0e10cSrcweir 		double AnimationEntryLinear::getNextEventTime(double fTime) const
154*cdf0e10cSrcweir 		{
155*cdf0e10cSrcweir 			if(basegfx::fTools::less(fTime, mfDuration))
156*cdf0e10cSrcweir 			{
157*cdf0e10cSrcweir 				// use the simple solution: just add the frequency. More correct (but also more
158*cdf0e10cSrcweir 				// complicated) would be to calculate the slice of time we are in and when this
159*cdf0e10cSrcweir 				// slice will end. For the animations, this makes no quality difference.
160*cdf0e10cSrcweir 				fTime += mfFrequency;
161*cdf0e10cSrcweir 
162*cdf0e10cSrcweir 				if(basegfx::fTools::more(fTime, mfDuration))
163*cdf0e10cSrcweir 				{
164*cdf0e10cSrcweir 					fTime = mfDuration;
165*cdf0e10cSrcweir 				}
166*cdf0e10cSrcweir 
167*cdf0e10cSrcweir 				return fTime;
168*cdf0e10cSrcweir 			}
169*cdf0e10cSrcweir 			else
170*cdf0e10cSrcweir 			{
171*cdf0e10cSrcweir 				return 0.0;
172*cdf0e10cSrcweir 			}
173*cdf0e10cSrcweir 		}
174*cdf0e10cSrcweir 
175*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////
176*cdf0e10cSrcweir 
177*cdf0e10cSrcweir 		sal_uInt32 AnimationEntryList::impGetIndexAtTime(double fTime, double &rfAddedTime) const
178*cdf0e10cSrcweir 		{
179*cdf0e10cSrcweir 			sal_uInt32 nIndex(0L);
180*cdf0e10cSrcweir 
181*cdf0e10cSrcweir 			while(nIndex < maEntries.size() && basegfx::fTools::lessOrEqual(rfAddedTime + maEntries[nIndex]->getDuration(), fTime))
182*cdf0e10cSrcweir 			{
183*cdf0e10cSrcweir 				rfAddedTime += maEntries[nIndex++]->getDuration();
184*cdf0e10cSrcweir 			}
185*cdf0e10cSrcweir 
186*cdf0e10cSrcweir 			return nIndex;
187*cdf0e10cSrcweir 		}
188*cdf0e10cSrcweir 
189*cdf0e10cSrcweir 		AnimationEntryList::AnimationEntryList()
190*cdf0e10cSrcweir 		:	mfDuration(0.0)
191*cdf0e10cSrcweir 		{
192*cdf0e10cSrcweir 		}
193*cdf0e10cSrcweir 
194*cdf0e10cSrcweir 		AnimationEntryList::~AnimationEntryList()
195*cdf0e10cSrcweir 		{
196*cdf0e10cSrcweir 			for(sal_uInt32 a(0L); a < maEntries.size(); a++)
197*cdf0e10cSrcweir 			{
198*cdf0e10cSrcweir 				delete maEntries[a];
199*cdf0e10cSrcweir 			}
200*cdf0e10cSrcweir 		}
201*cdf0e10cSrcweir 
202*cdf0e10cSrcweir 		AnimationEntry* AnimationEntryList::clone() const
203*cdf0e10cSrcweir 		{
204*cdf0e10cSrcweir 			AnimationEntryList* pNew = new AnimationEntryList();
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir 			for(sal_uInt32 a(0L); a < maEntries.size(); a++)
207*cdf0e10cSrcweir 			{
208*cdf0e10cSrcweir 				pNew->append(*maEntries[a]);
209*cdf0e10cSrcweir 			}
210*cdf0e10cSrcweir 
211*cdf0e10cSrcweir 			return pNew;
212*cdf0e10cSrcweir 		}
213*cdf0e10cSrcweir 
214*cdf0e10cSrcweir 		bool AnimationEntryList::operator==(const AnimationEntry& rCandidate) const
215*cdf0e10cSrcweir 		{
216*cdf0e10cSrcweir 			const AnimationEntryList* pCompare = dynamic_cast< const AnimationEntryList* >(&rCandidate);
217*cdf0e10cSrcweir 
218*cdf0e10cSrcweir 			if(pCompare && mfDuration == pCompare->mfDuration)
219*cdf0e10cSrcweir 			{
220*cdf0e10cSrcweir 				for(sal_uInt32 a(0L); a < maEntries.size(); a++)
221*cdf0e10cSrcweir 				{
222*cdf0e10cSrcweir 					if(!(*maEntries[a] == *pCompare->maEntries[a]))
223*cdf0e10cSrcweir 					{
224*cdf0e10cSrcweir 						return false;
225*cdf0e10cSrcweir 					}
226*cdf0e10cSrcweir 				}
227*cdf0e10cSrcweir 
228*cdf0e10cSrcweir 				return true;
229*cdf0e10cSrcweir 			}
230*cdf0e10cSrcweir 
231*cdf0e10cSrcweir 			return false;
232*cdf0e10cSrcweir 		}
233*cdf0e10cSrcweir 
234*cdf0e10cSrcweir 		void AnimationEntryList::append(const AnimationEntry& rCandidate)
235*cdf0e10cSrcweir 		{
236*cdf0e10cSrcweir 			const double fDuration(rCandidate.getDuration());
237*cdf0e10cSrcweir 
238*cdf0e10cSrcweir 			if(!basegfx::fTools::equalZero(fDuration))
239*cdf0e10cSrcweir 			{
240*cdf0e10cSrcweir 				maEntries.push_back(rCandidate.clone());
241*cdf0e10cSrcweir 				mfDuration += fDuration;
242*cdf0e10cSrcweir 			}
243*cdf0e10cSrcweir 		}
244*cdf0e10cSrcweir 
245*cdf0e10cSrcweir 		double AnimationEntryList::getDuration() const
246*cdf0e10cSrcweir 		{
247*cdf0e10cSrcweir 			return mfDuration;
248*cdf0e10cSrcweir 		}
249*cdf0e10cSrcweir 
250*cdf0e10cSrcweir 		double AnimationEntryList::getStateAtTime(double fTime) const
251*cdf0e10cSrcweir 		{
252*cdf0e10cSrcweir 			if(!basegfx::fTools::equalZero(mfDuration))
253*cdf0e10cSrcweir 			{
254*cdf0e10cSrcweir 				double fAddedTime(0.0);
255*cdf0e10cSrcweir 				const sal_uInt32 nIndex(impGetIndexAtTime(fTime, fAddedTime));
256*cdf0e10cSrcweir 
257*cdf0e10cSrcweir 				if(nIndex < maEntries.size())
258*cdf0e10cSrcweir 				{
259*cdf0e10cSrcweir 					return maEntries[nIndex]->getStateAtTime(fTime - fAddedTime);
260*cdf0e10cSrcweir 				}
261*cdf0e10cSrcweir 			}
262*cdf0e10cSrcweir 
263*cdf0e10cSrcweir 			return 0.0;
264*cdf0e10cSrcweir 		}
265*cdf0e10cSrcweir 
266*cdf0e10cSrcweir 		double AnimationEntryList::getNextEventTime(double fTime) const
267*cdf0e10cSrcweir 		{
268*cdf0e10cSrcweir 			double fNewTime(0.0);
269*cdf0e10cSrcweir 
270*cdf0e10cSrcweir 			if(!basegfx::fTools::equalZero(mfDuration))
271*cdf0e10cSrcweir 			{
272*cdf0e10cSrcweir 				double fAddedTime(0.0);
273*cdf0e10cSrcweir 				const sal_uInt32 nIndex(impGetIndexAtTime(fTime, fAddedTime));
274*cdf0e10cSrcweir 
275*cdf0e10cSrcweir 				if(nIndex < maEntries.size())
276*cdf0e10cSrcweir 				{
277*cdf0e10cSrcweir 					fNewTime = maEntries[nIndex]->getNextEventTime(fTime - fAddedTime) + fAddedTime;
278*cdf0e10cSrcweir 				}
279*cdf0e10cSrcweir 			}
280*cdf0e10cSrcweir 
281*cdf0e10cSrcweir 			return fNewTime;
282*cdf0e10cSrcweir 		}
283*cdf0e10cSrcweir 
284*cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////////////
285*cdf0e10cSrcweir 
286*cdf0e10cSrcweir 		AnimationEntryLoop::AnimationEntryLoop(sal_uInt32 nRepeat)
287*cdf0e10cSrcweir 		:	AnimationEntryList(),
288*cdf0e10cSrcweir 			mnRepeat(nRepeat)
289*cdf0e10cSrcweir 		{
290*cdf0e10cSrcweir 		}
291*cdf0e10cSrcweir 
292*cdf0e10cSrcweir 		AnimationEntryLoop::~AnimationEntryLoop()
293*cdf0e10cSrcweir 		{
294*cdf0e10cSrcweir 		}
295*cdf0e10cSrcweir 
296*cdf0e10cSrcweir 		AnimationEntry* AnimationEntryLoop::clone() const
297*cdf0e10cSrcweir 		{
298*cdf0e10cSrcweir 			AnimationEntryLoop* pNew = new AnimationEntryLoop(mnRepeat);
299*cdf0e10cSrcweir 
300*cdf0e10cSrcweir 			for(sal_uInt32 a(0L); a < maEntries.size(); a++)
301*cdf0e10cSrcweir 			{
302*cdf0e10cSrcweir 				pNew->append(*maEntries[a]);
303*cdf0e10cSrcweir 			}
304*cdf0e10cSrcweir 
305*cdf0e10cSrcweir 			return pNew;
306*cdf0e10cSrcweir 		}
307*cdf0e10cSrcweir 
308*cdf0e10cSrcweir 		bool AnimationEntryLoop::operator==(const AnimationEntry& rCandidate) const
309*cdf0e10cSrcweir 		{
310*cdf0e10cSrcweir 			const AnimationEntryLoop* pCompare = dynamic_cast< const AnimationEntryLoop* >(&rCandidate);
311*cdf0e10cSrcweir 
312*cdf0e10cSrcweir 			return (pCompare
313*cdf0e10cSrcweir 				&& mnRepeat == pCompare->mnRepeat
314*cdf0e10cSrcweir 				&& AnimationEntryList::operator==(rCandidate));
315*cdf0e10cSrcweir 		}
316*cdf0e10cSrcweir 
317*cdf0e10cSrcweir 		double AnimationEntryLoop::getDuration() const
318*cdf0e10cSrcweir 		{
319*cdf0e10cSrcweir 			return (mfDuration * (double)mnRepeat);
320*cdf0e10cSrcweir 		}
321*cdf0e10cSrcweir 
322*cdf0e10cSrcweir 		double AnimationEntryLoop::getStateAtTime(double fTime) const
323*cdf0e10cSrcweir 		{
324*cdf0e10cSrcweir 			if(mnRepeat && !basegfx::fTools::equalZero(mfDuration))
325*cdf0e10cSrcweir 			{
326*cdf0e10cSrcweir 				const sal_uInt32 nCurrentLoop((sal_uInt32)(fTime / mfDuration));
327*cdf0e10cSrcweir 
328*cdf0e10cSrcweir 				if(nCurrentLoop > mnRepeat)
329*cdf0e10cSrcweir 				{
330*cdf0e10cSrcweir 					return 1.0;
331*cdf0e10cSrcweir 				}
332*cdf0e10cSrcweir 				else
333*cdf0e10cSrcweir 				{
334*cdf0e10cSrcweir 					const double fTimeAtLoopStart((double)nCurrentLoop * mfDuration);
335*cdf0e10cSrcweir 					const double fRelativeTime(fTime - fTimeAtLoopStart);
336*cdf0e10cSrcweir 					return AnimationEntryList::getStateAtTime(fRelativeTime);
337*cdf0e10cSrcweir 				}
338*cdf0e10cSrcweir 			}
339*cdf0e10cSrcweir 
340*cdf0e10cSrcweir 			return 0.0;
341*cdf0e10cSrcweir 		}
342*cdf0e10cSrcweir 
343*cdf0e10cSrcweir 		double AnimationEntryLoop::getNextEventTime(double fTime) const
344*cdf0e10cSrcweir 		{
345*cdf0e10cSrcweir 			double fNewTime(0.0);
346*cdf0e10cSrcweir 
347*cdf0e10cSrcweir 			if(mnRepeat && !basegfx::fTools::equalZero(mfDuration))
348*cdf0e10cSrcweir 			{
349*cdf0e10cSrcweir 				const sal_uInt32 nCurrentLoop((sal_uInt32)(fTime / mfDuration));
350*cdf0e10cSrcweir 
351*cdf0e10cSrcweir 				if(nCurrentLoop <= mnRepeat)
352*cdf0e10cSrcweir 				{
353*cdf0e10cSrcweir 					const double fTimeAtLoopStart((double)nCurrentLoop * mfDuration);
354*cdf0e10cSrcweir 					const double fRelativeTime(fTime - fTimeAtLoopStart);
355*cdf0e10cSrcweir 					const double fNextEventAtLoop(AnimationEntryList::getNextEventTime(fRelativeTime));
356*cdf0e10cSrcweir 
357*cdf0e10cSrcweir 					if(!basegfx::fTools::equalZero(fNextEventAtLoop))
358*cdf0e10cSrcweir 					{
359*cdf0e10cSrcweir 						fNewTime = fNextEventAtLoop + fTimeAtLoopStart;
360*cdf0e10cSrcweir 					}
361*cdf0e10cSrcweir 				}
362*cdf0e10cSrcweir 			}
363*cdf0e10cSrcweir 
364*cdf0e10cSrcweir 			return fNewTime;
365*cdf0e10cSrcweir 		}
366*cdf0e10cSrcweir 	} // end of namespace animation
367*cdf0e10cSrcweir } // end of namespace drawinglayer
368*cdf0e10cSrcweir 
369*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
370*cdf0e10cSrcweir // eof
371