--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -475,31 +475,16 @@ nsAnimationManager::StopAnimationsForEle
if (!collection) {
return;
}
nsAutoAnimationMutationBatch mb(aElement->OwnerDoc());
collection->Destroy();
}
-struct KeyframeData {
- float mKey;
- uint32_t mIndex; // store original order since sort algorithm is not stable
- nsCSSKeyframeRule *mRule;
-};
-
-struct KeyframeDataComparator {
- bool Equals(const KeyframeData& A, const KeyframeData& B) const {
- return A.mKey == B.mKey && A.mIndex == B.mIndex;
- }
- bool LessThan(const KeyframeData& A, const KeyframeData& B) const {
- return A.mKey < B.mKey || (A.mKey == B.mKey && A.mIndex < B.mIndex);
- }
-};
-
class ResolvedStyleCache {
public:
ResolvedStyleCache() : mCache() {}
nsStyleContext* Get(nsPresContext *aPresContext,
nsStyleContext *aParentStyleContext,
Declaration* aKeyframeDeclaration);
private:
@@ -558,27 +543,16 @@ public:
// Or returns an existing animation matching StyleAnimation's name updated
// with the new StyleAnimation and keyframe rules.
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);
nsTArray<Keyframe> BuildAnimationFrames(nsPresContext* aPresContext,
const StyleAnimation& aSrc,
const nsCSSKeyframesRule* aRule);
Maybe<ComputedTimingFunction> GetKeyframeTimingFunction(
nsPresContext* aPresContext,
nsCSSKeyframeRule* aKeyframeRule,
const Maybe<ComputedTimingFunction>& aInheritedTimingFunction);
nsTArray<PropertyValuePair> GetKeyframePropertyValues(
@@ -692,226 +666,16 @@ CSSAnimationBuilder::Build(nsPresContext
// dispatched within the same tick as the animation is added
// so we need to queue up any animationstart events from newly-created
// animations.
animation->QueueEvents();
return animation.forget();
}
-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
- // 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;
-
- for (uint32_t ruleIdx = 0, ruleEnd = aRule->StyleRuleCount();
- ruleIdx != ruleEnd; ++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");
- nsCSSKeyframeRule *kfRule = static_cast<nsCSSKeyframeRule*>(cssRule);
-
- const nsTArray<float> &keys = kfRule->GetKeys();
- for (uint32_t keyIdx = 0, keyEnd = keys.Length();
- keyIdx != keyEnd; ++keyIdx) {
- float key = keys[keyIdx];
- // FIXME (spec): The spec doesn't say what to do with
- // out-of-range keyframes. We'll ignore them.
- if (0.0f <= key && key <= 1.0f) {
- KeyframeData *data = sortedKeyframes.AppendElement();
- data->mKey = key;
- data->mIndex = ruleIdx;
- data->mRule = kfRule;
- }
- }
- }
-
- sortedKeyframes.Sort(KeyframeDataComparator());
-
- if (sortedKeyframes.Length() == 0) {
- // 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;
- }
-
- // Build a list of the keyframes to use for this property. This
- // means we need every keyframe with the property in it, except
- // 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();
- 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;
- }
-
- AnimationProperty &propData = *aResult.AppendElement();
- propData.mProperty = prop;
-
- KeyframeData *fromKeyframe = nullptr;
- RefPtr<nsStyleContext> fromContext;
- bool interpolated = true;
- for (uint32_t wpIdx = 0, wpEnd = keyframesWithProperty.Length();
- wpIdx != wpEnd; ++wpIdx) {
- uint32_t kfIdx = keyframesWithProperty[wpIdx];
- KeyframeData &toKeyframe = sortedKeyframes[kfIdx];
-
- RefPtr<nsStyleContext> toContext =
- mResolvedStyles.Get(aPresContext, mStyleContext,
- toKeyframe.mRule->Declaration());
-
- if (fromKeyframe) {
- interpolated = interpolated &&
- BuildSegment(propData.mSegments, prop, aSrc,
- 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 (!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);
- }
- }
-
- 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 (!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,
- 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
-CSSAnimationBuilder::BuildSegment(InfallibleTArray<AnimationPropertySegment>&
- aSegments,
- nsCSSProperty aProperty,
- const StyleAnimation& aAnimation,
- float aFromKey, nsStyleContext* aFromContext,
- mozilla::css::Declaration* aFromDeclaration,
- float aToKey, nsStyleContext* aToContext)
-{
- StyleAnimationValue fromValue, toValue, dummyValue;
- if (!CommonAnimationManager<CSSAnimation>::ExtractComputedValueForTransition(
- aProperty, aFromContext, fromValue) ||
- !CommonAnimationManager<CSSAnimation>::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.)
- !StyleAnimationValue::Interpolate(aProperty, fromValue, toValue,
- 0.5, dummyValue)) {
- return false;
- }
-
- AnimationPropertySegment &segment = *aSegments.AppendElement();
-
- segment.mFromValue = fromValue;
- segment.mToValue = toValue;
- segment.mFromKey = aFromKey;
- segment.mToKey = aToKey;
- const nsTimingFunction *tf;
- if (aFromDeclaration &&
- aFromDeclaration->HasProperty(eCSSProperty_animation_timing_function)) {
- tf = &aFromContext->StyleDisplay()->mAnimations[0].GetTimingFunction();
- } else {
- tf = &aAnimation.GetTimingFunction();
- }
- if (tf->mType != nsTimingFunction::Type::Linear) {
- ComputedTimingFunction computedTimingFunction;
- computedTimingFunction.Init(*tf);
- segment.mTimingFunction = Some(computedTimingFunction);
- }
-
- return true;
-}
-
nsTArray<Keyframe>
CSSAnimationBuilder::BuildAnimationFrames(nsPresContext* aPresContext,
const StyleAnimation& aSrc,
const nsCSSKeyframesRule* aRule)
{
// Ideally we'd like to build up a set of Keyframe objects that more-or-less
// reflects the keyframes as-specified in the @keyframes rule(s). However,
// that proves to be difficult because the way CSS declarations are processed