зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1242872 - Part 1: Introduce CSSAnimationBuilder to factor a bunch of stuff in BuildAnimations and CheckAnimationRule out. r=dbaron
MozReview-Commit-ID: 7921De3IVA6
This commit is contained in:
Родитель
41d21a5791
Коммит
ed1cf18658
|
@ -560,6 +560,84 @@ ResolvedStyleCache::Get(nsPresContext *aPresContext,
|
|||
return result;
|
||||
}
|
||||
|
||||
class MOZ_STACK_CLASS CSSAnimationBuilder final {
|
||||
public:
|
||||
CSSAnimationBuilder(nsStyleContext* aStyleContext,
|
||||
dom::Element* aTarget)
|
||||
: mStyleContext(aStyleContext)
|
||||
, mTarget(aTarget)
|
||||
{
|
||||
MOZ_ASSERT(aStyleContext);
|
||||
MOZ_ASSERT(aTarget);
|
||||
}
|
||||
|
||||
already_AddRefed<CSSAnimation>
|
||||
Build(nsPresContext* aPresContext,
|
||||
const StyleAnimation& aSrc,
|
||||
const nsCSSKeyframesRule* aRule);
|
||||
|
||||
private:
|
||||
void BuildAnimationProperties(nsPresContext* aPresContext,
|
||||
const StyleAnimation& aSrc,
|
||||
const nsCSSKeyframesRule* aRule,
|
||||
InfallibleTArray<AnimationProperty>& aResult);
|
||||
bool BuildSegment(InfallibleTArray<mozilla::AnimationPropertySegment>&
|
||||
aSegments,
|
||||
nsCSSProperty aProperty,
|
||||
const mozilla::StyleAnimation& aAnimation,
|
||||
float aFromKey, nsStyleContext* aFromContext,
|
||||
mozilla::css::Declaration* aFromDeclaration,
|
||||
float aToKey, nsStyleContext* aToContext);
|
||||
|
||||
static TimingParams TimingParamsFrom(
|
||||
const StyleAnimation& aStyleAnimation)
|
||||
{
|
||||
TimingParams timing;
|
||||
|
||||
timing.mDuration.SetAsUnrestrictedDouble() = aStyleAnimation.GetDuration();
|
||||
timing.mDelay = TimeDuration::FromMilliseconds(aStyleAnimation.GetDelay());
|
||||
timing.mIterations = aStyleAnimation.GetIterationCount();
|
||||
timing.mDirection = aStyleAnimation.GetDirection();
|
||||
timing.mFill = aStyleAnimation.GetFillMode();
|
||||
|
||||
return timing;
|
||||
}
|
||||
|
||||
RefPtr<nsStyleContext> mStyleContext;
|
||||
RefPtr<dom::Element> mTarget;
|
||||
|
||||
ResolvedStyleCache mResolvedStyles;
|
||||
RefPtr<nsStyleContext> mStyleWithoutAnimation;
|
||||
};
|
||||
|
||||
already_AddRefed<CSSAnimation>
|
||||
CSSAnimationBuilder::Build(nsPresContext* aPresContext,
|
||||
const StyleAnimation& aSrc,
|
||||
const nsCSSKeyframesRule* aRule)
|
||||
{
|
||||
MOZ_ASSERT(aPresContext);
|
||||
MOZ_ASSERT(aRule);
|
||||
|
||||
TimingParams timing = TimingParamsFrom(aSrc);
|
||||
RefPtr<KeyframeEffectReadOnly> effect =
|
||||
new KeyframeEffectReadOnly(aPresContext->Document(), mTarget,
|
||||
mStyleContext->GetPseudoType(), timing);
|
||||
|
||||
InfallibleTArray<AnimationProperty> animationProperties;
|
||||
BuildAnimationProperties(aPresContext, aSrc, aRule, animationProperties);
|
||||
effect->Properties() = Move(animationProperties);
|
||||
|
||||
RefPtr<CSSAnimation> animation =
|
||||
new CSSAnimation(aPresContext->Document()->GetScopeObject(),
|
||||
aSrc.GetName());
|
||||
animation->SetOwningElement(
|
||||
OwningElementRef(*mTarget, mStyleContext->GetPseudoType()));
|
||||
|
||||
animation->SetEffect(effect);
|
||||
|
||||
return animation.forget();
|
||||
}
|
||||
|
||||
void
|
||||
nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
||||
dom::Element* aTarget,
|
||||
|
@ -568,11 +646,9 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
|||
{
|
||||
MOZ_ASSERT(aAnimations.IsEmpty(), "expect empty array");
|
||||
|
||||
ResolvedStyleCache resolvedStyles;
|
||||
|
||||
const nsStyleDisplay *disp = aStyleContext->StyleDisplay();
|
||||
|
||||
RefPtr<nsStyleContext> styleWithoutAnimation;
|
||||
CSSAnimationBuilder builder(aStyleContext, aTarget);
|
||||
|
||||
for (size_t animIdx = 0, animEnd = disp->mAnimationNameCount;
|
||||
animIdx != animEnd; ++animIdx) {
|
||||
|
@ -594,33 +670,26 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
|||
continue;
|
||||
}
|
||||
|
||||
RefPtr<CSSAnimation> dest =
|
||||
new CSSAnimation(mPresContext->Document()->GetScopeObject(),
|
||||
src.GetName());
|
||||
dest->SetOwningElement(
|
||||
OwningElementRef(*aTarget, aStyleContext->GetPseudoType()));
|
||||
RefPtr<CSSAnimation> dest = builder.Build(mPresContext, src, rule);
|
||||
dest->SetTimeline(aTimeline);
|
||||
dest->SetAnimationIndex(static_cast<uint64_t>(animIdx));
|
||||
aAnimations.AppendElement(dest);
|
||||
|
||||
TimingParams timing;
|
||||
timing.mDuration.SetAsUnrestrictedDouble() = src.GetDuration();
|
||||
timing.mDelay = TimeDuration::FromMilliseconds(src.GetDelay());
|
||||
timing.mIterations = src.GetIterationCount();
|
||||
timing.mDirection = src.GetDirection();
|
||||
timing.mFill = src.GetFillMode();
|
||||
|
||||
RefPtr<KeyframeEffectReadOnly> destEffect =
|
||||
new KeyframeEffectReadOnly(mPresContext->Document(), aTarget,
|
||||
aStyleContext->GetPseudoType(), timing);
|
||||
dest->SetEffect(destEffect);
|
||||
|
||||
if (src.GetPlayState() == NS_STYLE_ANIMATION_PLAY_STATE_PAUSED) {
|
||||
dest->PauseFromStyle();
|
||||
} else {
|
||||
dest->PlayFromStyle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CSSAnimationBuilder::BuildAnimationProperties(
|
||||
nsPresContext* aPresContext,
|
||||
const StyleAnimation& aSrc,
|
||||
const nsCSSKeyframesRule* aRule,
|
||||
InfallibleTArray<AnimationProperty>& aResult)
|
||||
{
|
||||
// While current drafts of css3-animations say that later keyframes
|
||||
// with the same key entirely replace earlier ones (no cascading),
|
||||
// this is a bad idea and contradictory to the rest of CSS. So
|
||||
|
@ -630,9 +699,9 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
|||
|
||||
AutoTArray<KeyframeData, 16> sortedKeyframes;
|
||||
|
||||
for (uint32_t ruleIdx = 0, ruleEnd = rule->StyleRuleCount();
|
||||
for (uint32_t ruleIdx = 0, ruleEnd = aRule->StyleRuleCount();
|
||||
ruleIdx != ruleEnd; ++ruleIdx) {
|
||||
css::Rule* cssRule = rule->GetStyleRuleAt(ruleIdx);
|
||||
css::Rule* cssRule = aRule->GetStyleRuleAt(ruleIdx);
|
||||
MOZ_ASSERT(cssRule, "must have rule");
|
||||
MOZ_ASSERT(cssRule->GetType() == css::Rule::KEYFRAME_RULE,
|
||||
"must be keyframe rule");
|
||||
|
@ -657,7 +726,7 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
|||
|
||||
if (sortedKeyframes.Length() == 0) {
|
||||
// no segments
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
// Record the properties that are present in any keyframe rules we
|
||||
|
@ -706,7 +775,7 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
|||
lastKey = kf.mKey;
|
||||
}
|
||||
|
||||
AnimationProperty &propData = *destEffect->Properties().AppendElement();
|
||||
AnimationProperty &propData = *aResult.AppendElement();
|
||||
propData.mProperty = prop;
|
||||
|
||||
KeyframeData *fromKeyframe = nullptr;
|
||||
|
@ -718,12 +787,12 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
|||
KeyframeData &toKeyframe = sortedKeyframes[kfIdx];
|
||||
|
||||
RefPtr<nsStyleContext> toContext =
|
||||
resolvedStyles.Get(mPresContext, aStyleContext,
|
||||
mResolvedStyles.Get(aPresContext, mStyleContext,
|
||||
toKeyframe.mRule->Declaration());
|
||||
|
||||
if (fromKeyframe) {
|
||||
interpolated = interpolated &&
|
||||
BuildSegment(propData.mSegments, prop, src,
|
||||
BuildSegment(propData.mSegments, prop, aSrc,
|
||||
fromKeyframe->mKey, fromContext,
|
||||
fromKeyframe->mRule->Declaration(),
|
||||
toKeyframe.mKey, toContext);
|
||||
|
@ -731,17 +800,17 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
|||
if (toKeyframe.mKey != 0.0f) {
|
||||
// There's no data for this property at 0%, so use the
|
||||
// cascaded value above us.
|
||||
if (!styleWithoutAnimation) {
|
||||
MOZ_ASSERT(mPresContext->StyleSet()->IsGecko(),
|
||||
if (!mStyleWithoutAnimation) {
|
||||
MOZ_ASSERT(aPresContext->StyleSet()->IsGecko(),
|
||||
"ServoStyleSet should not use nsAnimationManager for "
|
||||
"animations");
|
||||
styleWithoutAnimation = mPresContext->StyleSet()->AsGecko()->
|
||||
ResolveStyleWithoutAnimation(aTarget, aStyleContext,
|
||||
mStyleWithoutAnimation = aPresContext->StyleSet()->AsGecko()->
|
||||
ResolveStyleWithoutAnimation(mTarget, mStyleContext,
|
||||
eRestyle_AllHintsWithAnimations);
|
||||
}
|
||||
interpolated = interpolated &&
|
||||
BuildSegment(propData.mSegments, prop, src,
|
||||
0.0f, styleWithoutAnimation, nullptr,
|
||||
BuildSegment(propData.mSegments, prop, aSrc,
|
||||
0.0f, mStyleWithoutAnimation, nullptr,
|
||||
toKeyframe.mKey, toContext);
|
||||
}
|
||||
}
|
||||
|
@ -753,19 +822,19 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
|||
if (fromKeyframe->mKey != 1.0f) {
|
||||
// There's no data for this property at 100%, so use the
|
||||
// cascaded value above us.
|
||||
if (!styleWithoutAnimation) {
|
||||
MOZ_ASSERT(mPresContext->StyleSet()->IsGecko(),
|
||||
if (!mStyleWithoutAnimation) {
|
||||
MOZ_ASSERT(aPresContext->StyleSet()->IsGecko(),
|
||||
"ServoStyleSet should not use nsAnimationManager for "
|
||||
"animations");
|
||||
styleWithoutAnimation = mPresContext->StyleSet()->AsGecko()->
|
||||
ResolveStyleWithoutAnimation(aTarget, aStyleContext,
|
||||
mStyleWithoutAnimation = aPresContext->StyleSet()->AsGecko()->
|
||||
ResolveStyleWithoutAnimation(mTarget, mStyleContext,
|
||||
eRestyle_AllHintsWithAnimations);
|
||||
}
|
||||
interpolated = interpolated &&
|
||||
BuildSegment(propData.mSegments, prop, src,
|
||||
BuildSegment(propData.mSegments, prop, aSrc,
|
||||
fromKeyframe->mKey, fromContext,
|
||||
fromKeyframe->mRule->Declaration(),
|
||||
1.0f, styleWithoutAnimation);
|
||||
1.0f, mStyleWithoutAnimation);
|
||||
}
|
||||
|
||||
// If we failed to build any segments due to inability to
|
||||
|
@ -775,15 +844,13 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
|||
// values (which?) or skip segments, so best to skip the whole
|
||||
// thing for now.)
|
||||
if (!interpolated) {
|
||||
destEffect->Properties().RemoveElementAt(
|
||||
destEffect->Properties().Length() - 1);
|
||||
}
|
||||
aResult.RemoveElementAt(aResult.Length() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsAnimationManager::BuildSegment(InfallibleTArray<AnimationPropertySegment>&
|
||||
CSSAnimationBuilder::BuildSegment(InfallibleTArray<AnimationPropertySegment>&
|
||||
aSegments,
|
||||
nsCSSProperty aProperty,
|
||||
const StyleAnimation& aAnimation,
|
||||
|
@ -792,8 +859,12 @@ nsAnimationManager::BuildSegment(InfallibleTArray<AnimationPropertySegment>&
|
|||
float aToKey, nsStyleContext* aToContext)
|
||||
{
|
||||
StyleAnimationValue fromValue, toValue, dummyValue;
|
||||
if (!ExtractComputedValueForTransition(aProperty, aFromContext, fromValue) ||
|
||||
!ExtractComputedValueForTransition(aProperty, aToContext, toValue) ||
|
||||
if (!CommonAnimationManager::ExtractComputedValueForTransition(aProperty,
|
||||
aFromContext,
|
||||
fromValue) ||
|
||||
!CommonAnimationManager::ExtractComputedValueForTransition(aProperty,
|
||||
aToContext,
|
||||
toValue) ||
|
||||
// Check that we can interpolate between these values
|
||||
// (If this is ever a performance problem, we could add a
|
||||
// CanInterpolate method, but it seems fine for now.)
|
||||
|
|
|
@ -349,13 +349,6 @@ private:
|
|||
mozilla::dom::Element* aTarget,
|
||||
mozilla::dom::AnimationTimeline* aTimeline,
|
||||
mozilla::AnimationPtrArray& aAnimations);
|
||||
bool BuildSegment(InfallibleTArray<mozilla::AnimationPropertySegment>&
|
||||
aSegments,
|
||||
nsCSSProperty aProperty,
|
||||
const mozilla::StyleAnimation& aAnimation,
|
||||
float aFromKey, nsStyleContext* aFromContext,
|
||||
mozilla::css::Declaration* aFromDeclaration,
|
||||
float aToKey, nsStyleContext* aToContext);
|
||||
};
|
||||
|
||||
#endif /* !defined(nsAnimationManager_h_) */
|
||||
|
|
Загрузка…
Ссылка в новой задаче