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