Bug 1085769: Merge RulesMatching, GetAnimationPlayers, and GetAnimationRule r=birtles

This commit is contained in:
David Zbarsky 2014-11-19 21:48:41 -05:00
parent bacb520ce5
commit 8498454656
7 changed files with 194 additions and 288 deletions

View File

@ -22,6 +22,7 @@
#include "nsDisplayList.h"
#include "mozilla/MemoryReporting.h"
#include "RestyleManager.h"
#include "nsRuleProcessorData.h"
#include "nsStyleSet.h"
#include "nsStyleChangeList.h"
@ -186,6 +187,50 @@ CommonAnimationManager::MediumFeaturesChanged(nsPresContext* aPresContext)
return false;
}
/* virtual */ void
CommonAnimationManager::RulesMatching(ElementRuleProcessorData* aData)
{
NS_ABORT_IF_FALSE(aData->mPresContext == mPresContext,
"pres context mismatch");
nsIStyleRule *rule =
GetAnimationRule(aData->mElement,
nsCSSPseudoElements::ePseudo_NotPseudoElement);
if (rule) {
aData->mRuleWalker->Forward(rule);
}
}
/* virtual */ void
CommonAnimationManager::RulesMatching(PseudoElementRuleProcessorData* aData)
{
NS_ABORT_IF_FALSE(aData->mPresContext == mPresContext,
"pres context mismatch");
if (aData->mPseudoType != nsCSSPseudoElements::ePseudo_before &&
aData->mPseudoType != nsCSSPseudoElements::ePseudo_after) {
return;
}
// FIXME: Do we really want to be the only thing keeping a
// pseudo-element alive? I *think* the non-animation restyle should
// handle that, but should add a test.
nsIStyleRule *rule = GetAnimationRule(aData->mElement, aData->mPseudoType);
if (rule) {
aData->mRuleWalker->Forward(rule);
}
}
/* virtual */ void
CommonAnimationManager::RulesMatching(AnonBoxRuleProcessorData* aData)
{
}
#ifdef MOZ_XUL
/* virtual */ void
CommonAnimationManager::RulesMatching(XULTreeRuleProcessorData* aData)
{
}
#endif
/* virtual */ size_t
CommonAnimationManager::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
@ -257,6 +302,106 @@ CommonAnimationManager::ExtractComputedValueForTransition(
return result;
}
AnimationPlayerCollection*
CommonAnimationManager::GetAnimationPlayers(dom::Element *aElement,
nsCSSPseudoElements::Type aPseudoType,
bool aCreateIfNeeded)
{
if (!aCreateIfNeeded && PR_CLIST_IS_EMPTY(&mElementCollections)) {
// Early return for the most common case.
return nullptr;
}
nsIAtom *propName;
if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) {
propName = GetAnimationsAtom();
} else if (aPseudoType == nsCSSPseudoElements::ePseudo_before) {
propName = GetAnimationsBeforeAtom();
} else if (aPseudoType == nsCSSPseudoElements::ePseudo_after) {
propName = GetAnimationsAfterAtom();
} else {
NS_ASSERTION(!aCreateIfNeeded,
"should never try to create transitions for pseudo "
"other than :before or :after");
return nullptr;
}
AnimationPlayerCollection* collection =
static_cast<AnimationPlayerCollection*>(aElement->GetProperty(propName));
if (!collection && aCreateIfNeeded) {
// FIXME: Consider arena-allocating?
collection =
new AnimationPlayerCollection(aElement, propName, this);
nsresult rv =
aElement->SetProperty(propName, collection,
&AnimationPlayerCollection::PropertyDtor, false);
if (NS_FAILED(rv)) {
NS_WARNING("SetProperty failed");
delete collection;
return nullptr;
}
if (propName == nsGkAtoms::animationsProperty ||
propName == nsGkAtoms::transitionsProperty) {
aElement->SetMayHaveAnimations();
}
AddElementCollection(collection);
}
return collection;
}
nsIStyleRule*
CommonAnimationManager::GetAnimationRule(mozilla::dom::Element* aElement,
nsCSSPseudoElements::Type aPseudoType)
{
NS_ABORT_IF_FALSE(
aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement ||
aPseudoType == nsCSSPseudoElements::ePseudo_before ||
aPseudoType == nsCSSPseudoElements::ePseudo_after,
"forbidden pseudo type");
if (!mPresContext->IsDynamic()) {
// For print or print preview, ignore animations.
return nullptr;
}
AnimationPlayerCollection* collection =
GetAnimationPlayers(aElement, aPseudoType, false);
if (!collection) {
return nullptr;
}
RestyleManager* restyleManager = mPresContext->RestyleManager();
if (restyleManager->SkipAnimationRules()) {
// During the non-animation part of processing restyles, we don't
// add the animation rule.
if (collection->mStyleRule && restyleManager->PostAnimationRestyles()) {
collection->PostRestyleForAnimation(mPresContext);
}
return nullptr;
}
// Animations should already be refreshed, but transitions may not be.
// Note that this is temporary, we would like both animations and transitions
// to both be refreshed by this point.
if (IsAnimationManager()) {
NS_WARN_IF_FALSE(!collection->mNeedsRefreshes ||
collection->mStyleRuleRefreshTime ==
mPresContext->RefreshDriver()->MostRecentRefresh(),
"should already have refreshed style rule");
} else {
// FIXME: Remove this assignment. See bug 1061364.
collection->mNeedsRefreshes = true;
collection->EnsureStyleRuleFor(
mPresContext->RefreshDriver()->MostRecentRefresh(),
EnsureStyleRule_IsNotThrottled);
}
return collection->mStyleRule;
}
/* static */ const CommonAnimationManager::LayerAnimationRecord
CommonAnimationManager::sLayerAnimationInfo[] =
{ { eCSSProperty_transform,

View File

@ -53,6 +53,12 @@ public:
virtual nsRestyleHint
HasAttributeDependentStyle(AttributeRuleProcessorData* aData) MOZ_OVERRIDE;
virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) MOZ_OVERRIDE;
virtual void RulesMatching(ElementRuleProcessorData* aData) MOZ_OVERRIDE;
virtual void RulesMatching(PseudoElementRuleProcessorData* aData) MOZ_OVERRIDE;
virtual void RulesMatching(AnonBoxRuleProcessorData* aData) MOZ_OVERRIDE;
#ifdef MOZ_XUL
virtual void RulesMatching(XULTreeRuleProcessorData* aData) MOZ_OVERRIDE;
#endif
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
const MOZ_MUST_OVERRIDE MOZ_OVERRIDE;
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
@ -68,10 +74,10 @@ public:
// elements.
void AddStyleUpdatesTo(mozilla::RestyleTracker& aTracker);
virtual AnimationPlayerCollection*
AnimationPlayerCollection*
GetAnimationPlayers(dom::Element *aElement,
nsCSSPseudoElements::Type aPseudoType,
bool aCreateIfNeeded) = 0;
bool aCreateIfNeeded);
// Notify this manager that one of its collections of animation players,
// has been updated.
@ -82,6 +88,9 @@ public:
Cannot_Throttle
};
nsIStyleRule* GetAnimationRule(mozilla::dom::Element* aElement,
nsCSSPseudoElements::Type aPseudoType);
static bool ExtractComputedValueForTransition(
nsCSSProperty aProperty,
nsStyleContext* aStyleContext,
@ -114,6 +123,14 @@ protected:
// Check to see if we should stop or start observing the refresh driver
void CheckNeedsRefresh();
virtual nsIAtom* GetAnimationsAtom() = 0;
virtual nsIAtom* GetAnimationsBeforeAtom() = 0;
virtual nsIAtom* GetAnimationsAfterAtom() = 0;
virtual bool IsAnimationManager() {
return false;
}
// When this returns a value other than nullptr, it also,
// as a side-effect, notifies the ActiveLayerTracker.
static AnimationPlayerCollection*

View File

@ -11,7 +11,6 @@
#include "mozilla/StyleAnimationValue.h"
#include "nsPresContext.h"
#include "nsRuleProcessorData.h"
#include "nsStyleSet.h"
#include "nsStyleChangeList.h"
#include "nsCSSRules.h"
@ -198,97 +197,6 @@ nsAnimationManager::QueueEvents(AnimationPlayerCollection* aCollection,
}
}
AnimationPlayerCollection*
nsAnimationManager::GetAnimationPlayers(dom::Element *aElement,
nsCSSPseudoElements::Type aPseudoType,
bool aCreateIfNeeded)
{
if (!aCreateIfNeeded && PR_CLIST_IS_EMPTY(&mElementCollections)) {
// Early return for the most common case.
return nullptr;
}
nsIAtom *propName;
if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) {
propName = nsGkAtoms::animationsProperty;
} else if (aPseudoType == nsCSSPseudoElements::ePseudo_before) {
propName = nsGkAtoms::animationsOfBeforeProperty;
} else if (aPseudoType == nsCSSPseudoElements::ePseudo_after) {
propName = nsGkAtoms::animationsOfAfterProperty;
} else {
NS_ASSERTION(!aCreateIfNeeded,
"should never try to create transitions for pseudo "
"other than :before or :after");
return nullptr;
}
AnimationPlayerCollection* collection =
static_cast<AnimationPlayerCollection*>(aElement->GetProperty(propName));
if (!collection && aCreateIfNeeded) {
// FIXME: Consider arena-allocating?
collection =
new AnimationPlayerCollection(aElement, propName, this);
nsresult rv =
aElement->SetProperty(propName, collection,
&AnimationPlayerCollection::PropertyDtor, false);
if (NS_FAILED(rv)) {
NS_WARNING("SetProperty failed");
delete collection;
return nullptr;
}
if (propName == nsGkAtoms::animationsProperty) {
aElement->SetMayHaveAnimations();
}
AddElementCollection(collection);
}
return collection;
}
/* virtual */ void
nsAnimationManager::RulesMatching(ElementRuleProcessorData* aData)
{
NS_ABORT_IF_FALSE(aData->mPresContext == mPresContext,
"pres context mismatch");
nsIStyleRule *rule =
GetAnimationRule(aData->mElement,
nsCSSPseudoElements::ePseudo_NotPseudoElement);
if (rule) {
aData->mRuleWalker->Forward(rule);
}
}
/* virtual */ void
nsAnimationManager::RulesMatching(PseudoElementRuleProcessorData* aData)
{
NS_ABORT_IF_FALSE(aData->mPresContext == mPresContext,
"pres context mismatch");
if (aData->mPseudoType != nsCSSPseudoElements::ePseudo_before &&
aData->mPseudoType != nsCSSPseudoElements::ePseudo_after) {
return;
}
// FIXME: Do we really want to be the only thing keeping a
// pseudo-element alive? I *think* the non-animation restyle should
// handle that, but should add a test.
nsIStyleRule *rule = GetAnimationRule(aData->mElement, aData->mPseudoType);
if (rule) {
aData->mRuleWalker->Forward(rule);
}
}
/* virtual */ void
nsAnimationManager::RulesMatching(AnonBoxRuleProcessorData* aData)
{
}
#ifdef MOZ_XUL
/* virtual */ void
nsAnimationManager::RulesMatching(XULTreeRuleProcessorData* aData)
{
}
#endif
/* virtual */ size_t
nsAnimationManager::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{
@ -729,47 +637,6 @@ nsAnimationManager::BuildSegment(InfallibleTArray<AnimationPropertySegment>&
return true;
}
nsIStyleRule*
nsAnimationManager::GetAnimationRule(mozilla::dom::Element* aElement,
nsCSSPseudoElements::Type aPseudoType)
{
NS_ABORT_IF_FALSE(
aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement ||
aPseudoType == nsCSSPseudoElements::ePseudo_before ||
aPseudoType == nsCSSPseudoElements::ePseudo_after,
"forbidden pseudo type");
if (!mPresContext->IsDynamic()) {
// For print or print preview, ignore animations.
return nullptr;
}
AnimationPlayerCollection* collection =
GetAnimationPlayers(aElement, aPseudoType, false);
if (!collection) {
return nullptr;
}
RestyleManager* restyleManager = mPresContext->RestyleManager();
if (restyleManager->SkipAnimationRules()) {
// During the non-animation part of processing restyles, we don't
// add the animation rule.
if (collection->mStyleRule && restyleManager->PostAnimationRestyles()) {
collection->PostRestyleForAnimation(mPresContext);
}
return nullptr;
}
NS_WARN_IF_FALSE(!collection->mNeedsRefreshes ||
collection->mStyleRuleRefreshTime ==
mPresContext->RefreshDriver()->MostRecentRefresh(),
"should already have refreshed style rule");
return collection->mStyleRule;
}
/* virtual */ void
nsAnimationManager::WillRefresh(mozilla::TimeStamp aTime)
{

View File

@ -179,12 +179,6 @@ public:
mozilla::EventArray &aEventsToDispatch);
// nsIStyleRuleProcessor (parts)
virtual void RulesMatching(ElementRuleProcessorData* aData) MOZ_OVERRIDE;
virtual void RulesMatching(PseudoElementRuleProcessorData* aData) MOZ_OVERRIDE;
virtual void RulesMatching(AnonBoxRuleProcessorData* aData) MOZ_OVERRIDE;
#ifdef MOZ_XUL
virtual void RulesMatching(XULTreeRuleProcessorData* aData) MOZ_OVERRIDE;
#endif
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
const MOZ_MUST_OVERRIDE MOZ_OVERRIDE;
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
@ -223,12 +217,19 @@ public:
}
}
virtual mozilla::AnimationPlayerCollection*
GetAnimationPlayers(mozilla::dom::Element *aElement,
nsCSSPseudoElements::Type aPseudoType,
bool aCreateIfNeeded) MOZ_OVERRIDE;
nsIStyleRule* GetAnimationRule(mozilla::dom::Element* aElement,
nsCSSPseudoElements::Type aPseudoType);
protected:
virtual nsIAtom* GetAnimationsAtom() MOZ_OVERRIDE {
return nsGkAtoms::animationsProperty;
}
virtual nsIAtom* GetAnimationsBeforeAtom() MOZ_OVERRIDE {
return nsGkAtoms::animationsOfBeforeProperty;
}
virtual nsIAtom* GetAnimationsAfterAtom() MOZ_OVERRIDE {
return nsGkAtoms::animationsOfAfterProperty;
}
virtual bool IsAnimationManager() MOZ_OVERRIDE {
return true;
}
private:
void BuildAnimations(nsStyleContext* aStyleContext,

View File

@ -1450,8 +1450,11 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement,
if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement ||
aPseudoType == nsCSSPseudoElements::ePseudo_before ||
aPseudoType == nsCSSPseudoElements::ePseudo_after) {
PresContext()->TransitionManager()->
WalkTransitionRule(aElement, aPseudoType, &ruleWalker);
nsIStyleRule* rule = PresContext()->TransitionManager()->
GetAnimationRule(aElement, aPseudoType);
if (rule) {
ruleWalker.ForwardOnPossiblyCSSRule(rule);
}
}
break;
}

View File

@ -436,7 +436,7 @@ nsTransitionManager::ConsiderStartingTransition(
"Should have one animation property segment for a transition");
if (haveCurrentTransition && haveValues &&
oldPT->Properties()[0].mSegments[0].mToValue == endValue) {
// WalkTransitionRule already called RestyleForAnimation.
// GetAnimationRule already called RestyleForAnimation.
return;
}
@ -460,7 +460,7 @@ nsTransitionManager::ConsiderStartingTransition(
// |aElementTransitions| is now a dangling pointer!
aElementTransitions = nullptr;
}
// WalkTransitionRule already called RestyleForAnimation.
// GetAnimationRule already called RestyleForAnimation.
}
return;
}
@ -579,133 +579,10 @@ nsTransitionManager::ConsiderStartingTransition(
aWhichStarted->AddProperty(aProperty);
}
AnimationPlayerCollection*
nsTransitionManager::GetAnimationPlayers(
dom::Element *aElement,
nsCSSPseudoElements::Type aPseudoType,
bool aCreateIfNeeded)
{
if (!aCreateIfNeeded && PR_CLIST_IS_EMPTY(&mElementCollections)) {
// Early return for the most common case.
return nullptr;
}
nsIAtom *propName;
if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) {
propName = nsGkAtoms::transitionsProperty;
} else if (aPseudoType == nsCSSPseudoElements::ePseudo_before) {
propName = nsGkAtoms::transitionsOfBeforeProperty;
} else if (aPseudoType == nsCSSPseudoElements::ePseudo_after) {
propName = nsGkAtoms::transitionsOfAfterProperty;
} else {
NS_ASSERTION(!aCreateIfNeeded,
"should never try to create transitions for pseudo "
"other than :before or :after");
return nullptr;
}
AnimationPlayerCollection* collection =
static_cast<AnimationPlayerCollection*>(aElement->GetProperty(propName));
if (!collection && aCreateIfNeeded) {
// FIXME: Consider arena-allocating?
collection = new AnimationPlayerCollection(aElement, propName, this);
nsresult rv =
aElement->SetProperty(propName, collection,
&AnimationPlayerCollection::PropertyDtor, false);
if (NS_FAILED(rv)) {
NS_WARNING("SetProperty failed");
delete collection;
return nullptr;
}
if (propName == nsGkAtoms::transitionsProperty) {
aElement->SetMayHaveAnimations();
}
AddElementCollection(collection);
}
return collection;
}
/*
* nsIStyleRuleProcessor implementation
*/
void
nsTransitionManager::WalkTransitionRule(dom::Element* aElement,
nsCSSPseudoElements::Type aPseudoType,
nsRuleWalker* aRuleWalker)
{
AnimationPlayerCollection* collection =
GetAnimationPlayers(aElement, aPseudoType, false);
if (!collection) {
return;
}
if (!mPresContext->IsDynamic()) {
// For print or print preview, ignore animations.
return;
}
RestyleManager* restyleManager = mPresContext->RestyleManager();
if (restyleManager->SkipAnimationRules()) {
// If we're processing a normal style change rather than one from
// animation, don't add the transition rule. This allows us to
// compute the new style value rather than having the transition
// override it, so that we can start transitioning differently.
if (restyleManager->PostAnimationRestyles()) {
// We need to immediately restyle with animation
// after doing this.
collection->PostRestyleForAnimation(mPresContext);
}
return;
}
collection->mNeedsRefreshes = true;
collection->EnsureStyleRuleFor(
mPresContext->RefreshDriver()->MostRecentRefresh(),
EnsureStyleRule_IsNotThrottled);
if (collection->mStyleRule) {
aRuleWalker->Forward(collection->mStyleRule);
}
}
/* virtual */ void
nsTransitionManager::RulesMatching(ElementRuleProcessorData* aData)
{
NS_ABORT_IF_FALSE(aData->mPresContext == mPresContext,
"pres context mismatch");
WalkTransitionRule(aData->mElement,
nsCSSPseudoElements::ePseudo_NotPseudoElement,
aData->mRuleWalker);
}
/* virtual */ void
nsTransitionManager::RulesMatching(PseudoElementRuleProcessorData* aData)
{
NS_ABORT_IF_FALSE(aData->mPresContext == mPresContext,
"pres context mismatch");
// Note: If we're the only thing keeping a pseudo-element frame alive
// (per ProbePseudoStyleContext), we still want to keep it alive, so
// this is ok.
WalkTransitionRule(aData->mElement, aData->mPseudoType,
aData->mRuleWalker);
}
/* virtual */ void
nsTransitionManager::RulesMatching(AnonBoxRuleProcessorData* aData)
{
}
#ifdef MOZ_XUL
/* virtual */ void
nsTransitionManager::RulesMatching(XULTreeRuleProcessorData* aData)
{
}
#endif
/* virtual */ size_t
nsTransitionManager::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{

View File

@ -148,13 +148,6 @@ public:
mInAnimationOnlyStyleUpdate = aInAnimationOnlyUpdate;
}
// nsIStyleRuleProcessor (parts)
virtual void RulesMatching(ElementRuleProcessorData* aData) MOZ_OVERRIDE;
virtual void RulesMatching(PseudoElementRuleProcessorData* aData) MOZ_OVERRIDE;
virtual void RulesMatching(AnonBoxRuleProcessorData* aData) MOZ_OVERRIDE;
#ifdef MOZ_XUL
virtual void RulesMatching(XULTreeRuleProcessorData* aData) MOZ_OVERRIDE;
#endif
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
MOZ_MUST_OVERRIDE MOZ_OVERRIDE;
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
@ -165,13 +158,16 @@ public:
void FlushTransitions(FlushFlags aFlags);
virtual AnimationPlayerCollection*
GetAnimationPlayers(mozilla::dom::Element *aElement,
nsCSSPseudoElements::Type aPseudoType,
bool aCreateIfNeeded) MOZ_OVERRIDE;
void WalkTransitionRule(mozilla::dom::Element* aElement,
nsCSSPseudoElements::Type aPseudoType,
nsRuleWalker* aRuleWalker);
protected:
virtual nsIAtom* GetAnimationsAtom() MOZ_OVERRIDE {
return nsGkAtoms::transitionsProperty;
}
virtual nsIAtom* GetAnimationsBeforeAtom() MOZ_OVERRIDE {
return nsGkAtoms::transitionsOfBeforeProperty;
}
virtual nsIAtom* GetAnimationsAfterAtom() MOZ_OVERRIDE {
return nsGkAtoms::transitionsOfAfterProperty;
}
private:
void