mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Make the transitions style rule hold on to its values and thus preserve rule immutability. Do this by reusing the code for the covering style rule for both transitions style rule types. (Bug 582111) r=bzbarsky
This commit is contained in:
parent
b031cede9e
commit
18dff75787
@ -69,11 +69,7 @@ namespace dom = mozilla::dom;
|
||||
struct ElementPropertyTransition
|
||||
{
|
||||
nsCSSProperty mProperty;
|
||||
// We need to have mCurrentValue as a member of this structure because
|
||||
// the result of the calls to |Interpolate| might hold data that this
|
||||
// object's owning style rule needs to keep alive (after calling
|
||||
// UncomputeValue on it in MapRuleInfoInto).
|
||||
nsStyleAnimation::Value mStartValue, mEndValue, mCurrentValue;
|
||||
nsStyleAnimation::Value mStartValue, mEndValue;
|
||||
TimeStamp mStartTime; // actual start plus transition delay
|
||||
|
||||
// data from the relevant nsTransition
|
||||
@ -93,17 +89,12 @@ struct ElementPropertyTransition
|
||||
};
|
||||
|
||||
/**
|
||||
* An ElementTransitionsStyleRule overrides style data with the
|
||||
* currently-transitioning value for an element that is executing a
|
||||
* transition. It only matches when styling with animation. When we
|
||||
* style without animation, we need to not use it so that we can detect
|
||||
* any new changes; if necessary we restyle immediately afterwards with
|
||||
* animation.
|
||||
* A style rule that maps property-nsStyleAnimation::Value pairs.
|
||||
*/
|
||||
class ElementTransitionsStyleRule : public nsIStyleRule
|
||||
class AnimValuesStyleRule : public nsIStyleRule
|
||||
{
|
||||
public:
|
||||
// nsISupportsImplementation
|
||||
// nsISupports implementation
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIStyleRule implementation
|
||||
@ -112,55 +103,30 @@ public:
|
||||
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
||||
#endif
|
||||
|
||||
ElementTransitionsStyleRule(ElementTransitions *aOwner,
|
||||
TimeStamp aRefreshTime)
|
||||
: mElementTransitions(aOwner)
|
||||
, mRefreshTime(aRefreshTime)
|
||||
{}
|
||||
|
||||
void Disconnect() { mElementTransitions = nsnull; }
|
||||
|
||||
ElementTransitions *ElementData() { return mElementTransitions; }
|
||||
TimeStamp RefreshTime() { return mRefreshTime; }
|
||||
|
||||
private:
|
||||
ElementTransitions *mElementTransitions;
|
||||
// The time stamp for which this style rule is valid.
|
||||
TimeStamp mRefreshTime;
|
||||
};
|
||||
|
||||
/**
|
||||
* A CoverTransitionStyleRule sets any value for which we're starting a
|
||||
* transition back to the pre-transition value for the period when we're
|
||||
* resolving style on its descendants, so that we have the required
|
||||
* behavior for initiating transitions on such descendants. For more
|
||||
* detail, see comment below, above "new CoverTransitionStartStyleRule".
|
||||
*/
|
||||
class CoverTransitionStartStyleRule : public nsIStyleRule
|
||||
{
|
||||
public:
|
||||
// nsISupportsImplementation
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIStyleRule implementation
|
||||
virtual void MapRuleInfoInto(nsRuleData* aRuleData);
|
||||
#ifdef DEBUG
|
||||
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
||||
#endif
|
||||
|
||||
void CoverValue(nsCSSProperty aProperty, nsStyleAnimation::Value &aStartValue)
|
||||
void AddValue(nsCSSProperty aProperty, nsStyleAnimation::Value &aStartValue)
|
||||
{
|
||||
CoveredValue v = { aProperty, aStartValue };
|
||||
mCoveredValues.AppendElement(v);
|
||||
PropertyValuePair v = { aProperty, aStartValue };
|
||||
mPropertyValuePairs.AppendElement(v);
|
||||
}
|
||||
|
||||
struct CoveredValue {
|
||||
// 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 mCoveredValue;
|
||||
nsStyleAnimation::Value mValue;
|
||||
};
|
||||
|
||||
private:
|
||||
nsTArray<CoveredValue> mCoveredValues;
|
||||
nsTArray<PropertyValuePair> mPropertyValuePairs;
|
||||
};
|
||||
|
||||
struct ElementTransitions : public PRCList
|
||||
@ -175,7 +141,6 @@ struct ElementTransitions : public PRCList
|
||||
}
|
||||
~ElementTransitions()
|
||||
{
|
||||
DropStyleRule();
|
||||
PR_REMOVE_LINK(this);
|
||||
mTransitionManager->TransitionsRemoved();
|
||||
}
|
||||
@ -186,16 +151,21 @@ struct ElementTransitions : public PRCList
|
||||
mElement->DeleteProperty(mElementProperty);
|
||||
}
|
||||
|
||||
void DropStyleRule();
|
||||
void EnsureStyleRuleFor(TimeStamp aRefreshTime);
|
||||
|
||||
|
||||
// Either zero or one for each CSS property:
|
||||
nsTArray<ElementPropertyTransition> mPropertyTransitions;
|
||||
|
||||
// The style rule for the transitions (which contains the time stamp
|
||||
// for which it is valid).
|
||||
nsRefPtr<ElementTransitionsStyleRule> mStyleRule;
|
||||
// This style rule overrides style data with the currently
|
||||
// transitioning value for an element that is executing a transition.
|
||||
// It only matches when styling with animation. When we style without
|
||||
// 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;
|
||||
// The refresh time associated with mStyleRule.
|
||||
TimeStamp mStyleRuleRefreshTime;
|
||||
|
||||
dom::Element *mElement;
|
||||
|
||||
@ -216,37 +186,27 @@ ElementTransitionsPropertyDtor(void *aObject,
|
||||
delete et;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(ElementTransitionsStyleRule, nsIStyleRule)
|
||||
|
||||
/* virtual */ void
|
||||
ElementTransitionsStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
|
||||
void
|
||||
ElementTransitions::EnsureStyleRuleFor(TimeStamp aRefreshTime)
|
||||
{
|
||||
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;
|
||||
}
|
||||
if (!mStyleRule || mStyleRuleRefreshTime != aRefreshTime) {
|
||||
mStyleRule = new AnimValuesStyleRule();
|
||||
mStyleRuleRefreshTime = aRefreshTime;
|
||||
|
||||
ElementTransitions *et = ElementData();
|
||||
if (NS_UNLIKELY(!et)) { // FIXME (Bug 522597): Why can this be null?
|
||||
NS_WARNING("ElementData returned null");
|
||||
return;
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0, i_end = et->mPropertyTransitions.Length();
|
||||
i < i_end; ++i)
|
||||
{
|
||||
ElementPropertyTransition &pt = et->mPropertyTransitions[i];
|
||||
if (pt.IsRemovedSentinel()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aRuleData->mSIDs & nsCachedStyleData::GetBitForSID(
|
||||
nsCSSProps::kSIDTable[pt.mProperty]))
|
||||
for (PRUint32 i = 0, i_end = mPropertyTransitions.Length(); i < i_end; ++i)
|
||||
{
|
||||
ElementPropertyTransition &pt = mPropertyTransitions[i];
|
||||
if (pt.IsRemovedSentinel()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsStyleAnimation::Value *val = mStyleRule->AddEmptyValue(pt.mProperty);
|
||||
if (!val) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double timePortion =
|
||||
(RefreshTime() - pt.mStartTime).ToSeconds() / pt.mDuration.ToSeconds();
|
||||
(aRefreshTime - pt.mStartTime).ToSeconds() / pt.mDuration.ToSeconds();
|
||||
if (timePortion < 0.0)
|
||||
timePortion = 0.0; // use start value during transition-delay
|
||||
if (timePortion > 1.0)
|
||||
@ -259,58 +219,26 @@ ElementTransitionsStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
|
||||
#endif
|
||||
nsStyleAnimation::Interpolate(pt.mProperty,
|
||||
pt.mStartValue, pt.mEndValue,
|
||||
valuePortion, pt.mCurrentValue);
|
||||
valuePortion, *val);
|
||||
NS_ABORT_IF_FALSE(ok, "could not interpolate values");
|
||||
|
||||
void *prop =
|
||||
nsCSSExpandedDataBlock::RuleDataPropertyAt(aRuleData, pt.mProperty);
|
||||
#ifdef DEBUG
|
||||
ok =
|
||||
#endif
|
||||
nsStyleAnimation::UncomputeValue(pt.mProperty, aRuleData->mPresContext,
|
||||
pt.mCurrentValue, prop);
|
||||
NS_ABORT_IF_FALSE(ok, "could not store computed value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* virtual */ void
|
||||
ElementTransitionsStyleRule::List(FILE* out, PRInt32 aIndent) const
|
||||
{
|
||||
// WRITE ME?
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ElementTransitions::DropStyleRule()
|
||||
{
|
||||
if (mStyleRule) {
|
||||
mStyleRule->Disconnect();
|
||||
mStyleRule = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ElementTransitions::EnsureStyleRuleFor(TimeStamp aRefreshTime)
|
||||
{
|
||||
if (!mStyleRule || mStyleRule->RefreshTime() != aRefreshTime) {
|
||||
DropStyleRule();
|
||||
|
||||
ElementTransitionsStyleRule *newRule =
|
||||
new ElementTransitionsStyleRule(this, aRefreshTime);
|
||||
|
||||
mStyleRule = newRule;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(CoverTransitionStartStyleRule, nsIStyleRule)
|
||||
NS_IMPL_ISUPPORTS1(AnimValuesStyleRule, nsIStyleRule)
|
||||
|
||||
/* virtual */ void
|
||||
CoverTransitionStartStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
|
||||
AnimValuesStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
|
||||
{
|
||||
for (PRUint32 i = 0, i_end = mCoveredValues.Length(); i < i_end; ++i) {
|
||||
CoveredValue &cv = mCoveredValues[i];
|
||||
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]))
|
||||
{
|
||||
@ -320,7 +248,7 @@ CoverTransitionStartStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
|
||||
PRBool ok =
|
||||
#endif
|
||||
nsStyleAnimation::UncomputeValue(cv.mProperty, aRuleData->mPresContext,
|
||||
cv.mCoveredValue, prop);
|
||||
cv.mValue, prop);
|
||||
NS_ABORT_IF_FALSE(ok, "could not store computed value");
|
||||
}
|
||||
}
|
||||
@ -328,7 +256,7 @@ CoverTransitionStartStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
|
||||
|
||||
#ifdef DEBUG
|
||||
/* virtual */ void
|
||||
CoverTransitionStartStyleRule::List(FILE* out, PRInt32 aIndent) const
|
||||
AnimValuesStyleRule::List(FILE* out, PRInt32 aIndent) const
|
||||
{
|
||||
// WRITE ME?
|
||||
}
|
||||
@ -566,8 +494,7 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement,
|
||||
// Our caller is responsible for restyling again using this covering
|
||||
// rule.
|
||||
|
||||
nsRefPtr<CoverTransitionStartStyleRule> coverRule =
|
||||
new CoverTransitionStartStyleRule;
|
||||
nsRefPtr<AnimValuesStyleRule> coverRule = new AnimValuesStyleRule;
|
||||
if (!coverRule) {
|
||||
NS_WARNING("out of memory");
|
||||
return nsnull;
|
||||
@ -577,7 +504,7 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement,
|
||||
for (PRUint32 i = 0, i_end = pts.Length(); i < i_end; ++i) {
|
||||
ElementPropertyTransition &pt = pts[i];
|
||||
if (whichStarted.HasProperty(pt.mProperty)) {
|
||||
coverRule->CoverValue(pt.mProperty, pt.mStartValue);
|
||||
coverRule->AddValue(pt.mProperty, pt.mStartValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user