/* 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 values that are related to transformations. use euclid::Point2D; use std::fmt; use style_traits::{HasViewportPercentage, ToCss}; use values::CSSFloat; /// A generic transform origin. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)] pub struct TransformOrigin { /// The horizontal origin. pub horizontal: H, /// The vertical origin. pub vertical: V, /// The depth. pub depth: Depth, } /// A generic timing function. /// /// https://drafts.csswg.org/css-timing-1/#single-timing-function-production #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Copy, Debug, PartialEq)] pub enum TimingFunction { /// `linear | ease | ease-in | ease-out | ease-in-out` Keyword(TimingKeyword), /// `cubic-bezier(, , , )` CubicBezier(Point2D, Point2D), /// `step-start | step-end | steps(, [ start | end ]?)` Steps(Integer, StepPosition), /// `frames()` Frames(Integer), } impl HasViewportPercentage for TimingFunction { fn has_viewport_percentage(&self) -> bool { false } } define_css_keyword_enum! { TimingKeyword: "linear" => Linear, "ease" => Ease, "ease-in" => EaseIn, "ease-out" => EaseOut, "ease-in-out" => EaseInOut, } add_impls_for_keyword_enum!(TimingKeyword); define_css_keyword_enum! { StepPosition: "start" => Start, "end" => End, } add_impls_for_keyword_enum!(StepPosition); impl TransformOrigin { /// Returns a new transform origin. pub fn new(horizontal: H, vertical: V, depth: D) -> Self { Self { horizontal: horizontal, vertical: vertical, depth: depth, } } } impl TimingFunction { /// `ease` #[inline] pub fn ease() -> Self { TimingFunction::Keyword(TimingKeyword::Ease) } } impl ToCss for TimingFunction where Integer: ToCss, Number: ToCss, { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write, { match *self { TimingFunction::Keyword(keyword) => keyword.to_css(dest), TimingFunction::CubicBezier(ref p1, ref p2) => { dest.write_str("cubic-bezier(")?; p1.x.to_css(dest)?; dest.write_str(", ")?; p1.y.to_css(dest)?; dest.write_str(", ")?; p2.x.to_css(dest)?; dest.write_str(", ")?; p2.y.to_css(dest)?; dest.write_str(")") }, TimingFunction::Steps(ref intervals, position) => { dest.write_str("steps(")?; intervals.to_css(dest)?; if position != StepPosition::End { dest.write_str(", ")?; position.to_css(dest)?; } dest.write_str(")") }, TimingFunction::Frames(ref frames) => { dest.write_str("frames(")?; frames.to_css(dest)?; dest.write_str(")") }, } } } impl TimingKeyword { /// Returns this timing keyword as a pair of `cubic-bezier()` points. #[inline] pub fn to_bezier_points(self) -> (Point2D, Point2D) { match self { TimingKeyword::Linear => (Point2D::new(0., 0.), Point2D::new(1., 1.)), TimingKeyword::Ease => (Point2D::new(0.25, 0.1), Point2D::new(0.25, 1.)), TimingKeyword::EaseIn => (Point2D::new(0.42, 0.), Point2D::new(1., 1.)), TimingKeyword::EaseOut => (Point2D::new(0., 0.), Point2D::new(0.58, 1.)), TimingKeyword::EaseInOut => (Point2D::new(0.42, 0.), Point2D::new(0.58, 1.)), } } }