From f1feddf52c58643452a6bfb5fbcddba524e3f7d6 Mon Sep 17 00:00:00 2001 From: Boris Chiou Date: Mon, 6 Mar 2017 16:28:44 +0800 Subject: [PATCH] Add frames into style system and update animation with frames functions. --- components/style/animation.rs | 8 +++++ .../sugar/ns_timing_function.rs | 21 +++++++++++-- .../style/properties/longhand/box.mako.rs | 30 +++++++++++++++++-- components/style/values/specified/mod.rs | 3 +- 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/components/style/animation.rs b/components/style/animation.rs index 16c7dab364d..c69aca08bde 100644 --- a/components/style/animation.rs +++ b/components/style/animation.rs @@ -352,6 +352,14 @@ impl PropertyAnimation { TransitionTimingFunction::Steps(steps, StartEnd::End) => { (time * (steps as f64)).floor() / (steps as f64) } + TransitionTimingFunction::Frames(frames) => { + // https://drafts.csswg.org/css-timing/#frames-timing-functions + let mut out = (time * (frames as f64)).floor() / ((frames - 1) as f64); + if out > 1.0 && time <= 1.0 { + out = 1.0; + } + out + } }; self.property.update(style, progress); diff --git a/components/style/gecko_bindings/sugar/ns_timing_function.rs b/components/style/gecko_bindings/sugar/ns_timing_function.rs index 192125b4785..7b21d4bee59 100644 --- a/components/style/gecko_bindings/sugar/ns_timing_function.rs +++ b/components/style/gecko_bindings/sugar/ns_timing_function.rs @@ -21,6 +21,13 @@ impl nsTimingFunction { } } + fn set_as_frames(&mut self, frames: u32) { + self.mType = nsTimingFunction_Type::Frames; + unsafe { + self.__bindgen_anon_1.__bindgen_anon_1.as_mut().mStepsOrFrames = frames; + } + } + fn set_as_bezier(&mut self, function_type: nsTimingFunction_Type, p1: Point2D, @@ -48,6 +55,9 @@ impl From for nsTimingFunction { ComputedTimingFunction::Steps(steps, StartEnd::End) => { tf.set_as_step(nsTimingFunction_Type::StepEnd, steps); }, + ComputedTimingFunction::Frames(frames) => { + tf.set_as_frames(frames); + }, ComputedTimingFunction::CubicBezier(p1, p2) => { tf.set_as_bezier(nsTimingFunction_Type::CubicBezier, p1, p2); }, @@ -69,6 +79,10 @@ impl From for nsTimingFunction { debug_assert!(steps.value() >= 0); tf.set_as_step(nsTimingFunction_Type::StepEnd, steps.value() as u32); }, + SpecifiedTimingFunction::Frames(frames) => { + debug_assert!(frames.value() >= 2); + tf.set_as_frames(frames.value() as u32); + }, SpecifiedTimingFunction::CubicBezier(p1, p2) => { tf.set_as_bezier(nsTimingFunction_Type::CubicBezier, Point2D::new(p1.x.get(), p1.y.get()), @@ -104,6 +118,9 @@ impl From for nsTimingFunction { debug_assert!(keyword == FunctionKeyword::StepEnd && steps == 1); tf.set_as_step(nsTimingFunction_Type::StepEnd, steps); }, + ComputedTimingFunction::Frames(frames) => { + tf.set_as_frames(frames) + } } }, } @@ -125,8 +142,8 @@ impl From for ComputedTimingFunction { StartEnd::End) }, nsTimingFunction_Type::Frames => { - // https://github.com/servo/servo/issues/15740 - panic!("Frames timing function is not support yet"); + ComputedTimingFunction::Frames( + unsafe { function.__bindgen_anon_1.__bindgen_anon_1.as_ref().mStepsOrFrames }) } nsTimingFunction_Type::Ease | nsTimingFunction_Type::Linear | diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index 2806a04e803..9afcae44701 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -511,6 +511,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", pub enum T { CubicBezier(Point2D, Point2D), Steps(u32, StartEnd), + Frames(u32), } impl ToCss for T { @@ -528,10 +529,15 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", try!(dest.write_str(", ")); try!(p2.y.to_css(dest)); dest.write_str(")") - } + }, T::Steps(steps, start_end) => { super::serialize_steps(dest, specified::Integer::new(steps as i32), start_end) - } + }, + T::Frames(frames) => { + try!(dest.write_str("frames(")); + try!(frames.to_css(dest)); + dest.write_str(")") + }, } } } @@ -569,6 +575,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", pub enum SpecifiedValue { CubicBezier(Point2D, Point2D), Steps(specified::Integer, StartEnd), + Frames(specified::Integer), Keyword(FunctionKeyword), } @@ -617,6 +624,13 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", })); Ok(SpecifiedValue::Steps(step_count, start_end)) }, + "frames" => { + // https://drafts.csswg.org/css-timing/#frames-timing-functions + let frames = try!(input.parse_nested_block(|input| { + specified::Integer::parse_with_minimum(context, input, 2) + })); + Ok(SpecifiedValue::Frames(frames)) + }, _ => Err(()) } } @@ -655,6 +669,11 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", SpecifiedValue::Steps(steps, start_end) => { serialize_steps(dest, steps, start_end) }, + SpecifiedValue::Frames(frames) => { + try!(dest.write_str("frames(")); + try!(frames.to_css(dest)); + dest.write_str(")") + }, SpecifiedValue::Keyword(keyword) => { match keyword { FunctionKeyword::StepStart => { @@ -686,6 +705,9 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", SpecifiedValue::Steps(count, start_end) => { computed_value::T::Steps(count.to_computed_value(context) as u32, start_end) }, + SpecifiedValue::Frames(frames) => { + computed_value::T::Frames(frames.to_computed_value(context) as u32) + }, SpecifiedValue::Keyword(keyword) => keyword.to_computed_value(), } } @@ -703,6 +725,10 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", let int_count = count as i32; SpecifiedValue::Steps(specified::Integer::from_computed_value(&int_count), start_end) }, + computed_value::T::Frames(frames) => { + let frames = frames as i32; + SpecifiedValue::Frames(specified::Integer::from_computed_value(&frames)) + }, } } } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index b610401ac32..5b7393ebea9 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -845,7 +845,8 @@ impl Parse for Integer { } impl Integer { - fn parse_with_minimum(context: &ParserContext, input: &mut Parser, min: i32) -> Result { + #[allow(missing_docs)] + pub fn parse_with_minimum(context: &ParserContext, input: &mut Parser, min: i32) -> Result { match parse_integer(context, input) { Ok(value) if value.value() >= min => Ok(value), _ => Err(()),