Introduce Matrix for matrix() transformations

This commit is contained in:
Anthony Ramine 2017-07-06 12:55:38 +02:00
parent 5f1cb084d0
commit 118291ca91
2 changed files with 81 additions and 69 deletions

View file

@ -688,6 +688,7 @@ ${helpers.predefined_type(
use app_units::Au; use app_units::Au;
use values::computed::{LengthOrPercentageOrNumber as ComputedLoPoNumber, LengthOrNumber as ComputedLoN}; use values::computed::{LengthOrPercentageOrNumber as ComputedLoPoNumber, LengthOrNumber as ComputedLoN};
use values::computed::{LengthOrPercentage as ComputedLoP, Length as ComputedLength}; use values::computed::{LengthOrPercentage as ComputedLoP, Length as ComputedLength};
use values::generics::transform::Matrix;
use values::specified::{Angle, Integer, Length, LengthOrPercentage, Percentage}; use values::specified::{Angle, Integer, Length, LengthOrPercentage, Percentage};
use values::specified::{LengthOrNumber, LengthOrPercentageOrNumber as LoPoNumber, Number}; use values::specified::{LengthOrNumber, LengthOrPercentageOrNumber as LoPoNumber, Number};
use style_traits::ToCss; use style_traits::ToCss;
@ -791,10 +792,10 @@ ${helpers.predefined_type(
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum SpecifiedOperation { pub enum SpecifiedOperation {
/// Represents a 2D 2x3 matrix. /// Represents a 2D 2x3 matrix.
Matrix { a: Number, b: Number, c: Number, d: Number, e: Number, f: Number }, Matrix(Matrix<Number>),
/// Represents a 3D 4x4 matrix with percentage and length values. /// Represents a 3D 4x4 matrix with percentage and length values.
/// For `moz-transform`. /// For `moz-transform`.
PrefixedMatrix { a: Number, b: Number, c: Number, d: Number, e: LoPoNumber, f: LoPoNumber }, PrefixedMatrix(Matrix<Number, LoPoNumber>),
/// Represents a 3D 4x4 matrix. /// Represents a 3D 4x4 matrix.
Matrix3D { Matrix3D {
m11: Number, m12: Number, m13: Number, m14: Number, m11: Number, m12: Number, m13: Number, m14: Number,
@ -872,15 +873,10 @@ ${helpers.predefined_type(
impl ToCss for SpecifiedOperation { impl ToCss for SpecifiedOperation {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
use self::SpecifiedOperation::*;
match *self { match *self {
Matrix { a, b, c, d, e, f} => write!( SpecifiedOperation::Matrix(ref m) => m.to_css(dest),
dest, "matrix({}, {}, {}, {}, {}, {})", SpecifiedOperation::PrefixedMatrix(ref m) => m.to_css(dest),
Css(a), Css(b), Css(c), Css(d), Css(e), Css(f)), SpecifiedOperation::Matrix3D {
PrefixedMatrix { a, b, c, d, ref e, ref f} => write!(
dest, "matrix({}, {}, {}, {}, {}, {})",
Css(a), Css(b), Css(c), Css(d), Css(e), Css(f)),
Matrix3D {
m11, m12, m13, m14, m11, m12, m13, m14,
m21, m22, m23, m24, m21, m22, m23, m24,
m31, m32, m33, m34, m31, m32, m33, m34,
@ -890,7 +886,7 @@ ${helpers.predefined_type(
Css(m21), Css(m22), Css(m23), Css(m24), Css(m21), Css(m22), Css(m23), Css(m24),
Css(m31), Css(m32), Css(m33), Css(m34), Css(m31), Css(m32), Css(m33), Css(m34),
Css(m41), Css(m42), Css(m43), Css(m44)), Css(m41), Css(m42), Css(m43), Css(m44)),
PrefixedMatrix3D { SpecifiedOperation::PrefixedMatrix3D {
m11, m12, m13, m14, m11, m12, m13, m14,
m21, m22, m23, m24, m21, m22, m23, m24,
m31, m32, m33, m34, m31, m32, m33, m34,
@ -900,31 +896,35 @@ ${helpers.predefined_type(
Css(m21), Css(m22), Css(m23), Css(m24), Css(m21), Css(m22), Css(m23), Css(m24),
Css(m31), Css(m32), Css(m33), Css(m34), Css(m31), Css(m32), Css(m33), Css(m34),
Css(m41), Css(m42), Css(m43), Css(m44)), Css(m41), Css(m42), Css(m43), Css(m44)),
Skew(ax, None) => write!(dest, "skew({})", Css(ax)), SpecifiedOperation::Skew(ax, None) => write!(dest, "skew({})", Css(ax)),
Skew(ax, Some(ay)) => write!(dest, "skew({}, {})", Css(ax), Css(ay)), SpecifiedOperation::Skew(ax, Some(ay)) => write!(dest, "skew({}, {})", Css(ax), Css(ay)),
SkewX(angle) => write!(dest, "skewX({})", Css(angle)), SpecifiedOperation::SkewX(angle) => write!(dest, "skewX({})", Css(angle)),
SkewY(angle) => write!(dest, "skewY({})", Css(angle)), SpecifiedOperation::SkewY(angle) => write!(dest, "skewY({})", Css(angle)),
Translate(ref tx, None) => write!(dest, "translate({})", Css(tx)), SpecifiedOperation::Translate(ref tx, None) => write!(dest, "translate({})", Css(tx)),
Translate(ref tx, Some(ref ty)) => write!(dest, "translate({}, {})", Css(tx), Css(ty)), SpecifiedOperation::Translate(ref tx, Some(ref ty)) => {
TranslateX(ref tx) => write!(dest, "translateX({})", Css(tx)), write!(dest, "translate({}, {})", Css(tx), Css(ty))
TranslateY(ref ty) => write!(dest, "translateY({})", Css(ty)), },
TranslateZ(ref tz) => write!(dest, "translateZ({})", Css(tz)), SpecifiedOperation::TranslateX(ref tx) => write!(dest, "translateX({})", Css(tx)),
Translate3D(ref tx, ref ty, ref tz) => write!( SpecifiedOperation::TranslateY(ref ty) => write!(dest, "translateY({})", Css(ty)),
SpecifiedOperation::TranslateZ(ref tz) => write!(dest, "translateZ({})", Css(tz)),
SpecifiedOperation::Translate3D(ref tx, ref ty, ref tz) => write!(
dest, "translate3d({}, {}, {})", Css(tx), Css(ty), Css(tz)), dest, "translate3d({}, {}, {})", Css(tx), Css(ty), Css(tz)),
Scale(factor, None) => write!(dest, "scale({})", Css(factor)), SpecifiedOperation::Scale(factor, None) => write!(dest, "scale({})", Css(factor)),
Scale(sx, Some(sy)) => write!(dest, "scale({}, {})", Css(sx), Css(sy)), SpecifiedOperation::Scale(sx, Some(sy)) => write!(dest, "scale({}, {})", Css(sx), Css(sy)),
ScaleX(sx) => write!(dest, "scaleX({})", Css(sx)), SpecifiedOperation::ScaleX(sx) => write!(dest, "scaleX({})", Css(sx)),
ScaleY(sy) => write!(dest, "scaleY({})", Css(sy)), SpecifiedOperation::ScaleY(sy) => write!(dest, "scaleY({})", Css(sy)),
ScaleZ(sz) => write!(dest, "scaleZ({})", Css(sz)), SpecifiedOperation::ScaleZ(sz) => write!(dest, "scaleZ({})", Css(sz)),
Scale3D(sx, sy, sz) => write!(dest, "scale3d({}, {}, {})", Css(sx), Css(sy), Css(sz)), SpecifiedOperation::Scale3D(sx, sy, sz) => {
Rotate(theta) => write!(dest, "rotate({})", Css(theta)), write!(dest, "scale3d({}, {}, {})", Css(sx), Css(sy), Css(sz))
RotateX(theta) => write!(dest, "rotateX({})", Css(theta)), },
RotateY(theta) => write!(dest, "rotateY({})", Css(theta)), SpecifiedOperation::Rotate(theta) => write!(dest, "rotate({})", Css(theta)),
RotateZ(theta) => write!(dest, "rotateZ({})", Css(theta)), SpecifiedOperation::RotateX(theta) => write!(dest, "rotateX({})", Css(theta)),
Rotate3D(x, y, z, theta) => write!( SpecifiedOperation::RotateY(theta) => write!(dest, "rotateY({})", Css(theta)),
SpecifiedOperation::RotateZ(theta) => write!(dest, "rotateZ({})", Css(theta)),
SpecifiedOperation::Rotate3D(x, y, z, theta) => write!(
dest, "rotate3d({}, {}, {}, {})", dest, "rotate3d({}, {}, {}, {})",
Css(x), Css(y), Css(z), Css(theta)), Css(x), Css(y), Css(z), Css(theta)),
Perspective(ref length) => write!(dest, "perspective({})", Css(length)), SpecifiedOperation::Perspective(ref length) => write!(dest, "perspective({})", Css(length)),
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -988,13 +988,13 @@ ${helpers.predefined_type(
let e = specified::parse_number(context, input)?; let e = specified::parse_number(context, input)?;
input.expect_comma()?; input.expect_comma()?;
let f = specified::parse_number(context, input)?; let f = specified::parse_number(context, input)?;
Ok(SpecifiedOperation::Matrix { a, b, c, d, e, f }) Ok(SpecifiedOperation::Matrix(Matrix { a, b, c, d, e, f }))
} else { } else {
// Non-standard prefixed matrix parsing for -moz-transform. // Non-standard prefixed matrix parsing for -moz-transform.
let e = LoPoNumber::parse(context, input)?; let e = LoPoNumber::parse(context, input)?;
input.expect_comma()?; input.expect_comma()?;
let f = LoPoNumber::parse(context, input)?; let f = LoPoNumber::parse(context, input)?;
Ok(SpecifiedOperation::PrefixedMatrix { a, b, c, d, e, f }) Ok(SpecifiedOperation::PrefixedMatrix(Matrix { a, b, c, d, e, f }))
} }
}, },
"matrix3d" => { "matrix3d" => {
@ -1188,8 +1188,6 @@ ${helpers.predefined_type(
#[inline] #[inline]
fn to_computed_value(&self, context: &Context) -> computed_value::T { fn to_computed_value(&self, context: &Context) -> computed_value::T {
use self::SpecifiedOperation::*;
if self.0.is_empty() { if self.0.is_empty() {
return computed_value::T(None) return computed_value::T(None)
} }
@ -1197,7 +1195,7 @@ ${helpers.predefined_type(
let mut result = vec!(); let mut result = vec!();
for operation in &self.0 { for operation in &self.0 {
match *operation { match *operation {
Matrix { a, b, c, d, e, f } => { SpecifiedOperation::Matrix(Matrix { a, b, c, d, e, f }) => {
let mut comp = computed_value::ComputedMatrix::identity(); let mut comp = computed_value::ComputedMatrix::identity();
comp.m11 = a.to_computed_value(context); comp.m11 = a.to_computed_value(context);
comp.m12 = b.to_computed_value(context); comp.m12 = b.to_computed_value(context);
@ -1207,7 +1205,7 @@ ${helpers.predefined_type(
comp.m42 = f.to_computed_value(context); comp.m42 = f.to_computed_value(context);
result.push(computed_value::ComputedOperation::Matrix(comp)); result.push(computed_value::ComputedOperation::Matrix(comp));
} }
PrefixedMatrix { a, b, c, d, ref e, ref f } => { SpecifiedOperation::PrefixedMatrix(Matrix { a, b, c, d, ref e, ref f }) => {
let mut comp = computed_value::ComputedMatrixWithPercents::identity(); let mut comp = computed_value::ComputedMatrixWithPercents::identity();
comp.m11 = a.to_computed_value(context); comp.m11 = a.to_computed_value(context);
comp.m12 = b.to_computed_value(context); comp.m12 = b.to_computed_value(context);
@ -1217,7 +1215,7 @@ ${helpers.predefined_type(
comp.m42 = lopon_to_lop(&f.to_computed_value(context)); comp.m42 = lopon_to_lop(&f.to_computed_value(context));
result.push(computed_value::ComputedOperation::MatrixWithPercents(comp)); result.push(computed_value::ComputedOperation::MatrixWithPercents(comp));
} }
Matrix3D { SpecifiedOperation::Matrix3D {
m11, m12, m13, m14, m11, m12, m13, m14,
m21, m22, m23, m24, m21, m22, m23, m24,
m31, m32, m33, m34, m31, m32, m33, m34,
@ -1242,7 +1240,7 @@ ${helpers.predefined_type(
}; };
result.push(computed_value::ComputedOperation::Matrix(comp)); result.push(computed_value::ComputedOperation::Matrix(comp));
} }
PrefixedMatrix3D { SpecifiedOperation::PrefixedMatrix3D {
m11, m12, m13, m14, m11, m12, m13, m14,
m21, m22, m23, m24, m21, m22, m23, m24,
m31, m32, m33, m34, m31, m32, m33, m34,
@ -1267,14 +1265,14 @@ ${helpers.predefined_type(
}; };
result.push(computed_value::ComputedOperation::MatrixWithPercents(comp)); result.push(computed_value::ComputedOperation::MatrixWithPercents(comp));
} }
Translate(ref tx, None) => { SpecifiedOperation::Translate(ref tx, None) => {
let tx = tx.to_computed_value(context); let tx = tx.to_computed_value(context);
result.push(computed_value::ComputedOperation::Translate( result.push(computed_value::ComputedOperation::Translate(
tx, tx,
computed::length::LengthOrPercentage::zero(), computed::length::LengthOrPercentage::zero(),
computed::length::Length::new(0))); computed::length::Length::new(0)));
} }
Translate(ref tx, Some(ref ty)) => { SpecifiedOperation::Translate(ref tx, Some(ref ty)) => {
let tx = tx.to_computed_value(context); let tx = tx.to_computed_value(context);
let ty = ty.to_computed_value(context); let ty = ty.to_computed_value(context);
result.push(computed_value::ComputedOperation::Translate( result.push(computed_value::ComputedOperation::Translate(
@ -1282,77 +1280,77 @@ ${helpers.predefined_type(
ty, ty,
computed::length::Length::new(0))); computed::length::Length::new(0)));
} }
TranslateX(ref tx) => { SpecifiedOperation::TranslateX(ref tx) => {
let tx = tx.to_computed_value(context); let tx = tx.to_computed_value(context);
result.push(computed_value::ComputedOperation::Translate( result.push(computed_value::ComputedOperation::Translate(
tx, tx,
computed::length::LengthOrPercentage::zero(), computed::length::LengthOrPercentage::zero(),
computed::length::Length::new(0))); computed::length::Length::new(0)));
} }
TranslateY(ref ty) => { SpecifiedOperation::TranslateY(ref ty) => {
let ty = ty.to_computed_value(context); let ty = ty.to_computed_value(context);
result.push(computed_value::ComputedOperation::Translate( result.push(computed_value::ComputedOperation::Translate(
computed::length::LengthOrPercentage::zero(), computed::length::LengthOrPercentage::zero(),
ty, ty,
computed::length::Length::new(0))); computed::length::Length::new(0)));
} }
TranslateZ(ref tz) => { SpecifiedOperation::TranslateZ(ref tz) => {
let tz = tz.to_computed_value(context); let tz = tz.to_computed_value(context);
result.push(computed_value::ComputedOperation::Translate( result.push(computed_value::ComputedOperation::Translate(
computed::length::LengthOrPercentage::zero(), computed::length::LengthOrPercentage::zero(),
computed::length::LengthOrPercentage::zero(), computed::length::LengthOrPercentage::zero(),
tz)); tz));
} }
Translate3D(ref tx, ref ty, ref tz) => { SpecifiedOperation::Translate3D(ref tx, ref ty, ref tz) => {
let tx = tx.to_computed_value(context); let tx = tx.to_computed_value(context);
let ty = ty.to_computed_value(context); let ty = ty.to_computed_value(context);
let tz = tz.to_computed_value(context); let tz = tz.to_computed_value(context);
result.push(computed_value::ComputedOperation::Translate(tx, ty, tz)); result.push(computed_value::ComputedOperation::Translate(tx, ty, tz));
} }
Scale(factor, None) => { SpecifiedOperation::Scale(factor, None) => {
let factor = factor.to_computed_value(context); let factor = factor.to_computed_value(context);
result.push(computed_value::ComputedOperation::Scale(factor, factor, 1.0)); result.push(computed_value::ComputedOperation::Scale(factor, factor, 1.0));
} }
Scale(sx, Some(sy)) => { SpecifiedOperation::Scale(sx, Some(sy)) => {
let sx = sx.to_computed_value(context); let sx = sx.to_computed_value(context);
let sy = sy.to_computed_value(context); let sy = sy.to_computed_value(context);
result.push(computed_value::ComputedOperation::Scale(sx, sy, 1.0)); result.push(computed_value::ComputedOperation::Scale(sx, sy, 1.0));
} }
ScaleX(sx) => { SpecifiedOperation::ScaleX(sx) => {
let sx = sx.to_computed_value(context); let sx = sx.to_computed_value(context);
result.push(computed_value::ComputedOperation::Scale(sx, 1.0, 1.0)); result.push(computed_value::ComputedOperation::Scale(sx, 1.0, 1.0));
} }
ScaleY(sy) => { SpecifiedOperation::ScaleY(sy) => {
let sy = sy.to_computed_value(context); let sy = sy.to_computed_value(context);
result.push(computed_value::ComputedOperation::Scale(1.0, sy, 1.0)); result.push(computed_value::ComputedOperation::Scale(1.0, sy, 1.0));
} }
ScaleZ(sz) => { SpecifiedOperation::ScaleZ(sz) => {
let sz = sz.to_computed_value(context); let sz = sz.to_computed_value(context);
result.push(computed_value::ComputedOperation::Scale(1.0, 1.0, sz)); result.push(computed_value::ComputedOperation::Scale(1.0, 1.0, sz));
} }
Scale3D(sx, sy, sz) => { SpecifiedOperation::Scale3D(sx, sy, sz) => {
let sx = sx.to_computed_value(context); let sx = sx.to_computed_value(context);
let sy = sy.to_computed_value(context); let sy = sy.to_computed_value(context);
let sz = sz.to_computed_value(context); let sz = sz.to_computed_value(context);
result.push(computed_value::ComputedOperation::Scale(sx, sy, sz)); result.push(computed_value::ComputedOperation::Scale(sx, sy, sz));
} }
Rotate(theta) => { SpecifiedOperation::Rotate(theta) => {
let theta = theta.to_computed_value(context); let theta = theta.to_computed_value(context);
result.push(computed_value::ComputedOperation::Rotate(0.0, 0.0, 1.0, theta)); result.push(computed_value::ComputedOperation::Rotate(0.0, 0.0, 1.0, theta));
} }
RotateX(theta) => { SpecifiedOperation::RotateX(theta) => {
let theta = theta.to_computed_value(context); let theta = theta.to_computed_value(context);
result.push(computed_value::ComputedOperation::Rotate(1.0, 0.0, 0.0, theta)); result.push(computed_value::ComputedOperation::Rotate(1.0, 0.0, 0.0, theta));
} }
RotateY(theta) => { SpecifiedOperation::RotateY(theta) => {
let theta = theta.to_computed_value(context); let theta = theta.to_computed_value(context);
result.push(computed_value::ComputedOperation::Rotate(0.0, 1.0, 0.0, theta)); result.push(computed_value::ComputedOperation::Rotate(0.0, 1.0, 0.0, theta));
} }
RotateZ(theta) => { SpecifiedOperation::RotateZ(theta) => {
let theta = theta.to_computed_value(context); let theta = theta.to_computed_value(context);
result.push(computed_value::ComputedOperation::Rotate(0.0, 0.0, 1.0, theta)); result.push(computed_value::ComputedOperation::Rotate(0.0, 0.0, 1.0, theta));
} }
Rotate3D(ax, ay, az, theta) => { SpecifiedOperation::Rotate3D(ax, ay, az, theta) => {
let ax = ax.to_computed_value(context); let ax = ax.to_computed_value(context);
let ay = ay.to_computed_value(context); let ay = ay.to_computed_value(context);
let az = az.to_computed_value(context); let az = az.to_computed_value(context);
@ -1360,34 +1358,34 @@ ${helpers.predefined_type(
let len = (ax * ax + ay * ay + az * az).sqrt(); let len = (ax * ax + ay * ay + az * az).sqrt();
result.push(computed_value::ComputedOperation::Rotate(ax / len, ay / len, az / len, theta)); result.push(computed_value::ComputedOperation::Rotate(ax / len, ay / len, az / len, theta));
} }
Skew(theta_x, None) => { SpecifiedOperation::Skew(theta_x, None) => {
let theta_x = theta_x.to_computed_value(context); let theta_x = theta_x.to_computed_value(context);
result.push(computed_value::ComputedOperation::Skew(theta_x, computed::Angle::zero())); result.push(computed_value::ComputedOperation::Skew(theta_x, computed::Angle::zero()));
} }
Skew(theta_x, Some(theta_y)) => { SpecifiedOperation::Skew(theta_x, Some(theta_y)) => {
let theta_x = theta_x.to_computed_value(context); let theta_x = theta_x.to_computed_value(context);
let theta_y = theta_y.to_computed_value(context); let theta_y = theta_y.to_computed_value(context);
result.push(computed_value::ComputedOperation::Skew(theta_x, theta_y)); result.push(computed_value::ComputedOperation::Skew(theta_x, theta_y));
} }
SkewX(theta_x) => { SpecifiedOperation::SkewX(theta_x) => {
let theta_x = theta_x.to_computed_value(context); let theta_x = theta_x.to_computed_value(context);
result.push(computed_value::ComputedOperation::Skew(theta_x, computed::Angle::zero())); result.push(computed_value::ComputedOperation::Skew(theta_x, computed::Angle::zero()));
} }
SkewY(theta_y) => { SpecifiedOperation::SkewY(theta_y) => {
let theta_y = theta_y.to_computed_value(context); let theta_y = theta_y.to_computed_value(context);
result.push(computed_value::ComputedOperation::Skew(computed::Angle::zero(), theta_y)); result.push(computed_value::ComputedOperation::Skew(computed::Angle::zero(), theta_y));
} }
Perspective(ref d) => { SpecifiedOperation::Perspective(ref d) => {
result.push(computed_value::ComputedOperation::Perspective(d.to_computed_value(context))); result.push(computed_value::ComputedOperation::Perspective(d.to_computed_value(context)));
} }
InterpolateMatrix { ref from_list, ref to_list, progress } => { SpecifiedOperation::InterpolateMatrix { ref from_list, ref to_list, progress } => {
result.push(computed_value::ComputedOperation::InterpolateMatrix { result.push(computed_value::ComputedOperation::InterpolateMatrix {
from_list: from_list.to_computed_value(context), from_list: from_list.to_computed_value(context),
to_list: to_list.to_computed_value(context), to_list: to_list.to_computed_value(context),
progress: progress progress: progress
}); });
} }
AccumulateMatrix { ref from_list, ref to_list, count } => { SpecifiedOperation::AccumulateMatrix { ref from_list, ref to_list, count } => {
result.push(computed_value::ComputedOperation::AccumulateMatrix { result.push(computed_value::ComputedOperation::AccumulateMatrix {
from_list: from_list.to_computed_value(context), from_list: from_list.to_computed_value(context),
to_list: to_list.to_computed_value(context), to_list: to_list.to_computed_value(context),

View file

@ -9,6 +9,20 @@ use std::fmt;
use style_traits::{HasViewportPercentage, ToCss}; use style_traits::{HasViewportPercentage, ToCss};
use values::CSSFloat; use values::CSSFloat;
/// A generic 2D transformation matrix.
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)]
#[css(comma, function)]
pub struct Matrix<T, U = T> {
pub a: T,
pub b: T,
pub c: T,
pub d: T,
pub e: U,
pub f: U,
}
/// A generic transform origin. /// A generic transform origin.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)] #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)]
@ -37,10 +51,6 @@ pub enum TimingFunction<Integer, Number> {
Frames(Integer), Frames(Integer),
} }
impl<I, N> HasViewportPercentage for TimingFunction<I, N> {
fn has_viewport_percentage(&self) -> bool { false }
}
define_css_keyword_enum! { TimingKeyword: define_css_keyword_enum! { TimingKeyword:
"linear" => Linear, "linear" => Linear,
"ease" => Ease, "ease" => Ease,
@ -67,6 +77,10 @@ impl<H, V, D> TransformOrigin<H, V, D> {
} }
} }
impl<I, N> HasViewportPercentage for TimingFunction<I, N> {
fn has_viewport_percentage(&self) -> bool { false }
}
impl<Integer, Number> TimingFunction<Integer, Number> { impl<Integer, Number> TimingFunction<Integer, Number> {
/// `ease` /// `ease`
#[inline] #[inline]