--- a/dom/animation/KeyframeEffectReadOnly.cpp
+++ b/dom/animation/KeyframeEffectReadOnly.cpp
@@ -492,16 +492,19 @@ KeyframeEffectReadOnly::ComposeStyle(
// Note, however, that we don't actually send animations with a negative
// playback rate in their end delay phase to the compositor at this stage
// (bug 1330498).
EnsureBaseStylesForCompositor(aPropertiesToSkip);
return;
}
+ nsPresContext* presContext = GetPresContext();
+ bool isServoBackend = presContext && presContext->StyleSet()->IsServo();
+
mNeedsBaseStyleSet.Empty();
for (size_t propIdx = 0, propEnd = mProperties.Length();
propIdx != propEnd; ++propIdx)
{
const AnimationProperty& prop = mProperties[propIdx];
MOZ_ASSERT(prop.mSegments[0].mFromKey == 0.0, "incorrect first from key");
@@ -527,82 +530,141 @@ KeyframeEffectReadOnly::ComposeStyle(
MOZ_ASSERT(segment->mFromKey == (segment-1)->mToKey, "incorrect keys");
}
MOZ_ASSERT(segment->mFromKey <= segment->mToKey, "incorrect keys");
MOZ_ASSERT(segment >= prop.mSegments.Elements() &&
size_t(segment - prop.mSegments.Elements()) <
prop.mSegments.Length(),
"out of array bounds");
- if (!aStyleRule.mGecko) {
- // Allocate the style rule now that we know we have animation data.
- aStyleRule.mGecko = new AnimValuesStyleRule();
- }
+ // Bug 1333311 - We use two branches for Gecko and Stylo. However, it's
+ // better to remove the duplicated code.
+ if (isServoBackend) {
+ // Servo backend
+
+ // Bug 1329878 - Stylo: Implement accumulate and addition on Servo
+ // AnimationValue.
+ RawServoAnimationValue* servoFromValue = segment->mServoFromValue;
+ RawServoAnimationValue* servoToValue = segment->mServoToValue;
+
+ // For unsupported or non-animatable animation types, we get nullptrs.
+ if (!servoFromValue || !servoToValue) {
+ NS_ERROR("Compose style for unsupported or non-animatable property, "
+ "so get invalid RawServoAnimationValues");
+ continue;
+ }
+
+ if (!aStyleRule.mServo) {
+ // Allocate the style rule now that we know we have animation data.
+ aStyleRule.mServo = new ServoAnimationRule();
+ }
+
+ // Special handling for zero-length segments
+ if (segment->mToKey == segment->mFromKey) {
+ if (computedTiming.mProgress.Value() < 0) {
+ aStyleRule.mServo->AddValue(prop.mProperty, servoFromValue);
+ } else {
+ aStyleRule.mServo->AddValue(prop.mProperty, servoToValue);
+ }
+ continue;
+ }
- StyleAnimationValue fromValue =
- CompositeValue(prop.mProperty, aStyleRule.mGecko,
- segment->mFromValue,
- segment->mFromComposite);
- StyleAnimationValue toValue =
- CompositeValue(prop.mProperty, aStyleRule.mGecko,
- segment->mToValue,
- segment->mToComposite);
+ double positionInSegment =
+ (computedTiming.mProgress.Value() - segment->mFromKey) /
+ (segment->mToKey - segment->mFromKey);
+ double valuePosition =
+ ComputedTimingFunction::GetPortion(segment->mTimingFunction,
+ positionInSegment,
+ computedTiming.mBeforeFlag);
+
+ MOZ_ASSERT(IsFinite(valuePosition), "Position value should be finite");
+
+ RefPtr<RawServoAnimationValue> interpolated =
+ Servo_AnimationValues_Interpolate(servoFromValue,
+ servoToValue,
+ valuePosition).Consume();
- // Iteration composition for accumulate
- if (mEffectOptions.mIterationComposite ==
+ if (interpolated) {
+ aStyleRule.mServo->AddValue(prop.mProperty, interpolated);
+ } else if (valuePosition < 0.5) {
+ aStyleRule.mServo->AddValue(prop.mProperty, servoFromValue);
+ } else {
+ aStyleRule.mServo->AddValue(prop.mProperty, servoToValue);
+ }
+ } else {
+ // Gecko backend
+
+ if (!aStyleRule.mGecko) {
+ // Allocate the style rule now that we know we have animation data.
+ aStyleRule.mGecko = new AnimValuesStyleRule();
+ }
+
+ StyleAnimationValue fromValue =
+ CompositeValue(prop.mProperty, aStyleRule.mGecko,
+ segment->mFromValue,
+ segment->mFromComposite);
+ StyleAnimationValue toValue =
+ CompositeValue(prop.mProperty, aStyleRule.mGecko,
+ segment->mToValue,
+ segment->mToComposite);
+
+ // Iteration composition for accumulate
+ if (mEffectOptions.mIterationComposite ==
IterationCompositeOperation::Accumulate &&
- computedTiming.mCurrentIteration > 0) {
- const AnimationPropertySegment& lastSegment =
- prop.mSegments.LastElement();
- // FIXME: Bug 1293492: Add a utility function to calculate both of
- // below StyleAnimationValues.
- StyleAnimationValue lastValue = lastSegment.mToValue.IsNull()
- ? GetUnderlyingStyle(prop.mProperty, aStyleRule.mGecko)
- : lastSegment.mToValue;
- fromValue =
- StyleAnimationValue::Accumulate(prop.mProperty,
- lastValue,
- Move(fromValue),
- computedTiming.mCurrentIteration);
- toValue =
- StyleAnimationValue::Accumulate(prop.mProperty,
- lastValue,
- Move(toValue),
- computedTiming.mCurrentIteration);
- }
+ computedTiming.mCurrentIteration > 0) {
+ const AnimationPropertySegment& lastSegment =
+ prop.mSegments.LastElement();
+ // FIXME: Bug 1293492: Add a utility function to calculate both of
+ // below StyleAnimationValues.
+ StyleAnimationValue lastValue = lastSegment.mToValue.IsNull()
+ ? GetUnderlyingStyle(prop.mProperty, aStyleRule.mGecko)
+ : lastSegment.mToValue;
+ fromValue =
+ StyleAnimationValue::Accumulate(prop.mProperty,
+ lastValue,
+ Move(fromValue),
+ computedTiming.mCurrentIteration);
+ toValue =
+ StyleAnimationValue::Accumulate(prop.mProperty,
+ lastValue,
+ Move(toValue),
+ computedTiming.mCurrentIteration);
+ }
- // Special handling for zero-length segments
- if (segment->mToKey == segment->mFromKey) {
- if (computedTiming.mProgress.Value() < 0) {
+ // Special handling for zero-length segments
+ if (segment->mToKey == segment->mFromKey) {
+ if (computedTiming.mProgress.Value() < 0) {
+ aStyleRule.mGecko->AddValue(prop.mProperty, Move(fromValue));
+ } else {
+ aStyleRule.mGecko->AddValue(prop.mProperty, Move(toValue));
+ }
+ continue;
+ }
+
+ double positionInSegment =
+ (computedTiming.mProgress.Value() - segment->mFromKey) /
+ (segment->mToKey - segment->mFromKey);
+ double valuePosition =
+ ComputedTimingFunction::GetPortion(segment->mTimingFunction,
+ positionInSegment,
+ computedTiming.mBeforeFlag);
+
+ MOZ_ASSERT(IsFinite(valuePosition), "Position value should be finite");
+
+ StyleAnimationValue val;
+ if (StyleAnimationValue::Interpolate(prop.mProperty,
+ fromValue,
+ toValue,
+ valuePosition, val)) {
+ aStyleRule.mGecko->AddValue(prop.mProperty, Move(val));
+ } else if (valuePosition < 0.5) {
aStyleRule.mGecko->AddValue(prop.mProperty, Move(fromValue));
} else {
aStyleRule.mGecko->AddValue(prop.mProperty, Move(toValue));
}
- continue;
- }
-
- double positionInSegment =
- (computedTiming.mProgress.Value() - segment->mFromKey) /
- (segment->mToKey - segment->mFromKey);
- double valuePosition =
- ComputedTimingFunction::GetPortion(segment->mTimingFunction,
- positionInSegment,
- computedTiming.mBeforeFlag);
-
- MOZ_ASSERT(IsFinite(valuePosition), "Position value should be finite");
- StyleAnimationValue val;
- if (StyleAnimationValue::Interpolate(prop.mProperty,
- fromValue,
- toValue,
- valuePosition, val)) {
- aStyleRule.mGecko->AddValue(prop.mProperty, Move(val));
- } else if (valuePosition < 0.5) {
- aStyleRule.mGecko->AddValue(prop.mProperty, Move(fromValue));
- } else {
- aStyleRule.mGecko->AddValue(prop.mProperty, Move(toValue));
}
}
// For properties that can be run on the compositor, we may need to prepare
// base styles to send to the compositor even if the current processing
// segment for properties does not have either an additive or accumulative
// composite mode, and even if the animation is not in-effect. That's because
// the animation may later progress to a segment which has an additive or
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -108,16 +108,21 @@ SERVO_BINDING_FUNC(Servo_RestyleWithAdde
// AnimationValues handling
SERVO_BINDING_FUNC(Servo_AnimationValues_Populate, void,
RawGeckoAnimationValueListBorrowedMut,
RawServoDeclarationBlockBorrowed,
ServoComputedValuesBorrowed,
ServoComputedValuesBorrowedOrNull,
RawGeckoPresContextBorrowed)
+SERVO_BINDING_FUNC(Servo_AnimationValues_Interpolate,
+ RawServoAnimationValueStrong,
+ RawServoAnimationValueBorrowed from,
+ RawServoAnimationValueBorrowed to,
+ double progress)
SERVO_BINDING_FUNC(Servo_AnimationValues_Uncompute,
RawServoDeclarationBlockStrong,
RawServoAnimationValueBorrowedListBorrowed value)
// Style attribute
SERVO_BINDING_FUNC(Servo_ParseStyleAttribute, RawServoDeclarationBlockStrong,
const nsACString* data)
SERVO_BINDING_FUNC(Servo_DeclarationBlock_CreateEmpty,