Skip to content

Commit

Permalink
style: Split TimingFunction into a separate file to match spec.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
BorisChiou authored and emilio committed Oct 28, 2018
1 parent 3a536f4 commit a20b6a5
Show file tree
Hide file tree
Showing 11 changed files with 230 additions and 193 deletions.
4 changes: 2 additions & 2 deletions components/style/animation.rs
Expand Up @@ -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.
Expand Down
8 changes: 4 additions & 4 deletions components/style/gecko_bindings/sugar/ns_timing_function.rs
Expand Up @@ -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) {
Expand Down
11 changes: 11 additions & 0 deletions 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<u32, Number>;
4 changes: 3 additions & 1 deletion components/style/values/computed/mod.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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")]
Expand All @@ -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;
Expand Down
3 changes: 0 additions & 3 deletions components/style/values/computed/transform.rs
Expand Up @@ -22,9 +22,6 @@ pub type Transform = generic::Transform<TransformOperation>;
/// The computed value of a CSS `<transform-origin>`
pub type TransformOrigin = generic::TransformOrigin<LengthOrPercentage, LengthOrPercentage, Length>;

/// A computed timing function.
pub type TimingFunction = generic::TimingFunction<u32, Number>;

/// A vector to represent the direction vector (rotate axis) for Rotate3D.
pub type DirectionVector = Vector3D<CSSFloat>;

Expand Down
87 changes: 87 additions & 0 deletions 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<Integer, Number> {
/// `linear | ease | ease-in | ease-out | ease-in-out`
Keyword(TimingKeyword),
/// `cubic-bezier(<number>, <number>, <number>, <number>)`
#[allow(missing_docs)]
#[css(comma, function)]
CubicBezier {
x1: Number,
y1: Number,
x2: Number,
y2: Number,
},
/// `step-start | step-end | steps(<integer>, [ 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<Integer, Number> TimingFunction<Integer, Number> {
/// `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.),
}
}
}
1 change: 1 addition & 0 deletions components/style/values/generics/mod.rs
Expand Up @@ -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;
Expand Down
81 changes: 0 additions & 81 deletions components/style/values/generics/transform.rs
Expand Up @@ -90,64 +90,6 @@ pub struct TransformOrigin<H, V, Depth> {
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<Integer, Number> {
/// `linear | ease | ease-in | ease-out | ease-in-out`
Keyword(TimingKeyword),
/// `cubic-bezier(<number>, <number>, <number>, <number>)`
#[allow(missing_docs)]
#[css(comma, function)]
CubicBezier {
x1: Number,
y1: Number,
x2: Number,
y2: Number,
},
/// `step-start | step-end | steps(<integer>, [ 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<H, V, D> TransformOrigin<H, V, D> {
/// Returns a new transform origin.
pub fn new(horizontal: H, vertical: V, depth: D) -> Self {
Expand All @@ -159,29 +101,6 @@ impl<H, V, D> TransformOrigin<H, V, D> {
}
}

impl<Integer, Number> TimingFunction<Integer, Number> {
/// `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<Angle, Number, Length, Integer, LengthOrPercentage> {
Expand Down
118 changes: 118 additions & 0 deletions 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<Integer, Number>;

impl Parse for TimingFunction {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
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,
),
}
}
}

0 comments on commit a20b6a5

Please sign in to comment.