layout/style/AnimationCommon.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/style/AnimationCommon.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,387 @@
     1.4 +/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef mozilla_css_AnimationCommon_h
    1.10 +#define mozilla_css_AnimationCommon_h
    1.11 +
    1.12 +#include "nsIStyleRuleProcessor.h"
    1.13 +#include "nsIStyleRule.h"
    1.14 +#include "nsRefreshDriver.h"
    1.15 +#include "prclist.h"
    1.16 +#include "nsStyleAnimation.h"
    1.17 +#include "nsCSSProperty.h"
    1.18 +#include "mozilla/MemoryReporting.h"
    1.19 +#include "mozilla/dom/Element.h"
    1.20 +#include "nsSMILKeySpline.h"
    1.21 +#include "nsStyleStruct.h"
    1.22 +#include "mozilla/Attributes.h"
    1.23 +#include "nsCSSPseudoElements.h"
    1.24 +
    1.25 +class nsPresContext;
    1.26 +class nsIFrame;
    1.27 +
    1.28 +
    1.29 +namespace mozilla {
    1.30 +namespace css {
    1.31 +
    1.32 +bool IsGeometricProperty(nsCSSProperty aProperty);
    1.33 +
    1.34 +struct CommonElementAnimationData;
    1.35 +
    1.36 +class CommonAnimationManager : public nsIStyleRuleProcessor,
    1.37 +                               public nsARefreshObserver {
    1.38 +public:
    1.39 +  CommonAnimationManager(nsPresContext *aPresContext);
    1.40 +  virtual ~CommonAnimationManager();
    1.41 +
    1.42 +  // nsISupports
    1.43 +  NS_DECL_ISUPPORTS
    1.44 +
    1.45 +  // nsIStyleRuleProcessor (parts)
    1.46 +  virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData) MOZ_OVERRIDE;
    1.47 +  virtual nsRestyleHint HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) MOZ_OVERRIDE;
    1.48 +  virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) MOZ_OVERRIDE;
    1.49 +  virtual nsRestyleHint
    1.50 +    HasAttributeDependentStyle(AttributeRuleProcessorData* aData) MOZ_OVERRIDE;
    1.51 +  virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) MOZ_OVERRIDE;
    1.52 +  virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
    1.53 +    const MOZ_MUST_OVERRIDE MOZ_OVERRIDE;
    1.54 +  virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
    1.55 +    const MOZ_MUST_OVERRIDE MOZ_OVERRIDE;
    1.56 +
    1.57 +  /**
    1.58 +   * Notify the manager that the pres context is going away.
    1.59 +   */
    1.60 +  void Disconnect();
    1.61 +
    1.62 +  enum FlushFlags {
    1.63 +    Can_Throttle,
    1.64 +    Cannot_Throttle
    1.65 +  };
    1.66 +
    1.67 +  static bool ExtractComputedValueForTransition(
    1.68 +                  nsCSSProperty aProperty,
    1.69 +                  nsStyleContext* aStyleContext,
    1.70 +                  nsStyleAnimation::Value& aComputedValue);
    1.71 +protected:
    1.72 +  friend struct CommonElementAnimationData; // for ElementDataRemoved
    1.73 +
    1.74 +  virtual void AddElementData(CommonElementAnimationData* aData) = 0;
    1.75 +  virtual void ElementDataRemoved() = 0;
    1.76 +  void RemoveAllElementData();
    1.77 +
    1.78 +  // Update the style on aElement from the transition stored in this manager and
    1.79 +  // the new parent style - aParentStyle. aElement must be transitioning or
    1.80 +  // animated. Returns the updated style.
    1.81 +  nsStyleContext* UpdateThrottledStyle(mozilla::dom::Element* aElement,
    1.82 +                                       nsStyleContext* aParentStyle,
    1.83 +                                       nsStyleChangeList &aChangeList);
    1.84 +  // Reparent the style of aContent and any :before and :after pseudo-elements.
    1.85 +  already_AddRefed<nsStyleContext> ReparentContent(nsIContent* aContent,
    1.86 +                                                  nsStyleContext* aParentStyle);
    1.87 +  // reparent :before and :after pseudo elements of aElement
    1.88 +  static void ReparentBeforeAndAfter(dom::Element* aElement,
    1.89 +                                     nsIFrame* aPrimaryFrame,
    1.90 +                                     nsStyleContext* aNewStyle,
    1.91 +                                     nsStyleSet* aStyleSet);
    1.92 +
    1.93 +  PRCList mElementData;
    1.94 +  nsPresContext *mPresContext; // weak (non-null from ctor to Disconnect)
    1.95 +};
    1.96 +
    1.97 +// The internals of UpdateAllThrottledStyles, used by nsAnimationManager and
    1.98 +// nsTransitionManager, see the comments in the declaration of the latter.
    1.99 +#define IMPL_UPDATE_ALL_THROTTLED_STYLES_INTERNAL(class_, animations_getter_)  \
   1.100 +void                                                                           \
   1.101 +class_::UpdateAllThrottledStylesInternal()                                     \
   1.102 +{                                                                              \
   1.103 +  TimeStamp now = mPresContext->RefreshDriver()->MostRecentRefresh();          \
   1.104 +                                                                               \
   1.105 +  nsStyleChangeList changeList;                                                \
   1.106 +                                                                               \
   1.107 +  /* update each transitioning element by finding its root-most ancestor
   1.108 +     with a transition, and flushing the style on that ancestor and all
   1.109 +     its descendants*/                                                         \
   1.110 +  PRCList *next = PR_LIST_HEAD(&mElementData);                                 \
   1.111 +  while (next != &mElementData) {                                              \
   1.112 +    CommonElementAnimationData* ea =                                           \
   1.113 +      static_cast<CommonElementAnimationData*>(next);                          \
   1.114 +    next = PR_NEXT_LINK(next);                                                 \
   1.115 +                                                                               \
   1.116 +    if (ea->mFlushGeneration == now) {                                         \
   1.117 +      /* this element has been ticked already */                               \
   1.118 +      continue;                                                                \
   1.119 +    }                                                                          \
   1.120 +                                                                               \
   1.121 +    /* element is initialised to the starting element (i.e., one we know has
   1.122 +       an animation) and ends up with the root-most animated ancestor,
   1.123 +       that is, the element where we begin updates. */                         \
   1.124 +    dom::Element* element = ea->mElement;                                      \
   1.125 +    /* make a list of ancestors */                                             \
   1.126 +    nsTArray<dom::Element*> ancestors;                                         \
   1.127 +    do {                                                                       \
   1.128 +      ancestors.AppendElement(element);                                        \
   1.129 +    } while ((element = element->GetParentElement()));                         \
   1.130 +                                                                               \
   1.131 +    /* walk down the ancestors until we find one with a throttled transition */\
   1.132 +    for (int32_t i = ancestors.Length() - 1; i >= 0; --i) {                    \
   1.133 +      if (animations_getter_(ancestors[i],                                     \
   1.134 +                            nsCSSPseudoElements::ePseudo_NotPseudoElement,     \
   1.135 +                            false)) {                                          \
   1.136 +        element = ancestors[i];                                                \
   1.137 +        break;                                                                 \
   1.138 +      }                                                                        \
   1.139 +    }                                                                          \
   1.140 +                                                                               \
   1.141 +    nsIFrame* primaryFrame;                                                    \
   1.142 +    if (element &&                                                             \
   1.143 +        (primaryFrame = nsLayoutUtils::GetStyleFrame(element))) {              \
   1.144 +      UpdateThrottledStylesForSubtree(element,                                 \
   1.145 +        primaryFrame->StyleContext()->GetParent(), changeList);                \
   1.146 +    }                                                                          \
   1.147 +  }                                                                            \
   1.148 +                                                                               \
   1.149 +  RestyleManager* restyleManager = mPresContext->RestyleManager();             \
   1.150 +  restyleManager->ProcessRestyledFrames(changeList);                           \
   1.151 +  restyleManager->FlushOverflowChangedTracker();                               \
   1.152 +}
   1.153 +
   1.154 +/**
   1.155 + * A style rule that maps property-nsStyleAnimation::Value pairs.
   1.156 + */
   1.157 +class AnimValuesStyleRule MOZ_FINAL : public nsIStyleRule
   1.158 +{
   1.159 +public:
   1.160 +  // nsISupports implementation
   1.161 +  NS_DECL_ISUPPORTS
   1.162 +
   1.163 +  // nsIStyleRule implementation
   1.164 +  virtual void MapRuleInfoInto(nsRuleData* aRuleData) MOZ_OVERRIDE;
   1.165 +#ifdef DEBUG
   1.166 +  virtual void List(FILE* out = stdout, int32_t aIndent = 0) const MOZ_OVERRIDE;
   1.167 +#endif
   1.168 +
   1.169 +  void AddValue(nsCSSProperty aProperty, nsStyleAnimation::Value &aStartValue)
   1.170 +  {
   1.171 +    PropertyValuePair v = { aProperty, aStartValue };
   1.172 +    mPropertyValuePairs.AppendElement(v);
   1.173 +  }
   1.174 +
   1.175 +  // Caller must fill in returned value.
   1.176 +  nsStyleAnimation::Value* AddEmptyValue(nsCSSProperty aProperty)
   1.177 +  {
   1.178 +    PropertyValuePair *p = mPropertyValuePairs.AppendElement();
   1.179 +    p->mProperty = aProperty;
   1.180 +    return &p->mValue;
   1.181 +  }
   1.182 +
   1.183 +  struct PropertyValuePair {
   1.184 +    nsCSSProperty mProperty;
   1.185 +    nsStyleAnimation::Value mValue;
   1.186 +  };
   1.187 +
   1.188 +private:
   1.189 +  InfallibleTArray<PropertyValuePair> mPropertyValuePairs;
   1.190 +};
   1.191 +
   1.192 +class ComputedTimingFunction {
   1.193 +public:
   1.194 +  typedef nsTimingFunction::Type Type;
   1.195 +  void Init(const nsTimingFunction &aFunction);
   1.196 +  double GetValue(double aPortion) const;
   1.197 +  const nsSMILKeySpline* GetFunction() const {
   1.198 +    NS_ASSERTION(mType == nsTimingFunction::Function, "Type mismatch");
   1.199 +    return &mTimingFunction;
   1.200 +  }
   1.201 +  Type GetType() const { return mType; }
   1.202 +  uint32_t GetSteps() const { return mSteps; }
   1.203 +private:
   1.204 +  Type mType;
   1.205 +  nsSMILKeySpline mTimingFunction;
   1.206 +  uint32_t mSteps;
   1.207 +};
   1.208 +
   1.209 +} /* end css sub-namespace */
   1.210 +
   1.211 +struct AnimationPropertySegment
   1.212 +{
   1.213 +  float mFromKey, mToKey;
   1.214 +  nsStyleAnimation::Value mFromValue, mToValue;
   1.215 +  mozilla::css::ComputedTimingFunction mTimingFunction;
   1.216 +};
   1.217 +
   1.218 +struct AnimationProperty
   1.219 +{
   1.220 +  nsCSSProperty mProperty;
   1.221 +  InfallibleTArray<AnimationPropertySegment> mSegments;
   1.222 +};
   1.223 +
   1.224 +/**
   1.225 + * Data about one animation (i.e., one of the values of
   1.226 + * 'animation-name') running on an element.
   1.227 + */
   1.228 +struct StyleAnimation
   1.229 +{
   1.230 +  StyleAnimation()
   1.231 +    : mIsRunningOnCompositor(false)
   1.232 +    , mLastNotification(LAST_NOTIFICATION_NONE)
   1.233 +  {
   1.234 +  }
   1.235 +
   1.236 +  nsString mName; // empty string for 'none'
   1.237 +  float mIterationCount; // NS_IEEEPositiveInfinity() means infinite
   1.238 +  uint8_t mDirection;
   1.239 +  uint8_t mFillMode;
   1.240 +  uint8_t mPlayState;
   1.241 +
   1.242 +  bool FillsForwards() const {
   1.243 +    return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH ||
   1.244 +           mFillMode == NS_STYLE_ANIMATION_FILL_MODE_FORWARDS;
   1.245 +  }
   1.246 +  bool FillsBackwards() const {
   1.247 +    return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH ||
   1.248 +           mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BACKWARDS;
   1.249 +  }
   1.250 +
   1.251 +  bool IsPaused() const {
   1.252 +    return mPlayState == NS_STYLE_ANIMATION_PLAY_STATE_PAUSED;
   1.253 +  }
   1.254 +
   1.255 +  bool HasAnimationOfProperty(nsCSSProperty aProperty) const;
   1.256 +  bool IsRunningAt(mozilla::TimeStamp aTime) const;
   1.257 +
   1.258 +  // Return the duration, at aTime (or, if paused, mPauseStart), since
   1.259 +  // the *end* of the delay period.  May be negative.
   1.260 +  mozilla::TimeDuration ElapsedDurationAt(mozilla::TimeStamp aTime) const {
   1.261 +    NS_ABORT_IF_FALSE(!IsPaused() || aTime >= mPauseStart,
   1.262 +                      "if paused, aTime must be at least mPauseStart");
   1.263 +    return (IsPaused() ? mPauseStart : aTime) - mStartTime - mDelay;
   1.264 +  }
   1.265 +
   1.266 +  // The beginning of the delay period.  This is also used by
   1.267 +  // ElementPropertyTransition in its IsRemovedSentinel and
   1.268 +  // SetRemovedSentinel methods.
   1.269 +  mozilla::TimeStamp mStartTime;
   1.270 +  mozilla::TimeStamp mPauseStart;
   1.271 +  mozilla::TimeDuration mDelay;
   1.272 +  mozilla::TimeDuration mIterationDuration;
   1.273 +  bool mIsRunningOnCompositor;
   1.274 +
   1.275 +  enum {
   1.276 +    LAST_NOTIFICATION_NONE = uint32_t(-1),
   1.277 +    LAST_NOTIFICATION_END = uint32_t(-2)
   1.278 +  };
   1.279 +  // One of the above constants, or an integer for the iteration
   1.280 +  // whose start we last notified on.
   1.281 +  uint32_t mLastNotification;
   1.282 +
   1.283 +  InfallibleTArray<AnimationProperty> mProperties;
   1.284 +};
   1.285 +
   1.286 +namespace css {
   1.287 +
   1.288 +struct CommonElementAnimationData : public PRCList
   1.289 +{
   1.290 +  CommonElementAnimationData(dom::Element *aElement, nsIAtom *aElementProperty,
   1.291 +                             CommonAnimationManager *aManager, TimeStamp aNow)
   1.292 +    : mElement(aElement)
   1.293 +    , mElementProperty(aElementProperty)
   1.294 +    , mManager(aManager)
   1.295 +    , mAnimationGeneration(0)
   1.296 +    , mFlushGeneration(aNow)
   1.297 +#ifdef DEBUG
   1.298 +    , mCalledPropertyDtor(false)
   1.299 +#endif
   1.300 +  {
   1.301 +    MOZ_COUNT_CTOR(CommonElementAnimationData);
   1.302 +    PR_INIT_CLIST(this);
   1.303 +  }
   1.304 +  ~CommonElementAnimationData()
   1.305 +  {
   1.306 +    NS_ABORT_IF_FALSE(mCalledPropertyDtor,
   1.307 +                      "must call destructor through element property dtor");
   1.308 +    MOZ_COUNT_DTOR(CommonElementAnimationData);
   1.309 +    PR_REMOVE_LINK(this);
   1.310 +    mManager->ElementDataRemoved();
   1.311 +  }
   1.312 +
   1.313 +  void Destroy()
   1.314 +  {
   1.315 +    // This will call our destructor.
   1.316 +    mElement->DeleteProperty(mElementProperty);
   1.317 +  }
   1.318 +
   1.319 +  bool CanThrottleTransformChanges(mozilla::TimeStamp aTime);
   1.320 +
   1.321 +  bool CanThrottleAnimation(mozilla::TimeStamp aTime);
   1.322 +
   1.323 +  enum CanAnimateFlags {
   1.324 +    // Testing for width, height, top, right, bottom, or left.
   1.325 +    CanAnimate_HasGeometricProperty = 1,
   1.326 +    // Allow the case where OMTA is allowed in general, but not for the
   1.327 +    // specified property.
   1.328 +    CanAnimate_AllowPartial = 2
   1.329 +  };
   1.330 +
   1.331 +  static bool
   1.332 +  CanAnimatePropertyOnCompositor(const dom::Element *aElement,
   1.333 +                                 nsCSSProperty aProperty,
   1.334 +                                 CanAnimateFlags aFlags);
   1.335 +
   1.336 +  static bool IsCompositorAnimationDisabledForFrame(nsIFrame* aFrame);
   1.337 +
   1.338 +  // True if this animation can be performed on the compositor thread.
   1.339 +  // Do not pass CanAnimate_AllowPartial to make sure that all properties of this
   1.340 +  // animation are supported by the compositor.
   1.341 +  virtual bool CanPerformOnCompositorThread(CanAnimateFlags aFlags) const = 0;
   1.342 +  virtual bool HasAnimationOfProperty(nsCSSProperty aProperty) const = 0;
   1.343 +
   1.344 +  static void LogAsyncAnimationFailure(nsCString& aMessage,
   1.345 +                                       const nsIContent* aContent = nullptr);
   1.346 +
   1.347 +  dom::Element *mElement;
   1.348 +
   1.349 +  // the atom we use in mElement's prop table (must be a static atom,
   1.350 +  // i.e., in an atom list)
   1.351 +  nsIAtom *mElementProperty;
   1.352 +
   1.353 +  CommonAnimationManager *mManager;
   1.354 +
   1.355 +  // This style rule contains the style data for currently animating
   1.356 +  // values.  It only matches when styling with animation.  When we
   1.357 +  // style without animation, we need to not use it so that we can
   1.358 +  // detect any new changes; if necessary we restyle immediately
   1.359 +  // afterwards with animation.
   1.360 +  // NOTE: If we don't need to apply any styles, mStyleRule will be
   1.361 +  // null, but mStyleRuleRefreshTime will still be valid.
   1.362 +  nsRefPtr<mozilla::css::AnimValuesStyleRule> mStyleRule;
   1.363 +
   1.364 +  // RestyleManager keeps track of the number of animation
   1.365 +  // 'mini-flushes' (see nsTransitionManager::UpdateAllThrottledStyles()).
   1.366 +  // mAnimationGeneration is the sequence number of the last flush where a
   1.367 +  // transition/animation changed.  We keep a similar count on the
   1.368 +  // corresponding layer so we can check that the layer is up to date with
   1.369 +  // the animation manager.
   1.370 +  uint64_t mAnimationGeneration;
   1.371 +  // Update mAnimationGeneration to nsCSSFrameConstructor's count
   1.372 +  void UpdateAnimationGeneration(nsPresContext* aPresContext);
   1.373 +
   1.374 +  // The refresh time associated with mStyleRule.
   1.375 +  TimeStamp mStyleRuleRefreshTime;
   1.376 +
   1.377 +  // Generation counter for flushes of throttled animations.
   1.378 +  // Used to prevent updating the styles twice for a given element during
   1.379 +  // UpdateAllThrottledStyles.
   1.380 +  TimeStamp mFlushGeneration;
   1.381 +
   1.382 +#ifdef DEBUG
   1.383 +  bool mCalledPropertyDtor;
   1.384 +#endif
   1.385 +};
   1.386 +
   1.387 +}
   1.388 +}
   1.389 +
   1.390 +#endif /* !defined(mozilla_css_AnimationCommon_h) */

mercurial