зеркало из 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;
|
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
|
void
|
||||||
nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
||||||
dom::Element* aTarget,
|
dom::Element* aTarget,
|
||||||
|
@ -568,11 +646,9 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aAnimations.IsEmpty(), "expect empty array");
|
MOZ_ASSERT(aAnimations.IsEmpty(), "expect empty array");
|
||||||
|
|
||||||
ResolvedStyleCache resolvedStyles;
|
|
||||||
|
|
||||||
const nsStyleDisplay *disp = aStyleContext->StyleDisplay();
|
const nsStyleDisplay *disp = aStyleContext->StyleDisplay();
|
||||||
|
|
||||||
RefPtr<nsStyleContext> styleWithoutAnimation;
|
CSSAnimationBuilder builder(aStyleContext, aTarget);
|
||||||
|
|
||||||
for (size_t animIdx = 0, animEnd = disp->mAnimationNameCount;
|
for (size_t animIdx = 0, animEnd = disp->mAnimationNameCount;
|
||||||
animIdx != animEnd; ++animIdx) {
|
animIdx != animEnd; ++animIdx) {
|
||||||
|
@ -594,206 +670,201 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<CSSAnimation> dest =
|
RefPtr<CSSAnimation> dest = builder.Build(mPresContext, src, rule);
|
||||||
new CSSAnimation(mPresContext->Document()->GetScopeObject(),
|
|
||||||
src.GetName());
|
|
||||||
dest->SetOwningElement(
|
|
||||||
OwningElementRef(*aTarget, aStyleContext->GetPseudoType()));
|
|
||||||
dest->SetTimeline(aTimeline);
|
dest->SetTimeline(aTimeline);
|
||||||
dest->SetAnimationIndex(static_cast<uint64_t>(animIdx));
|
dest->SetAnimationIndex(static_cast<uint64_t>(animIdx));
|
||||||
aAnimations.AppendElement(dest);
|
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) {
|
if (src.GetPlayState() == NS_STYLE_ANIMATION_PLAY_STATE_PAUSED) {
|
||||||
dest->PauseFromStyle();
|
dest->PauseFromStyle();
|
||||||
} else {
|
} else {
|
||||||
dest->PlayFromStyle();
|
dest->PlayFromStyle();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// While current drafts of css3-animations say that later keyframes
|
void
|
||||||
// with the same key entirely replace earlier ones (no cascading),
|
CSSAnimationBuilder::BuildAnimationProperties(
|
||||||
// this is a bad idea and contradictory to the rest of CSS. So
|
nsPresContext* aPresContext,
|
||||||
// we're going to keep all the keyframes for each key and then do
|
const StyleAnimation& aSrc,
|
||||||
// the replacement on a per-property basis rather than a per-rule
|
const nsCSSKeyframesRule* aRule,
|
||||||
// basis, just like everything else in CSS.
|
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
|
||||||
|
// we're going to keep all the keyframes for each key and then do
|
||||||
|
// the replacement on a per-property basis rather than a per-rule
|
||||||
|
// basis, just like everything else in CSS.
|
||||||
|
|
||||||
AutoTArray<KeyframeData, 16> sortedKeyframes;
|
AutoTArray<KeyframeData, 16> sortedKeyframes;
|
||||||
|
|
||||||
for (uint32_t ruleIdx = 0, ruleEnd = rule->StyleRuleCount();
|
for (uint32_t ruleIdx = 0, ruleEnd = aRule->StyleRuleCount();
|
||||||
ruleIdx != ruleEnd; ++ruleIdx) {
|
ruleIdx != ruleEnd; ++ruleIdx) {
|
||||||
css::Rule* cssRule = rule->GetStyleRuleAt(ruleIdx);
|
css::Rule* cssRule = aRule->GetStyleRuleAt(ruleIdx);
|
||||||
MOZ_ASSERT(cssRule, "must have rule");
|
MOZ_ASSERT(cssRule, "must have rule");
|
||||||
MOZ_ASSERT(cssRule->GetType() == css::Rule::KEYFRAME_RULE,
|
MOZ_ASSERT(cssRule->GetType() == css::Rule::KEYFRAME_RULE,
|
||||||
"must be keyframe rule");
|
"must be keyframe rule");
|
||||||
nsCSSKeyframeRule *kfRule = static_cast<nsCSSKeyframeRule*>(cssRule);
|
nsCSSKeyframeRule *kfRule = static_cast<nsCSSKeyframeRule*>(cssRule);
|
||||||
|
|
||||||
const nsTArray<float> &keys = kfRule->GetKeys();
|
const nsTArray<float> &keys = kfRule->GetKeys();
|
||||||
for (uint32_t keyIdx = 0, keyEnd = keys.Length();
|
for (uint32_t keyIdx = 0, keyEnd = keys.Length();
|
||||||
keyIdx != keyEnd; ++keyIdx) {
|
keyIdx != keyEnd; ++keyIdx) {
|
||||||
float key = keys[keyIdx];
|
float key = keys[keyIdx];
|
||||||
// FIXME (spec): The spec doesn't say what to do with
|
// FIXME (spec): The spec doesn't say what to do with
|
||||||
// out-of-range keyframes. We'll ignore them.
|
// out-of-range keyframes. We'll ignore them.
|
||||||
if (0.0f <= key && key <= 1.0f) {
|
if (0.0f <= key && key <= 1.0f) {
|
||||||
KeyframeData *data = sortedKeyframes.AppendElement();
|
KeyframeData *data = sortedKeyframes.AppendElement();
|
||||||
data->mKey = key;
|
data->mKey = key;
|
||||||
data->mIndex = ruleIdx;
|
data->mIndex = ruleIdx;
|
||||||
data->mRule = kfRule;
|
data->mRule = kfRule;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sortedKeyframes.Sort(KeyframeDataComparator());
|
sortedKeyframes.Sort(KeyframeDataComparator());
|
||||||
|
|
||||||
if (sortedKeyframes.Length() == 0) {
|
if (sortedKeyframes.Length() == 0) {
|
||||||
// no segments
|
// no segments
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the properties that are present in any keyframe rules we
|
||||||
|
// are using.
|
||||||
|
nsCSSPropertySet properties;
|
||||||
|
|
||||||
|
for (uint32_t kfIdx = 0, kfEnd = sortedKeyframes.Length();
|
||||||
|
kfIdx != kfEnd; ++kfIdx) {
|
||||||
|
css::Declaration *decl = sortedKeyframes[kfIdx].mRule->Declaration();
|
||||||
|
for (uint32_t propIdx = 0, propEnd = decl->Count();
|
||||||
|
propIdx != propEnd; ++propIdx) {
|
||||||
|
nsCSSProperty prop = decl->GetPropertyAt(propIdx);
|
||||||
|
if (prop != eCSSPropertyExtra_variable) {
|
||||||
|
// CSS Variables are not animatable
|
||||||
|
properties.AddProperty(prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (nsCSSProperty prop = nsCSSProperty(0);
|
||||||
|
prop < eCSSProperty_COUNT_no_shorthands;
|
||||||
|
prop = nsCSSProperty(prop + 1)) {
|
||||||
|
if (!properties.HasProperty(prop) ||
|
||||||
|
nsCSSProps::kAnimTypeTable[prop] == eStyleAnimType_None) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record the properties that are present in any keyframe rules we
|
// Build a list of the keyframes to use for this property. This
|
||||||
// are using.
|
// means we need every keyframe with the property in it, except
|
||||||
nsCSSPropertySet properties;
|
// for those keyframes where a later keyframe with the *same key*
|
||||||
|
// also has the property.
|
||||||
|
AutoTArray<uint32_t, 16> keyframesWithProperty;
|
||||||
|
float lastKey = 100.0f; // an invalid key
|
||||||
for (uint32_t kfIdx = 0, kfEnd = sortedKeyframes.Length();
|
for (uint32_t kfIdx = 0, kfEnd = sortedKeyframes.Length();
|
||||||
kfIdx != kfEnd; ++kfIdx) {
|
kfIdx != kfEnd; ++kfIdx) {
|
||||||
css::Declaration *decl = sortedKeyframes[kfIdx].mRule->Declaration();
|
KeyframeData &kf = sortedKeyframes[kfIdx];
|
||||||
for (uint32_t propIdx = 0, propEnd = decl->Count();
|
if (!kf.mRule->Declaration()->HasProperty(prop)) {
|
||||||
propIdx != propEnd; ++propIdx) {
|
|
||||||
nsCSSProperty prop = decl->GetPropertyAt(propIdx);
|
|
||||||
if (prop != eCSSPropertyExtra_variable) {
|
|
||||||
// CSS Variables are not animatable
|
|
||||||
properties.AddProperty(prop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (nsCSSProperty prop = nsCSSProperty(0);
|
|
||||||
prop < eCSSProperty_COUNT_no_shorthands;
|
|
||||||
prop = nsCSSProperty(prop + 1)) {
|
|
||||||
if (!properties.HasProperty(prop) ||
|
|
||||||
nsCSSProps::kAnimTypeTable[prop] == eStyleAnimType_None) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (kf.mKey == lastKey) {
|
||||||
// Build a list of the keyframes to use for this property. This
|
// Replace previous occurrence of same key.
|
||||||
// means we need every keyframe with the property in it, except
|
keyframesWithProperty[keyframesWithProperty.Length() - 1] = kfIdx;
|
||||||
// for those keyframes where a later keyframe with the *same key*
|
} else {
|
||||||
// also has the property.
|
keyframesWithProperty.AppendElement(kfIdx);
|
||||||
AutoTArray<uint32_t, 16> keyframesWithProperty;
|
|
||||||
float lastKey = 100.0f; // an invalid key
|
|
||||||
for (uint32_t kfIdx = 0, kfEnd = sortedKeyframes.Length();
|
|
||||||
kfIdx != kfEnd; ++kfIdx) {
|
|
||||||
KeyframeData &kf = sortedKeyframes[kfIdx];
|
|
||||||
if (!kf.mRule->Declaration()->HasProperty(prop)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (kf.mKey == lastKey) {
|
|
||||||
// Replace previous occurrence of same key.
|
|
||||||
keyframesWithProperty[keyframesWithProperty.Length() - 1] = kfIdx;
|
|
||||||
} else {
|
|
||||||
keyframesWithProperty.AppendElement(kfIdx);
|
|
||||||
}
|
|
||||||
lastKey = kf.mKey;
|
|
||||||
}
|
}
|
||||||
|
lastKey = kf.mKey;
|
||||||
|
}
|
||||||
|
|
||||||
AnimationProperty &propData = *destEffect->Properties().AppendElement();
|
AnimationProperty &propData = *aResult.AppendElement();
|
||||||
propData.mProperty = prop;
|
propData.mProperty = prop;
|
||||||
|
|
||||||
KeyframeData *fromKeyframe = nullptr;
|
KeyframeData *fromKeyframe = nullptr;
|
||||||
RefPtr<nsStyleContext> fromContext;
|
RefPtr<nsStyleContext> fromContext;
|
||||||
bool interpolated = true;
|
bool interpolated = true;
|
||||||
for (uint32_t wpIdx = 0, wpEnd = keyframesWithProperty.Length();
|
for (uint32_t wpIdx = 0, wpEnd = keyframesWithProperty.Length();
|
||||||
wpIdx != wpEnd; ++wpIdx) {
|
wpIdx != wpEnd; ++wpIdx) {
|
||||||
uint32_t kfIdx = keyframesWithProperty[wpIdx];
|
uint32_t kfIdx = keyframesWithProperty[wpIdx];
|
||||||
KeyframeData &toKeyframe = sortedKeyframes[kfIdx];
|
KeyframeData &toKeyframe = sortedKeyframes[kfIdx];
|
||||||
|
|
||||||
RefPtr<nsStyleContext> toContext =
|
RefPtr<nsStyleContext> toContext =
|
||||||
resolvedStyles.Get(mPresContext, aStyleContext,
|
mResolvedStyles.Get(aPresContext, mStyleContext,
|
||||||
toKeyframe.mRule->Declaration());
|
toKeyframe.mRule->Declaration());
|
||||||
|
|
||||||
if (fromKeyframe) {
|
if (fromKeyframe) {
|
||||||
interpolated = interpolated &&
|
|
||||||
BuildSegment(propData.mSegments, prop, src,
|
|
||||||
fromKeyframe->mKey, fromContext,
|
|
||||||
fromKeyframe->mRule->Declaration(),
|
|
||||||
toKeyframe.mKey, toContext);
|
|
||||||
} else {
|
|
||||||
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(),
|
|
||||||
"ServoStyleSet should not use nsAnimationManager for "
|
|
||||||
"animations");
|
|
||||||
styleWithoutAnimation = mPresContext->StyleSet()->AsGecko()->
|
|
||||||
ResolveStyleWithoutAnimation(aTarget, aStyleContext,
|
|
||||||
eRestyle_AllHintsWithAnimations);
|
|
||||||
}
|
|
||||||
interpolated = interpolated &&
|
|
||||||
BuildSegment(propData.mSegments, prop, src,
|
|
||||||
0.0f, styleWithoutAnimation, nullptr,
|
|
||||||
toKeyframe.mKey, toContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fromContext = toContext;
|
|
||||||
fromKeyframe = &toKeyframe;
|
|
||||||
}
|
|
||||||
|
|
||||||
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(),
|
|
||||||
"ServoStyleSet should not use nsAnimationManager for "
|
|
||||||
"animations");
|
|
||||||
styleWithoutAnimation = mPresContext->StyleSet()->AsGecko()->
|
|
||||||
ResolveStyleWithoutAnimation(aTarget, aStyleContext,
|
|
||||||
eRestyle_AllHintsWithAnimations);
|
|
||||||
}
|
|
||||||
interpolated = interpolated &&
|
interpolated = interpolated &&
|
||||||
BuildSegment(propData.mSegments, prop, src,
|
BuildSegment(propData.mSegments, prop, aSrc,
|
||||||
fromKeyframe->mKey, fromContext,
|
fromKeyframe->mKey, fromContext,
|
||||||
fromKeyframe->mRule->Declaration(),
|
fromKeyframe->mRule->Declaration(),
|
||||||
1.0f, styleWithoutAnimation);
|
toKeyframe.mKey, toContext);
|
||||||
|
} else {
|
||||||
|
if (toKeyframe.mKey != 0.0f) {
|
||||||
|
// There's no data for this property at 0%, so use the
|
||||||
|
// cascaded value above us.
|
||||||
|
if (!mStyleWithoutAnimation) {
|
||||||
|
MOZ_ASSERT(aPresContext->StyleSet()->IsGecko(),
|
||||||
|
"ServoStyleSet should not use nsAnimationManager for "
|
||||||
|
"animations");
|
||||||
|
mStyleWithoutAnimation = aPresContext->StyleSet()->AsGecko()->
|
||||||
|
ResolveStyleWithoutAnimation(mTarget, mStyleContext,
|
||||||
|
eRestyle_AllHintsWithAnimations);
|
||||||
|
}
|
||||||
|
interpolated = interpolated &&
|
||||||
|
BuildSegment(propData.mSegments, prop, aSrc,
|
||||||
|
0.0f, mStyleWithoutAnimation, nullptr,
|
||||||
|
toKeyframe.mKey, toContext);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we failed to build any segments due to inability to
|
fromContext = toContext;
|
||||||
// interpolate, remove the property from the animation. (It's not
|
fromKeyframe = &toKeyframe;
|
||||||
// clear if this is the right thing to do -- we could run some of
|
}
|
||||||
// the segments, but it's really not clear whether we should skip
|
|
||||||
// values (which?) or skip segments, so best to skip the whole
|
if (fromKeyframe->mKey != 1.0f) {
|
||||||
// thing for now.)
|
// There's no data for this property at 100%, so use the
|
||||||
if (!interpolated) {
|
// cascaded value above us.
|
||||||
destEffect->Properties().RemoveElementAt(
|
if (!mStyleWithoutAnimation) {
|
||||||
destEffect->Properties().Length() - 1);
|
MOZ_ASSERT(aPresContext->StyleSet()->IsGecko(),
|
||||||
|
"ServoStyleSet should not use nsAnimationManager for "
|
||||||
|
"animations");
|
||||||
|
mStyleWithoutAnimation = aPresContext->StyleSet()->AsGecko()->
|
||||||
|
ResolveStyleWithoutAnimation(mTarget, mStyleContext,
|
||||||
|
eRestyle_AllHintsWithAnimations);
|
||||||
}
|
}
|
||||||
|
interpolated = interpolated &&
|
||||||
|
BuildSegment(propData.mSegments, prop, aSrc,
|
||||||
|
fromKeyframe->mKey, fromContext,
|
||||||
|
fromKeyframe->mRule->Declaration(),
|
||||||
|
1.0f, mStyleWithoutAnimation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we failed to build any segments due to inability to
|
||||||
|
// interpolate, remove the property from the animation. (It's not
|
||||||
|
// clear if this is the right thing to do -- we could run some of
|
||||||
|
// the segments, but it's really not clear whether we should skip
|
||||||
|
// values (which?) or skip segments, so best to skip the whole
|
||||||
|
// thing for now.)
|
||||||
|
if (!interpolated) {
|
||||||
|
aResult.RemoveElementAt(aResult.Length() - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsAnimationManager::BuildSegment(InfallibleTArray<AnimationPropertySegment>&
|
CSSAnimationBuilder::BuildSegment(InfallibleTArray<AnimationPropertySegment>&
|
||||||
aSegments,
|
aSegments,
|
||||||
nsCSSProperty aProperty,
|
nsCSSProperty aProperty,
|
||||||
const StyleAnimation& aAnimation,
|
const StyleAnimation& aAnimation,
|
||||||
float aFromKey, nsStyleContext* aFromContext,
|
float aFromKey, nsStyleContext* aFromContext,
|
||||||
mozilla::css::Declaration* aFromDeclaration,
|
mozilla::css::Declaration* aFromDeclaration,
|
||||||
float aToKey, nsStyleContext* aToContext)
|
float aToKey, nsStyleContext* aToContext)
|
||||||
{
|
{
|
||||||
StyleAnimationValue fromValue, toValue, dummyValue;
|
StyleAnimationValue fromValue, toValue, dummyValue;
|
||||||
if (!ExtractComputedValueForTransition(aProperty, aFromContext, fromValue) ||
|
if (!CommonAnimationManager::ExtractComputedValueForTransition(aProperty,
|
||||||
!ExtractComputedValueForTransition(aProperty, aToContext, toValue) ||
|
aFromContext,
|
||||||
|
fromValue) ||
|
||||||
|
!CommonAnimationManager::ExtractComputedValueForTransition(aProperty,
|
||||||
|
aToContext,
|
||||||
|
toValue) ||
|
||||||
// Check that we can interpolate between these values
|
// Check that we can interpolate between these values
|
||||||
// (If this is ever a performance problem, we could add a
|
// (If this is ever a performance problem, we could add a
|
||||||
// CanInterpolate method, but it seems fine for now.)
|
// CanInterpolate method, but it seems fine for now.)
|
||||||
|
|
|
@ -349,13 +349,6 @@ private:
|
||||||
mozilla::dom::Element* aTarget,
|
mozilla::dom::Element* aTarget,
|
||||||
mozilla::dom::AnimationTimeline* aTimeline,
|
mozilla::dom::AnimationTimeline* aTimeline,
|
||||||
mozilla::AnimationPtrArray& aAnimations);
|
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_) */
|
#endif /* !defined(nsAnimationManager_h_) */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче