Bug 1234095 - Rework sorting to handle to script-generated animations; r=heycam

This commit is contained in:
Brian Birtles 2016-01-14 10:24:24 +09:00
parent c3523a2cbf
commit 901a37e215
6 changed files with 78 additions and 64 deletions

View File

@ -11,11 +11,13 @@
#include "mozilla/AutoRestore.h"
#include "mozilla/AsyncEventDispatcher.h" // For AsyncEventDispatcher
#include "mozilla/Maybe.h" // For Maybe
#include "nsAnimationManager.h" // For CSSAnimation
#include "nsDOMMutationObserver.h" // For nsAutoAnimationMutationBatch
#include "nsIDocument.h" // For nsIDocument
#include "nsIPresShell.h" // For nsIPresShell
#include "nsLayoutUtils.h" // For PostRestyleEvent (remove after bug 1073336)
#include "nsThreadUtils.h" // For nsRunnableMethod and nsRevocableEventPtr
#include "nsTransitionManager.h" // For CSSTransition
#include "PendingAnimationTracker.h" // For PendingAnimationTracker
namespace mozilla {
@ -667,14 +669,58 @@ Animation::UpdateRelevance()
bool
Animation::HasLowerCompositeOrderThan(const Animation& aOther) const
{
// Due to the way subclasses of this repurpose the mAnimationIndex to
// implement their own brand of composite ordering it is possible for
// two animations to have an identical mAnimationIndex member.
// However, these subclasses override this method so we shouldn't see
// identical animation indices here.
MOZ_ASSERT(mAnimationIndex != aOther.mAnimationIndex || &aOther == this,
// 0. Object-equality case
if (&aOther == this) {
return false;
}
// 1. CSS Transitions sort lowest
{
auto asCSSTransitionForSorting =
[] (const Animation& anim) -> const CSSTransition*
{
const CSSTransition* transition = anim.AsCSSTransition();
return transition && transition->IsTiedToMarkup() ?
transition :
nullptr;
};
auto thisTransition = asCSSTransitionForSorting(*this);
auto otherTransition = asCSSTransitionForSorting(aOther);
if (thisTransition && otherTransition) {
return thisTransition->HasLowerCompositeOrderThan(*otherTransition);
}
if (thisTransition || otherTransition) {
return thisTransition;
}
}
// 2. CSS Animations sort next
{
auto asCSSAnimationForSorting =
[] (const Animation& anim) -> const CSSAnimation*
{
const CSSAnimation* animation = anim.AsCSSAnimation();
return animation && animation->IsTiedToMarkup() ? animation : nullptr;
};
auto thisAnimation = asCSSAnimationForSorting(*this);
auto otherAnimation = asCSSAnimationForSorting(aOther);
if (thisAnimation && otherAnimation) {
return thisAnimation->HasLowerCompositeOrderThan(*otherAnimation);
}
if (thisAnimation || otherAnimation) {
return thisAnimation;
}
}
// Subclasses of Animation repurpose mAnimationIndex to implement their
// own brand of composite ordering. However, by this point we should have
// handled any such custom composite ordering so we should now have unique
// animation indices.
MOZ_ASSERT(mAnimationIndex != aOther.mAnimationIndex,
"Animation indices should be unique");
// 3. Finally, generic animations sort by their position in the global
// animation array.
return mAnimationIndex < aOther.mAnimationIndex;
}

View File

@ -283,7 +283,7 @@ public:
/**
* Returns true if this Animation has a lower composite order than aOther.
*/
virtual bool HasLowerCompositeOrderThan(const Animation& aOther) const;
bool HasLowerCompositeOrderThan(const Animation& aOther) const;
/**
* Returns the level at which the effect(s) associated with this Animation

View File

@ -124,43 +124,24 @@ CSSAnimation::Tick()
}
bool
CSSAnimation::HasLowerCompositeOrderThan(const Animation& aOther) const
CSSAnimation::HasLowerCompositeOrderThan(const CSSAnimation& aOther) const
{
MOZ_ASSERT(IsTiedToMarkup() && aOther.IsTiedToMarkup(),
"Should only be called for CSS animations that are sorted "
"as CSS animations (i.e. tied to CSS markup)");
// 0. Object-equality case
if (&aOther == this) {
return false;
}
// 1. Transitions sort lower
//
// FIXME: We need to differentiate between transitions and generic Animations.
// Generic animations don't exist yet (that's bug 1096773) so for now we're
// ok.
const CSSAnimation* otherAnimation = aOther.AsCSSAnimation();
if (!otherAnimation) {
MOZ_ASSERT(aOther.AsCSSTransition(),
"Animation being compared is a CSS transition");
return false;
// 1. Sort by document order
if (!mOwningElement.Equals(aOther.mOwningElement)) {
return mOwningElement.LessThan(aOther.mOwningElement);
}
// 2. CSS animations that correspond to an animation-name property sort lower
// than other CSS animations (e.g. those created or kept-alive by script).
if (!IsTiedToMarkup()) {
return !otherAnimation->IsTiedToMarkup() ?
Animation::HasLowerCompositeOrderThan(aOther) :
false;
}
if (!otherAnimation->IsTiedToMarkup()) {
return true;
}
// 3. Sort by document order
if (!mOwningElement.Equals(otherAnimation->mOwningElement)) {
return mOwningElement.LessThan(otherAnimation->mOwningElement);
}
// 4. (Same element and pseudo): Sort by position in animation-name
return mAnimationIndex < otherAnimation->mAnimationIndex;
// 2. (Same element and pseudo): Sort by position in animation-name
return mAnimationIndex < aOther.mAnimationIndex;
}
void

View File

@ -130,7 +130,7 @@ public:
bool IsStylePaused() const { return mIsStylePaused; }
bool HasLowerCompositeOrderThan(const Animation& aOther) const override;
bool HasLowerCompositeOrderThan(const CSSAnimation& aOther) const;
void SetAnimationIndex(uint64_t aIndex)
{

View File

@ -175,43 +175,30 @@ CSSTransition::TransitionProperty() const
}
bool
CSSTransition::HasLowerCompositeOrderThan(const Animation& aOther) const
CSSTransition::HasLowerCompositeOrderThan(const CSSTransition& aOther) const
{
MOZ_ASSERT(IsTiedToMarkup() && aOther.IsTiedToMarkup(),
"Should only be called for CSS transitions that are sorted "
"as CSS transitions (i.e. tied to CSS markup)");
// 0. Object-equality case
if (&aOther == this) {
return false;
}
// 1. Transitions sort lowest
const CSSTransition* otherTransition = aOther.AsCSSTransition();
if (!otherTransition) {
return true;
// 1. Sort by document order
if (!mOwningElement.Equals(aOther.mOwningElement)) {
return mOwningElement.LessThan(aOther.mOwningElement);
}
// 2. CSS transitions that correspond to a transition-property property sort
// lower than CSS transitions owned by script.
if (!IsTiedToMarkup()) {
return !otherTransition->IsTiedToMarkup() ?
Animation::HasLowerCompositeOrderThan(aOther) :
false;
}
if (!otherTransition->IsTiedToMarkup()) {
return true;
// 2. (Same element and pseudo): Sort by transition generation
if (mAnimationIndex != aOther.mAnimationIndex) {
return mAnimationIndex < aOther.mAnimationIndex;
}
// 3. Sort by document order
if (!mOwningElement.Equals(otherTransition->mOwningElement)) {
return mOwningElement.LessThan(otherTransition->mOwningElement);
}
// 4. (Same element and pseudo): Sort by transition generation
if (mAnimationIndex != otherTransition->mAnimationIndex) {
return mAnimationIndex < otherTransition->mAnimationIndex;
}
// 5. (Same transition generation): Sort by transition property
// 3. (Same transition generation): Sort by transition property
return nsCSSProps::GetStringValue(TransitionProperty()) <
nsCSSProps::GetStringValue(otherTransition->TransitionProperty());
nsCSSProps::GetStringValue(aOther.TransitionProperty());
}
////////////////////////// nsTransitionManager ////////////////////////////

View File

@ -138,7 +138,7 @@ public:
nsCSSProperty TransitionProperty() const;
bool HasLowerCompositeOrderThan(const Animation& aOther) const override;
bool HasLowerCompositeOrderThan(const CSSTransition& aOther) const;
EffectCompositor::CascadeLevel CascadeLevel() const override
{
return IsTiedToMarkup() ?