diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index a103f42049a..58ca0cb5a76 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -40,7 +40,7 @@ use style::gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedVal use style::gecko_bindings::bindings::{RawServoSupportsRule, RawServoSupportsRuleBorrowed}; use style::gecko_bindings::bindings::{ServoCssRulesBorrowed, ServoCssRulesStrong}; use style::gecko_bindings::bindings::{nsACString, nsAString}; -use style::gecko_bindings::bindings::Gecko_AnimationAppendKeyframe; +use style::gecko_bindings::bindings::Gecko_GetOrCreateKeyframeAtStart; use style::gecko_bindings::bindings::RawGeckoAnimationPropertySegmentBorrowed; use style::gecko_bindings::bindings::RawGeckoComputedKeyframeValuesListBorrowedMut; use style::gecko_bindings::bindings::RawGeckoComputedTimingBorrowed; @@ -2207,17 +2207,29 @@ pub extern "C" fn Servo_StyleSet_FillKeyframesForName(raw_data: RawServoStyleSet let global_style_data = &*GLOBAL_STYLE_DATA; let guard = global_style_data.shared_lock.read(); - for step in &animation.steps { + let mut properties_set_at_current_offset = LonghandIdSet::new(); + let mut current_offset = -1.; + + // Walk backwards through the keyframes and drop overridden properties. + for step in animation.steps.iter().rev() { + if step.start_percentage.0 != current_offset { + properties_set_at_current_offset.clear(); + current_offset = step.start_percentage.0; + } + // Override timing_function if the keyframe has animation-timing-function. let timing_function = match step.get_animation_timing_function(&guard) { Some(val) => val.into(), None => *timing_function, }; + // Look for an existing keyframe with the same offset and timing + // function or else add a new keyframe at the beginning of the keyframe + // array. let keyframe = unsafe { - Gecko_AnimationAppendKeyframe(keyframes, - step.start_percentage.0 as f32, - &timing_function) + Gecko_GetOrCreateKeyframeAtStart(keyframes, + step.start_percentage.0 as f32, + &timing_function) }; fn add_computed_property_value(keyframe: *mut Keyframe, @@ -2253,22 +2265,23 @@ pub extern "C" fn Servo_StyleSet_FillKeyframesForName(raw_data: RawServoStyleSet declaration.is_animatable() }); - let mut seen = LonghandIdSet::new(); + let mut index = unsafe { (*keyframe).mPropertyValues.len() }; + for &(ref declaration, _) in animatable { + let property = TransitionProperty::from_declaration(declaration).unwrap(); + if !properties_set_at_current_offset.has_transition_property_bit(&property) { + properties_set_at_current_offset.set_transition_property_bit(&property); - for (index, &(ref declaration, _)) in animatable.enumerate() { - unsafe { - let property = TransitionProperty::from_declaration(declaration).unwrap(); - (*keyframe).mPropertyValues.set_len((index + 1) as u32); - (*keyframe).mPropertyValues[index].mProperty = (&property).into(); - (*keyframe).mPropertyValues[index].mServoDeclarationBlock.set_arc_leaky( - Arc::new(global_style_data.shared_lock.wrap( - PropertyDeclarationBlock::with_one( - declaration.clone(), Importance::Normal - )))); - if step.start_percentage.0 == 0. || - step.start_percentage.0 == 1. { - seen.set_transition_property_bit(&property); + unsafe { + let property = TransitionProperty::from_declaration(declaration).unwrap(); + (*keyframe).mPropertyValues.set_len((index + 1) as u32); + (*keyframe).mPropertyValues[index].mProperty = (&property).into(); + (*keyframe).mPropertyValues[index].mServoDeclarationBlock.set_arc_leaky( + Arc::new(global_style_data.shared_lock.wrap( + PropertyDeclarationBlock::with_one( + declaration.clone(), Importance::Normal + )))); } + index += 1; } } @@ -2277,7 +2290,7 @@ pub extern "C" fn Servo_StyleSet_FillKeyframesForName(raw_data: RawServoStyleSet step.start_percentage.0 == 1. { let mut index = unsafe { (*keyframe).mPropertyValues.len() }; for property in animation.properties_changed.iter() { - if !seen.has_transition_property_bit(&property) { + if !properties_set_at_current_offset.has_transition_property_bit(&property) { add_computed_property_value( keyframe, index, style, property, &global_style_data.shared_lock); index += 1;