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"
12 #include "nsSMILTargetIdentifier.h"
13 #include "nsSMILTimeValue.h"
14 #include "nsSMILKeySpline.h"
15 #include "nsSMILValue.h"
16 #include "nsAutoPtr.h"
18 #include "nsAttrValue.h"
19 #include "nsSMILTypes.h"
23 class SVGAnimationElement
;
27 //----------------------------------------------------------------------
28 // nsSMILAnimationFunction
30 // The animation function calculates animation values. It it is provided with
31 // time parameters (sample time, repeat iteration etc.) and it uses this to
32 // build an appropriate animation value by performing interpolation and
33 // addition operations.
35 // It is responsible for implementing the animation parameters of an animation
36 // element (e.g. from, by, to, values, calcMode, additive, accumulate, keyTimes,
39 class nsSMILAnimationFunction
42 nsSMILAnimationFunction();
45 * Sets the owning animation element which this class uses to query attribute
46 * values and compare document positions.
48 void SetAnimationElement(mozilla::dom::SVGAnimationElement
* aAnimationElement
);
51 * Sets animation-specific attributes (or marks them dirty, in the case
52 * of from/to/by/values).
54 * @param aAttribute The attribute being set
55 * @param aValue The updated value of the attribute.
56 * @param aResult The nsAttrValue object that may be used for storing the
58 * @param aParseResult Outparam used for reporting parse errors. Will be set
59 * to NS_OK if everything succeeds.
60 * @return true if aAttribute is a recognized animation-related
61 * attribute; false otherwise.
63 virtual bool SetAttr(nsIAtom
* aAttribute
, const nsAString
& aValue
,
64 nsAttrValue
& aResult
, nsresult
* aParseResult
= nullptr);
67 * Unsets the given attribute.
69 * @returns true if aAttribute is a recognized animation-related
70 * attribute; false otherwise.
72 virtual bool UnsetAttr(nsIAtom
* aAttribute
);
75 * Indicate a new sample has occurred.
77 * @param aSampleTime The sample time for this timed element expressed in
79 * @param aSimpleDuration The simple duration for this timed element.
80 * @param aRepeatIteration The repeat iteration for this sample. The first
81 * iteration has a value of 0.
83 void SampleAt(nsSMILTime aSampleTime
,
84 const nsSMILTimeValue
& aSimpleDuration
,
85 uint32_t aRepeatIteration
);
88 * Indicate to sample using the last value defined for the animation function.
89 * This value is not normally sampled due to the end-point exclusive timing
90 * model but only occurs when the fill mode is "freeze" and the active
91 * duration is an even multiple of the simple duration.
93 * @param aRepeatIteration The repeat iteration for this sample. The first
94 * iteration has a value of 0.
96 void SampleLastValue(uint32_t aRepeatIteration
);
99 * Indicate that this animation is now active. This is used to instruct the
100 * animation function that it should now add its result to the animation
101 * sandwich. The begin time is also provided for proper prioritization of
102 * animation functions, and for this reason, this method must be called
103 * before either of the Sample methods.
105 * @param aBeginTime The begin time for the newly active interval.
107 void Activate(nsSMILTime aBeginTime
);
110 * Indicate that this animation is no longer active. This is used to instruct
111 * the animation function that it should no longer add its result to the
112 * animation sandwich.
114 * @param aIsFrozen true if this animation should continue to contribute
115 * to the animation sandwich using the most recent sample
118 void Inactivate(bool aIsFrozen
);
121 * Combines the result of this animation function for the last sample with the
124 * @param aSMILAttr This animation's target attribute. Used here for
125 * doing attribute-specific parsing of from/to/by/values.
127 * @param aResult The value to compose with.
129 void ComposeResult(const nsISMILAttr
& aSMILAttr
, nsSMILValue
& aResult
);
132 * Returns the relative priority of this animation to another. The priority is
133 * used for determining the position of the animation in the animation
134 * sandwich -- higher priority animations are applied on top of lower
135 * priority animations.
137 * @return -1 if this animation has lower priority or 1 if this animation has
140 * This method should never return any other value, including 0.
142 int8_t CompareTo(const nsSMILAnimationFunction
* aOther
) const;
145 * The following methods are provided so that the compositor can optimize its
146 * operations by only composing those animation that will affect the final
151 * Indicates if the animation is currently active or frozen. Inactive
152 * animations will not contribute to the composed result.
154 * @return true if the animation is active or frozen, false otherwise.
156 bool IsActiveOrFrozen() const
159 * - Frozen animations should be considered active for the purposes of
161 * - This function does not assume that our nsSMILValues (by/from/to/values)
162 * have already been parsed.
164 return (mIsActive
|| mIsFrozen
);
168 * Indicates if this animation will replace the passed in result rather than
169 * adding to it. Animations that replace the underlying value may be called
170 * without first calling lower priority animations.
172 * @return True if the animation will replace, false if it will add or
173 * otherwise build on the passed in value.
175 virtual bool WillReplace() const;
178 * Indicates if the parameters for this animation have changed since the last
179 * time it was composited. This allows rendering to be performed only when
180 * necessary, particularly when no animations are active.
182 * Note that the caller is responsible for determining if the animation
183 * target has changed (with help from my UpdateCachedTarget() method).
185 * @return true if the animation parameters have changed, false
188 bool HasChanged() const;
191 * This method lets us clear the 'HasChanged' flag for inactive animations
192 * after we've reacted to their change to the 'inactive' state, so that we
193 * won't needlessly recompose their targets in every sample.
195 * This should only be called on an animation function that is inactive and
196 * that returns true from HasChanged().
198 void ClearHasChanged()
200 NS_ABORT_IF_FALSE(HasChanged(),
201 "clearing mHasChanged flag, when it's already false");
202 NS_ABORT_IF_FALSE(!IsActiveOrFrozen(),
203 "clearing mHasChanged flag for active animation");
208 * Updates the cached record of our animation target, and returns a boolean
209 * that indicates whether the target has changed since the last call to this
210 * function. (This lets nsSMILCompositor check whether its animation
211 * functions have changed value or target since the last sample. If none of
212 * them have, then the compositor doesn't need to do anything.)
214 * @param aNewTarget A nsSMILTargetIdentifier representing the animation
215 * target of this function for this sample.
216 * @return true if |aNewTarget| is different from the old cached value;
219 bool UpdateCachedTarget(const nsSMILTargetIdentifier
& aNewTarget
);
222 * Returns true if this function was skipped in the previous sample (because
223 * there was a higher-priority non-additive animation). If a skipped animation
224 * function is later used, then the animation sandwich must be recomposited.
226 bool WasSkippedInPrevSample() const {
227 return mWasSkippedInPrevSample
;
231 * Mark this animation function as having been skipped. By marking the
232 * function as skipped, if it is used in a subsequent sample we'll know to
233 * recomposite the sandwich.
235 void SetWasSkipped() {
236 mWasSkippedInPrevSample
= true;
239 // Comparator utility class, used for sorting nsSMILAnimationFunctions
242 bool Equals(const nsSMILAnimationFunction
* aElem1
,
243 const nsSMILAnimationFunction
* aElem2
) const {
244 return (aElem1
->CompareTo(aElem2
) == 0);
246 bool LessThan(const nsSMILAnimationFunction
* aElem1
,
247 const nsSMILAnimationFunction
* aElem2
) const {
248 return (aElem1
->CompareTo(aElem2
) < 0);
254 typedef nsTArray
<nsSMILValue
> nsSMILValueArray
;
265 // Used for sorting nsSMILAnimationFunctions
266 nsSMILTime
GetBeginTime() const { return mBeginTime
; }
269 bool GetAccumulate() const;
270 bool GetAdditive() const;
271 virtual nsSMILCalcMode
GetCalcMode() const;
274 nsresult
SetAccumulate(const nsAString
& aAccumulate
, nsAttrValue
& aResult
);
275 nsresult
SetAdditive(const nsAString
& aAdditive
, nsAttrValue
& aResult
);
276 nsresult
SetCalcMode(const nsAString
& aCalcMode
, nsAttrValue
& aResult
);
277 nsresult
SetKeyTimes(const nsAString
& aKeyTimes
, nsAttrValue
& aResult
);
278 nsresult
SetKeySplines(const nsAString
& aKeySplines
, nsAttrValue
& aResult
);
280 // Property un-setters
281 void UnsetAccumulate();
282 void UnsetAdditive();
283 void UnsetCalcMode();
284 void UnsetKeyTimes();
285 void UnsetKeySplines();
288 virtual nsresult
InterpolateResult(const nsSMILValueArray
& aValues
,
289 nsSMILValue
& aResult
,
290 nsSMILValue
& aBaseValue
);
291 nsresult
AccumulateResult(const nsSMILValueArray
& aValues
,
292 nsSMILValue
& aResult
);
294 nsresult
ComputePacedPosition(const nsSMILValueArray
& aValues
,
295 double aSimpleProgress
,
296 double& aIntervalProgress
,
297 const nsSMILValue
*& aFrom
,
298 const nsSMILValue
*& aTo
);
299 double ComputePacedTotalDistance(const nsSMILValueArray
& aValues
) const;
302 * Adjust the simple progress, that is, the point within the simple duration,
303 * by applying any keyTimes.
305 double ScaleSimpleProgress(double aProgress
, nsSMILCalcMode aCalcMode
);
307 * Adjust the progress within an interval, that is, between two animation
308 * values, by applying any keySplines.
310 double ScaleIntervalProgress(double aProgress
, uint32_t aIntervalIndex
);
312 // Convenience attribute getters -- use these instead of querying
313 // mAnimationElement as these may need to be overridden by subclasses
314 virtual bool HasAttr(nsIAtom
* aAttName
) const;
315 virtual const nsAttrValue
* GetAttr(nsIAtom
* aAttName
) const;
316 virtual bool GetAttr(nsIAtom
* aAttName
,
317 nsAString
& aResult
) const;
319 bool ParseAttr(nsIAtom
* aAttName
, const nsISMILAttr
& aSMILAttr
,
320 nsSMILValue
& aResult
,
321 bool& aPreventCachingOfSandwich
) const;
323 virtual nsresult
GetValues(const nsISMILAttr
& aSMILAttr
,
324 nsSMILValueArray
& aResult
);
326 virtual void CheckValueListDependentAttrs(uint32_t aNumValues
);
327 void CheckKeyTimes(uint32_t aNumValues
);
328 void CheckKeySplines(uint32_t aNumValues
);
330 virtual bool IsToAnimation() const {
331 return !HasAttr(nsGkAtoms::values
) &&
332 HasAttr(nsGkAtoms::to
) &&
333 !HasAttr(nsGkAtoms::from
);
336 // Returns true if we know our composited value won't change over the
337 // simple duration of this animation (for a fixed base value).
338 virtual bool IsValueFixedForSimpleDuration() const;
340 inline bool IsAdditive() const {
342 * Animation is additive if:
344 * (1) additive = "sum" (GetAdditive() == true), or
345 * (2) it is 'by animation' (by is set, from and values are not)
347 * Although animation is not additive if it is 'to animation'
349 bool isByAnimation
= (!HasAttr(nsGkAtoms::values
) &&
350 HasAttr(nsGkAtoms::by
) &&
351 !HasAttr(nsGkAtoms::from
));
352 return !IsToAnimation() && (GetAdditive() || isByAnimation
);
355 // Setters for error flags
356 // These correspond to bit-indices in mErrorFlags, for tracking parse errors
357 // in these attributes, when those parse errors should block us from doing
359 enum AnimationAttributeIdx
{
365 BF_KEY_POINTS
= 5 // <animateMotion> only
368 inline void SetAccumulateErrorFlag(bool aNewValue
) {
369 SetErrorFlag(BF_ACCUMULATE
, aNewValue
);
371 inline void SetAdditiveErrorFlag(bool aNewValue
) {
372 SetErrorFlag(BF_ADDITIVE
, aNewValue
);
374 inline void SetCalcModeErrorFlag(bool aNewValue
) {
375 SetErrorFlag(BF_CALC_MODE
, aNewValue
);
377 inline void SetKeyTimesErrorFlag(bool aNewValue
) {
378 SetErrorFlag(BF_KEY_TIMES
, aNewValue
);
380 inline void SetKeySplinesErrorFlag(bool aNewValue
) {
381 SetErrorFlag(BF_KEY_SPLINES
, aNewValue
);
383 inline void SetKeyPointsErrorFlag(bool aNewValue
) {
384 SetErrorFlag(BF_KEY_POINTS
, aNewValue
);
386 inline void SetErrorFlag(AnimationAttributeIdx aField
, bool aValue
) {
388 mErrorFlags
|= (0x01 << aField
);
390 mErrorFlags
&= ~(0x01 << aField
);
397 static nsAttrValue::EnumTable sAdditiveTable
[];
398 static nsAttrValue::EnumTable sCalcModeTable
[];
399 static nsAttrValue::EnumTable sAccumulateTable
[];
401 nsTArray
<double> mKeyTimes
;
402 nsTArray
<nsSMILKeySpline
> mKeySplines
;
404 // These are the parameters provided by the previous sample. Currently we
405 // perform lazy calculation. That is, we only calculate the result if and when
406 // instructed by the compositor. This allows us to apply the result directly
407 // to the animation value and allows the compositor to filter out functions
408 // that it determines will not contribute to the final result.
409 nsSMILTime mSampleTime
; // sample time within simple dur
410 nsSMILTimeValue mSimpleDuration
;
411 uint32_t mRepeatIteration
;
413 nsSMILTime mBeginTime
; // document time
415 // The owning animation element. This is used for sorting based on document
416 // position and for fetching attribute values stored in the element.
417 // Raw pointer is OK here, because this nsSMILAnimationFunction can't outlive
418 // its owning animation element.
419 mozilla::dom::SVGAnimationElement
* mAnimationElement
;
421 // Which attributes have been set but have had errors. This is not used for
422 // all attributes but only those which have specified error behaviour
423 // associated with them.
424 uint16_t mErrorFlags
;
426 // Allows us to check whether an animation function has changed target from
427 // sample to sample (because if neither target nor animated value have
428 // changed, we don't have to do anything).
429 nsSMILWeakTargetIdentifier mLastTarget
;
436 bool mValueNeedsReparsingEverySample
:1;
437 bool mPrevSampleWasSingleValueAnimation
:1;
438 bool mWasSkippedInPrevSample
:1;
441 #endif // NS_SMILANIMATIONFUNCTION_H_