layout/style/AnimationCommon.h

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     1 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
     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 mozilla_css_AnimationCommon_h
     7 #define mozilla_css_AnimationCommon_h
     9 #include "nsIStyleRuleProcessor.h"
    10 #include "nsIStyleRule.h"
    11 #include "nsRefreshDriver.h"
    12 #include "prclist.h"
    13 #include "nsStyleAnimation.h"
    14 #include "nsCSSProperty.h"
    15 #include "mozilla/MemoryReporting.h"
    16 #include "mozilla/dom/Element.h"
    17 #include "nsSMILKeySpline.h"
    18 #include "nsStyleStruct.h"
    19 #include "mozilla/Attributes.h"
    20 #include "nsCSSPseudoElements.h"
    22 class nsPresContext;
    23 class nsIFrame;
    26 namespace mozilla {
    27 namespace css {
    29 bool IsGeometricProperty(nsCSSProperty aProperty);
    31 struct CommonElementAnimationData;
    33 class CommonAnimationManager : public nsIStyleRuleProcessor,
    34                                public nsARefreshObserver {
    35 public:
    36   CommonAnimationManager(nsPresContext *aPresContext);
    37   virtual ~CommonAnimationManager();
    39   // nsISupports
    40   NS_DECL_ISUPPORTS
    42   // nsIStyleRuleProcessor (parts)
    43   virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData) MOZ_OVERRIDE;
    44   virtual nsRestyleHint HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) MOZ_OVERRIDE;
    45   virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) MOZ_OVERRIDE;
    46   virtual nsRestyleHint
    47     HasAttributeDependentStyle(AttributeRuleProcessorData* aData) MOZ_OVERRIDE;
    48   virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) MOZ_OVERRIDE;
    49   virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
    50     const MOZ_MUST_OVERRIDE MOZ_OVERRIDE;
    51   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
    52     const MOZ_MUST_OVERRIDE MOZ_OVERRIDE;
    54   /**
    55    * Notify the manager that the pres context is going away.
    56    */
    57   void Disconnect();
    59   enum FlushFlags {
    60     Can_Throttle,
    61     Cannot_Throttle
    62   };
    64   static bool ExtractComputedValueForTransition(
    65                   nsCSSProperty aProperty,
    66                   nsStyleContext* aStyleContext,
    67                   nsStyleAnimation::Value& aComputedValue);
    68 protected:
    69   friend struct CommonElementAnimationData; // for ElementDataRemoved
    71   virtual void AddElementData(CommonElementAnimationData* aData) = 0;
    72   virtual void ElementDataRemoved() = 0;
    73   void RemoveAllElementData();
    75   // Update the style on aElement from the transition stored in this manager and
    76   // the new parent style - aParentStyle. aElement must be transitioning or
    77   // animated. Returns the updated style.
    78   nsStyleContext* UpdateThrottledStyle(mozilla::dom::Element* aElement,
    79                                        nsStyleContext* aParentStyle,
    80                                        nsStyleChangeList &aChangeList);
    81   // Reparent the style of aContent and any :before and :after pseudo-elements.
    82   already_AddRefed<nsStyleContext> ReparentContent(nsIContent* aContent,
    83                                                   nsStyleContext* aParentStyle);
    84   // reparent :before and :after pseudo elements of aElement
    85   static void ReparentBeforeAndAfter(dom::Element* aElement,
    86                                      nsIFrame* aPrimaryFrame,
    87                                      nsStyleContext* aNewStyle,
    88                                      nsStyleSet* aStyleSet);
    90   PRCList mElementData;
    91   nsPresContext *mPresContext; // weak (non-null from ctor to Disconnect)
    92 };
    94 // The internals of UpdateAllThrottledStyles, used by nsAnimationManager and
    95 // nsTransitionManager, see the comments in the declaration of the latter.
    96 #define IMPL_UPDATE_ALL_THROTTLED_STYLES_INTERNAL(class_, animations_getter_)  \
    97 void                                                                           \
    98 class_::UpdateAllThrottledStylesInternal()                                     \
    99 {                                                                              \
   100   TimeStamp now = mPresContext->RefreshDriver()->MostRecentRefresh();          \
   101                                                                                \
   102   nsStyleChangeList changeList;                                                \
   103                                                                                \
   104   /* update each transitioning element by finding its root-most ancestor
   105      with a transition, and flushing the style on that ancestor and all
   106      its descendants*/                                                         \
   107   PRCList *next = PR_LIST_HEAD(&mElementData);                                 \
   108   while (next != &mElementData) {                                              \
   109     CommonElementAnimationData* ea =                                           \
   110       static_cast<CommonElementAnimationData*>(next);                          \
   111     next = PR_NEXT_LINK(next);                                                 \
   112                                                                                \
   113     if (ea->mFlushGeneration == now) {                                         \
   114       /* this element has been ticked already */                               \
   115       continue;                                                                \
   116     }                                                                          \
   117                                                                                \
   118     /* element is initialised to the starting element (i.e., one we know has
   119        an animation) and ends up with the root-most animated ancestor,
   120        that is, the element where we begin updates. */                         \
   121     dom::Element* element = ea->mElement;                                      \
   122     /* make a list of ancestors */                                             \
   123     nsTArray<dom::Element*> ancestors;                                         \
   124     do {                                                                       \
   125       ancestors.AppendElement(element);                                        \
   126     } while ((element = element->GetParentElement()));                         \
   127                                                                                \
   128     /* walk down the ancestors until we find one with a throttled transition */\
   129     for (int32_t i = ancestors.Length() - 1; i >= 0; --i) {                    \
   130       if (animations_getter_(ancestors[i],                                     \
   131                             nsCSSPseudoElements::ePseudo_NotPseudoElement,     \
   132                             false)) {                                          \
   133         element = ancestors[i];                                                \
   134         break;                                                                 \
   135       }                                                                        \
   136     }                                                                          \
   137                                                                                \
   138     nsIFrame* primaryFrame;                                                    \
   139     if (element &&                                                             \
   140         (primaryFrame = nsLayoutUtils::GetStyleFrame(element))) {              \
   141       UpdateThrottledStylesForSubtree(element,                                 \
   142         primaryFrame->StyleContext()->GetParent(), changeList);                \
   143     }                                                                          \
   144   }                                                                            \
   145                                                                                \
   146   RestyleManager* restyleManager = mPresContext->RestyleManager();             \
   147   restyleManager->ProcessRestyledFrames(changeList);                           \
   148   restyleManager->FlushOverflowChangedTracker();                               \
   149 }
   151 /**
   152  * A style rule that maps property-nsStyleAnimation::Value pairs.
   153  */
   154 class AnimValuesStyleRule MOZ_FINAL : public nsIStyleRule
   155 {
   156 public:
   157   // nsISupports implementation
   158   NS_DECL_ISUPPORTS
   160   // nsIStyleRule implementation
   161   virtual void MapRuleInfoInto(nsRuleData* aRuleData) MOZ_OVERRIDE;
   162 #ifdef DEBUG
   163   virtual void List(FILE* out = stdout, int32_t aIndent = 0) const MOZ_OVERRIDE;
   164 #endif
   166   void AddValue(nsCSSProperty aProperty, nsStyleAnimation::Value &aStartValue)
   167   {
   168     PropertyValuePair v = { aProperty, aStartValue };
   169     mPropertyValuePairs.AppendElement(v);
   170   }
   172   // Caller must fill in returned value.
   173   nsStyleAnimation::Value* AddEmptyValue(nsCSSProperty aProperty)
   174   {
   175     PropertyValuePair *p = mPropertyValuePairs.AppendElement();
   176     p->mProperty = aProperty;
   177     return &p->mValue;
   178   }
   180   struct PropertyValuePair {
   181     nsCSSProperty mProperty;
   182     nsStyleAnimation::Value mValue;
   183   };
   185 private:
   186   InfallibleTArray<PropertyValuePair> mPropertyValuePairs;
   187 };
   189 class ComputedTimingFunction {
   190 public:
   191   typedef nsTimingFunction::Type Type;
   192   void Init(const nsTimingFunction &aFunction);
   193   double GetValue(double aPortion) const;
   194   const nsSMILKeySpline* GetFunction() const {
   195     NS_ASSERTION(mType == nsTimingFunction::Function, "Type mismatch");
   196     return &mTimingFunction;
   197   }
   198   Type GetType() const { return mType; }
   199   uint32_t GetSteps() const { return mSteps; }
   200 private:
   201   Type mType;
   202   nsSMILKeySpline mTimingFunction;
   203   uint32_t mSteps;
   204 };
   206 } /* end css sub-namespace */
   208 struct AnimationPropertySegment
   209 {
   210   float mFromKey, mToKey;
   211   nsStyleAnimation::Value mFromValue, mToValue;
   212   mozilla::css::ComputedTimingFunction mTimingFunction;
   213 };
   215 struct AnimationProperty
   216 {
   217   nsCSSProperty mProperty;
   218   InfallibleTArray<AnimationPropertySegment> mSegments;
   219 };
   221 /**
   222  * Data about one animation (i.e., one of the values of
   223  * 'animation-name') running on an element.
   224  */
   225 struct StyleAnimation
   226 {
   227   StyleAnimation()
   228     : mIsRunningOnCompositor(false)
   229     , mLastNotification(LAST_NOTIFICATION_NONE)
   230   {
   231   }
   233   nsString mName; // empty string for 'none'
   234   float mIterationCount; // NS_IEEEPositiveInfinity() means infinite
   235   uint8_t mDirection;
   236   uint8_t mFillMode;
   237   uint8_t mPlayState;
   239   bool FillsForwards() const {
   240     return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH ||
   241            mFillMode == NS_STYLE_ANIMATION_FILL_MODE_FORWARDS;
   242   }
   243   bool FillsBackwards() const {
   244     return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH ||
   245            mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BACKWARDS;
   246   }
   248   bool IsPaused() const {
   249     return mPlayState == NS_STYLE_ANIMATION_PLAY_STATE_PAUSED;
   250   }
   252   bool HasAnimationOfProperty(nsCSSProperty aProperty) const;
   253   bool IsRunningAt(mozilla::TimeStamp aTime) const;
   255   // Return the duration, at aTime (or, if paused, mPauseStart), since
   256   // the *end* of the delay period.  May be negative.
   257   mozilla::TimeDuration ElapsedDurationAt(mozilla::TimeStamp aTime) const {
   258     NS_ABORT_IF_FALSE(!IsPaused() || aTime >= mPauseStart,
   259                       "if paused, aTime must be at least mPauseStart");
   260     return (IsPaused() ? mPauseStart : aTime) - mStartTime - mDelay;
   261   }
   263   // The beginning of the delay period.  This is also used by
   264   // ElementPropertyTransition in its IsRemovedSentinel and
   265   // SetRemovedSentinel methods.
   266   mozilla::TimeStamp mStartTime;
   267   mozilla::TimeStamp mPauseStart;
   268   mozilla::TimeDuration mDelay;
   269   mozilla::TimeDuration mIterationDuration;
   270   bool mIsRunningOnCompositor;
   272   enum {
   273     LAST_NOTIFICATION_NONE = uint32_t(-1),
   274     LAST_NOTIFICATION_END = uint32_t(-2)
   275   };
   276   // One of the above constants, or an integer for the iteration
   277   // whose start we last notified on.
   278   uint32_t mLastNotification;
   280   InfallibleTArray<AnimationProperty> mProperties;
   281 };
   283 namespace css {
   285 struct CommonElementAnimationData : public PRCList
   286 {
   287   CommonElementAnimationData(dom::Element *aElement, nsIAtom *aElementProperty,
   288                              CommonAnimationManager *aManager, TimeStamp aNow)
   289     : mElement(aElement)
   290     , mElementProperty(aElementProperty)
   291     , mManager(aManager)
   292     , mAnimationGeneration(0)
   293     , mFlushGeneration(aNow)
   294 #ifdef DEBUG
   295     , mCalledPropertyDtor(false)
   296 #endif
   297   {
   298     MOZ_COUNT_CTOR(CommonElementAnimationData);
   299     PR_INIT_CLIST(this);
   300   }
   301   ~CommonElementAnimationData()
   302   {
   303     NS_ABORT_IF_FALSE(mCalledPropertyDtor,
   304                       "must call destructor through element property dtor");
   305     MOZ_COUNT_DTOR(CommonElementAnimationData);
   306     PR_REMOVE_LINK(this);
   307     mManager->ElementDataRemoved();
   308   }
   310   void Destroy()
   311   {
   312     // This will call our destructor.
   313     mElement->DeleteProperty(mElementProperty);
   314   }
   316   bool CanThrottleTransformChanges(mozilla::TimeStamp aTime);
   318   bool CanThrottleAnimation(mozilla::TimeStamp aTime);
   320   enum CanAnimateFlags {
   321     // Testing for width, height, top, right, bottom, or left.
   322     CanAnimate_HasGeometricProperty = 1,
   323     // Allow the case where OMTA is allowed in general, but not for the
   324     // specified property.
   325     CanAnimate_AllowPartial = 2
   326   };
   328   static bool
   329   CanAnimatePropertyOnCompositor(const dom::Element *aElement,
   330                                  nsCSSProperty aProperty,
   331                                  CanAnimateFlags aFlags);
   333   static bool IsCompositorAnimationDisabledForFrame(nsIFrame* aFrame);
   335   // True if this animation can be performed on the compositor thread.
   336   // Do not pass CanAnimate_AllowPartial to make sure that all properties of this
   337   // animation are supported by the compositor.
   338   virtual bool CanPerformOnCompositorThread(CanAnimateFlags aFlags) const = 0;
   339   virtual bool HasAnimationOfProperty(nsCSSProperty aProperty) const = 0;
   341   static void LogAsyncAnimationFailure(nsCString& aMessage,
   342                                        const nsIContent* aContent = nullptr);
   344   dom::Element *mElement;
   346   // the atom we use in mElement's prop table (must be a static atom,
   347   // i.e., in an atom list)
   348   nsIAtom *mElementProperty;
   350   CommonAnimationManager *mManager;
   352   // This style rule contains the style data for currently animating
   353   // values.  It only matches when styling with animation.  When we
   354   // style without animation, we need to not use it so that we can
   355   // detect any new changes; if necessary we restyle immediately
   356   // afterwards with animation.
   357   // NOTE: If we don't need to apply any styles, mStyleRule will be
   358   // null, but mStyleRuleRefreshTime will still be valid.
   359   nsRefPtr<mozilla::css::AnimValuesStyleRule> mStyleRule;
   361   // RestyleManager keeps track of the number of animation
   362   // 'mini-flushes' (see nsTransitionManager::UpdateAllThrottledStyles()).
   363   // mAnimationGeneration is the sequence number of the last flush where a
   364   // transition/animation changed.  We keep a similar count on the
   365   // corresponding layer so we can check that the layer is up to date with
   366   // the animation manager.
   367   uint64_t mAnimationGeneration;
   368   // Update mAnimationGeneration to nsCSSFrameConstructor's count
   369   void UpdateAnimationGeneration(nsPresContext* aPresContext);
   371   // The refresh time associated with mStyleRule.
   372   TimeStamp mStyleRuleRefreshTime;
   374   // Generation counter for flushes of throttled animations.
   375   // Used to prevent updating the styles twice for a given element during
   376   // UpdateAllThrottledStyles.
   377   TimeStamp mFlushGeneration;
   379 #ifdef DEBUG
   380   bool mCalledPropertyDtor;
   381 #endif
   382 };
   384 }
   385 }
   387 #endif /* !defined(mozilla_css_AnimationCommon_h) */

mercurial