From a20b6a51665c9009ebe65dd1b9dc5d1d1c289faa Mon Sep 17 00:00:00 2001 From: Boris Chiou Date: Fri, 26 Oct 2018 18:03:29 +0000 Subject: [PATCH] style: Split TimingFunction into a separate file to match spec. TimingFunction is defined in a separate spec (i.e. css-easing), instead of transform, so we move it into a different file. Depends on D9310 Differential Revision: https://phabricator.services.mozilla.com/D9311 --- components/style/animation.rs | 4 +- .../sugar/ns_timing_function.rs | 8 +- components/style/values/computed/easing.rs | 11 ++ components/style/values/computed/mod.rs | 4 +- components/style/values/computed/transform.rs | 3 - components/style/values/generics/easing.rs | 87 +++++++++++++ components/style/values/generics/mod.rs | 1 + components/style/values/generics/transform.rs | 81 ------------ components/style/values/specified/easing.rs | 118 ++++++++++++++++++ components/style/values/specified/mod.rs | 4 +- .../style/values/specified/transform.rs | 102 +-------------- 11 files changed, 230 insertions(+), 193 deletions(-) create mode 100644 components/style/values/computed/easing.rs create mode 100644 components/style/values/generics/easing.rs create mode 100644 components/style/values/specified/easing.rs diff --git a/components/style/animation.rs b/components/style/animation.rs index 59d45dc6302..311d102729f 100644 --- a/components/style/animation.rs +++ b/components/style/animation.rs @@ -28,9 +28,9 @@ use stylesheets::keyframes_rule::{KeyframesAnimation, KeyframesStep, KeyframesSt use timer::Timer; use values::computed::Time; use values::computed::box_::TransitionProperty; -use values::computed::transform::TimingFunction; +use values::computed::TimingFunction; use values::generics::box_::AnimationIterationCount; -use values::generics::transform::{StepPosition, TimingFunction as GenericTimingFunction}; +use values::generics::easing::{StepPosition, TimingFunction as GenericTimingFunction}; /// This structure represents a keyframes animation current iteration state. diff --git a/components/style/gecko_bindings/sugar/ns_timing_function.rs b/components/style/gecko_bindings/sugar/ns_timing_function.rs index 8d7e68b5b44..ff3352ea6c9 100644 --- a/components/style/gecko_bindings/sugar/ns_timing_function.rs +++ b/components/style/gecko_bindings/sugar/ns_timing_function.rs @@ -5,10 +5,10 @@ use gecko_bindings::structs::{nsTimingFunction, nsTimingFunction_Type}; use std::mem; use values::computed::ToComputedValue; -use values::computed::transform::TimingFunction as ComputedTimingFunction; -use values::generics::transform::{StepPosition, TimingKeyword}; -use values::generics::transform::TimingFunction as GenericTimingFunction; -use values::specified::transform::TimingFunction; +use values::computed::easing::TimingFunction as ComputedTimingFunction; +use values::generics::easing::{StepPosition, TimingKeyword}; +use values::generics::easing::TimingFunction as GenericTimingFunction; +use values::specified::easing::TimingFunction; impl nsTimingFunction { fn set_as_step(&mut self, function_type: nsTimingFunction_Type, steps: u32) { diff --git a/components/style/values/computed/easing.rs b/components/style/values/computed/easing.rs new file mode 100644 index 00000000000..a2fefe3a811 --- /dev/null +++ b/components/style/values/computed/easing.rs @@ -0,0 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! Computed types for CSS Easing functions. + +use values::computed::Number; +use values::generics::easing::TimingFunction as GenericTimingFunction; + +/// A computed timing function. +pub type TimingFunction = GenericTimingFunction; diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index d8cc938c1f3..d1787decf46 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -49,6 +49,7 @@ pub use self::box_::{ScrollSnapType, TouchAction, VerticalAlign, WillChange}; pub use self::color::{Color, ColorPropertyValue, RGBAColor}; pub use self::column::ColumnCount; pub use self::counters::{Content, ContentItem, CounterIncrement, CounterReset}; +pub use self::easing::TimingFunction; pub use self::effects::{BoxShadow, Filter, SimpleShadow}; pub use self::flex::FlexBasis; pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect}; @@ -76,7 +77,7 @@ pub use self::table::XSpan; pub use self::text::{InitialLetter, LetterSpacing, LineHeight, MozTabSize}; pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle, TextOverflow, WordSpacing}; pub use self::time::Time; -pub use self::transform::{Rotate, Scale, TimingFunction, Transform, TransformOperation}; +pub use self::transform::{Rotate, Scale, Transform, TransformOperation}; pub use self::transform::{TransformOrigin, TransformStyle, Translate}; pub use self::ui::{ColorOrAuto, Cursor, MozForceBrokenImageIcon}; #[cfg(feature = "gecko")] @@ -93,6 +94,7 @@ pub mod box_; pub mod color; pub mod column; pub mod counters; +pub mod easing; pub mod effects; pub mod flex; pub mod font; diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs index a83495a09b5..33c55d8a1e2 100644 --- a/components/style/values/computed/transform.rs +++ b/components/style/values/computed/transform.rs @@ -22,9 +22,6 @@ pub type Transform = generic::Transform; /// The computed value of a CSS `` pub type TransformOrigin = generic::TransformOrigin; -/// A computed timing function. -pub type TimingFunction = generic::TimingFunction; - /// A vector to represent the direction vector (rotate axis) for Rotate3D. pub type DirectionVector = Vector3D; diff --git a/components/style/values/generics/easing.rs b/components/style/values/generics/easing.rs new file mode 100644 index 00000000000..0d0ebdfe44c --- /dev/null +++ b/components/style/values/generics/easing.rs @@ -0,0 +1,87 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! Generic types for CSS Easing Functions. +//! https://drafts.csswg.org/css-easing/#timing-functions + +use values::CSSFloat; + +/// A generic easing function. +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)] +#[value_info(ty = "TIMING_FUNCTION")] +pub enum TimingFunction { + /// `linear | ease | ease-in | ease-out | ease-in-out` + Keyword(TimingKeyword), + /// `cubic-bezier(, , , )` + #[allow(missing_docs)] + #[css(comma, function)] + CubicBezier { + x1: Number, + y1: Number, + x2: Number, + y2: Number, + }, + /// `step-start | step-end | steps(, [ start | end ]?)` + #[css(comma, function)] + #[value_info(other_values = "step-start,step-end")] + Steps(Integer, #[css(skip_if = "is_end")] StepPosition), +} + +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive( + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] +pub enum TimingKeyword { + Linear, + Ease, + EaseIn, + EaseOut, + EaseInOut, +} + +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)] +pub enum StepPosition { + Start, + End, +} + +#[inline] +fn is_end(position: &StepPosition) -> bool { + *position == StepPosition::End +} + +impl TimingFunction { + /// `ease` + #[inline] + pub fn ease() -> Self { + TimingFunction::Keyword(TimingKeyword::Ease) + } +} + +impl TimingKeyword { + /// Returns the keyword as a quadruplet of Bezier point coordinates + /// `(x1, y1, x2, y2)`. + #[inline] + pub fn to_bezier(self) -> (CSSFloat, CSSFloat, CSSFloat, CSSFloat) { + match self { + TimingKeyword::Linear => (0., 0., 1., 1.), + TimingKeyword::Ease => (0.25, 0.1, 0.25, 1.), + TimingKeyword::EaseIn => (0.42, 0., 1., 1.), + TimingKeyword::EaseOut => (0., 0., 0.58, 1.), + TimingKeyword::EaseInOut => (0.42, 0., 0.58, 1.), + } + } +} diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 32e389512e4..712b62679d8 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -20,6 +20,7 @@ pub mod box_; pub mod color; pub mod column; pub mod counters; +pub mod easing; pub mod effects; pub mod flex; pub mod font; diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index 61c9821a816..7a3eaead1cb 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -90,64 +90,6 @@ pub struct TransformOrigin { pub depth: Depth, } -/// A generic timing function. -/// -/// https://drafts.csswg.org/css-easing-1/#timing-functions -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)] -#[value_info(ty = "TIMING_FUNCTION")] -pub enum TimingFunction { - /// `linear | ease | ease-in | ease-out | ease-in-out` - Keyword(TimingKeyword), - /// `cubic-bezier(, , , )` - #[allow(missing_docs)] - #[css(comma, function)] - CubicBezier { - x1: Number, - y1: Number, - x2: Number, - y2: Number, - }, - /// `step-start | step-end | steps(, [ start | end ]?)` - #[css(comma, function)] - #[value_info(other_values = "step-start,step-end")] - Steps(Integer, #[css(skip_if = "is_end")] StepPosition), -} - -#[allow(missing_docs)] -#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive( - Clone, - Copy, - Debug, - Eq, - MallocSizeOf, - Parse, - PartialEq, - SpecifiedValueInfo, - ToComputedValue, - ToCss, -)] -pub enum TimingKeyword { - Linear, - Ease, - EaseIn, - EaseOut, - EaseInOut, -} - -#[allow(missing_docs)] -#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)] -pub enum StepPosition { - Start, - End, -} - -#[inline] -fn is_end(position: &StepPosition) -> bool { - *position == StepPosition::End -} - impl TransformOrigin { /// Returns a new transform origin. pub fn new(horizontal: H, vertical: V, depth: D) -> Self { @@ -159,29 +101,6 @@ impl TransformOrigin { } } -impl TimingFunction { - /// `ease` - #[inline] - pub fn ease() -> Self { - TimingFunction::Keyword(TimingKeyword::Ease) - } -} - -impl TimingKeyword { - /// Returns the keyword as a quadruplet of Bezier point coordinates - /// `(x1, y1, x2, y2)`. - #[inline] - pub fn to_bezier(self) -> (CSSFloat, CSSFloat, CSSFloat, CSSFloat) { - match self { - TimingKeyword::Linear => (0., 0., 1., 1.), - TimingKeyword::Ease => (0.25, 0.1, 0.25, 1.), - TimingKeyword::EaseIn => (0.42, 0., 1., 1.), - TimingKeyword::EaseOut => (0., 0., 0.58, 1.), - TimingKeyword::EaseInOut => (0.42, 0., 0.58, 1.), - } - } -} - #[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] /// A single operation in the list of a `transform` value pub enum TransformOperation { diff --git a/components/style/values/specified/easing.rs b/components/style/values/specified/easing.rs new file mode 100644 index 00000000000..051029c233d --- /dev/null +++ b/components/style/values/specified/easing.rs @@ -0,0 +1,118 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! Specified types for CSS Easing functions. + +use cssparser::Parser; +use parser::{Parse, ParserContext}; +use selectors::parser::SelectorParseErrorKind; +use style_traits::{ParseError, StyleParseErrorKind}; +use values::computed::{Context, TimingFunction as ComputedTimingFunction, ToComputedValue}; +use values::generics::easing::{StepPosition, TimingKeyword}; +use values::generics::easing::TimingFunction as GenericTimingFunction; +use values::specified::{Integer, Number}; + +/// A specified timing function. +pub type TimingFunction = GenericTimingFunction; + +impl Parse for TimingFunction { + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + if let Ok(keyword) = input.try(TimingKeyword::parse) { + return Ok(GenericTimingFunction::Keyword(keyword)); + } + if let Ok(ident) = input.try(|i| i.expect_ident_cloned()) { + let position = match_ignore_ascii_case! { &ident, + "step-start" => StepPosition::Start, + "step-end" => StepPosition::End, + _ => { + return Err(input.new_custom_error( + SelectorParseErrorKind::UnexpectedIdent(ident.clone()) + )); + }, + }; + return Ok(GenericTimingFunction::Steps(Integer::new(1), position)); + } + let location = input.current_source_location(); + let function = input.expect_function()?.clone(); + input.parse_nested_block(move |i| { + (match_ignore_ascii_case! { &function, + "cubic-bezier" => { + let x1 = Number::parse(context, i)?; + i.expect_comma()?; + let y1 = Number::parse(context, i)?; + i.expect_comma()?; + let x2 = Number::parse(context, i)?; + i.expect_comma()?; + let y2 = Number::parse(context, i)?; + + if x1.get() < 0.0 || x1.get() > 1.0 || x2.get() < 0.0 || x2.get() > 1.0 { + return Err(i.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + } + + Ok(GenericTimingFunction::CubicBezier { x1, y1, x2, y2 }) + }, + "steps" => { + let steps = Integer::parse_positive(context, i)?; + let position = i.try(|i| { + i.expect_comma()?; + StepPosition::parse(i) + }).unwrap_or(StepPosition::End); + Ok(GenericTimingFunction::Steps(steps, position)) + }, + _ => Err(()), + }).map_err(|()| { + location.new_custom_error( + StyleParseErrorKind::UnexpectedFunction(function.clone()) + ) + }) + }) + } +} + +impl ToComputedValue for TimingFunction { + type ComputedValue = ComputedTimingFunction; + + #[inline] + fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { + match *self { + GenericTimingFunction::Keyword(keyword) => GenericTimingFunction::Keyword(keyword), + GenericTimingFunction::CubicBezier { x1, y1, x2, y2 } => { + GenericTimingFunction::CubicBezier { + x1: x1.to_computed_value(context), + y1: y1.to_computed_value(context), + x2: x2.to_computed_value(context), + y2: y2.to_computed_value(context), + } + }, + GenericTimingFunction::Steps(steps, position) => { + GenericTimingFunction::Steps(steps.to_computed_value(context) as u32, position) + }, + } + } + + #[inline] + fn from_computed_value(computed: &Self::ComputedValue) -> Self { + match *computed { + GenericTimingFunction::Keyword(keyword) => GenericTimingFunction::Keyword(keyword), + GenericTimingFunction::CubicBezier { + ref x1, + ref y1, + ref x2, + ref y2, + } => GenericTimingFunction::CubicBezier { + x1: Number::from_computed_value(x1), + y1: Number::from_computed_value(y1), + x2: Number::from_computed_value(x2), + y2: Number::from_computed_value(y2), + }, + GenericTimingFunction::Steps(steps, position) => GenericTimingFunction::Steps( + Integer::from_computed_value(&(steps as i32)), + position, + ), + } + } +} diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index b8c2cd01fe9..9955f7232be 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -43,6 +43,7 @@ pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize}; pub use self::box_::{ScrollSnapType, TouchAction, TransitionProperty, VerticalAlign, WillChange}; pub use self::color::{Color, ColorPropertyValue, RGBAColor}; pub use self::counters::{Content, ContentItem, CounterIncrement, CounterReset}; +pub use self::easing::TimingFunction; pub use self::effects::{BoxShadow, Filter, SimpleShadow}; pub use self::flex::FlexBasis; #[cfg(feature = "gecko")] @@ -74,7 +75,7 @@ pub use self::text::{InitialLetter, LetterSpacing, LineHeight, MozTabSize, TextA pub use self::text::{TextEmphasisPosition, TextEmphasisStyle}; pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing}; pub use self::time::Time; -pub use self::transform::{Rotate, Scale, TimingFunction, Transform}; +pub use self::transform::{Rotate, Scale, Transform}; pub use self::transform::{TransformOrigin, TransformStyle, Translate}; pub use self::ui::{ColorOrAuto, Cursor, MozForceBrokenImageIcon}; #[cfg(feature = "gecko")] @@ -93,6 +94,7 @@ pub mod calc; pub mod color; pub mod column; pub mod counters; +pub mod easing; pub mod effects; pub mod flex; pub mod font; diff --git a/components/style/values/specified/transform.rs b/components/style/values/specified/transform.rs index 749a3d7b265..1a789c1959d 100644 --- a/components/style/values/specified/transform.rs +++ b/components/style/values/specified/transform.rs @@ -6,13 +6,11 @@ use cssparser::Parser; use parser::{Parse, ParserContext}; -use selectors::parser::SelectorParseErrorKind; use style_traits::{ParseError, StyleParseErrorKind}; use values::computed::{Context, LengthOrPercentage as ComputedLengthOrPercentage}; use values::computed::{Percentage as ComputedPercentage, ToComputedValue}; -use values::computed::transform::TimingFunction as ComputedTimingFunction; use values::generics::transform as generic; -use values::generics::transform::{Matrix, Matrix3D, StepPosition, TimingKeyword}; +use values::generics::transform::{Matrix, Matrix3D}; use values::specified::{self, Angle, Integer, Length, LengthOrPercentage, Number}; use values::specified::position::{Side, X, Y}; @@ -243,9 +241,6 @@ pub enum OriginComponent { Side(S), } -/// A specified timing function. -pub type TimingFunction = generic::TimingFunction; - impl Parse for TransformOrigin { fn parse<'i, 't>( context: &ParserContext, @@ -350,101 +345,6 @@ impl OriginComponent { } } -impl Parse for TimingFunction { - fn parse<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - if let Ok(keyword) = input.try(TimingKeyword::parse) { - return Ok(generic::TimingFunction::Keyword(keyword)); - } - if let Ok(ident) = input.try(|i| i.expect_ident_cloned()) { - let position = match_ignore_ascii_case! { &ident, - "step-start" => StepPosition::Start, - "step-end" => StepPosition::End, - _ => return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone()))), - }; - return Ok(generic::TimingFunction::Steps(Integer::new(1), position)); - } - let location = input.current_source_location(); - let function = input.expect_function()?.clone(); - input.parse_nested_block(move |i| { - (match_ignore_ascii_case! { &function, - "cubic-bezier" => { - let x1 = Number::parse(context, i)?; - i.expect_comma()?; - let y1 = Number::parse(context, i)?; - i.expect_comma()?; - let x2 = Number::parse(context, i)?; - i.expect_comma()?; - let y2 = Number::parse(context, i)?; - - if x1.get() < 0.0 || x1.get() > 1.0 || x2.get() < 0.0 || x2.get() > 1.0 { - return Err(i.new_custom_error(StyleParseErrorKind::UnspecifiedError)); - } - - Ok(generic::TimingFunction::CubicBezier { x1, y1, x2, y2 }) - }, - "steps" => { - let steps = Integer::parse_positive(context, i)?; - let position = i.try(|i| { - i.expect_comma()?; - StepPosition::parse(i) - }).unwrap_or(StepPosition::End); - Ok(generic::TimingFunction::Steps(steps, position)) - }, - _ => Err(()), - }).map_err(|()| { - location.new_custom_error(StyleParseErrorKind::UnexpectedFunction(function.clone())) - }) - }) - } -} - -impl ToComputedValue for TimingFunction { - type ComputedValue = ComputedTimingFunction; - - #[inline] - fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { - match *self { - generic::TimingFunction::Keyword(keyword) => generic::TimingFunction::Keyword(keyword), - generic::TimingFunction::CubicBezier { x1, y1, x2, y2 } => { - generic::TimingFunction::CubicBezier { - x1: x1.to_computed_value(context), - y1: y1.to_computed_value(context), - x2: x2.to_computed_value(context), - y2: y2.to_computed_value(context), - } - }, - generic::TimingFunction::Steps(steps, position) => { - generic::TimingFunction::Steps(steps.to_computed_value(context) as u32, position) - }, - } - } - - #[inline] - fn from_computed_value(computed: &Self::ComputedValue) -> Self { - match *computed { - generic::TimingFunction::Keyword(keyword) => generic::TimingFunction::Keyword(keyword), - generic::TimingFunction::CubicBezier { - ref x1, - ref y1, - ref x2, - ref y2, - } => generic::TimingFunction::CubicBezier { - x1: Number::from_computed_value(x1), - y1: Number::from_computed_value(y1), - x2: Number::from_computed_value(x2), - y2: Number::from_computed_value(y2), - }, - generic::TimingFunction::Steps(steps, position) => generic::TimingFunction::Steps( - Integer::from_computed_value(&(steps as i32)), - position, - ), - } - } -} - /// A specified CSS `rotate` pub type Rotate = generic::Rotate;