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:
Hiroyuki Ikezoe 2016-02-19 09:16:15 +09:00
Родитель 41d21a5791
Коммит ed1cf18658
2 изменённых файлов: 231 добавлений и 167 удалений

Просмотреть файл

@ -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_) */