mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Auto merge of #12118 - emilio:animation-shorthand, r=SimonSapin
style: Add support to the animation shorthand and fix parsing of animation-name <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Part of #11916. r? @SimonSapin <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/12118) <!-- Reviewable:end -->
This commit is contained in:
commit
1fabfee27e
10 changed files with 249 additions and 59 deletions
|
@ -331,6 +331,7 @@ partial interface CSSStyleDeclaration {
|
||||||
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString alignSelf;
|
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString alignSelf;
|
||||||
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString align-self;
|
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString align-self;
|
||||||
|
|
||||||
|
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString animation;
|
||||||
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString animation-name;
|
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString animation-name;
|
||||||
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString animationName;
|
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString animationName;
|
||||||
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString animation-duration;
|
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString animation-duration;
|
||||||
|
|
|
@ -626,7 +626,9 @@ where Impl: SelectorImplExt,
|
||||||
// NB: The spec says that the timing function can be overwritten
|
// NB: The spec says that the timing function can be overwritten
|
||||||
// from the keyframe style.
|
// from the keyframe style.
|
||||||
let mut timing_function = style.get_box().animation_timing_function_mod(index);
|
let mut timing_function = style.get_box().animation_timing_function_mod(index);
|
||||||
if from_style.get_box().animation_timing_function_count() != 0 {
|
if last_keyframe.declared_timing_function {
|
||||||
|
// NB: animation_timing_function can never be empty, always has
|
||||||
|
// at least the default value (`ease`).
|
||||||
timing_function = from_style.get_box().animation_timing_function_at(0);
|
timing_function = from_style.get_box().animation_timing_function_at(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,15 +114,33 @@ pub struct KeyframesStep {
|
||||||
/// Declarations that will determine the final style during the step, or
|
/// Declarations that will determine the final style during the step, or
|
||||||
/// `ComputedValues` if this is an autogenerated step.
|
/// `ComputedValues` if this is an autogenerated step.
|
||||||
pub value: KeyframesStepValue,
|
pub value: KeyframesStepValue,
|
||||||
|
/// Wether a animation-timing-function declaration exists in the list of
|
||||||
|
/// declarations.
|
||||||
|
///
|
||||||
|
/// This is used to know when to override the keyframe animation style.
|
||||||
|
pub declared_timing_function: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KeyframesStep {
|
impl KeyframesStep {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn new(percentage: KeyframePercentage,
|
fn new(percentage: KeyframePercentage,
|
||||||
value: KeyframesStepValue) -> Self {
|
value: KeyframesStepValue) -> Self {
|
||||||
|
let declared_timing_function = match value {
|
||||||
|
KeyframesStepValue::Declarations(ref declarations) => {
|
||||||
|
declarations.iter().any(|prop_decl| {
|
||||||
|
match *prop_decl {
|
||||||
|
PropertyDeclaration::AnimationTimingFunction(..) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
KeyframesStep {
|
KeyframesStep {
|
||||||
start_percentage: percentage,
|
start_percentage: percentage,
|
||||||
value: value,
|
value: value,
|
||||||
|
declared_timing_function: declared_timing_function,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,11 +235,21 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub use self::computed_value::${to_camel_case(name)} as SingleSpecifiedValue;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn parse_one(input: &mut Parser) -> Result<SingleSpecifiedValue, ()> {
|
||||||
|
SingleSpecifiedValue::parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
computed_value::T(vec![
|
computed_value::T(vec![get_initial_single_value()])
|
||||||
computed_value::${to_camel_case(name)}::${to_rust_ident(values.split()[0])}
|
}
|
||||||
])
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get_initial_single_value() -> SingleSpecifiedValue {
|
||||||
|
SingleSpecifiedValue::${to_rust_ident(values.split()[0])}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -490,8 +490,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
||||||
|
|
||||||
pub fn parse_one(input: &mut Parser) -> Result<SingleSpecifiedValue,()> {
|
pub fn parse_one(input: &mut Parser) -> Result<SingleSpecifiedValue,()> {
|
||||||
if let Ok(function_name) = input.try(|input| input.expect_function()) {
|
if let Ok(function_name) = input.try(|input| input.expect_function()) {
|
||||||
return match_ignore_ascii_case! {
|
return match_ignore_ascii_case! { function_name,
|
||||||
function_name,
|
|
||||||
"cubic-bezier" => {
|
"cubic-bezier" => {
|
||||||
let (mut p1x, mut p1y, mut p2x, mut p2y) = (0.0, 0.0, 0.0, 0.0);
|
let (mut p1x, mut p1y, mut p2x, mut p2y) = (0.0, 0.0, 0.0, 0.0);
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
|
@ -508,16 +507,17 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
||||||
Ok(TransitionTimingFunction::CubicBezier(p1, p2))
|
Ok(TransitionTimingFunction::CubicBezier(p1, p2))
|
||||||
},
|
},
|
||||||
"steps" => {
|
"steps" => {
|
||||||
let (mut step_count, mut start_end) = (0, computed_value::StartEnd::Start);
|
let (mut step_count, mut start_end) = (0, computed_value::StartEnd::End);
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
step_count = try!(specified::parse_integer(input));
|
step_count = try!(specified::parse_integer(input));
|
||||||
try!(input.expect_comma());
|
if input.try(|input| input.expect_comma()).is_ok() {
|
||||||
start_end = try!(match_ignore_ascii_case! {
|
start_end = try!(match_ignore_ascii_case! {
|
||||||
try!(input.expect_ident()),
|
try!(input.expect_ident()),
|
||||||
"start" => Ok(computed_value::StartEnd::Start),
|
"start" => Ok(computed_value::StartEnd::Start),
|
||||||
"end" => Ok(computed_value::StartEnd::End),
|
"end" => Ok(computed_value::StartEnd::End),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
});
|
});
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}));
|
}));
|
||||||
Ok(TransitionTimingFunction::Steps(step_count as u32, start_end))
|
Ok(TransitionTimingFunction::Steps(step_count as u32, start_end))
|
||||||
|
@ -582,6 +582,12 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
||||||
computed_value::T(Vec::new())
|
computed_value::T(Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn parse_one(input: &mut Parser) -> Result<SingleSpecifiedValue, ()> {
|
||||||
|
SingleSpecifiedValue::parse(input)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||||
Ok(SpecifiedValue(try!(input.parse_comma_separated(SingleSpecifiedValue::parse))))
|
Ok(SpecifiedValue(try!(input.parse_comma_separated(SingleSpecifiedValue::parse))))
|
||||||
}
|
}
|
||||||
|
@ -640,6 +646,18 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use self::computed_value::T as SpecifiedValue;
|
pub use self::computed_value::T as SpecifiedValue;
|
||||||
|
pub use string_cache::Atom as SingleSpecifiedValue;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn parse_one(input: &mut Parser) -> Result<SingleSpecifiedValue, ()> {
|
||||||
|
use cssparser::Token;
|
||||||
|
|
||||||
|
Ok(match input.next() {
|
||||||
|
Ok(Token::Ident(ref value)) if value != "none" => Atom::from(&**value),
|
||||||
|
Ok(Token::QuotedString(value)) => Atom::from(&*value),
|
||||||
|
_ => return Err(()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
|
@ -648,9 +666,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
||||||
|
|
||||||
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
Ok(SpecifiedValue(try!(input.parse_comma_separated(|input| {
|
Ok(SpecifiedValue(try!(input.parse_comma_separated(parse_one))))
|
||||||
input.expect_ident().map(Atom::from)
|
|
||||||
}))))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||||
|
@ -660,16 +676,20 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
||||||
need_index="True"
|
need_index="True"
|
||||||
animatable="False">
|
animatable="False">
|
||||||
pub use super::transition_duration::computed_value;
|
pub use super::transition_duration::computed_value;
|
||||||
pub use super::transition_duration::{parse, get_initial_value};
|
pub use super::transition_duration::{get_initial_value, get_initial_single_value};
|
||||||
|
pub use super::transition_duration::{parse, parse_one};
|
||||||
pub use super::transition_duration::SpecifiedValue;
|
pub use super::transition_duration::SpecifiedValue;
|
||||||
|
pub use super::transition_duration::SingleSpecifiedValue;
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
<%helpers:longhand name="animation-timing-function"
|
<%helpers:longhand name="animation-timing-function"
|
||||||
need_index="True"
|
need_index="True"
|
||||||
animatable="False">
|
animatable="False">
|
||||||
pub use super::transition_timing_function::computed_value;
|
pub use super::transition_timing_function::computed_value;
|
||||||
pub use super::transition_timing_function::{parse, get_initial_value};
|
pub use super::transition_timing_function::{get_initial_value, get_initial_single_value};
|
||||||
|
pub use super::transition_timing_function::{parse, parse_one};
|
||||||
pub use super::transition_timing_function::SpecifiedValue;
|
pub use super::transition_timing_function::SpecifiedValue;
|
||||||
|
pub use super::transition_timing_function::SingleSpecifiedValue;
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
<%helpers:longhand name="animation-iteration-count"
|
<%helpers:longhand name="animation-iteration-count"
|
||||||
|
@ -720,8 +740,14 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use self::computed_value::AnimationIterationCount;
|
pub use self::computed_value::AnimationIterationCount;
|
||||||
|
pub use self::computed_value::AnimationIterationCount as SingleSpecifiedValue;
|
||||||
pub use self::computed_value::T as SpecifiedValue;
|
pub use self::computed_value::T as SpecifiedValue;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get_initial_single_value() -> AnimationIterationCount {
|
||||||
|
AnimationIterationCount::Number(1)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_one(input: &mut Parser) -> Result<AnimationIterationCount, ()> {
|
pub fn parse_one(input: &mut Parser) -> Result<AnimationIterationCount, ()> {
|
||||||
if input.try(|input| input.expect_ident_matching("infinite")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("infinite")).is_ok() {
|
||||||
Ok(AnimationIterationCount::Infinite)
|
Ok(AnimationIterationCount::Infinite)
|
||||||
|
@ -740,8 +766,9 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
||||||
Ok(SpecifiedValue(try!(input.parse_comma_separated(parse_one))))
|
Ok(SpecifiedValue(try!(input.parse_comma_separated(parse_one))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
computed_value::T(vec![AnimationIterationCount::Number(1)])
|
computed_value::T(vec![get_initial_single_value()])
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||||
|
@ -767,8 +794,10 @@ ${helpers.keyword_list("animation-fill-mode",
|
||||||
need_index="True"
|
need_index="True"
|
||||||
animatable="False">
|
animatable="False">
|
||||||
pub use super::transition_duration::computed_value;
|
pub use super::transition_duration::computed_value;
|
||||||
pub use super::transition_duration::{parse, get_initial_value};
|
pub use super::transition_duration::{get_initial_value, get_initial_single_value};
|
||||||
|
pub use super::transition_duration::{parse, parse_one};
|
||||||
pub use super::transition_duration::SpecifiedValue;
|
pub use super::transition_duration::SpecifiedValue;
|
||||||
|
pub use super::transition_duration::SingleSpecifiedValue;
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
// CSSOM View Module
|
// CSSOM View Module
|
||||||
|
|
|
@ -25,7 +25,8 @@
|
||||||
use cssparser;
|
use cssparser;
|
||||||
pub type T = cssparser::RGBA;
|
pub type T = cssparser::RGBA;
|
||||||
}
|
}
|
||||||
#[inline] pub fn get_initial_value() -> computed_value::T {
|
#[inline]
|
||||||
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
RGBA { red: 0., green: 0., blue: 0., alpha: 1. } /* black */
|
RGBA { red: 0., green: 0., blue: 0., alpha: 1. } /* black */
|
||||||
}
|
}
|
||||||
pub fn parse_specified(_context: &ParserContext, input: &mut Parser)
|
pub fn parse_specified(_context: &ParserContext, input: &mut Parser)
|
||||||
|
|
|
@ -14,8 +14,20 @@
|
||||||
})
|
})
|
||||||
</%helpers:shorthand>
|
</%helpers:shorthand>
|
||||||
|
|
||||||
|
macro_rules! try_parse_one {
|
||||||
|
($input: expr, $var: ident, $prop_module: ident) => {
|
||||||
|
if $var.is_none() {
|
||||||
|
if let Ok(value) = $input.try($prop_module::parse_one) {
|
||||||
|
$var = Some(value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
<%helpers:shorthand name="transition"
|
<%helpers:shorthand name="transition"
|
||||||
sub_properties="transition-property transition-duration transition-timing-function
|
sub_properties="transition-property transition-duration
|
||||||
|
transition-timing-function
|
||||||
transition-delay">
|
transition-delay">
|
||||||
use properties::longhands::{transition_delay, transition_duration, transition_property};
|
use properties::longhands::{transition_delay, transition_duration, transition_property};
|
||||||
use properties::longhands::{transition_timing_function};
|
use properties::longhands::{transition_timing_function};
|
||||||
|
@ -31,35 +43,10 @@
|
||||||
let (mut property, mut duration) = (None, None);
|
let (mut property, mut duration) = (None, None);
|
||||||
let (mut timing_function, mut delay) = (None, None);
|
let (mut timing_function, mut delay) = (None, None);
|
||||||
loop {
|
loop {
|
||||||
if property.is_none() {
|
try_parse_one!(input, property, transition_property);
|
||||||
if let Ok(value) = input.try(transition_property::SingleSpecifiedValue::parse) {
|
try_parse_one!(input, duration, transition_duration);
|
||||||
property = Some(value);
|
try_parse_one!(input, timing_function, transition_timing_function);
|
||||||
continue
|
try_parse_one!(input, delay, transition_delay);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if duration.is_none() {
|
|
||||||
if let Ok(value) = input.try(|input| transition_duration::parse_one(input)) {
|
|
||||||
duration = Some(value);
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if timing_function.is_none() {
|
|
||||||
if let Ok(value) = input.try(|input| {
|
|
||||||
transition_timing_function::parse_one(input)
|
|
||||||
}) {
|
|
||||||
timing_function = Some(value);
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if delay.is_none() {
|
|
||||||
if let Ok(value) = input.try(|input| transition_delay::parse_one(input)) {
|
|
||||||
delay = Some(value);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -68,12 +55,12 @@
|
||||||
Ok(SingleTransition {
|
Ok(SingleTransition {
|
||||||
transition_property: property,
|
transition_property: property,
|
||||||
transition_duration:
|
transition_duration:
|
||||||
duration.unwrap_or(transition_duration::get_initial_single_value()),
|
duration.unwrap_or_else(transition_duration::get_initial_single_value),
|
||||||
transition_timing_function:
|
transition_timing_function:
|
||||||
timing_function.unwrap_or(
|
timing_function.unwrap_or_else(
|
||||||
transition_timing_function::get_initial_single_value()),
|
transition_timing_function::get_initial_single_value),
|
||||||
transition_delay:
|
transition_delay:
|
||||||
delay.unwrap_or(transition_delay::get_initial_single_value()),
|
delay.unwrap_or_else(transition_delay::get_initial_single_value),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
|
@ -107,3 +94,121 @@
|
||||||
transition_delay: Some(transition_delay::SpecifiedValue(delays)),
|
transition_delay: Some(transition_delay::SpecifiedValue(delays)),
|
||||||
})
|
})
|
||||||
</%helpers:shorthand>
|
</%helpers:shorthand>
|
||||||
|
|
||||||
|
<%helpers:shorthand name="animation"
|
||||||
|
sub_properties="animation-name animation-duration
|
||||||
|
animation-timing-function animation-delay
|
||||||
|
animation-iteration-count animation-direction
|
||||||
|
animation-fill-mode animation-play-state">
|
||||||
|
use properties::longhands::{animation_name, animation_duration, animation_timing_function};
|
||||||
|
use properties::longhands::{animation_delay, animation_iteration_count, animation_direction};
|
||||||
|
use properties::longhands::{animation_fill_mode, animation_play_state};
|
||||||
|
|
||||||
|
struct SingleAnimation {
|
||||||
|
animation_name: animation_name::SingleSpecifiedValue,
|
||||||
|
animation_duration: animation_duration::SingleSpecifiedValue,
|
||||||
|
animation_timing_function: animation_timing_function::SingleSpecifiedValue,
|
||||||
|
animation_delay: animation_delay::SingleSpecifiedValue,
|
||||||
|
animation_iteration_count: animation_iteration_count::SingleSpecifiedValue,
|
||||||
|
animation_direction: animation_direction::SingleSpecifiedValue,
|
||||||
|
animation_fill_mode: animation_fill_mode::SingleSpecifiedValue,
|
||||||
|
animation_play_state: animation_play_state::SingleSpecifiedValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_one_animation(input: &mut Parser) -> Result<SingleAnimation,()> {
|
||||||
|
let mut duration = None;
|
||||||
|
let mut timing_function = None;
|
||||||
|
let mut delay = None;
|
||||||
|
let mut iteration_count = None;
|
||||||
|
let mut direction = None;
|
||||||
|
let mut fill_mode = None;
|
||||||
|
let mut play_state = None;
|
||||||
|
let mut name = None;
|
||||||
|
|
||||||
|
// NB: Name must be the last one here so that keywords valid for other
|
||||||
|
// longhands are not interpreted as names.
|
||||||
|
//
|
||||||
|
// Also, duration must be before delay, see
|
||||||
|
// https://drafts.csswg.org/css-animations/#typedef-single-animation
|
||||||
|
loop {
|
||||||
|
try_parse_one!(input, duration, animation_duration);
|
||||||
|
try_parse_one!(input, timing_function, animation_timing_function);
|
||||||
|
try_parse_one!(input, delay, animation_delay);
|
||||||
|
try_parse_one!(input, iteration_count, animation_iteration_count);
|
||||||
|
try_parse_one!(input, direction, animation_direction);
|
||||||
|
try_parse_one!(input, fill_mode, animation_fill_mode);
|
||||||
|
try_parse_one!(input, play_state, animation_play_state);
|
||||||
|
try_parse_one!(input, name, animation_name);
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(name) = name {
|
||||||
|
Ok(SingleAnimation {
|
||||||
|
animation_name: name,
|
||||||
|
animation_duration:
|
||||||
|
duration.unwrap_or_else(animation_duration::get_initial_single_value),
|
||||||
|
animation_timing_function:
|
||||||
|
timing_function.unwrap_or_else(animation_timing_function::get_initial_single_value),
|
||||||
|
animation_delay:
|
||||||
|
delay.unwrap_or_else(animation_delay::get_initial_single_value),
|
||||||
|
animation_iteration_count:
|
||||||
|
iteration_count.unwrap_or_else(animation_iteration_count::get_initial_single_value),
|
||||||
|
animation_direction:
|
||||||
|
direction.unwrap_or_else(animation_direction::get_initial_single_value),
|
||||||
|
animation_fill_mode:
|
||||||
|
fill_mode.unwrap_or_else(animation_fill_mode::get_initial_single_value),
|
||||||
|
animation_play_state:
|
||||||
|
play_state.unwrap_or_else(animation_play_state::get_initial_single_value),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
|
return Ok(Longhands {
|
||||||
|
animation_name: None,
|
||||||
|
animation_duration: None,
|
||||||
|
animation_timing_function: None,
|
||||||
|
animation_delay: None,
|
||||||
|
animation_iteration_count: None,
|
||||||
|
animation_direction: None,
|
||||||
|
animation_fill_mode: None,
|
||||||
|
animation_play_state: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let results = try!(input.parse_comma_separated(parse_one_animation));
|
||||||
|
|
||||||
|
let mut names = vec![];
|
||||||
|
let mut durations = vec![];
|
||||||
|
let mut timing_functions = vec![];
|
||||||
|
let mut delays = vec![];
|
||||||
|
let mut iteration_counts = vec![];
|
||||||
|
let mut directions = vec![];
|
||||||
|
let mut fill_modes = vec![];
|
||||||
|
let mut play_states = vec![];
|
||||||
|
|
||||||
|
for result in results.into_iter() {
|
||||||
|
names.push(result.animation_name);
|
||||||
|
durations.push(result.animation_duration);
|
||||||
|
timing_functions.push(result.animation_timing_function);
|
||||||
|
delays.push(result.animation_delay);
|
||||||
|
iteration_counts.push(result.animation_iteration_count);
|
||||||
|
directions.push(result.animation_direction);
|
||||||
|
fill_modes.push(result.animation_fill_mode);
|
||||||
|
play_states.push(result.animation_play_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Longhands {
|
||||||
|
animation_name: Some(animation_name::SpecifiedValue(names)),
|
||||||
|
animation_duration: Some(animation_duration::SpecifiedValue(durations)),
|
||||||
|
animation_timing_function: Some(animation_timing_function::SpecifiedValue(timing_functions)),
|
||||||
|
animation_delay: Some(animation_delay::SpecifiedValue(delays)),
|
||||||
|
animation_iteration_count: Some(animation_iteration_count::SpecifiedValue(iteration_counts)),
|
||||||
|
animation_direction: Some(animation_direction::SpecifiedValue(directions)),
|
||||||
|
animation_fill_mode: Some(animation_fill_mode::SpecifiedValue(fill_modes)),
|
||||||
|
animation_play_state: Some(animation_play_state::SpecifiedValue(play_states)),
|
||||||
|
})
|
||||||
|
</%helpers:shorthand>
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style>
|
||||||
|
@keyframes foo {
|
||||||
|
from { background: white; animation-timing-function: ease; }
|
||||||
|
to { background: black; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bar {
|
||||||
|
from { background: white }
|
||||||
|
to { background: black }
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
height: 50px;
|
||||||
|
width: 100px;
|
||||||
|
animation: foo 1s infinite steps(4, end);
|
||||||
|
}
|
||||||
|
.bar { animation-name: bar }
|
||||||
|
</style>
|
||||||
|
<p>You should see an eased animation in the first-element, and a stepped one in the second one</p>
|
||||||
|
<div></div>
|
||||||
|
<div class="bar"></div>
|
|
@ -0,0 +1,4 @@
|
||||||
|
[css-flexbox-height-animation-stretch.htm]
|
||||||
|
type: reftest
|
||||||
|
expected: TIMEOUT
|
||||||
|
bug: https://github.com/servo/servo/issues/12328
|
|
@ -1,8 +1,5 @@
|
||||||
[transition-timing-function-001.htm]
|
[transition-timing-function-001.htm]
|
||||||
type: testharness
|
type: testharness
|
||||||
[parse 'steps(3)']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[parse 'cubic-bezier(-0.1, -0.2, -0.3, -0.4)']
|
[parse 'cubic-bezier(-0.1, -0.2, -0.3, -0.4)']
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue