From e3859b3244f4da61b0fb86752d9d9984ca085a52 Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Thu, 15 May 2014 08:38:37 +0900 Subject: [PATCH] Bug 1004383 part 1 - Put StyleAnimation on the heap; r=dbaron This patch takes StyleAnimation and makes it ref-counted heap object. This should allow us to store StyleAnimation and its subclasses (transitions only currently) in a consistent fashion (an array of base-class pointers). Furthermore, this will be helpful if we want these things to be pointed to from Javascript objects that may, for example, preserve their lifetime beyond that of the element that currently owns them. This patch also introduces a typedef for an array of refptrs to StyleAnimation objects (and similarly for the subclass ElementPropertyTransition) to simplify the code somewhat. --- layout/base/nsDisplayList.cpp | 2 +- layout/base/nsLayoutUtils.cpp | 18 ++--- layout/style/AnimationCommon.h | 4 + layout/style/nsAnimationManager.cpp | 110 +++++++++++++------------- layout/style/nsAnimationManager.h | 4 +- layout/style/nsTransitionManager.cpp | 113 ++++++++++++++------------- layout/style/nsTransitionManager.h | 4 +- 7 files changed, 133 insertions(+), 122 deletions(-) diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index bc799a64bc5..22471efbe75 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -377,7 +377,7 @@ AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty, mozilla::TimeStamp currentTime = aFrame->PresContext()->RefreshDriver()->MostRecentRefresh(); for (uint32_t animIdx = 0; animIdx < aAnimations.Length(); animIdx++) { - mozilla::StyleAnimation* anim = &aAnimations[animIdx]; + mozilla::StyleAnimation* anim = aAnimations[animIdx]; if (!(anim->HasAnimationOfProperty(aProperty) && anim->IsRunningAt(currentTime))) { continue; diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index b31ee752a52..d0ab19719cd 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -391,9 +391,9 @@ nsLayoutUtils::ComputeSuitableScaleForAnimation(nsIContent* aContent) (aContent, nsGkAtoms::animationsProperty, eCSSProperty_transform); if (animations) { for (uint32_t animIdx = animations->mAnimations.Length(); animIdx-- != 0; ) { - mozilla::StyleAnimation& anim = animations->mAnimations[animIdx]; - for (uint32_t propIdx = anim.mProperties.Length(); propIdx-- != 0; ) { - AnimationProperty& prop = anim.mProperties[propIdx]; + mozilla::StyleAnimation* anim = animations->mAnimations[animIdx]; + for (uint32_t propIdx = anim->mProperties.Length(); propIdx-- != 0; ) { + AnimationProperty& prop = anim->mProperties[propIdx]; if (prop.mProperty == eCSSProperty_transform) { for (uint32_t segIdx = prop.mSegments.Length(); segIdx-- != 0; ) { AnimationPropertySegment& segment = prop.mSegments[segIdx]; @@ -420,17 +420,17 @@ nsLayoutUtils::ComputeSuitableScaleForAnimation(nsIContent* aContent) if (transitions) { for (uint32_t i = 0, i_end = transitions->mPropertyTransitions.Length(); i < i_end; ++i){ - ElementPropertyTransition &pt = transitions->mPropertyTransitions[i]; - if (pt.IsRemovedSentinel()) { + ElementPropertyTransition* pt = transitions->mPropertyTransitions[i]; + if (pt->IsRemovedSentinel()) { continue; } - MOZ_ASSERT(pt.mProperties.Length() == 1, + MOZ_ASSERT(pt->mProperties.Length() == 1, "Should have one animation property for a transition"); - MOZ_ASSERT(pt.mProperties[0].mSegments.Length() == 1, + MOZ_ASSERT(pt->mProperties[0].mSegments.Length() == 1, "Animation property should have one segment for a transition"); - const AnimationPropertySegment& segment = pt.mProperties[0].mSegments[0]; + const AnimationPropertySegment& segment = pt->mProperties[0].mSegments[0]; - if (pt.mProperties[0].mProperty == eCSSProperty_transform) { + if (pt->mProperties[0].mProperty == eCSSProperty_transform) { gfxSize start = GetScaleForValue(segment.mFromValue, aContent->GetPrimaryFrame()); maxScale.width = std::max(maxScale.width, start.width); diff --git a/layout/style/AnimationCommon.h b/layout/style/AnimationCommon.h index 8ec040e0040..ddfc606dbd3 100644 --- a/layout/style/AnimationCommon.h +++ b/layout/style/AnimationCommon.h @@ -278,8 +278,12 @@ struct StyleAnimation uint32_t mLastNotification; InfallibleTArray mProperties; + + NS_INLINE_DECL_REFCOUNTING(StyleAnimation) }; +typedef InfallibleTArray > StyleAnimationPtrArray; + namespace css { struct CommonElementAnimationData : public PRCList diff --git a/layout/style/nsAnimationManager.cpp b/layout/style/nsAnimationManager.cpp index b581918c693..9b4b8ba089b 100644 --- a/layout/style/nsAnimationManager.cpp +++ b/layout/style/nsAnimationManager.cpp @@ -179,22 +179,22 @@ ElementAnimations::EnsureStyleRuleFor(TimeStamp aRefreshTime, // the style recalculation if we find any. if (aIsThrottled) { for (uint32_t animIdx = mAnimations.Length(); animIdx-- != 0; ) { - StyleAnimation &anim = mAnimations[animIdx]; + StyleAnimation* anim = mAnimations[animIdx]; - if (anim.mProperties.Length() == 0 || - anim.mIterationDuration.ToMilliseconds() <= 0.0) { + if (anim->mProperties.Length() == 0 || + anim->mIterationDuration.ToMilliseconds() <= 0.0) { continue; } - uint32_t oldLastNotification = anim.mLastNotification; + uint32_t oldLastNotification = anim->mLastNotification; // We need to call GetPositionInIteration here to populate // aEventsToDispatch. // The ElapsedDurationAt() call here handles pausing. But: // FIXME: avoid recalculating every time when paused. - GetPositionInIteration(anim.ElapsedDurationAt(aRefreshTime), - anim.mIterationDuration, anim.mIterationCount, - anim.mDirection, &anim, this, &aEventsToDispatch); + GetPositionInIteration(anim->ElapsedDurationAt(aRefreshTime), + anim->mIterationDuration, anim->mIterationCount, + anim->mDirection, anim, this, &aEventsToDispatch); // GetPositionInIteration just adjusted mLastNotification; check // its new value against the value before we called @@ -203,9 +203,9 @@ ElementAnimations::EnsureStyleRuleFor(TimeStamp aRefreshTime, // indicator that the animation has finished, it should be reserved for // events. If we use it differently in the future this use might need // changing. - if (!anim.mIsRunningOnCompositor || - (anim.mLastNotification != oldLastNotification && - anim.mLastNotification == StyleAnimation::LAST_NOTIFICATION_END)) { + if (!anim->mIsRunningOnCompositor || + (anim->mLastNotification != oldLastNotification && + anim->mLastNotification == StyleAnimation::LAST_NOTIFICATION_END)) { aIsThrottled = false; break; } @@ -230,10 +230,10 @@ ElementAnimations::EnsureStyleRuleFor(TimeStamp aRefreshTime, nsCSSPropertySet properties; for (uint32_t animIdx = mAnimations.Length(); animIdx-- != 0; ) { - StyleAnimation &anim = mAnimations[animIdx]; + StyleAnimation* anim = mAnimations[animIdx]; - if (anim.mProperties.Length() == 0 || - anim.mIterationDuration.ToMilliseconds() <= 0.0) { + if (anim->mProperties.Length() == 0 || + anim->mIterationDuration.ToMilliseconds() <= 0.0) { // No animation data. continue; } @@ -241,9 +241,9 @@ ElementAnimations::EnsureStyleRuleFor(TimeStamp aRefreshTime, // The ElapsedDurationAt() call here handles pausing. But: // FIXME: avoid recalculating every time when paused. double positionInIteration = - GetPositionInIteration(anim.ElapsedDurationAt(aRefreshTime), - anim.mIterationDuration, anim.mIterationCount, - anim.mDirection, &anim, this, + GetPositionInIteration(anim->ElapsedDurationAt(aRefreshTime), + anim->mIterationDuration, anim->mIterationCount, + anim->mDirection, anim, this, &aEventsToDispatch); // The position is -1 when we don't have fill data for the current time, @@ -255,10 +255,10 @@ ElementAnimations::EnsureStyleRuleFor(TimeStamp aRefreshTime, positionInIteration <= 1.0, "position should be in [0-1]"); - for (uint32_t propIdx = 0, propEnd = anim.mProperties.Length(); + for (uint32_t propIdx = 0, propEnd = anim->mProperties.Length(); propIdx != propEnd; ++propIdx) { - const AnimationProperty &prop = anim.mProperties[propIdx]; + const AnimationProperty &prop = anim->mProperties[propIdx]; NS_ABORT_IF_FALSE(prop.mSegments[0].mFromKey == 0.0, "incorrect first from key"); @@ -330,8 +330,8 @@ bool ElementAnimations::HasAnimationOfProperty(nsCSSProperty aProperty) const { for (uint32_t animIdx = mAnimations.Length(); animIdx-- != 0; ) { - const StyleAnimation &anim = mAnimations[animIdx]; - if (anim.HasAnimationOfProperty(aProperty)) { + const StyleAnimation* anim = mAnimations[animIdx]; + if (anim->HasAnimationOfProperty(aProperty)) { return true; } } @@ -360,11 +360,11 @@ ElementAnimations::CanPerformOnCompositorThread(CanAnimateFlags aFlags) const TimeStamp now = frame->PresContext()->RefreshDriver()->MostRecentRefresh(); for (uint32_t animIdx = mAnimations.Length(); animIdx-- != 0; ) { - const StyleAnimation& anim = mAnimations[animIdx]; - for (uint32_t propIdx = 0, propEnd = anim.mProperties.Length(); + const StyleAnimation* anim = mAnimations[animIdx]; + for (uint32_t propIdx = 0, propEnd = anim->mProperties.Length(); propIdx != propEnd; ++propIdx) { - if (IsGeometricProperty(anim.mProperties[propIdx].mProperty) && - anim.IsRunningAt(now)) { + if (IsGeometricProperty(anim->mProperties[propIdx].mProperty) && + anim->IsRunningAt(now)) { aFlags = CanAnimateFlags(aFlags | CanAnimate_HasGeometricProperty); break; } @@ -374,14 +374,14 @@ ElementAnimations::CanPerformOnCompositorThread(CanAnimateFlags aFlags) const bool hasOpacity = false; bool hasTransform = false; for (uint32_t animIdx = mAnimations.Length(); animIdx-- != 0; ) { - const StyleAnimation& anim = mAnimations[animIdx]; - if (!anim.IsRunningAt(now)) { + const StyleAnimation* anim = mAnimations[animIdx]; + if (!anim->IsRunningAt(now)) { continue; } - for (uint32_t propIdx = 0, propEnd = anim.mProperties.Length(); + for (uint32_t propIdx = 0, propEnd = anim->mProperties.Length(); propIdx != propEnd; ++propIdx) { - const AnimationProperty& prop = anim.mProperties[propIdx]; + const AnimationProperty& prop = anim->mProperties[propIdx]; if (!CanAnimatePropertyOnCompositor(mElement, prop.mProperty, aFlags) || @@ -547,7 +547,7 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, } // build the animations list - InfallibleTArray newAnimations; + StyleAnimationPtrArray newAnimations; BuildAnimations(aStyleContext, newAnimations); if (newAnimations.IsEmpty()) { @@ -577,7 +577,7 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, if (!ea->mAnimations.IsEmpty()) { for (uint32_t newIdx = 0, newEnd = newAnimations.Length(); newIdx != newEnd; ++newIdx) { - StyleAnimation *newAnim = &newAnimations[newIdx]; + nsRefPtr newAnim = newAnimations[newIdx]; // Find the matching animation with this name in the old list // of animations. Because of this code, they must all have @@ -587,9 +587,9 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, // different pause states, they, well, get what they deserve. // We'll use the last one since it's more likely to be the one // doing something. - const StyleAnimation *oldAnim = nullptr; + const StyleAnimation* oldAnim = nullptr; for (uint32_t oldIdx = ea->mAnimations.Length(); oldIdx-- != 0; ) { - const StyleAnimation *a = &ea->mAnimations[oldIdx]; + const StyleAnimation* a = ea->mAnimations[oldIdx]; if (a->mName == newAnim->mName) { oldAnim = a; break; @@ -717,8 +717,7 @@ ResolvedStyleCache::Get(nsPresContext *aPresContext, void nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext, - InfallibleTArray& - aAnimations) + StyleAnimationPtrArray& aAnimations) { NS_ABORT_IF_FALSE(aAnimations.IsEmpty(), "expect empty array"); @@ -728,27 +727,30 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext, TimeStamp now = mPresContext->RefreshDriver()->MostRecentRefresh(); for (uint32_t animIdx = 0, animEnd = disp->mAnimationNameCount; animIdx != animEnd; ++animIdx) { - const nsAnimation& aSrc = disp->mAnimations[animIdx]; - StyleAnimation& aDest = *aAnimations.AppendElement(); + const nsAnimation& src = disp->mAnimations[animIdx]; + nsRefPtr dest = + *aAnimations.AppendElement(new StyleAnimation()); - aDest.mName = aSrc.GetName(); - aDest.mIterationCount = aSrc.GetIterationCount(); - aDest.mDirection = aSrc.GetDirection(); - aDest.mFillMode = aSrc.GetFillMode(); - aDest.mPlayState = aSrc.GetPlayState(); + dest->mName = src.GetName(); + dest->mIterationCount = src.GetIterationCount(); + dest->mDirection = src.GetDirection(); + dest->mFillMode = src.GetFillMode(); + dest->mPlayState = src.GetPlayState(); - aDest.mDelay = TimeDuration::FromMilliseconds(aSrc.GetDelay()); - aDest.mStartTime = now; - if (aDest.IsPaused()) { - aDest.mPauseStart = now; + dest->mDelay = TimeDuration::FromMilliseconds(src.GetDelay()); + dest->mStartTime = now; + if (dest->IsPaused()) { + dest->mPauseStart = now; } else { - aDest.mPauseStart = TimeStamp(); + dest->mPauseStart = TimeStamp(); } - aDest.mIterationDuration = TimeDuration::FromMilliseconds(aSrc.GetDuration()); + dest->mIterationDuration = + TimeDuration::FromMilliseconds(src.GetDuration()); nsCSSKeyframesRule* rule = - mPresContext->StyleSet()->KeyframesRuleForName(mPresContext, aDest.mName); + mPresContext->StyleSet()->KeyframesRuleForName(mPresContext, + dest->mName); if (!rule) { // no segments continue; @@ -841,7 +843,7 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext, lastKey = kf.mKey; } - AnimationProperty &propData = *aDest.mProperties.AppendElement(); + AnimationProperty &propData = *dest->mProperties.AppendElement(); propData.mProperty = prop; KeyframeData *fromKeyframe = nullptr; @@ -857,7 +859,7 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext, if (fromKeyframe) { interpolated = interpolated && - BuildSegment(propData.mSegments, prop, aSrc, + BuildSegment(propData.mSegments, prop, src, fromKeyframe->mKey, fromContext, fromKeyframe->mRule->Declaration(), toKeyframe.mKey, toContext); @@ -866,7 +868,7 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext, // There's no data for this property at 0%, so use the // cascaded value above us. interpolated = interpolated && - BuildSegment(propData.mSegments, prop, aSrc, + BuildSegment(propData.mSegments, prop, src, 0.0f, aStyleContext, nullptr, toKeyframe.mKey, toContext); } @@ -880,7 +882,7 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext, // There's no data for this property at 100%, so use the // cascaded value above us. interpolated = interpolated && - BuildSegment(propData.mSegments, prop, aSrc, + BuildSegment(propData.mSegments, prop, src, fromKeyframe->mKey, fromContext, fromKeyframe->mRule->Declaration(), 1.0f, aStyleContext); @@ -893,9 +895,11 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext, // values (which?) or skip segments, so best to skip the whole // thing for now.) if (!interpolated) { - aDest.mProperties.RemoveElementAt(aDest.mProperties.Length() - 1); + dest->mProperties.RemoveElementAt(dest->mProperties.Length() - 1); } } + + aAnimations.AppendElement(dest); } } diff --git a/layout/style/nsAnimationManager.h b/layout/style/nsAnimationManager.h index 4833bb2edb1..1c12755a846 100644 --- a/layout/style/nsAnimationManager.h +++ b/layout/style/nsAnimationManager.h @@ -127,7 +127,7 @@ struct ElementAnimations MOZ_FINAL // either completed or paused). May be invalidated by a style change. bool mNeedsRefreshes; - InfallibleTArray mAnimations; + mozilla::StyleAnimationPtrArray mAnimations; }; class nsAnimationManager MOZ_FINAL @@ -236,7 +236,7 @@ protected: private: void BuildAnimations(nsStyleContext* aStyleContext, - InfallibleTArray& aAnimations); + mozilla::StyleAnimationPtrArray& aAnimations); bool BuildSegment(InfallibleTArray& aSegments, nsCSSProperty aProperty, const nsAnimation& aAnimation, diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index 375adff6d74..402016934a8 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -105,18 +105,18 @@ ElementTransitions::EnsureStyleRuleFor(TimeStamp aRefreshTime) for (uint32_t i = 0, i_end = mPropertyTransitions.Length(); i < i_end; ++i) { - ElementPropertyTransition &pt = mPropertyTransitions[i]; - if (pt.IsRemovedSentinel()) { + ElementPropertyTransition* pt = mPropertyTransitions[i]; + if (pt->IsRemovedSentinel()) { continue; } - MOZ_ASSERT(pt.mProperties.Length() == 1, + MOZ_ASSERT(pt->mProperties.Length() == 1, "Should have one animation property for a transition"); - const AnimationProperty &prop = pt.mProperties[0]; + const AnimationProperty &prop = pt->mProperties[0]; nsStyleAnimation::Value *val = mStyleRule->AddEmptyValue(prop.mProperty); - double valuePortion = pt.ValuePortionFor(aRefreshTime); + double valuePortion = pt->ValuePortionFor(aRefreshTime); MOZ_ASSERT(prop.mSegments.Length() == 1, "Animation property should have one segment for a transition"); @@ -136,8 +136,8 @@ bool ElementTransitions::HasAnimationOfProperty(nsCSSProperty aProperty) const { for (uint32_t tranIdx = mPropertyTransitions.Length(); tranIdx-- != 0; ) { - const ElementPropertyTransition& pt = mPropertyTransitions[tranIdx]; - if (pt.HasAnimationOfProperty(aProperty) && !pt.IsRemovedSentinel()) { + const ElementPropertyTransition* pt = mPropertyTransitions[tranIdx]; + if (pt->HasAnimationOfProperty(aProperty) && !pt->IsRemovedSentinel()) { return true; } } @@ -164,11 +164,11 @@ ElementTransitions::CanPerformOnCompositorThread(CanAnimateFlags aFlags) const TimeStamp now = frame->PresContext()->RefreshDriver()->MostRecentRefresh(); for (uint32_t i = 0, i_end = mPropertyTransitions.Length(); i < i_end; ++i) { - const ElementPropertyTransition& pt = mPropertyTransitions[i]; - MOZ_ASSERT(pt.mProperties.Length() == 1, + const ElementPropertyTransition* pt = mPropertyTransitions[i]; + MOZ_ASSERT(pt->mProperties.Length() == 1, "Should have one animation property for a transition"); - if (css::IsGeometricProperty(pt.mProperties[0].mProperty) && - pt.IsRunningAt(now)) { + if (css::IsGeometricProperty(pt->mProperties[0].mProperty) && + pt->IsRunningAt(now)) { aFlags = CanAnimateFlags(aFlags | CanAnimate_HasGeometricProperty); break; } @@ -178,16 +178,16 @@ ElementTransitions::CanPerformOnCompositorThread(CanAnimateFlags aFlags) const bool hasTransform = false; bool existsProperty = false; for (uint32_t i = 0, i_end = mPropertyTransitions.Length(); i < i_end; ++i) { - const ElementPropertyTransition& pt = mPropertyTransitions[i]; - if (!pt.IsRunningAt(now)) { + const ElementPropertyTransition* pt = mPropertyTransitions[i]; + if (!pt->IsRunningAt(now)) { continue; } existsProperty = true; - MOZ_ASSERT(pt.mProperties.Length() == 1, + MOZ_ASSERT(pt->mProperties.Length() == 1, "Should have one animation property for a transition"); - const AnimationProperty& prop = pt.mProperties[0]; + const AnimationProperty& prop = pt->mProperties[0]; if (!css::CommonElementAnimationData::CanAnimatePropertyOnCompositor( mElement, prop.mProperty, aFlags) || @@ -449,18 +449,18 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement, } } - nsTArray &pts = et->mPropertyTransitions; + ElementTransitions::TransitionPtrArray &pts = et->mPropertyTransitions; uint32_t i = pts.Length(); NS_ABORT_IF_FALSE(i != 0, "empty transitions list?"); nsStyleAnimation::Value currentValue; do { --i; - ElementPropertyTransition &pt = pts[i]; - MOZ_ASSERT(pt.mProperties.Length() == 1, + ElementPropertyTransition* pt = pts[i]; + MOZ_ASSERT(pt->mProperties.Length() == 1, "Should have one animation property for a transition"); - MOZ_ASSERT(pt.mProperties[0].mSegments.Length() == 1, + MOZ_ASSERT(pt->mProperties[0].mSegments.Length() == 1, "Animation property should have one segment for a transition"); - const AnimationProperty& prop = pt.mProperties[0]; + const AnimationProperty& prop = pt->mProperties[0]; const AnimationPropertySegment& segment = prop.mSegments[0]; // properties no longer in 'transition-property' if ((checkProperties && @@ -506,14 +506,14 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement, nsRefPtr coverRule = new css::AnimValuesStyleRule; - nsTArray &pts = et->mPropertyTransitions; + ElementTransitions::TransitionPtrArray &pts = et->mPropertyTransitions; for (uint32_t i = 0, i_end = pts.Length(); i < i_end; ++i) { - ElementPropertyTransition &pt = pts[i]; - MOZ_ASSERT(pt.mProperties.Length() == 1, + ElementPropertyTransition* pt = pts[i]; + MOZ_ASSERT(pt->mProperties.Length() == 1, "Should have one animation property for a transition"); - MOZ_ASSERT(pt.mProperties[0].mSegments.Length() == 1, + MOZ_ASSERT(pt->mProperties[0].mSegments.Length() == 1, "Animation property should have one segment for a transition"); - AnimationProperty& prop = pt.mProperties[0]; + AnimationProperty& prop = pt->mProperties[0]; AnimationPropertySegment& segment = prop.mSegments[0]; if (whichStarted.HasProperty(prop.mProperty)) { coverRule->AddValue(prop.mProperty, segment.mFromValue); @@ -553,7 +553,7 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty, return; } - ElementPropertyTransition pt; + nsRefPtr pt = new ElementPropertyTransition(); nsStyleAnimation::Value startValue, endValue, dummyValue; bool haveValues = @@ -577,15 +577,15 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty, size_t currentIndex = nsTArray::NoIndex; const ElementPropertyTransition *oldPT = nullptr; if (aElementTransitions) { - nsTArray &pts = + ElementTransitions::TransitionPtrArray &pts = aElementTransitions->mPropertyTransitions; for (size_t i = 0, i_end = pts.Length(); i < i_end; ++i) { - MOZ_ASSERT(pts[i].mProperties.Length() == 1, + MOZ_ASSERT(pts[i]->mProperties.Length() == 1, "Should have one animation property for a transition"); - if (pts[i].mProperties[0].mProperty == aProperty) { + if (pts[i]->mProperties[0].mProperty == aProperty) { haveCurrentTransition = true; currentIndex = i; - oldPT = &aElementTransitions->mPropertyTransitions[currentIndex]; + oldPT = aElementTransitions->mPropertyTransitions[currentIndex]; break; } } @@ -618,7 +618,7 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty, // in-progress value (which is particularly easy to cause when we're // currently in the 'transition-delay'). It also might happen because we // just got a style change to a value that can't be interpolated. - nsTArray &pts = + ElementTransitions::TransitionPtrArray &pts = aElementTransitions->mPropertyTransitions; pts.RemoveElementAt(currentIndex); aElementTransitions->UpdateAnimationGeneration(mPresContext); @@ -643,8 +643,8 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty, // The spec says a negative duration is treated as zero. duration = 0.0; } - pt.mStartForReversingTest = startValue; - pt.mReversePortion = 1.0; + pt->mStartForReversingTest = startValue; + pt->mReversePortion = 1.0; // If the new transition reverses an existing one, we'll need to // handle the timing differently. @@ -681,11 +681,11 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty, duration *= valuePortion; - pt.mStartForReversingTest = oldPT->mProperties[0].mSegments[0].mToValue; - pt.mReversePortion = valuePortion; + pt->mStartForReversingTest = oldPT->mProperties[0].mSegments[0].mToValue; + pt->mReversePortion = valuePortion; } - AnimationProperty& prop = *pt.mProperties.AppendElement(); + AnimationProperty& prop = *pt->mProperties.AppendElement(); prop.mProperty = aProperty; AnimationPropertySegment& segment = *prop.mSegments.AppendElement(); @@ -695,14 +695,14 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty, segment.mToKey = 1; segment.mTimingFunction.Init(tf); - pt.mStartTime = mostRecentRefresh; - pt.mDelay = TimeDuration::FromMilliseconds(delay); - pt.mIterationDuration = TimeDuration::FromMilliseconds(duration); - pt.mIterationCount = 1; - pt.mDirection = NS_STYLE_ANIMATION_DIRECTION_NORMAL; - pt.mFillMode = NS_STYLE_ANIMATION_FILL_MODE_BACKWARDS; - pt.mPlayState = NS_STYLE_ANIMATION_PLAY_STATE_RUNNING; - pt.mPauseStart = TimeStamp(); + pt->mStartTime = mostRecentRefresh; + pt->mDelay = TimeDuration::FromMilliseconds(delay); + pt->mIterationDuration = TimeDuration::FromMilliseconds(duration); + pt->mIterationCount = 1; + pt->mDirection = NS_STYLE_ANIMATION_DIRECTION_NORMAL; + pt->mFillMode = NS_STYLE_ANIMATION_FILL_MODE_BACKWARDS; + pt->mPlayState = NS_STYLE_ANIMATION_PLAY_STATE_RUNNING; + pt->mPauseStart = TimeStamp(); if (!aElementTransitions) { aElementTransitions = @@ -714,14 +714,14 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty, } } - nsTArray &pts = + ElementTransitions::TransitionPtrArray &pts = aElementTransitions->mPropertyTransitions; #ifdef DEBUG for (uint32_t i = 0, i_end = pts.Length(); i < i_end; ++i) { - NS_ABORT_IF_FALSE(pts[i].mProperties.Length() == 1, + NS_ABORT_IF_FALSE(pts[i]->mProperties.Length() == 1, "Should have one animation property for a transition"); NS_ABORT_IF_FALSE(i == currentIndex || - pts[i].mProperties[0].mProperty != aProperty, + pts[i]->mProperties[0].mProperty != aProperty, "duplicate transitions for property"); } #endif @@ -955,8 +955,8 @@ nsTransitionManager::FlushTransitions(FlushFlags aFlags) bool transitionStartedOrEnded = false; do { --i; - ElementPropertyTransition &pt = et->mPropertyTransitions[i]; - if (pt.IsRemovedSentinel()) { + ElementPropertyTransition* pt = et->mPropertyTransitions[i]; + if (pt->IsRemovedSentinel()) { // Actually remove transitions one throttle-able cycle after their // completion. We only clear on a throttle-able cycle because that // means it is a regular restyle tick and thus it is safe to discard @@ -965,10 +965,11 @@ nsTransitionManager::FlushTransitions(FlushFlags aFlags) if (aFlags == Can_Throttle) { et->mPropertyTransitions.RemoveElementAt(i); } - } else if (pt.mStartTime + pt.mDelay + pt.mIterationDuration <= now) { - MOZ_ASSERT(pt.mProperties.Length() == 1, + } else if (pt->mStartTime + pt->mDelay + pt->mIterationDuration <= + now) { + MOZ_ASSERT(pt->mProperties.Length() == 1, "Should have one animation property for a transition"); - nsCSSProperty prop = pt.mProperties[0].mProperty; + nsCSSProperty prop = pt->mProperties[0].mProperty; if (nsCSSProps::PropHasFlags(prop, CSS_PROPERTY_REPORT_OTHER_NAME)) { prop = nsCSSProps::OtherNameFor(prop); @@ -977,7 +978,7 @@ nsTransitionManager::FlushTransitions(FlushFlags aFlags) NS_NAMED_LITERAL_STRING(before, "::before"); NS_NAMED_LITERAL_STRING(after, "::after"); events.AppendElement( - TransitionEventInfo(et->mElement, prop, pt.mIterationDuration, + TransitionEventInfo(et->mElement, prop, pt->mIterationDuration, ep == nsGkAtoms::transitionsProperty ? EmptyString() : ep == nsGkAtoms::transitionsOfBeforeProperty ? @@ -991,11 +992,11 @@ nsTransitionManager::FlushTransitions(FlushFlags aFlags) // a non-animation style change that would affect it, we need // to know not to start a new transition for the transition // from the almost-completed value to the final value. - pt.SetRemovedSentinel(); + pt->SetRemovedSentinel(); et->UpdateAnimationGeneration(mPresContext); transitionStartedOrEnded = true; - } else if (pt.mStartTime + pt.mDelay <= now && canThrottleTick && - !pt.mIsRunningOnCompositor) { + } else if (pt->mStartTime + pt->mDelay <= now && canThrottleTick && + !pt->mIsRunningOnCompositor) { // Start a transition with a delay where we should start the // transition proper. et->UpdateAnimationGeneration(mPresContext); diff --git a/layout/style/nsTransitionManager.h b/layout/style/nsTransitionManager.h index 2487425488a..0e49591b019 100644 --- a/layout/style/nsTransitionManager.h +++ b/layout/style/nsTransitionManager.h @@ -87,8 +87,10 @@ struct ElementTransitions MOZ_FINAL // should probably move to the relevant callers. virtual bool CanPerformOnCompositorThread(CanAnimateFlags aFlags) const MOZ_OVERRIDE; + typedef InfallibleTArray > + TransitionPtrArray; // Either zero or one for each CSS property: - nsTArray mPropertyTransitions; + TransitionPtrArray mPropertyTransitions; };