Bug 828901 - Get the seek time as mBasePosition instead of the stream position in...
[gecko.git] / content / smil / nsSMILAnimationFunction.h
blobc9bac9baa36c19b2a52a95e3634b49b8c0137243
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef NS_SMILANIMATIONFUNCTION_H_
7 #define NS_SMILANIMATIONFUNCTION_H_
9 #include "nsISMILAttr.h"
10 #include "nsGkAtoms.h"
11 #include "nsString.h"
12 #include "nsSMILTargetIdentifier.h"
13 #include "nsSMILTimeValue.h"
14 #include "nsSMILKeySpline.h"
15 #include "nsSMILValue.h"
16 #include "nsAutoPtr.h"
17 #include "nsTArray.h"
18 #include "nsAttrValue.h"
19 #include "nsSMILTypes.h"
21 class nsISMILAnimationElement;
23 //----------------------------------------------------------------------
24 // nsSMILAnimationFunction
26 // The animation function calculates animation values. It it is provided with
27 // time parameters (sample time, repeat iteration etc.) and it uses this to
28 // build an appropriate animation value by performing interpolation and
29 // addition operations.
31 // It is responsible for implementing the animation parameters of an animation
32 // element (e.g. from, by, to, values, calcMode, additive, accumulate, keyTimes,
33 // keySplines)
35 class nsSMILAnimationFunction
37 public:
38 nsSMILAnimationFunction();
41 * Sets the owning animation element which this class uses to query attribute
42 * values and compare document positions.
44 void SetAnimationElement(nsISMILAnimationElement* aAnimationElement);
47 * Sets animation-specific attributes (or marks them dirty, in the case
48 * of from/to/by/values).
50 * @param aAttribute The attribute being set
51 * @param aValue The updated value of the attribute.
52 * @param aResult The nsAttrValue object that may be used for storing the
53 * parsed result.
54 * @param aParseResult Outparam used for reporting parse errors. Will be set
55 * to NS_OK if everything succeeds.
56 * @return true if aAttribute is a recognized animation-related
57 * attribute; false otherwise.
59 virtual bool SetAttr(nsIAtom* aAttribute, const nsAString& aValue,
60 nsAttrValue& aResult, nsresult* aParseResult = nullptr);
63 * Unsets the given attribute.
65 * @returns true if aAttribute is a recognized animation-related
66 * attribute; false otherwise.
68 virtual bool UnsetAttr(nsIAtom* aAttribute);
70 /**
71 * Indicate a new sample has occurred.
73 * @param aSampleTime The sample time for this timed element expressed in
74 * simple time.
75 * @param aSimpleDuration The simple duration for this timed element.
76 * @param aRepeatIteration The repeat iteration for this sample. The first
77 * iteration has a value of 0.
79 void SampleAt(nsSMILTime aSampleTime,
80 const nsSMILTimeValue& aSimpleDuration,
81 uint32_t aRepeatIteration);
83 /**
84 * Indicate to sample using the last value defined for the animation function.
85 * This value is not normally sampled due to the end-point exclusive timing
86 * model but only occurs when the fill mode is "freeze" and the active
87 * duration is an even multiple of the simple duration.
89 * @param aRepeatIteration The repeat iteration for this sample. The first
90 * iteration has a value of 0.
92 void SampleLastValue(uint32_t aRepeatIteration);
94 /**
95 * Indicate that this animation is now active. This is used to instruct the
96 * animation function that it should now add its result to the animation
97 * sandwich. The begin time is also provided for proper prioritization of
98 * animation functions, and for this reason, this method must be called
99 * before either of the Sample methods.
101 * @param aBeginTime The begin time for the newly active interval.
103 void Activate(nsSMILTime aBeginTime);
106 * Indicate that this animation is no longer active. This is used to instruct
107 * the animation function that it should no longer add its result to the
108 * animation sandwich.
110 * @param aIsFrozen true if this animation should continue to contribute
111 * to the animation sandwich using the most recent sample
112 * parameters.
114 void Inactivate(bool aIsFrozen);
117 * Combines the result of this animation function for the last sample with the
118 * specified value.
120 * @param aSMILAttr This animation's target attribute. Used here for
121 * doing attribute-specific parsing of from/to/by/values.
123 * @param aResult The value to compose with.
125 void ComposeResult(const nsISMILAttr& aSMILAttr, nsSMILValue& aResult);
128 * Returns the relative priority of this animation to another. The priority is
129 * used for determining the position of the animation in the animation
130 * sandwich -- higher priority animations are applied on top of lower
131 * priority animations.
133 * @return -1 if this animation has lower priority or 1 if this animation has
134 * higher priority
136 * This method should never return any other value, including 0.
138 int8_t CompareTo(const nsSMILAnimationFunction* aOther) const;
141 * The following methods are provided so that the compositor can optimize its
142 * operations by only composing those animation that will affect the final
143 * result.
147 * Indicates if the animation is currently active or frozen. Inactive
148 * animations will not contribute to the composed result.
150 * @return true if the animation is active or frozen, false otherwise.
152 bool IsActiveOrFrozen() const
155 * - Frozen animations should be considered active for the purposes of
156 * compositing.
157 * - This function does not assume that our nsSMILValues (by/from/to/values)
158 * have already been parsed.
160 return (mIsActive || mIsFrozen);
164 * Indicates if this animation will replace the passed in result rather than
165 * adding to it. Animations that replace the underlying value may be called
166 * without first calling lower priority animations.
168 * @return True if the animation will replace, false if it will add or
169 * otherwise build on the passed in value.
171 virtual bool WillReplace() const;
174 * Indicates if the parameters for this animation have changed since the last
175 * time it was composited. This allows rendering to be performed only when
176 * necessary, particularly when no animations are active.
178 * Note that the caller is responsible for determining if the animation
179 * target has changed (with help from my UpdateCachedTarget() method).
181 * @return true if the animation parameters have changed, false
182 * otherwise.
184 bool HasChanged() const;
187 * This method lets us clear the 'HasChanged' flag for inactive animations
188 * after we've reacted to their change to the 'inactive' state, so that we
189 * won't needlessly recompose their targets in every sample.
191 * This should only be called on an animation function that is inactive and
192 * that returns true from HasChanged().
194 void ClearHasChanged()
196 NS_ABORT_IF_FALSE(HasChanged(),
197 "clearing mHasChanged flag, when it's already false");
198 NS_ABORT_IF_FALSE(!IsActiveOrFrozen(),
199 "clearing mHasChanged flag for active animation");
200 mHasChanged = false;
204 * Updates the cached record of our animation target, and returns a boolean
205 * that indicates whether the target has changed since the last call to this
206 * function. (This lets nsSMILCompositor check whether its animation
207 * functions have changed value or target since the last sample. If none of
208 * them have, then the compositor doesn't need to do anything.)
210 * @param aNewTarget A nsSMILTargetIdentifier representing the animation
211 * target of this function for this sample.
212 * @return true if |aNewTarget| is different from the old cached value;
213 * otherwise, false.
215 bool UpdateCachedTarget(const nsSMILTargetIdentifier& aNewTarget);
218 * Returns true if this function was skipped in the previous sample (because
219 * there was a higher-priority non-additive animation). If a skipped animation
220 * function is later used, then the animation sandwich must be recomposited.
222 bool WasSkippedInPrevSample() const {
223 return mWasSkippedInPrevSample;
227 * Mark this animation function as having been skipped. By marking the
228 * function as skipped, if it is used in a subsequent sample we'll know to
229 * recomposite the sandwich.
231 void SetWasSkipped() {
232 mWasSkippedInPrevSample = true;
235 // Comparator utility class, used for sorting nsSMILAnimationFunctions
236 class Comparator {
237 public:
238 bool Equals(const nsSMILAnimationFunction* aElem1,
239 const nsSMILAnimationFunction* aElem2) const {
240 return (aElem1->CompareTo(aElem2) == 0);
242 bool LessThan(const nsSMILAnimationFunction* aElem1,
243 const nsSMILAnimationFunction* aElem2) const {
244 return (aElem1->CompareTo(aElem2) < 0);
248 protected:
249 // Typedefs
250 typedef nsTArray<nsSMILValue> nsSMILValueArray;
252 // Types
253 enum nsSMILCalcMode
255 CALC_LINEAR,
256 CALC_DISCRETE,
257 CALC_PACED,
258 CALC_SPLINE
261 // Used for sorting nsSMILAnimationFunctions
262 nsSMILTime GetBeginTime() const { return mBeginTime; }
264 // Property getters
265 bool GetAccumulate() const;
266 bool GetAdditive() const;
267 virtual nsSMILCalcMode GetCalcMode() const;
269 // Property setters
270 nsresult SetAccumulate(const nsAString& aAccumulate, nsAttrValue& aResult);
271 nsresult SetAdditive(const nsAString& aAdditive, nsAttrValue& aResult);
272 nsresult SetCalcMode(const nsAString& aCalcMode, nsAttrValue& aResult);
273 nsresult SetKeyTimes(const nsAString& aKeyTimes, nsAttrValue& aResult);
274 nsresult SetKeySplines(const nsAString& aKeySplines, nsAttrValue& aResult);
276 // Property un-setters
277 void UnsetAccumulate();
278 void UnsetAdditive();
279 void UnsetCalcMode();
280 void UnsetKeyTimes();
281 void UnsetKeySplines();
283 // Helpers
284 virtual nsresult InterpolateResult(const nsSMILValueArray& aValues,
285 nsSMILValue& aResult,
286 nsSMILValue& aBaseValue);
287 nsresult AccumulateResult(const nsSMILValueArray& aValues,
288 nsSMILValue& aResult);
290 nsresult ComputePacedPosition(const nsSMILValueArray& aValues,
291 double aSimpleProgress,
292 double& aIntervalProgress,
293 const nsSMILValue*& aFrom,
294 const nsSMILValue*& aTo);
295 double ComputePacedTotalDistance(const nsSMILValueArray& aValues) const;
298 * Adjust the simple progress, that is, the point within the simple duration,
299 * by applying any keyTimes.
301 double ScaleSimpleProgress(double aProgress, nsSMILCalcMode aCalcMode);
303 * Adjust the progress within an interval, that is, between two animation
304 * values, by applying any keySplines.
306 double ScaleIntervalProgress(double aProgress, uint32_t aIntervalIndex);
308 // Convenience attribute getters -- use these instead of querying
309 // mAnimationElement as these may need to be overridden by subclasses
310 virtual bool HasAttr(nsIAtom* aAttName) const;
311 virtual const nsAttrValue* GetAttr(nsIAtom* aAttName) const;
312 virtual bool GetAttr(nsIAtom* aAttName,
313 nsAString& aResult) const;
315 bool ParseAttr(nsIAtom* aAttName, const nsISMILAttr& aSMILAttr,
316 nsSMILValue& aResult,
317 bool& aPreventCachingOfSandwich) const;
319 virtual nsresult GetValues(const nsISMILAttr& aSMILAttr,
320 nsSMILValueArray& aResult);
322 virtual void CheckValueListDependentAttrs(uint32_t aNumValues);
323 void CheckKeyTimes(uint32_t aNumValues);
324 void CheckKeySplines(uint32_t aNumValues);
326 virtual bool IsToAnimation() const {
327 return !HasAttr(nsGkAtoms::values) &&
328 HasAttr(nsGkAtoms::to) &&
329 !HasAttr(nsGkAtoms::from);
332 // Returns true if we know our composited value won't change over the
333 // simple duration of this animation (for a fixed base value).
334 virtual bool IsValueFixedForSimpleDuration() const;
336 inline bool IsAdditive() const {
338 * Animation is additive if:
340 * (1) additive = "sum" (GetAdditive() == true), or
341 * (2) it is 'by animation' (by is set, from and values are not)
343 * Although animation is not additive if it is 'to animation'
345 bool isByAnimation = (!HasAttr(nsGkAtoms::values) &&
346 HasAttr(nsGkAtoms::by) &&
347 !HasAttr(nsGkAtoms::from));
348 return !IsToAnimation() && (GetAdditive() || isByAnimation);
351 // Setters for error flags
352 // These correspond to bit-indices in mErrorFlags, for tracking parse errors
353 // in these attributes, when those parse errors should block us from doing
354 // animation.
355 enum AnimationAttributeIdx {
356 BF_ACCUMULATE = 0,
357 BF_ADDITIVE = 1,
358 BF_CALC_MODE = 2,
359 BF_KEY_TIMES = 3,
360 BF_KEY_SPLINES = 4,
361 BF_KEY_POINTS = 5 // <animateMotion> only
364 inline void SetAccumulateErrorFlag(bool aNewValue) {
365 SetErrorFlag(BF_ACCUMULATE, aNewValue);
367 inline void SetAdditiveErrorFlag(bool aNewValue) {
368 SetErrorFlag(BF_ADDITIVE, aNewValue);
370 inline void SetCalcModeErrorFlag(bool aNewValue) {
371 SetErrorFlag(BF_CALC_MODE, aNewValue);
373 inline void SetKeyTimesErrorFlag(bool aNewValue) {
374 SetErrorFlag(BF_KEY_TIMES, aNewValue);
376 inline void SetKeySplinesErrorFlag(bool aNewValue) {
377 SetErrorFlag(BF_KEY_SPLINES, aNewValue);
379 inline void SetKeyPointsErrorFlag(bool aNewValue) {
380 SetErrorFlag(BF_KEY_POINTS, aNewValue);
382 // Helper method -- based on SET_BOOLBIT in nsHTMLInputElement.cpp
383 inline void SetErrorFlag(AnimationAttributeIdx aField, bool aValue) {
384 if (aValue) {
385 mErrorFlags |= (0x01 << aField);
386 } else {
387 mErrorFlags &= ~(0x01 << aField);
391 // Members
392 // -------
394 static nsAttrValue::EnumTable sAdditiveTable[];
395 static nsAttrValue::EnumTable sCalcModeTable[];
396 static nsAttrValue::EnumTable sAccumulateTable[];
398 nsTArray<double> mKeyTimes;
399 nsTArray<nsSMILKeySpline> mKeySplines;
401 // These are the parameters provided by the previous sample. Currently we
402 // perform lazy calculation. That is, we only calculate the result if and when
403 // instructed by the compositor. This allows us to apply the result directly
404 // to the animation value and allows the compositor to filter out functions
405 // that it determines will not contribute to the final result.
406 nsSMILTime mSampleTime; // sample time within simple dur
407 nsSMILTimeValue mSimpleDuration;
408 uint32_t mRepeatIteration;
410 nsSMILTime mBeginTime; // document time
412 // The owning animation element. This is used for sorting based on document
413 // position and for fetching attribute values stored in the element.
414 // Raw pointer is OK here, because this nsSMILAnimationFunction can't outlive
415 // its owning animation element.
416 nsISMILAnimationElement* mAnimationElement;
418 // Which attributes have been set but have had errors. This is not used for
419 // all attributes but only those which have specified error behaviour
420 // associated with them.
421 uint16_t mErrorFlags;
423 // Allows us to check whether an animation function has changed target from
424 // sample to sample (because if neither target nor animated value have
425 // changed, we don't have to do anything).
426 nsSMILWeakTargetIdentifier mLastTarget;
428 // Boolean flags
429 bool mIsActive:1;
430 bool mIsFrozen:1;
431 bool mLastValue:1;
432 bool mHasChanged:1;
433 bool mValueNeedsReparsingEverySample:1;
434 bool mPrevSampleWasSingleValueAnimation:1;
435 bool mWasSkippedInPrevSample:1;
438 #endif // NS_SMILANIMATIONFUNCTION_H_