layout/style/AnimationCommon.h

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

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

mercurial