Derive ToCss for TransformOperation

Now that SequenceWriter<W> does not monomorphise excessively, we can actually
type check a derived ToCss without too much type recursion.
This commit is contained in:
Anthony Ramine 2018-01-22 23:37:15 +01:00
parent cd8f96cc9e
commit 42c8dc983f
2 changed files with 61 additions and 125 deletions

View file

@ -30,7 +30,8 @@ pub struct Matrix<T, U = T> {
#[allow(missing_docs)]
#[cfg_attr(rustfmt, rustfmt_skip)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
#[css(comma, function = "matrix3d")]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
pub struct Matrix3D<T, U = T, V = T> {
pub m11: T, pub m12: T, pub m13: T, pub m14: T,
pub m21: T, pub m22: T, pub m23: T, pub m24: T,
@ -191,7 +192,7 @@ impl TimingKeyword {
}
}
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
/// A single operation in the list of a `transform` value
pub enum TransformOperation<Angle, Number, Length, Integer, LengthOrNumber, LengthOrPercentage, LoPoNumber> {
/// Represents a 2D 2x3 matrix.
@ -200,31 +201,37 @@ pub enum TransformOperation<Angle, Number, Length, Integer, LengthOrNumber, Leng
/// For `moz-transform`.
PrefixedMatrix(Matrix<Number, LoPoNumber>),
/// Represents a 3D 4x4 matrix.
#[allow(missing_docs)]
Matrix3D(Matrix3D<Number>),
/// Represents a 3D 4x4 matrix with percentage and length values.
/// For `moz-transform`.
#[allow(missing_docs)]
PrefixedMatrix3D(Matrix3D<Number, LoPoNumber, LengthOrNumber>),
/// A 2D skew.
///
/// If the second angle is not provided it is assumed zero.
///
/// Syntax can be skew(angle) or skew(angle, angle)
#[css(comma, function)]
Skew(Angle, Option<Angle>),
/// skewX(angle)
#[css(function = "skewX")]
SkewX(Angle),
/// skewY(angle)
#[css(function = "skewY")]
SkewY(Angle),
/// translate(x, y) or translate(x)
#[css(comma, function)]
Translate(LengthOrPercentage, Option<LengthOrPercentage>),
/// translateX(x)
#[css(function = "translateX")]
TranslateX(LengthOrPercentage),
/// translateY(y)
#[css(function = "translateY")]
TranslateY(LengthOrPercentage),
/// translateZ(z)
#[css(function = "translateZ")]
TranslateZ(Length),
/// translate3d(x, y, z)
#[css(comma, function = "translate3d")]
Translate3D(LengthOrPercentage, LengthOrPercentage, Length),
/// A 2D scaling factor.
///
@ -234,28 +241,38 @@ pub enum TransformOperation<Angle, Number, Length, Integer, LengthOrNumber, Leng
/// Negative values are allowed and flip the element.
///
/// Syntax can be scale(factor) or scale(factor, factor)
#[css(comma, function)]
Scale(Number, Option<Number>),
/// scaleX(factor)
#[css(function = "scaleX")]
ScaleX(Number),
/// scaleY(factor)
#[css(function = "scaleY")]
ScaleY(Number),
/// scaleZ(factor)
#[css(function = "scaleZ")]
ScaleZ(Number),
/// scale3D(factorX, factorY, factorZ)
#[css(comma, function = "scale3d")]
Scale3D(Number, Number, Number),
/// Describes a 2D Rotation.
///
/// In a 3D scene `rotate(angle)` is equivalent to `rotateZ(angle)`.
#[css(function)]
Rotate(Angle),
/// Rotation in 3D space around the x-axis.
#[css(function = "rotateX")]
RotateX(Angle),
/// Rotation in 3D space around the y-axis.
#[css(function = "rotateY")]
RotateY(Angle),
/// Rotation in 3D space around the z-axis.
#[css(function = "rotateZ")]
RotateZ(Angle),
/// Rotation in 3D space.
///
/// Generalization of rotateX, rotateY and rotateZ.
#[css(comma, function = "rotate3d")]
Rotate3D(Number, Number, Number, Angle),
/// Specifies a perspective projection matrix.
///
@ -263,11 +280,14 @@ pub enum TransformOperation<Angle, Number, Length, Integer, LengthOrNumber, Leng
/// [§ 13.1. 3D Transform Function](https://drafts.csswg.org/css-transforms-2/#funcdef-perspective).
///
/// The value must be greater than or equal to zero.
#[css(function)]
Perspective(Length),
/// A intermediate type for interpolation of mismatched transform lists.
#[allow(missing_docs)]
#[css(comma, function = "interpolatematrix")]
InterpolateMatrix {
#[compute(ignore_bound)]
#[css(ignore_bound)]
from_list: Transform<
TransformOperation<
Angle,
@ -280,6 +300,7 @@ pub enum TransformOperation<Angle, Number, Length, Integer, LengthOrNumber, Leng
>,
>,
#[compute(ignore_bound)]
#[css(ignore_bound)]
to_list: Transform<
TransformOperation<
Angle,
@ -296,8 +317,10 @@ pub enum TransformOperation<Angle, Number, Length, Integer, LengthOrNumber, Leng
},
/// A intermediate type for accumulation of mismatched transform lists.
#[allow(missing_docs)]
#[css(comma, function = "accumulatematrix")]
AccumulateMatrix {
#[compute(ignore_bound)]
#[css(ignore_bound)]
from_list: Transform<
TransformOperation<
Angle,
@ -310,6 +333,7 @@ pub enum TransformOperation<Angle, Number, Length, Integer, LengthOrNumber, Leng
>,
>,
#[compute(ignore_bound)]
#[css(ignore_bound)]
to_list: Transform<
TransformOperation<
Angle,
@ -541,120 +565,6 @@ where
}
}
#[cfg_attr(rustfmt, rustfmt_skip)]
impl<Angle: ToCss + Copy, Number: ToCss + Copy, Length: ToCss,
Integer: ToCss + Copy, LengthOrNumber: ToCss, LengthOrPercentage: ToCss, LoPoNumber: ToCss>
ToCss for
TransformOperation<Angle, Number, Length, Integer, LengthOrNumber, LengthOrPercentage, LoPoNumber> {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
match *self {
TransformOperation::Matrix(ref m) => m.to_css(dest),
TransformOperation::PrefixedMatrix(ref m) => m.to_css(dest),
TransformOperation::Matrix3D(Matrix3D {
m11, m12, m13, m14,
m21, m22, m23, m24,
m31, m32, m33, m34,
m41, m42, m43, m44,
}) => {
serialize_function!(dest, matrix3d(
m11, m12, m13, m14,
m21, m22, m23, m24,
m31, m32, m33, m34,
m41, m42, m43, m44,
))
}
TransformOperation::PrefixedMatrix3D(Matrix3D {
m11, m12, m13, m14,
m21, m22, m23, m24,
m31, m32, m33, m34,
ref m41, ref m42, ref m43, m44,
}) => {
serialize_function!(dest, matrix3d(
m11, m12, m13, m14,
m21, m22, m23, m24,
m31, m32, m33, m34,
m41, m42, m43, m44,
))
}
TransformOperation::Skew(ax, None) => {
serialize_function!(dest, skew(ax))
}
TransformOperation::Skew(ax, Some(ay)) => {
serialize_function!(dest, skew(ax, ay))
}
TransformOperation::SkewX(angle) => {
serialize_function!(dest, skewX(angle))
}
TransformOperation::SkewY(angle) => {
serialize_function!(dest, skewY(angle))
}
TransformOperation::Translate(ref tx, None) => {
serialize_function!(dest, translate(tx))
}
TransformOperation::Translate(ref tx, Some(ref ty)) => {
serialize_function!(dest, translate(tx, ty))
}
TransformOperation::TranslateX(ref tx) => {
serialize_function!(dest, translateX(tx))
}
TransformOperation::TranslateY(ref ty) => {
serialize_function!(dest, translateY(ty))
}
TransformOperation::TranslateZ(ref tz) => {
serialize_function!(dest, translateZ(tz))
}
TransformOperation::Translate3D(ref tx, ref ty, ref tz) => {
serialize_function!(dest, translate3d(tx, ty, tz))
}
TransformOperation::Scale(factor, None) => {
serialize_function!(dest, scale(factor))
}
TransformOperation::Scale(sx, Some(sy)) => {
serialize_function!(dest, scale(sx, sy))
}
TransformOperation::ScaleX(sx) => {
serialize_function!(dest, scaleX(sx))
}
TransformOperation::ScaleY(sy) => {
serialize_function!(dest, scaleY(sy))
}
TransformOperation::ScaleZ(sz) => {
serialize_function!(dest, scaleZ(sz))
}
TransformOperation::Scale3D(sx, sy, sz) => {
serialize_function!(dest, scale3d(sx, sy, sz))
}
TransformOperation::Rotate(theta) => {
serialize_function!(dest, rotate(theta))
}
TransformOperation::RotateX(theta) => {
serialize_function!(dest, rotateX(theta))
}
TransformOperation::RotateY(theta) => {
serialize_function!(dest, rotateY(theta))
}
TransformOperation::RotateZ(theta) => {
serialize_function!(dest, rotateZ(theta))
}
TransformOperation::Rotate3D(x, y, z, theta) => {
serialize_function!(dest, rotate3d(x, y, z, theta))
}
TransformOperation::Perspective(ref length) => {
serialize_function!(dest, perspective(length))
}
TransformOperation::InterpolateMatrix { ref from_list, ref to_list, progress } => {
serialize_function!(dest, interpolatematrix(from_list, to_list, progress))
}
TransformOperation::AccumulateMatrix { ref from_list, ref to_list, count } => {
serialize_function!(dest, accumulatematrix(from_list, to_list, count))
}
}
}
}
impl<T: ToCss> ToCss for Transform<T> {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where