Refactor some parts of nsTransitionManager into common base class to be shared with AnimationManager. (Bug 435442, patch 7) r=bzbarsky

This commit is contained in:
L. David Baron 2011-04-11 23:18:43 -07:00
parent 914379bb82
commit 32f7f568a9
5 changed files with 443 additions and 303 deletions

View File

@ -0,0 +1,231 @@
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is AnimationCommon, common animation code for transitions
* and animations.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "AnimationCommon.h"
#include "nsRuleData.h"
#include "nsCSSValue.h"
#include "nsStyleContext.h"
namespace mozilla {
namespace css {
CommonAnimationManager::CommonAnimationManager(nsPresContext *aPresContext)
: mPresContext(aPresContext)
{
PR_INIT_CLIST(&mElementData);
}
CommonAnimationManager::~CommonAnimationManager()
{
NS_ABORT_IF_FALSE(!mPresContext, "Disconnect should have been called");
}
void
CommonAnimationManager::Disconnect()
{
// Content nodes might outlive the transition or animation manager.
RemoveAllElementData();
mPresContext = nsnull;
}
void
CommonAnimationManager::AddElementData(CommonElementAnimationData* aData)
{
if (PR_CLIST_IS_EMPTY(&mElementData)) {
// We need to observe the refresh driver.
nsRefreshDriver *rd = mPresContext->RefreshDriver();
rd->AddRefreshObserver(this, Flush_Style);
}
PR_INSERT_BEFORE(aData, &mElementData);
}
void
CommonAnimationManager::ElementDataRemoved()
{
// If we have no transitions or animations left, remove ourselves from
// the refresh driver.
if (PR_CLIST_IS_EMPTY(&mElementData)) {
mPresContext->RefreshDriver()->RemoveRefreshObserver(this, Flush_Style);
}
}
void
CommonAnimationManager::RemoveAllElementData()
{
while (!PR_CLIST_IS_EMPTY(&mElementData)) {
CommonElementAnimationData *head =
static_cast<CommonElementAnimationData*>(PR_LIST_HEAD(&mElementData));
head->Destroy();
}
}
/*
* nsISupports implementation
*/
NS_IMPL_ISUPPORTS1(CommonAnimationManager, nsIStyleRuleProcessor)
nsRestyleHint
CommonAnimationManager::HasStateDependentStyle(StateRuleProcessorData* aData)
{
return nsRestyleHint(0);
}
PRBool
CommonAnimationManager::HasDocumentStateDependentStyle(StateRuleProcessorData* aData)
{
return PR_FALSE;
}
nsRestyleHint
CommonAnimationManager::HasAttributeDependentStyle(AttributeRuleProcessorData* aData)
{
return nsRestyleHint(0);
}
/* virtual */ PRBool
CommonAnimationManager::MediumFeaturesChanged(nsPresContext* aPresContext)
{
return PR_FALSE;
}
/* static */ PRBool
CommonAnimationManager::ExtractComputedValueForTransition(
nsCSSProperty aProperty,
nsStyleContext* aStyleContext,
nsStyleAnimation::Value& aComputedValue)
{
PRBool result =
nsStyleAnimation::ExtractComputedValue(aProperty, aStyleContext,
aComputedValue);
if (aProperty == eCSSProperty_visibility) {
NS_ABORT_IF_FALSE(aComputedValue.GetUnit() ==
nsStyleAnimation::eUnit_Enumerated,
"unexpected unit");
aComputedValue.SetIntValue(aComputedValue.GetIntValue(),
nsStyleAnimation::eUnit_Visibility);
}
return result;
}
NS_IMPL_ISUPPORTS1(AnimValuesStyleRule, nsIStyleRule)
/* virtual */ void
AnimValuesStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
{
nsStyleContext *contextParent = aRuleData->mStyleContext->GetParent();
if (contextParent && contextParent->HasPseudoElementData()) {
// Don't apply transitions or animations to things inside of
// pseudo-elements.
// FIXME (Bug 522599): Add tests for this.
return;
}
for (PRUint32 i = 0, i_end = mPropertyValuePairs.Length(); i < i_end; ++i) {
PropertyValuePair &cv = mPropertyValuePairs[i];
if (aRuleData->mSIDs & nsCachedStyleData::GetBitForSID(
nsCSSProps::kSIDTable[cv.mProperty]))
{
nsCSSValue *prop = aRuleData->ValueFor(cv.mProperty);
if (prop->GetUnit() == eCSSUnit_Null) {
#ifdef DEBUG
PRBool ok =
#endif
nsStyleAnimation::UncomputeValue(cv.mProperty,
aRuleData->mPresContext,
cv.mValue, *prop);
NS_ABORT_IF_FALSE(ok, "could not store computed value");
}
}
}
}
#ifdef DEBUG
/* virtual */ void
AnimValuesStyleRule::List(FILE* out, PRInt32 aIndent) const
{
// WRITE ME?
}
#endif
void
ComputedTimingFunction::Init(const nsTimingFunction &aFunction)
{
mType = aFunction.mType;
if (mType == nsTimingFunction::Function) {
mTimingFunction.Init(aFunction.mFunc.mX1, aFunction.mFunc.mY1,
aFunction.mFunc.mX2, aFunction.mFunc.mY2);
} else {
mSteps = aFunction.mSteps;
}
}
static inline double
StepEnd(PRUint32 aSteps, double aPortion)
{
NS_ABORT_IF_FALSE(0.0 <= aPortion && aPortion <= 1.0, "out of range");
PRUint32 step = PRUint32(aPortion * aSteps); // floor
return double(step) / double(aSteps);
}
double
ComputedTimingFunction::GetValue(double aPortion) const
{
switch (mType) {
case nsTimingFunction::Function:
return mTimingFunction.GetSplineValue(aPortion);
case nsTimingFunction::StepStart:
// There are diagrams in the spec that seem to suggest this check
// and the bounds point should not be symmetric with StepEnd, but
// should actually step up at rather than immediately after the
// fraction points. However, we rely on rounding negative values
// up to zero, so we can't do that. And it's not clear the spec
// really meant it.
return 1.0 - StepEnd(mSteps, 1.0 - aPortion);
default:
NS_ABORT_IF_FALSE(PR_FALSE, "bad type");
// fall through
case nsTimingFunction::StepEnd:
return StepEnd(mSteps, aPortion);
}
}
}
}

View File

@ -0,0 +1,183 @@
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is AnimationCommon, common animation code for transitions
* and animations.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_css_AnimationCommon_h
#define mozilla_css_AnimationCommon_h
#include "nsIStyleRuleProcessor.h"
#include "nsIStyleRule.h"
#include "nsRefreshDriver.h"
#include "prclist.h"
#include "nsStyleAnimation.h"
#include "nsCSSProperty.h"
#include "mozilla/dom/Element.h"
#include "nsSMILKeySpline.h"
#include "nsStyleStruct.h"
class nsPresContext;
namespace mozilla {
namespace css {
struct CommonElementAnimationData;
class CommonAnimationManager : public nsIStyleRuleProcessor,
public nsARefreshObserver {
public:
CommonAnimationManager(nsPresContext *aPresContext);
virtual ~CommonAnimationManager();
// nsISupports
NS_DECL_ISUPPORTS
// nsIStyleRuleProcessor (parts)
virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData);
virtual PRBool HasDocumentStateDependentStyle(StateRuleProcessorData* aData);
virtual nsRestyleHint
HasAttributeDependentStyle(AttributeRuleProcessorData* aData);
virtual PRBool MediumFeaturesChanged(nsPresContext* aPresContext);
/**
* Notify the manager that the pres context is going away.
*/
void Disconnect();
static PRBool ExtractComputedValueForTransition(
nsCSSProperty aProperty,
nsStyleContext* aStyleContext,
nsStyleAnimation::Value& aComputedValue);
protected:
friend struct CommonElementAnimationData; // for ElementDataRemoved
void AddElementData(CommonElementAnimationData* aData);
void ElementDataRemoved();
void RemoveAllElementData();
PRCList mElementData;
nsPresContext *mPresContext; // weak (non-null from ctor to Disconnect)
};
/**
* A style rule that maps property-nsStyleAnimation::Value pairs.
*/
class AnimValuesStyleRule : public nsIStyleRule
{
public:
// nsISupports implementation
NS_DECL_ISUPPORTS
// nsIStyleRule implementation
virtual void MapRuleInfoInto(nsRuleData* aRuleData);
#ifdef DEBUG
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
#endif
void AddValue(nsCSSProperty aProperty, nsStyleAnimation::Value &aStartValue)
{
PropertyValuePair v = { aProperty, aStartValue };
mPropertyValuePairs.AppendElement(v);
}
// Caller must fill in returned value, when non-null.
nsStyleAnimation::Value* AddEmptyValue(nsCSSProperty aProperty)
{
PropertyValuePair *p = mPropertyValuePairs.AppendElement();
if (!p) {
return nsnull;
}
p->mProperty = aProperty;
return &p->mValue;
}
struct PropertyValuePair {
nsCSSProperty mProperty;
nsStyleAnimation::Value mValue;
};
private:
nsTArray<PropertyValuePair> mPropertyValuePairs;
};
class ComputedTimingFunction {
public:
typedef nsTimingFunction::Type Type;
void Init(const nsTimingFunction &aFunction);
double GetValue(double aPortion) const;
private:
Type mType;
nsSMILKeySpline mTimingFunction;
PRUint32 mSteps;
};
struct CommonElementAnimationData : public PRCList
{
CommonElementAnimationData(dom::Element *aElement, nsIAtom *aElementProperty,
CommonAnimationManager *aManager)
: mElement(aElement)
, mElementProperty(aElementProperty)
, mManager(aManager)
{
MOZ_COUNT_CTOR(CommonElementAnimationData);
PR_INIT_CLIST(this);
}
~CommonElementAnimationData()
{
MOZ_COUNT_DTOR(CommonElementAnimationData);
PR_REMOVE_LINK(this);
mManager->ElementDataRemoved();
}
void Destroy()
{
// This will call our destructor.
mElement->DeleteProperty(mElementProperty);
}
dom::Element *mElement;
// the atom we use in mElement's prop table (must be a static atom,
// i.e., in an atom list)
nsIAtom *mElementProperty;
CommonAnimationManager *mManager;
};
}
}
#endif /* !defined(mozilla_css_AnimationCommon_h) */

View File

@ -106,6 +106,7 @@ EXPORTS_mozilla/css = \
$(NULL)
CPPSRCS = \
AnimationCommon.cpp \
nsCSSAnonBoxes.cpp \
nsCSSDataBlock.cpp \
Declaration.cpp \

View File

@ -48,7 +48,6 @@
#include "nsIStyleRule.h"
#include "nsRuleWalker.h"
#include "nsRuleData.h"
#include "nsSMILKeySpline.h"
#include "gfxColor.h"
#include "nsCSSPropertySet.h"
#include "nsStyleAnimation.h"
@ -60,64 +59,12 @@ using mozilla::TimeStamp;
using mozilla::TimeDuration;
namespace dom = mozilla::dom;
namespace css = mozilla::css;
/*****************************************************************************
* Per-Element data *
*****************************************************************************/
class ComputedTimingFunction {
public:
typedef nsTimingFunction::Type Type;
void Init(const nsTimingFunction &aFunction);
double GetValue(double aPortion) const;
private:
Type mType;
nsSMILKeySpline mTimingFunction;
PRUint32 mSteps;
};
void
ComputedTimingFunction::Init(const nsTimingFunction &aFunction)
{
mType = aFunction.mType;
if (mType == nsTimingFunction::Function) {
mTimingFunction.Init(aFunction.mFunc.mX1, aFunction.mFunc.mY1,
aFunction.mFunc.mX2, aFunction.mFunc.mY2);
} else {
mSteps = aFunction.mSteps;
}
}
static inline double
StepEnd(PRUint32 aSteps, double aPortion)
{
NS_ABORT_IF_FALSE(0.0 <= aPortion && aPortion <= 1.0, "out of range");
PRUint32 step = PRUint32(aPortion * aSteps); // floor
return double(step) / double(aSteps);
}
double
ComputedTimingFunction::GetValue(double aPortion) const
{
switch (mType) {
case nsTimingFunction::Function:
return mTimingFunction.GetSplineValue(aPortion);
case nsTimingFunction::StepStart:
// There are diagrams in the spec that seem to suggest this check
// and the bounds point should not be symmetric with StepEnd, but
// should actually step up at rather than immediately after the
// fraction points. However, we rely on rounding negative values
// up to zero, so we can't do that. And it's not clear the spec
// really meant it.
return 1.0 - StepEnd(mSteps, 1.0 - aPortion);
default:
NS_ABORT_IF_FALSE(PR_FALSE, "bad type");
// fall through
case nsTimingFunction::StepEnd:
return StepEnd(mSteps, aPortion);
}
}
struct ElementPropertyTransition
{
nsCSSProperty mProperty;
@ -126,7 +73,7 @@ struct ElementPropertyTransition
// data from the relevant nsTransition
TimeDuration mDuration;
ComputedTimingFunction mTimingFunction;
css::ComputedTimingFunction mTimingFunction;
// This is the start value to be used for a check for whether a
// transition is being reversed. Normally the same as mStartValue,
@ -190,67 +137,13 @@ ElementPropertyTransition::ValuePortionFor(TimeStamp aRefreshTime) const
return mTimingFunction.GetValue(timePortion);
}
/**
* A style rule that maps property-nsStyleAnimation::Value pairs.
*/
class AnimValuesStyleRule : public nsIStyleRule
{
public:
// nsISupports implementation
NS_DECL_ISUPPORTS
// nsIStyleRule implementation
virtual void MapRuleInfoInto(nsRuleData* aRuleData);
#ifdef DEBUG
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
#endif
void AddValue(nsCSSProperty aProperty, nsStyleAnimation::Value &aStartValue)
{
PropertyValuePair v = { aProperty, aStartValue };
mPropertyValuePairs.AppendElement(v);
}
// Caller must fill in returned value, when non-null.
nsStyleAnimation::Value* AddEmptyValue(nsCSSProperty aProperty)
{
PropertyValuePair *p = mPropertyValuePairs.AppendElement();
if (!p) {
return nsnull;
}
p->mProperty = aProperty;
return &p->mValue;
}
struct PropertyValuePair {
nsCSSProperty mProperty;
nsStyleAnimation::Value mValue;
};
private:
nsTArray<PropertyValuePair> mPropertyValuePairs;
};
struct ElementTransitions : public PRCList
struct ElementTransitions : public mozilla::css::CommonElementAnimationData
{
ElementTransitions(dom::Element *aElement, nsIAtom *aElementProperty,
nsTransitionManager *aTransitionManager)
: mElement(aElement)
, mElementProperty(aElementProperty)
, mTransitionManager(aTransitionManager)
: CommonElementAnimationData(aElement, aElementProperty,
aTransitionManager)
{
PR_INIT_CLIST(this);
}
~ElementTransitions()
{
PR_REMOVE_LINK(this);
mTransitionManager->TransitionsRemoved();
}
void Destroy()
{
// This will call our destructor.
mElement->DeleteProperty(mElementProperty);
}
void EnsureStyleRuleFor(TimeStamp aRefreshTime);
@ -265,17 +158,9 @@ struct ElementTransitions : public PRCList
// animation, we need to not use it so that we can detect any new
// changes; if necessary we restyle immediately afterwards with
// animation.
nsRefPtr<AnimValuesStyleRule> mStyleRule;
nsRefPtr<css::AnimValuesStyleRule> mStyleRule;
// The refresh time associated with mStyleRule.
TimeStamp mStyleRuleRefreshTime;
dom::Element *mElement;
// the atom we use in mElement's prop table (must be a static atom,
// i.e., in an atom list)
nsIAtom *mElementProperty;
nsTransitionManager *mTransitionManager;
};
static void
@ -292,7 +177,7 @@ void
ElementTransitions::EnsureStyleRuleFor(TimeStamp aRefreshTime)
{
if (!mStyleRule || mStyleRuleRefreshTime != aRefreshTime) {
mStyleRule = new AnimValuesStyleRule();
mStyleRule = new css::AnimValuesStyleRule();
mStyleRuleRefreshTime = aRefreshTime;
for (PRUint32 i = 0, i_end = mPropertyTransitions.Length(); i < i_end; ++i)
@ -319,97 +204,10 @@ ElementTransitions::EnsureStyleRuleFor(TimeStamp aRefreshTime)
}
}
NS_IMPL_ISUPPORTS1(AnimValuesStyleRule, nsIStyleRule)
/* virtual */ void
AnimValuesStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
{
nsStyleContext *contextParent = aRuleData->mStyleContext->GetParent();
if (contextParent && contextParent->HasPseudoElementData()) {
// Don't apply transitions to things inside of pseudo-elements.
// FIXME (Bug 522599): Add tests for this.
return;
}
for (PRUint32 i = 0, i_end = mPropertyValuePairs.Length(); i < i_end; ++i) {
PropertyValuePair &cv = mPropertyValuePairs[i];
if (aRuleData->mSIDs & nsCachedStyleData::GetBitForSID(
nsCSSProps::kSIDTable[cv.mProperty]))
{
nsCSSValue *prop = aRuleData->ValueFor(cv.mProperty);
if (prop->GetUnit() == eCSSUnit_Null) {
#ifdef DEBUG
PRBool ok =
#endif
nsStyleAnimation::UncomputeValue(cv.mProperty,
aRuleData->mPresContext,
cv.mValue, *prop);
NS_ABORT_IF_FALSE(ok, "could not store computed value");
}
}
}
}
#ifdef DEBUG
/* virtual */ void
AnimValuesStyleRule::List(FILE* out, PRInt32 aIndent) const
{
// WRITE ME?
}
#endif
/*****************************************************************************
* nsTransitionManager *
*****************************************************************************/
nsTransitionManager::nsTransitionManager(nsPresContext *aPresContext)
: mPresContext(aPresContext)
{
PR_INIT_CLIST(&mElementTransitions);
}
nsTransitionManager::~nsTransitionManager()
{
NS_ABORT_IF_FALSE(!mPresContext, "Disconnect should have been called");
}
void
nsTransitionManager::Disconnect()
{
// Content nodes might outlive the transition manager.
RemoveAllTransitions();
mPresContext = nsnull;
}
void
nsTransitionManager::RemoveAllTransitions()
{
while (!PR_CLIST_IS_EMPTY(&mElementTransitions)) {
ElementTransitions *head = static_cast<ElementTransitions*>(
PR_LIST_HEAD(&mElementTransitions));
head->Destroy();
}
}
static PRBool
TransExtractComputedValue(nsCSSProperty aProperty,
nsStyleContext* aStyleContext,
nsStyleAnimation::Value& aComputedValue)
{
PRBool result =
nsStyleAnimation::ExtractComputedValue(aProperty, aStyleContext,
aComputedValue);
if (aProperty == eCSSProperty_visibility) {
NS_ABORT_IF_FALSE(aComputedValue.GetUnit() ==
nsStyleAnimation::eUnit_Enumerated,
"unexpected unit");
aComputedValue.SetIntValue(aComputedValue.GetIntValue(),
nsStyleAnimation::eUnit_Visibility);
}
return result;
}
already_AddRefed<nsIStyleRule>
nsTransitionManager::StyleContextChanged(dom::Element *aElement,
nsStyleContext *aOldStyleContext,
@ -560,8 +358,8 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement,
!allTransitionProperties.HasProperty(pt.mProperty)) ||
// properties whose computed values changed but delay and
// duration are both zero
!TransExtractComputedValue(pt.mProperty, aNewStyleContext,
currentValue) ||
!ExtractComputedValueForTransition(pt.mProperty, aNewStyleContext,
currentValue) ||
currentValue != pt.mEndValue) {
// stop the transition
pts.RemoveElementAt(i);
@ -596,7 +394,7 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement,
// Our caller is responsible for restyling again using this covering
// rule.
nsRefPtr<AnimValuesStyleRule> coverRule = new AnimValuesStyleRule;
nsRefPtr<css::AnimValuesStyleRule> coverRule = new css::AnimValuesStyleRule;
if (!coverRule) {
NS_WARNING("out of memory");
return nsnull;
@ -642,8 +440,10 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty,
ElementPropertyTransition pt;
nsStyleAnimation::Value dummyValue;
PRBool haveValues =
TransExtractComputedValue(aProperty, aOldStyleContext, pt.mStartValue) &&
TransExtractComputedValue(aProperty, aNewStyleContext, pt.mEndValue);
ExtractComputedValueForTransition(aProperty, aOldStyleContext,
pt.mStartValue) &&
ExtractComputedValueForTransition(aProperty, aNewStyleContext,
pt.mEndValue);
PRBool shouldAnimate =
haveValues &&
pt.mStartValue != pt.mEndValue &&
@ -802,7 +602,7 @@ nsTransitionManager::GetElementTransitions(dom::Element *aElement,
nsCSSPseudoElements::Type aPseudoType,
PRBool aCreateIfNeeded)
{
if (!aCreateIfNeeded && PR_CLIST_IS_EMPTY(&mElementTransitions)) {
if (!aCreateIfNeeded && PR_CLIST_IS_EMPTY(&mElementData)) {
// Early return for the most common case.
return nsnull;
}
@ -837,30 +637,12 @@ nsTransitionManager::GetElementTransitions(dom::Element *aElement,
return nsnull;
}
AddElementTransitions(et);
AddElementData(et);
}
return et;
}
void
nsTransitionManager::AddElementTransitions(ElementTransitions* aElementTransitions)
{
if (PR_CLIST_IS_EMPTY(&mElementTransitions)) {
// We need to observe the refresh driver.
nsRefreshDriver *rd = mPresContext->RefreshDriver();
rd->AddRefreshObserver(this, Flush_Style);
}
PR_INSERT_BEFORE(aElementTransitions, &mElementTransitions);
}
/*
* nsISupports implementation
*/
NS_IMPL_ISUPPORTS1(nsTransitionManager, nsIStyleRuleProcessor)
/*
* nsIStyleRuleProcessor implementation
*/
@ -932,30 +714,6 @@ nsTransitionManager::RulesMatching(XULTreeRuleProcessorData* aData)
}
#endif
nsRestyleHint
nsTransitionManager::HasStateDependentStyle(StateRuleProcessorData* aData)
{
return nsRestyleHint(0);
}
PRBool
nsTransitionManager::HasDocumentStateDependentStyle(StateRuleProcessorData* aData)
{
return PR_FALSE;
}
nsRestyleHint
nsTransitionManager::HasAttributeDependentStyle(AttributeRuleProcessorData* aData)
{
return nsRestyleHint(0);
}
/* virtual */ PRBool
nsTransitionManager::MediumFeaturesChanged(nsPresContext* aPresContext)
{
return PR_FALSE;
}
struct TransitionEventInfo {
nsCOMPtr<nsIContent> mElement;
nsTransitionEvent mEvent;
@ -990,7 +748,7 @@ nsTransitionManager::WillRefresh(mozilla::TimeStamp aTime)
// where it has been torn down; don't bother doing anything in
// this case. But do get rid of all our transitions so we stop
// triggering refreshes.
RemoveAllTransitions();
RemoveAllElementData();
return;
}
@ -999,8 +757,8 @@ nsTransitionManager::WillRefresh(mozilla::TimeStamp aTime)
// Trim transitions that have completed, and post restyle events for
// frames that are still transitioning.
{
PRCList *next = PR_LIST_HEAD(&mElementTransitions);
while (next != &mElementTransitions) {
PRCList *next = PR_LIST_HEAD(&mElementData);
while (next != &mElementData) {
ElementTransitions *et = static_cast<ElementTransitions*>(next);
next = PR_NEXT_LINK(next);
@ -1064,7 +822,7 @@ nsTransitionManager::WillRefresh(mozilla::TimeStamp aTime)
}
// We might have removed transitions above.
TransitionsRemoved();
ElementDataRemoved();
for (PRUint32 i = 0, i_end = events.Length(); i < i_end; ++i) {
TransitionEventInfo &info = events[i];
@ -1075,13 +833,3 @@ nsTransitionManager::WillRefresh(mozilla::TimeStamp aTime)
}
}
}
void
nsTransitionManager::TransitionsRemoved()
{
// If we have no transitions left, remove ourselves from the refresh
// driver.
if (PR_CLIST_IS_EMPTY(&mElementTransitions)) {
mPresContext->RefreshDriver()->RemoveRefreshObserver(this, Flush_Style);
}
}

View File

@ -40,10 +40,7 @@
#ifndef nsTransitionManager_h_
#define nsTransitionManager_h_
#include "prclist.h"
#include "nsCSSProperty.h"
#include "nsIStyleRuleProcessor.h"
#include "nsRefreshDriver.h"
#include "AnimationCommon.h"
#include "nsCSSPseudoElements.h"
class nsStyleContext;
@ -52,16 +49,13 @@ class nsCSSPropertySet;
struct nsTransition;
struct ElementTransitions;
class nsTransitionManager : public nsIStyleRuleProcessor,
public nsARefreshObserver {
class nsTransitionManager : public mozilla::css::CommonAnimationManager
{
public:
nsTransitionManager(nsPresContext *aPresContext);
~nsTransitionManager();
/**
* Notify the transition manager that the pres context is going away.
*/
void Disconnect();
nsTransitionManager(nsPresContext *aPresContext)
: mozilla::css::CommonAnimationManager(aPresContext)
{
}
/**
* StyleContextChanged
@ -84,28 +78,18 @@ public:
nsStyleContext *aOldStyleContext,
nsStyleContext *aNewStyleContext);
// nsISupports
NS_DECL_ISUPPORTS
// nsIStyleRuleProcessor
// nsIStyleRuleProcessor (parts)
virtual void RulesMatching(ElementRuleProcessorData* aData);
virtual void RulesMatching(PseudoElementRuleProcessorData* aData);
virtual void RulesMatching(AnonBoxRuleProcessorData* aData);
#ifdef MOZ_XUL
virtual void RulesMatching(XULTreeRuleProcessorData* aData);
#endif
virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData);
virtual PRBool HasDocumentStateDependentStyle(StateRuleProcessorData* aData);
virtual nsRestyleHint
HasAttributeDependentStyle(AttributeRuleProcessorData* aData);
virtual PRBool MediumFeaturesChanged(nsPresContext* aPresContext);
// nsARefreshObserver
virtual void WillRefresh(mozilla::TimeStamp aTime);
private:
friend struct ElementTransitions; // for TransitionsRemoved
void ConsiderStartingTransition(nsCSSProperty aProperty,
const nsTransition& aTransition,
mozilla::dom::Element *aElement,
@ -117,15 +101,8 @@ private:
ElementTransitions* GetElementTransitions(mozilla::dom::Element *aElement,
nsCSSPseudoElements::Type aPseudoType,
PRBool aCreateIfNeeded);
void AddElementTransitions(ElementTransitions* aElementTransitions);
void TransitionsRemoved();
void WalkTransitionRule(RuleProcessorData* aData,
nsCSSPseudoElements::Type aPseudoType);
void RemoveAllTransitions();
PRCList mElementTransitions;
nsPresContext *mPresContext; // weak (non-null from ctor to Disconnect)
};
#endif /* !defined(nsTransitionManager_h_) */