diff --git a/dom/animation/ComputedTimingFunction.cpp b/dom/animation/ComputedTimingFunction.cpp index 2d7c321d823a..e792ec6f0d92 100644 --- a/dom/animation/ComputedTimingFunction.cpp +++ b/dom/animation/ComputedTimingFunction.cpp @@ -96,4 +96,29 @@ ComputedTimingFunction::AppendToString(nsAString& aResult) const } } +/* static */ int32_t +ComputedTimingFunction::Compare(const Maybe& aLhs, + const Maybe& aRhs) +{ + // We can't use |operator<| for const Maybe<>& here because + // 'ease' is prior to 'linear' which is represented by Nothing(). + // So we have to convert Nothing() as 'linear' and check it first. + nsTimingFunction::Type lhsType = aLhs.isNothing() ? + nsTimingFunction::Type::Linear : aLhs->GetType(); + nsTimingFunction::Type rhsType = aRhs.isNothing() ? + nsTimingFunction::Type::Linear : aRhs->GetType(); + + if (lhsType != rhsType) { + return int32_t(lhsType) - int32_t(rhsType); + } + + // Both of them are Nothing(). + if (lhsType == nsTimingFunction::Type::Linear) { + return 0; + } + + // Other types. + return aLhs->Compare(aRhs.value()); +} + } // namespace mozilla diff --git a/dom/animation/ComputedTimingFunction.h b/dom/animation/ComputedTimingFunction.h index c865a924b51c..5c7e578f27a6 100644 --- a/dom/animation/ComputedTimingFunction.h +++ b/dom/animation/ComputedTimingFunction.h @@ -46,6 +46,8 @@ public: { return aFunction.isSome() ? aFunction->GetValue(aPortion) : aPortion; } + static int32_t Compare(const Maybe& aLhs, + const Maybe& aRhs); private: nsTimingFunction::Type mType; diff --git a/dom/animation/KeyframeEffect.cpp b/dom/animation/KeyframeEffect.cpp index f5eab07f1977..9190792a5c1b 100644 --- a/dom/animation/KeyframeEffect.cpp +++ b/dom/animation/KeyframeEffect.cpp @@ -678,7 +678,7 @@ enum class ValuePosition struct OrderedKeyframeValueEntry : KeyframeValue { float mOffset; - const ComputedTimingFunction* mTimingFunction; + const Maybe* mTimingFunction; ValuePosition mPosition; bool SameKeyframe(const OrderedKeyframeValueEntry& aOther) const @@ -713,7 +713,9 @@ struct OrderedKeyframeValueEntry : KeyframeValue // Third, by easing. if (aLhs.mTimingFunction) { if (aRhs.mTimingFunction) { - int32_t order = aLhs.mTimingFunction->Compare(*aRhs.mTimingFunction); + int32_t order = + ComputedTimingFunction::Compare(*aLhs.mTimingFunction, + *aRhs.mTimingFunction); if (order != 0) { return order < 0; } @@ -1648,14 +1650,6 @@ KeyframeEffectReadOnly::GetFrames(JSContext*& aCx, { nsTArray entries; - // We need a linear function here to sort key frames correctly. - // mTimingFunction in AnimationPropertySegment is Nothing() in case of - // the timing function is 'linear'. So if the mTimingFunction is - // Nothing(), we need a dummy ComputedTimingFunction to be passed to - // ComputedTimingFunction::Compare. - ComputedTimingFunction linear; - linear.Init(nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR)); - for (const AnimationProperty& property : mProperties) { for (size_t i = 0, n = property.mSegments.Length(); i < n; i++) { const AnimationPropertySegment& segment = property.mSegments[i]; @@ -1678,7 +1672,7 @@ KeyframeEffectReadOnly::GetFrames(JSContext*& aCx, entry->mProperty = property.mProperty; entry->mValue = segment.mFromValue; entry->mOffset = segment.mFromKey; - entry->mTimingFunction = segment.mTimingFunction.ptrOr(&linear); + entry->mTimingFunction = &segment.mTimingFunction; entry->mPosition = segment.mFromKey == segment.mToKey && segment.mFromKey == 0.0f ? ValuePosition::First : @@ -1691,8 +1685,7 @@ KeyframeEffectReadOnly::GetFrames(JSContext*& aCx, entry->mValue = segment.mToValue; entry->mOffset = segment.mToKey; entry->mTimingFunction = segment.mToKey == 1.0f ? - nullptr : - segment.mTimingFunction.ptrOr(&linear); + nullptr : &segment.mTimingFunction; entry->mPosition = segment.mFromKey == segment.mToKey && segment.mToKey == 1.0f ? ValuePosition::Last : @@ -1711,10 +1704,10 @@ KeyframeEffectReadOnly::GetFrames(JSContext*& aCx, ComputedKeyframe keyframeDict; keyframeDict.mOffset.SetValue(entry->mOffset); keyframeDict.mComputedOffset.Construct(entry->mOffset); - if (entry->mTimingFunction) { + if (entry->mTimingFunction && entry->mTimingFunction->isSome()) { // If null, leave easing as its default "linear". keyframeDict.mEasing.Truncate(); - entry->mTimingFunction->AppendToString(keyframeDict.mEasing); + entry->mTimingFunction->value().AppendToString(keyframeDict.mEasing); } keyframeDict.mComposite.SetValue(CompositeOperation::Replace);