Bug 1328787 - Part 8: Animation timing function can be overridden by animation-timing-function specified in keyframe. r?heycam
MozReview-Commit-ID: HcoNx1XJ0EH
--- a/servo/components/style/keyframes.rs
+++ b/servo/components/style/keyframes.rs
@@ -6,18 +6,20 @@
#![deny(missing_docs)]
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser};
use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule};
use parking_lot::RwLock;
use parser::{ParserContext, ParserContextExtraData, log_css_error};
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock, PropertyId};
+use properties::{PropertyDeclarationId, LonghandId, DeclaredValue};
use properties::PropertyDeclarationParseResult;
use properties::animated_properties::TransitionProperty;
+use properties::longhands::transition_timing_function::single_value::SpecifiedValue as SpecifiedTimingFunction;
use std::fmt;
use std::sync::Arc;
use style_traits::ToCss;
use stylesheets::{MemoryHoleReporter, Stylesheet};
/// A number from 0 to 1, indicating the percentage of the animation when this
/// keyframe should run.
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
@@ -193,16 +195,45 @@ impl KeyframesStep {
};
KeyframesStep {
start_percentage: percentage,
value: value,
declared_timing_function: declared_timing_function,
}
}
+
+ /// Return specified TransitionTimingFunction if this KeyframesSteps has 'animation-timing-function'.
+ pub fn get_animation_timing_function(&self) -> Option<SpecifiedTimingFunction> {
+ if !self.declared_timing_function {
+ return None;
+ }
+ match self.value {
+ KeyframesStepValue::Declarations { ref block } => {
+ let guard = block.read();
+ let &(ref declaration, _) =
+ guard.get(PropertyDeclarationId::Longhand(LonghandId::AnimationTimingFunction)).unwrap();
+ match *declaration {
+ PropertyDeclaration::AnimationTimingFunction(ref value) => {
+ match *value {
+ DeclaredValue::Value(ref value) => {
+ // Use the first value.
+ Some(value.0[0])
+ },
+ _ => None,
+ }
+ },
+ _ => panic!(),
+ }
+ },
+ KeyframesStepValue::ComputedValues => {
+ panic!("Shouldn't happen to set animation-timing-function in missing keyframes")
+ },
+ }
+ }
}
/// This structure represents a list of animation steps computed from the list
/// of keyframes, in order.
///
/// It only takes into account animable properties.
#[derive(Debug, Clone)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -825,17 +825,17 @@
pub use properties::longhands::transition_duration::single_value::SpecifiedValue;
</%helpers:vector_longhand>
<%helpers:vector_longhand name="animation-timing-function"
need_index="True"
animatable="False",
extra_prefixes="moz webkit"
spec="https://drafts.csswg.org/css-animations/#propdef-animation-timing-function",
- allowed_in_keyframe_block="False">
+ allowed_in_keyframe_block="True">
pub use properties::longhands::transition_timing_function::single_value::computed_value;
pub use properties::longhands::transition_timing_function::single_value::get_initial_value;
pub use properties::longhands::transition_timing_function::single_value::get_initial_specified_value;
pub use properties::longhands::transition_timing_function::single_value::parse;
pub use properties::longhands::transition_timing_function::single_value::SpecifiedValue;
</%helpers:vector_longhand>
<%helpers:vector_longhand name="animation-iteration-count"
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -1149,17 +1149,22 @@ pub extern "C" fn Servo_StyleSet_FillKey
_style: ServoComputedValuesBorrowed,
keyframes: RawGeckoKeyframeListBorrowedMut) -> bool {
let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
let name = unsafe { Atom::from(name.as_ref().unwrap().as_str_unchecked()) };
let style_timing_function = unsafe { timing_function.as_ref().unwrap() };
if let Some(ref animation) = data.stylist.animations().get(&name) {
for step in &animation.steps {
- let timing_function = *style_timing_function;
+ // Override timing_function if the keyframe has animation-timing-function.
+ let timing_function = if let Some(val) = step.get_animation_timing_function() {
+ val.into()
+ } else {
+ *style_timing_function
+ };
let _keyframe = unsafe {
Gecko_AnimationAppendKeyframe(keyframes,
step.start_percentage.0 as f32,
&timing_function)
};
// Set each PropertyValuePair.
}