Bug 1890793: Assert CallArgs::newTarget is not gray. r=spidermonkey-reviewers,sfink...
[gecko.git] / dom / smil / SMILAnimationFunction.h
blob8e85da76f6170be599b03018f027d5ff38db614e
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef DOM_SMIL_SMILANIMATIONFUNCTION_H_
8 #define DOM_SMIL_SMILANIMATIONFUNCTION_H_
10 #include "mozilla/SMILAttr.h"
11 #include "mozilla/SMILKeySpline.h"
12 #include "mozilla/SMILTargetIdentifier.h"
13 #include "mozilla/SMILTimeValue.h"
14 #include "mozilla/SMILTypes.h"
15 #include "mozilla/SMILValue.h"
16 #include "nsAttrValue.h"
17 #include "nsGkAtoms.h"
18 #include "nsString.h"
19 #include "nsTArray.h"
21 namespace mozilla {
22 namespace dom {
23 class SVGAnimationElement;
24 } // namespace dom
26 //----------------------------------------------------------------------
27 // SMILAnimationFunction
29 // The animation function calculates animation values. It it is provided with
30 // time parameters (sample time, repeat iteration etc.) and it uses this to
31 // build an appropriate animation value by performing interpolation and
32 // addition operations.
34 // It is responsible for implementing the animation parameters of an animation
35 // element (e.g. from, by, to, values, calcMode, additive, accumulate, keyTimes,
36 // keySplines)
38 class SMILAnimationFunction {
39 public:
40 SMILAnimationFunction();
43 * Sets the owning animation element which this class uses to query attribute
44 * values and compare document positions.
46 void SetAnimationElement(
47 mozilla::dom::SVGAnimationElement* aAnimationElement);
50 * Sets animation-specific attributes (or marks them dirty, in the case
51 * of from/to/by/values).
53 * @param aAttribute The attribute being set
54 * @param aValue The updated value of the attribute.
55 * @param aResult The nsAttrValue object that may be used for storing the
56 * parsed result.
57 * @param aParseResult Outparam used for reporting parse errors. Will be set
58 * to NS_OK if everything succeeds.
59 * @return true if aAttribute is a recognized animation-related
60 * attribute; false otherwise.
62 virtual bool SetAttr(nsAtom* aAttribute, const nsAString& aValue,
63 nsAttrValue& aResult, nsresult* aParseResult = nullptr);
66 * Unsets the given attribute.
68 * @returns true if aAttribute is a recognized animation-related
69 * attribute; false otherwise.
71 virtual bool UnsetAttr(nsAtom* aAttribute);
73 /**
74 * Indicate a new sample has occurred.
76 * @param aSampleTime The sample time for this timed element expressed in
77 * simple time.
78 * @param aSimpleDuration The simple duration for this timed element.
79 * @param aRepeatIteration The repeat iteration for this sample. The first
80 * iteration has a value of 0.
82 void SampleAt(SMILTime aSampleTime, const SMILTimeValue& aSimpleDuration,
83 uint32_t aRepeatIteration);
85 /**
86 * Indicate to sample using the last value defined for the animation function.
87 * This value is not normally sampled due to the end-point exclusive timing
88 * model but only occurs when the fill mode is "freeze" and the active
89 * duration is an even multiple of the simple duration.
91 * @param aRepeatIteration The repeat iteration for this sample. The first
92 * iteration has a value of 0.
94 void SampleLastValue(uint32_t aRepeatIteration);
96 /**
97 * Indicate that this animation is now active. This is used to instruct the
98 * animation function that it should now add its result to the animation
99 * sandwich. The begin time is also provided for proper prioritization of
100 * animation functions, and for this reason, this method must be called
101 * before either of the Sample methods.
103 * @param aBeginTime The begin time for the newly active interval.
105 void Activate(SMILTime aBeginTime);
108 * Indicate that this animation is no longer active. This is used to instruct
109 * the animation function that it should no longer add its result to the
110 * animation sandwich.
112 * @param aIsFrozen true if this animation should continue to contribute
113 * to the animation sandwich using the most recent sample
114 * parameters.
116 void Inactivate(bool aIsFrozen);
119 * Combines the result of this animation function for the last sample with the
120 * specified value.
122 * @param aSMILAttr This animation's target attribute. Used here for
123 * doing attribute-specific parsing of from/to/by/values.
125 * @param aResult The value to compose with.
127 void ComposeResult(const SMILAttr& aSMILAttr, SMILValue& aResult);
130 * Returns the relative priority of this animation to another. The priority is
131 * used for determining the position of the animation in the animation
132 * sandwich -- higher priority animations are applied on top of lower
133 * priority animations.
135 * @return -1 if this animation has lower priority or 1 if this animation has
136 * higher priority
138 * This method should never return any other value, including 0.
140 int8_t CompareTo(const SMILAnimationFunction* aOther) const;
143 * The following methods are provided so that the compositor can optimize its
144 * operations by only composing those animation that will affect the final
145 * result.
149 * Indicates if the animation is currently active or frozen. Inactive
150 * animations will not contribute to the composed result.
152 * @return true if the animation is active or frozen, false otherwise.
154 bool IsActiveOrFrozen() const {
156 * - Frozen animations should be considered active for the purposes of
157 * compositing.
158 * - This function does not assume that our SMILValues (by/from/to/values)
159 * have already been parsed.
161 return (mIsActive || mIsFrozen);
165 * Indicates if the animation is active.
167 * @return true if the animation is active, false otherwise.
169 bool IsActive() const { return mIsActive; }
172 * Indicates if this animation will replace the passed in result rather than
173 * adding to it. Animations that replace the underlying value may be called
174 * without first calling lower priority animations.
176 * @return True if the animation will replace, false if it will add or
177 * otherwise build on the passed in value.
179 virtual bool WillReplace() const;
182 * Indicates if the parameters for this animation have changed since the last
183 * time it was composited. This allows rendering to be performed only when
184 * necessary, particularly when no animations are active.
186 * Note that the caller is responsible for determining if the animation
187 * target has changed (with help from my UpdateCachedTarget() method).
189 * @return true if the animation parameters have changed, false
190 * otherwise.
192 bool HasChanged() const;
195 * This method lets us clear the 'HasChanged' flag for inactive animations
196 * after we've reacted to their change to the 'inactive' state, so that we
197 * won't needlessly recompose their targets in every sample.
199 * This should only be called on an animation function that is inactive and
200 * that returns true from HasChanged().
202 void ClearHasChanged() {
203 MOZ_ASSERT(HasChanged(),
204 "clearing mHasChanged flag, when it's already false");
205 MOZ_ASSERT(!IsActiveOrFrozen(),
206 "clearing mHasChanged flag for active animation");
207 mHasChanged = false;
211 * Updates the cached record of our animation target, and returns a boolean
212 * that indicates whether the target has changed since the last call to this
213 * function. (This lets SMILCompositor check whether its animation
214 * functions have changed value or target since the last sample. If none of
215 * them have, then the compositor doesn't need to do anything.)
217 * @param aNewTarget A SMILTargetIdentifier representing the animation
218 * target of this function for this sample.
219 * @return true if |aNewTarget| is different from the old cached value;
220 * otherwise, false.
222 bool UpdateCachedTarget(const SMILTargetIdentifier& aNewTarget);
225 * Returns true if this function was skipped in the previous sample (because
226 * there was a higher-priority non-additive animation). If a skipped animation
227 * function is later used, then the animation sandwich must be recomposited.
229 bool WasSkippedInPrevSample() const { return mWasSkippedInPrevSample; }
232 * Mark this animation function as having been skipped. By marking the
233 * function as skipped, if it is used in a subsequent sample we'll know to
234 * recomposite the sandwich.
236 void SetWasSkipped() { mWasSkippedInPrevSample = true; }
239 * Returns true if we need to recalculate the animation value on every sample.
240 * (e.g. because it depends on context like the font-size)
242 bool ValueNeedsReparsingEverySample() const {
243 return mValueNeedsReparsingEverySample;
246 // Comparator utility class, used for sorting SMILAnimationFunctions
247 class Comparator {
248 public:
249 bool Equals(const SMILAnimationFunction* aElem1,
250 const SMILAnimationFunction* aElem2) const {
251 return (aElem1->CompareTo(aElem2) == 0);
253 bool LessThan(const SMILAnimationFunction* aElem1,
254 const SMILAnimationFunction* aElem2) const {
255 return (aElem1->CompareTo(aElem2) < 0);
259 protected:
260 // alias declarations
261 using SMILValueArray = FallibleTArray<SMILValue>;
263 // Types
264 enum SMILCalcMode : uint8_t {
265 CALC_LINEAR,
266 CALC_DISCRETE,
267 CALC_PACED,
268 CALC_SPLINE
271 // Used for sorting SMILAnimationFunctions
272 SMILTime GetBeginTime() const { return mBeginTime; }
274 // Property getters
275 bool GetAccumulate() const;
276 bool GetAdditive() const;
277 virtual SMILCalcMode GetCalcMode() const;
279 // Property setters
280 nsresult SetAccumulate(const nsAString& aAccumulate, nsAttrValue& aResult);
281 nsresult SetAdditive(const nsAString& aAdditive, nsAttrValue& aResult);
282 nsresult SetCalcMode(const nsAString& aCalcMode, nsAttrValue& aResult);
283 nsresult SetKeyTimes(const nsAString& aKeyTimes, nsAttrValue& aResult);
284 nsresult SetKeySplines(const nsAString& aKeySplines, nsAttrValue& aResult);
286 // Property un-setters
287 void UnsetAccumulate();
288 void UnsetAdditive();
289 void UnsetCalcMode();
290 void UnsetKeyTimes();
291 void UnsetKeySplines();
293 // Helpers
294 virtual bool IsDisallowedAttribute(const nsAtom* aAttribute) const {
295 return false;
297 virtual nsresult InterpolateResult(const SMILValueArray& aValues,
298 SMILValue& aResult, SMILValue& aBaseValue);
299 nsresult AccumulateResult(const SMILValueArray& aValues, SMILValue& aResult);
301 nsresult ComputePacedPosition(const SMILValueArray& aValues,
302 double aSimpleProgress,
303 double& aIntervalProgress,
304 const SMILValue*& aFrom, const SMILValue*& aTo);
305 double ComputePacedTotalDistance(const SMILValueArray& aValues) const;
308 * Adjust the simple progress, that is, the point within the simple duration,
309 * by applying any keyTimes.
311 double ScaleSimpleProgress(double aProgress, SMILCalcMode aCalcMode);
313 * Adjust the progress within an interval, that is, between two animation
314 * values, by applying any keySplines.
316 double ScaleIntervalProgress(double aProgress, uint32_t aIntervalIndex);
318 // Convenience attribute getters
319 bool HasAttr(nsAtom* aAttName) const;
320 const nsAttrValue* GetAttr(nsAtom* aAttName) const;
321 bool GetAttr(nsAtom* aAttName, nsAString& aResult) const;
323 bool ParseAttr(nsAtom* aAttName, const SMILAttr& aSMILAttr,
324 SMILValue& aResult, bool& aPreventCachingOfSandwich) const;
326 virtual nsresult GetValues(const SMILAttr& aSMILAttr,
327 SMILValueArray& aResult);
329 virtual void CheckValueListDependentAttrs(uint32_t aNumValues);
330 void CheckKeyTimes(uint32_t aNumValues);
331 void CheckKeySplines(uint32_t aNumValues);
333 virtual bool IsToAnimation() const {
334 return !HasAttr(nsGkAtoms::values) && HasAttr(nsGkAtoms::to) &&
335 !HasAttr(nsGkAtoms::from);
338 // Returns true if we know our composited value won't change over the
339 // simple duration of this animation (for a fixed base value).
340 virtual bool IsValueFixedForSimpleDuration() const;
342 inline bool IsAdditive() const {
344 * Animation is additive if:
346 * (1) additive = "sum" (GetAdditive() == true), or
347 * (2) it is 'by animation' (by is set, from and values are not)
349 * Although animation is not additive if it is 'to animation'
351 bool isByAnimation = (!HasAttr(nsGkAtoms::values) &&
352 HasAttr(nsGkAtoms::by) && !HasAttr(nsGkAtoms::from));
353 return !IsToAnimation() && (GetAdditive() || isByAnimation);
356 // Setters for error flags
357 // These correspond to bit-indices in mErrorFlags, for tracking parse errors
358 // in these attributes, when those parse errors should block us from doing
359 // animation.
360 enum AnimationAttributeIdx {
361 BF_ACCUMULATE = 0,
362 BF_ADDITIVE = 1,
363 BF_CALC_MODE = 2,
364 BF_KEY_TIMES = 3,
365 BF_KEY_SPLINES = 4,
366 BF_KEY_POINTS = 5 // <animateMotion> only
369 inline void SetAccumulateErrorFlag(bool aNewValue) {
370 SetErrorFlag(BF_ACCUMULATE, aNewValue);
372 inline void SetAdditiveErrorFlag(bool aNewValue) {
373 SetErrorFlag(BF_ADDITIVE, aNewValue);
375 inline void SetCalcModeErrorFlag(bool aNewValue) {
376 SetErrorFlag(BF_CALC_MODE, aNewValue);
378 inline void SetKeyTimesErrorFlag(bool aNewValue) {
379 SetErrorFlag(BF_KEY_TIMES, aNewValue);
381 inline void SetKeySplinesErrorFlag(bool aNewValue) {
382 SetErrorFlag(BF_KEY_SPLINES, aNewValue);
384 inline void SetKeyPointsErrorFlag(bool aNewValue) {
385 SetErrorFlag(BF_KEY_POINTS, aNewValue);
387 inline void SetErrorFlag(AnimationAttributeIdx aField, bool aValue) {
388 if (aValue) {
389 mErrorFlags |= (0x01 << aField);
390 } else {
391 mErrorFlags &= ~(0x01 << aField);
395 // Members
396 // -------
398 static nsAttrValue::EnumTable sAdditiveTable[];
399 static nsAttrValue::EnumTable sCalcModeTable[];
400 static nsAttrValue::EnumTable sAccumulateTable[];
402 FallibleTArray<double> mKeyTimes;
403 FallibleTArray<SMILKeySpline> mKeySplines;
405 // These are the parameters provided by the previous sample. Currently we
406 // perform lazy calculation. That is, we only calculate the result if and when
407 // instructed by the compositor. This allows us to apply the result directly
408 // to the animation value and allows the compositor to filter out functions
409 // that it determines will not contribute to the final result.
410 SMILTime mSampleTime; // sample time within simple dur
411 SMILTimeValue mSimpleDuration;
412 uint32_t mRepeatIteration;
414 SMILTime mBeginTime; // document time
416 // The owning animation element. This is used for sorting based on document
417 // position and for fetching attribute values stored in the element.
418 // Raw pointer is OK here, because this SMILAnimationFunction can't outlive
419 // its owning animation element.
420 mozilla::dom::SVGAnimationElement* mAnimationElement;
422 // Which attributes have been set but have had errors. This is not used for
423 // all attributes but only those which have specified error behaviour
424 // associated with them.
425 uint16_t mErrorFlags;
427 // Allows us to check whether an animation function has changed target from
428 // sample to sample (because if neither target nor animated value have
429 // changed, we don't have to do anything).
430 SMILWeakTargetIdentifier mLastTarget;
432 // Boolean flags
433 bool mIsActive : 1;
434 bool mIsFrozen : 1;
435 bool mLastValue : 1;
436 bool mHasChanged : 1;
437 bool mValueNeedsReparsingEverySample : 1;
438 bool mPrevSampleWasSingleValueAnimation : 1;
439 bool mWasSkippedInPrevSample : 1;
442 } // namespace mozilla
444 #endif // DOM_SMIL_SMILANIMATIONFUNCTION_H_