dom/smil/nsSMILAnimationFunction.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial