diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index 4b7b1a2dd3e..1326341cc8f 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -29,53 +29,13 @@ using mozilla::TimeDuration; namespace dom = mozilla::dom; namespace css = mozilla::css; -/***************************************************************************** - * Per-Element data * - *****************************************************************************/ - -struct ElementPropertyTransition +ElementTransitions::ElementTransitions(mozilla::dom::Element *aElement, nsIAtom *aElementProperty, + nsTransitionManager *aTransitionManager) + : CommonElementAnimationData(aElement, aElementProperty, + aTransitionManager) { - nsCSSProperty mProperty; - nsStyleAnimation::Value mStartValue, mEndValue; - TimeStamp mStartTime; // actual start plus transition delay +} - // data from the relevant nsTransition - TimeDuration mDuration; - 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, - // except when this transition started as the reversal of another - // in-progress transition. Needed so we can handle two reverses in a - // row. - nsStyleAnimation::Value mStartForReversingTest; - // Likewise, the portion (in value space) of the "full" reversed - // transition that we're actually covering. For example, if a :hover - // effect has a transition that moves the element 10px to the right - // (by changing 'left' from 0px to 10px), and the mouse moves in to - // the element (starting the transition) but then moves out after the - // transition has advanced 4px, the second transition (from 10px/4px - // to 0px) will have mReversePortion of 0.4. (If the mouse then moves - // in again when the transition is back to 2px, the mReversePortion - // for the third transition (from 0px/2px to 10px) will be 0.8. - double mReversePortion; - - // Compute the portion of the *value* space that we should be through - // at the given time. (The input to the transition timing function - // has time units, the output has value units.) - double ValuePortionFor(TimeStamp aRefreshTime) const; - - bool IsRemovedSentinel() const - { - return mStartTime.IsNull(); - } - - void SetRemovedSentinel() - { - // assign the null time stamp - mStartTime = TimeStamp(); - } -}; double ElementPropertyTransition::ValuePortionFor(TimeStamp aRefreshTime) const @@ -105,32 +65,6 @@ ElementPropertyTransition::ValuePortionFor(TimeStamp aRefreshTime) const return mTimingFunction.GetValue(timePortion); } -struct ElementTransitions : public mozilla::css::CommonElementAnimationData -{ - ElementTransitions(dom::Element *aElement, nsIAtom *aElementProperty, - nsTransitionManager *aTransitionManager) - : CommonElementAnimationData(aElement, aElementProperty, - aTransitionManager) - { - } - - void EnsureStyleRuleFor(TimeStamp aRefreshTime); - - - // Either zero or one for each CSS property: - nsTArray mPropertyTransitions; - - // 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 mStyleRule; - // The refresh time associated with mStyleRule. - TimeStamp mStyleRuleRefreshTime; -}; - static void ElementTransitionsPropertyDtor(void *aObject, nsIAtom *aPropertyName, @@ -225,13 +159,13 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement, disp->mTransitions[0].GetDelay() == 0.0f && disp->mTransitions[0].GetDuration() == 0.0f) { return nsnull; - } + } if (aNewStyleContext->PresContext()->IsProcessingAnimationStyleChange()) { return nsnull; } - + if (aNewStyleContext->GetParent() && aNewStyleContext->GetParent()->HasPseudoElementData()) { // Ignore transitions on things that inherit properties from @@ -260,7 +194,7 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement, property == eCSSProperty_UNKNOWN) { // Nothing to do, but need to exclude this from cases below. } else if (property == eCSSPropertyExtra_all_properties) { - for (nsCSSProperty p = nsCSSProperty(0); + for (nsCSSProperty p = nsCSSProperty(0); p < eCSSProperty_COUNT_no_shorthands; p = nsCSSProperty(p + 1)) { ConsiderStartingTransition(p, t, aElement, et, @@ -300,7 +234,7 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement, property == eCSSProperty_UNKNOWN) { // Nothing to do, but need to exclude this from cases below. } else if (property == eCSSPropertyExtra_all_properties) { - for (nsCSSProperty p = nsCSSProperty(0); + for (nsCSSProperty p = nsCSSProperty(0); p < eCSSProperty_COUNT_no_shorthands; p = nsCSSProperty(p + 1)) { allTransitionProperties.AddProperty(p); @@ -368,7 +302,7 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement, NS_WARNING("out of memory"); return nsnull; } - + nsTArray &pts = et->mPropertyTransitions; for (PRUint32 i = 0, i_end = pts.Length(); i < i_end; ++i) { ElementPropertyTransition &pt = pts[i]; @@ -496,7 +430,7 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty, // now we'd end up at the current position. double valuePortion = oldPT.ValuePortionFor(mostRecentRefresh) * oldPT.mReversePortion + - (1.0 - oldPT.mReversePortion); + (1.0 - oldPT.mReversePortion); // A timing function with negative y1 (or y2!) might make // valuePortion negative. In this case, we still want to apply our // reversing logic based on relative distances, not make duration @@ -537,7 +471,7 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty, return; } } - + nsTArray &pts = aElementTransitions->mPropertyTransitions; #ifdef DEBUG @@ -594,10 +528,6 @@ nsTransitionManager::GetElementTransitions(dom::Element *aElement, if (!et && aCreateIfNeeded) { // FIXME: Consider arena-allocating? et = new ElementTransitions(aElement, propName, this); - if (!et) { - NS_WARNING("out of memory"); - return nsnull; - } nsresult rv = aElement->SetProperty(propName, et, ElementTransitionsPropertyDtor, nsnull); if (NS_FAILED(rv)) { diff --git a/layout/style/nsTransitionManager.h b/layout/style/nsTransitionManager.h index 33b45f292c0..245b6b00a3d 100644 --- a/layout/style/nsTransitionManager.h +++ b/layout/style/nsTransitionManager.h @@ -15,7 +15,79 @@ class nsStyleContext; class nsPresContext; class nsCSSPropertySet; struct nsTransition; -struct ElementTransitions; + +/***************************************************************************** + * Per-Element data * + *****************************************************************************/ + +struct ElementPropertyTransition +{ + nsCSSProperty mProperty; + nsStyleAnimation::Value mStartValue, mEndValue; + mozilla::TimeStamp mStartTime; // actual start plus transition delay + + // data from the relevant nsTransition + mozilla::TimeDuration mDuration; + mozilla::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, + // except when this transition started as the reversal of another + // in-progress transition. Needed so we can handle two reverses in a + // row. + nsStyleAnimation::Value mStartForReversingTest; + // Likewise, the portion (in value space) of the "full" reversed + // transition that we're actually covering. For example, if a :hover + // effect has a transition that moves the element 10px to the right + // (by changing 'left' from 0px to 10px), and the mouse moves in to + // the element (starting the transition) but then moves out after the + // transition has advanced 4px, the second transition (from 10px/4px + // to 0px) will have mReversePortion of 0.4. (If the mouse then moves + // in again when the transition is back to 2px, the mReversePortion + // for the third transition (from 0px/2px to 10px) will be 0.8. + double mReversePortion; + + // Compute the portion of the *value* space that we should be through + // at the given time. (The input to the transition timing function + // has time units, the output has value units.) + double ValuePortionFor(mozilla::TimeStamp aRefreshTime) const; + + bool IsRemovedSentinel() const + { + return mStartTime.IsNull(); + } + + void SetRemovedSentinel() + { + // assign the null time stamp + mStartTime = mozilla::TimeStamp(); + } +}; + +struct ElementTransitions : public mozilla::css::CommonElementAnimationData +{ + ElementTransitions(mozilla::dom::Element *aElement, nsIAtom *aElementProperty, + nsTransitionManager *aTransitionManager); + + void EnsureStyleRuleFor(mozilla::TimeStamp aRefreshTime); + + // True if this animation can be performed on the compositor thread. + // virtual CanPerformOnCompositorThread() const; + // Either zero or one for each CSS property: + nsTArray mPropertyTransitions; + + // 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 mStyleRule; + // The refresh time associated with mStyleRule. + mozilla::TimeStamp mStyleRuleRefreshTime; +}; + + class nsTransitionManager : public mozilla::css::CommonAnimationManager {