From 5f1cb084d07b232544c3a220542c7f76c130a7fa Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 5 Jul 2017 14:38:37 +0200 Subject: [PATCH 01/12] Clean up parsing code for specified transform values --- .../style/properties/longhand/box.mako.rs | 404 +++++++----------- 1 file changed, 156 insertions(+), 248 deletions(-) diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index 3f70a05bf41..0dffc85bc2d 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -959,248 +959,176 @@ ${helpers.predefined_type( } // Allow unitless zero angle for rotate() and skew() to align with gecko - fn parse_internal<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>, prefixed: bool) - -> Result> { + fn parse_internal<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + prefixed: bool, + ) -> Result> { + use style_traits::{Separator, Space}; + if input.try(|input| input.expect_ident_matching("none")).is_ok() { return Ok(SpecifiedValue(Vec::new())) } - let mut result = Vec::new(); - loop { - let name = match input.try(|i| i.expect_function()) { - Ok(name) => name, - Err(_) => break, - }; - let valid_fn = match_ignore_ascii_case! { - &name, - "matrix" => { - input.parse_nested_block(|input| { - // Standard matrix parsing. + Ok(SpecifiedValue(Space::parse(input, |input| { + let function = input.expect_function()?; + input.parse_nested_block(|input| { + let result = match_ignore_ascii_case! { &function, + "matrix" => { + let a = specified::parse_number(context, input)?; + input.expect_comma()?; + let b = specified::parse_number(context, input)?; + input.expect_comma()?; + let c = specified::parse_number(context, input)?; + input.expect_comma()?; + let d = specified::parse_number(context, input)?; + input.expect_comma()?; if !prefixed { - let values = input.parse_comma_separated(|input| { - specified::parse_number(context, input) - })?; - if values.len() != 6 { - return Err(StyleParseError::UnspecifiedError.into()) - } - - result.push(SpecifiedOperation::Matrix { - a: values[0], - b: values[1], - c: values[2], - d: values[3], - e: values[4], - f: values[5], - }); - return Ok(true); - } - - // Non-standard prefixed matrix parsing. - // - // -moz-transform accepts LengthOrPercentageOrNumber in the - // nondiagonal homogeneous components. transform accepts only number. - let mut values = Vec::with_capacity(4); - let mut lengths = Vec::with_capacity(2); - - // Consume first number - values.push(specified::parse_number(context, input)?); - - // Parse other 5 number/LengthOrPercentageOrNumber - for i in 0..5 { + // Standard matrix parsing. + let e = specified::parse_number(context, input)?; input.expect_comma()?; - if i < 3 { - values.push(specified::parse_number(context, input)?); - } else { - // -moz-transform accepts LengthOrPercentageOrNumber in the nondiagonal - // homogeneous components. transform accepts only number. - lengths.push(LoPoNumber::parse(context, input)?) - } + let f = specified::parse_number(context, input)?; + Ok(SpecifiedOperation::Matrix { a, b, c, d, e, f }) + } else { + // Non-standard prefixed matrix parsing for -moz-transform. + let e = LoPoNumber::parse(context, input)?; + input.expect_comma()?; + let f = LoPoNumber::parse(context, input)?; + Ok(SpecifiedOperation::PrefixedMatrix { a, b, c, d, e, f }) } - - result.push(SpecifiedOperation::PrefixedMatrix { - a: values[0], - b: values[1], - c: values[2], - d: values[3], - e: lengths[0].clone(), - f: lengths[1].clone(), - }); - Ok(true) - })? - }, - "matrix3d" => { - input.parse_nested_block(|input| { - // Standard matrix3d parsing. + }, + "matrix3d" => { + let m11 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m12 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m13 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m14 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m21 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m22 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m23 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m24 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m31 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m32 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m33 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m34 = specified::parse_number(context, input)?; + input.expect_comma()?; if !prefixed { - let values = input.parse_comma_separated(|i| specified::parse_number(context, i))?; - if values.len() != 16 { - return Err(StyleParseError::UnspecifiedError.into()) - } - - result.push(SpecifiedOperation::Matrix3D { - m11: values[ 0], m12: values[ 1], m13: values[ 2], m14: values[ 3], - m21: values[ 4], m22: values[ 5], m23: values[ 6], m24: values[ 7], - m31: values[ 8], m32: values[ 9], m33: values[10], m34: values[11], - m41: values[12], m42: values[13], m43: values[14], m44: values[15] - }); - return Ok(true); - } - - // Non-standard prefixed matrix3d parsing. - // - // -moz-transform accepts LengthOrPercentageOrNumber in the - // nondiagonal homogeneous components. transform accepts only number. - let mut values = Vec::with_capacity(13); - let mut lops = Vec::with_capacity(2); - let mut length_or_number = None; - - // Parse first number - values.push(specified::parse_number(context, input)?); - - // Parse other 15 number/LengthOrPercentageOrNumber - for i in 0..15 { + // Standard matrix3d parsing. + let m41 = specified::parse_number(context, input)?; input.expect_comma()?; - // -moz-transform accepts LengthOrPercentageOrNumber in the nondiagonal - // homogeneous components. transform accepts only number. - if i < 11 || i > 13 { - values.push(specified::parse_number(context, input)?); - } else if i == 13 { - // m43 - length_or_number = Some(LengthOrNumber::parse(context, input)?); - } else { - // m41 and m42 - lops.push(LoPoNumber::parse(context, input)?); - } + let m42 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m43 = specified::parse_number(context, input)?; + input.expect_comma()?; + let m44 = specified::parse_number(context, input)?; + Ok(SpecifiedOperation::Matrix3D { + m11, m12, m13, m14, + m21, m22, m23, m24, + m31, m32, m33, m34, + m41, m42, m43, m44, + }) + } else { + // Non-standard prefixed matrix parsing for -moz-transform. + let m41 = LoPoNumber::parse(context, input)?; + input.expect_comma()?; + let m42 = LoPoNumber::parse(context, input)?; + input.expect_comma()?; + let m43 = LengthOrNumber::parse(context, input)?; + input.expect_comma()?; + let m44 = specified::parse_number(context, input)?; + Ok(SpecifiedOperation::PrefixedMatrix3D { + m11, m12, m13, m14, + m21, m22, m23, m24, + m31, m32, m33, m34, + m41, m42, m43, m44, + }) } - - result.push(SpecifiedOperation::PrefixedMatrix3D { - m11: values[ 0], m12: values[ 1], m13: values[ 2], m14: values[ 3], - m21: values[ 4], m22: values[ 5], m23: values[ 6], m24: values[ 7], - m31: values[ 8], m32: values[ 9], m33: values[10], m34: values[11], - m41: lops[0].clone(), m42: lops[1].clone(), m43: length_or_number.unwrap(), - m44: values[12] - }); - Ok(true) - })? - }, - "translate" => { - input.parse_nested_block(|input| { + }, + "translate" => { let sx = specified::LengthOrPercentage::parse(context, input)?; if input.try(|input| input.expect_comma()).is_ok() { let sy = specified::LengthOrPercentage::parse(context, input)?; - result.push(SpecifiedOperation::Translate(sx, Some(sy))); + Ok(SpecifiedOperation::Translate(sx, Some(sy))) } else { - result.push(SpecifiedOperation::Translate(sx, None)); + Ok(SpecifiedOperation::Translate(sx, None)) } - Ok(true) - })? - }, - "translatex" => { - input.parse_nested_block(|input| { + }, + "translatex" => { let tx = specified::LengthOrPercentage::parse(context, input)?; - result.push(SpecifiedOperation::TranslateX(tx)); - Ok(true) - })? - }, - "translatey" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::TranslateX(tx)) + }, + "translatey" => { let ty = specified::LengthOrPercentage::parse(context, input)?; - result.push(SpecifiedOperation::TranslateY(ty)); - Ok(true) - })? - }, - "translatez" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::TranslateY(ty)) + }, + "translatez" => { let tz = specified::Length::parse(context, input)?; - result.push(SpecifiedOperation::TranslateZ(tz)); - Ok(true) - })? - }, - "translate3d" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::TranslateZ(tz)) + }, + "translate3d" => { let tx = specified::LengthOrPercentage::parse(context, input)?; input.expect_comma()?; let ty = specified::LengthOrPercentage::parse(context, input)?; input.expect_comma()?; let tz = specified::Length::parse(context, input)?; - result.push(SpecifiedOperation::Translate3D(tx, ty, tz)); - Ok(true) - })? - }, - "scale" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::Translate3D(tx, ty, tz)) + }, + "scale" => { let sx = specified::parse_number(context, input)?; if input.try(|input| input.expect_comma()).is_ok() { let sy = specified::parse_number(context, input)?; - result.push(SpecifiedOperation::Scale(sx, Some(sy))); + Ok(SpecifiedOperation::Scale(sx, Some(sy))) } else { - result.push(SpecifiedOperation::Scale(sx, None)); + Ok(SpecifiedOperation::Scale(sx, None)) } - Ok(true) - })? - }, - "scalex" => { - input.parse_nested_block(|input| { + }, + "scalex" => { let sx = specified::parse_number(context, input)?; - result.push(SpecifiedOperation::ScaleX(sx)); - Ok(true) - })? - }, - "scaley" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::ScaleX(sx)) + }, + "scaley" => { let sy = specified::parse_number(context, input)?; - result.push(SpecifiedOperation::ScaleY(sy)); - Ok(true) - })? - }, - "scalez" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::ScaleY(sy)) + }, + "scalez" => { let sz = specified::parse_number(context, input)?; - result.push(SpecifiedOperation::ScaleZ(sz)); - Ok(true) - })? - }, - "scale3d" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::ScaleZ(sz)) + }, + "scale3d" => { let sx = specified::parse_number(context, input)?; input.expect_comma()?; let sy = specified::parse_number(context, input)?; input.expect_comma()?; let sz = specified::parse_number(context, input)?; - result.push(SpecifiedOperation::Scale3D(sx, sy, sz)); - Ok(true) - })? - }, - "rotate" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::Scale3D(sx, sy, sz)) + }, + "rotate" => { let theta = specified::Angle::parse_with_unitless(context, input)?; - result.push(SpecifiedOperation::Rotate(theta)); - Ok(true) - })? - }, - "rotatex" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::Rotate(theta)) + }, + "rotatex" => { let theta = specified::Angle::parse_with_unitless(context, input)?; - result.push(SpecifiedOperation::RotateX(theta)); - Ok(true) - })? - }, - "rotatey" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::RotateX(theta)) + }, + "rotatey" => { let theta = specified::Angle::parse_with_unitless(context, input)?; - result.push(SpecifiedOperation::RotateY(theta)); - Ok(true) - })? - }, - "rotatez" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::RotateY(theta)) + }, + "rotatez" => { let theta = specified::Angle::parse_with_unitless(context, input)?; - result.push(SpecifiedOperation::RotateZ(theta)); - Ok(true) - })? - }, - "rotate3d" => { - input.parse_nested_block(|input| { + Ok(SpecifiedOperation::RotateZ(theta)) + }, + "rotate3d" => { let ax = specified::parse_number(context, input)?; input.expect_comma()?; let ay = specified::parse_number(context, input)?; @@ -1208,56 +1136,36 @@ ${helpers.predefined_type( let az = specified::parse_number(context, input)?; input.expect_comma()?; let theta = specified::Angle::parse_with_unitless(context, input)?; - // TODO(gw): Check the axis can be normalized!! - result.push(SpecifiedOperation::Rotate3D(ax, ay, az, theta)); - Ok(true) - })? - }, - "skew" => { - input.parse_nested_block(|input| { - let theta_x = specified::Angle::parse_with_unitless(context, input)?; + // TODO(gw): Check that the axis can be normalized. + Ok(SpecifiedOperation::Rotate3D(ax, ay, az, theta)) + }, + "skew" => { + let ax = specified::Angle::parse_with_unitless(context, input)?; if input.try(|input| input.expect_comma()).is_ok() { - let theta_y = specified::Angle::parse_with_unitless(context, input)?; - result.push(SpecifiedOperation::Skew(theta_x, Some(theta_y))); + let ay = specified::Angle::parse_with_unitless(context, input)?; + Ok(SpecifiedOperation::Skew(ax, Some(ay))) } else { - result.push(SpecifiedOperation::Skew(theta_x, None)); + Ok(SpecifiedOperation::Skew(ax, None)) } - Ok(true) - })? - }, - "skewx" => { - input.parse_nested_block(|input| { - let theta_x = specified::Angle::parse_with_unitless(context, input)?; - result.push(SpecifiedOperation::SkewX(theta_x)); - Ok(true) - })? - }, - "skewy" => { - input.parse_nested_block(|input| { - let theta_y = specified::Angle::parse_with_unitless(context, input)?; - result.push(SpecifiedOperation::SkewY(theta_y)); - Ok(true) - })? - }, - "perspective" => { - input.parse_nested_block(|input| { + }, + "skewx" => { + let theta = specified::Angle::parse_with_unitless(context, input)?; + Ok(SpecifiedOperation::SkewX(theta)) + }, + "skewy" => { + let theta = specified::Angle::parse_with_unitless(context, input)?; + Ok(SpecifiedOperation::SkewY(theta)) + }, + "perspective" => { let d = specified::Length::parse_non_negative(context, input)?; - result.push(SpecifiedOperation::Perspective(d)); - Ok(true) - })? - }, - _ => false - }; - if !valid_fn { - return Err(StyleParseError::UnexpectedFunction(name).into()); - } - } - - if !result.is_empty() { - Ok(SpecifiedValue(result)) - } else { - Err(StyleParseError::UnspecifiedError.into()) - } + Ok(SpecifiedOperation::Perspective(d)) + }, + _ => Err(()), + }; + result + .map_err(|()| StyleParseError::UnexpectedFunction(function).into()) + }) + })?)) } /// Parses `transform` property. From 118291ca91c85380e56b849a63e766619cea57b1 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 6 Jul 2017 12:55:38 +0200 Subject: [PATCH 02/12] Introduce Matrix for matrix() transformations --- .../style/properties/longhand/box.mako.rs | 128 +++++++++--------- components/style/values/generics/transform.rs | 22 ++- 2 files changed, 81 insertions(+), 69 deletions(-) diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index 0dffc85bc2d..02122a2fc70 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -688,6 +688,7 @@ ${helpers.predefined_type( use app_units::Au; use values::computed::{LengthOrPercentageOrNumber as ComputedLoPoNumber, LengthOrNumber as ComputedLoN}; 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::{LengthOrNumber, LengthOrPercentageOrNumber as LoPoNumber, Number}; use style_traits::ToCss; @@ -791,10 +792,10 @@ ${helpers.predefined_type( #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum SpecifiedOperation { /// Represents a 2D 2x3 matrix. - Matrix { a: Number, b: Number, c: Number, d: Number, e: Number, f: Number }, + Matrix(Matrix), /// Represents a 3D 4x4 matrix with percentage and length values. /// For `moz-transform`. - PrefixedMatrix { a: Number, b: Number, c: Number, d: Number, e: LoPoNumber, f: LoPoNumber }, + PrefixedMatrix(Matrix), /// Represents a 3D 4x4 matrix. Matrix3D { m11: Number, m12: Number, m13: Number, m14: Number, @@ -872,15 +873,10 @@ ${helpers.predefined_type( impl ToCss for SpecifiedOperation { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - use self::SpecifiedOperation::*; match *self { - Matrix { a, b, c, d, e, f} => write!( - dest, "matrix({}, {}, {}, {}, {}, {})", - Css(a), Css(b), Css(c), Css(d), Css(e), Css(f)), - 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 { + SpecifiedOperation::Matrix(ref m) => m.to_css(dest), + SpecifiedOperation::PrefixedMatrix(ref m) => m.to_css(dest), + SpecifiedOperation::Matrix3D { m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, @@ -890,7 +886,7 @@ ${helpers.predefined_type( Css(m21), Css(m22), Css(m23), Css(m24), Css(m31), Css(m32), Css(m33), Css(m34), Css(m41), Css(m42), Css(m43), Css(m44)), - PrefixedMatrix3D { + SpecifiedOperation::PrefixedMatrix3D { m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, @@ -900,31 +896,35 @@ ${helpers.predefined_type( Css(m21), Css(m22), Css(m23), Css(m24), Css(m31), Css(m32), Css(m33), Css(m34), Css(m41), Css(m42), Css(m43), Css(m44)), - Skew(ax, None) => write!(dest, "skew({})", Css(ax)), - Skew(ax, Some(ay)) => write!(dest, "skew({}, {})", Css(ax), Css(ay)), - SkewX(angle) => write!(dest, "skewX({})", Css(angle)), - SkewY(angle) => write!(dest, "skewY({})", Css(angle)), - Translate(ref tx, None) => write!(dest, "translate({})", Css(tx)), - Translate(ref tx, Some(ref ty)) => write!(dest, "translate({}, {})", Css(tx), Css(ty)), - TranslateX(ref tx) => write!(dest, "translateX({})", Css(tx)), - TranslateY(ref ty) => write!(dest, "translateY({})", Css(ty)), - TranslateZ(ref tz) => write!(dest, "translateZ({})", Css(tz)), - Translate3D(ref tx, ref ty, ref tz) => write!( + SpecifiedOperation::Skew(ax, None) => write!(dest, "skew({})", Css(ax)), + SpecifiedOperation::Skew(ax, Some(ay)) => write!(dest, "skew({}, {})", Css(ax), Css(ay)), + SpecifiedOperation::SkewX(angle) => write!(dest, "skewX({})", Css(angle)), + SpecifiedOperation::SkewY(angle) => write!(dest, "skewY({})", Css(angle)), + SpecifiedOperation::Translate(ref tx, None) => write!(dest, "translate({})", Css(tx)), + SpecifiedOperation::Translate(ref tx, Some(ref ty)) => { + write!(dest, "translate({}, {})", Css(tx), Css(ty)) + }, + SpecifiedOperation::TranslateX(ref tx) => write!(dest, "translateX({})", Css(tx)), + 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)), - Scale(factor, None) => write!(dest, "scale({})", Css(factor)), - Scale(sx, Some(sy)) => write!(dest, "scale({}, {})", Css(sx), Css(sy)), - ScaleX(sx) => write!(dest, "scaleX({})", Css(sx)), - ScaleY(sy) => write!(dest, "scaleY({})", Css(sy)), - ScaleZ(sz) => write!(dest, "scaleZ({})", Css(sz)), - Scale3D(sx, sy, sz) => write!(dest, "scale3d({}, {}, {})", Css(sx), Css(sy), Css(sz)), - Rotate(theta) => write!(dest, "rotate({})", Css(theta)), - RotateX(theta) => write!(dest, "rotateX({})", Css(theta)), - RotateY(theta) => write!(dest, "rotateY({})", Css(theta)), - RotateZ(theta) => write!(dest, "rotateZ({})", Css(theta)), - Rotate3D(x, y, z, theta) => write!( + SpecifiedOperation::Scale(factor, None) => write!(dest, "scale({})", Css(factor)), + SpecifiedOperation::Scale(sx, Some(sy)) => write!(dest, "scale({}, {})", Css(sx), Css(sy)), + SpecifiedOperation::ScaleX(sx) => write!(dest, "scaleX({})", Css(sx)), + SpecifiedOperation::ScaleY(sy) => write!(dest, "scaleY({})", Css(sy)), + SpecifiedOperation::ScaleZ(sz) => write!(dest, "scaleZ({})", Css(sz)), + SpecifiedOperation::Scale3D(sx, sy, sz) => { + write!(dest, "scale3d({}, {}, {})", Css(sx), Css(sy), Css(sz)) + }, + SpecifiedOperation::Rotate(theta) => write!(dest, "rotate({})", Css(theta)), + SpecifiedOperation::RotateX(theta) => write!(dest, "rotateX({})", Css(theta)), + 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({}, {}, {}, {})", 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!(), } } @@ -988,13 +988,13 @@ ${helpers.predefined_type( let e = specified::parse_number(context, input)?; input.expect_comma()?; 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 { // Non-standard prefixed matrix parsing for -moz-transform. let e = LoPoNumber::parse(context, input)?; input.expect_comma()?; 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" => { @@ -1188,8 +1188,6 @@ ${helpers.predefined_type( #[inline] fn to_computed_value(&self, context: &Context) -> computed_value::T { - use self::SpecifiedOperation::*; - if self.0.is_empty() { return computed_value::T(None) } @@ -1197,7 +1195,7 @@ ${helpers.predefined_type( let mut result = vec!(); for operation in &self.0 { 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(); comp.m11 = a.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); 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(); comp.m11 = a.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)); result.push(computed_value::ComputedOperation::MatrixWithPercents(comp)); } - Matrix3D { + SpecifiedOperation::Matrix3D { m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, @@ -1242,7 +1240,7 @@ ${helpers.predefined_type( }; result.push(computed_value::ComputedOperation::Matrix(comp)); } - PrefixedMatrix3D { + SpecifiedOperation::PrefixedMatrix3D { m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, @@ -1267,14 +1265,14 @@ ${helpers.predefined_type( }; result.push(computed_value::ComputedOperation::MatrixWithPercents(comp)); } - Translate(ref tx, None) => { + SpecifiedOperation::Translate(ref tx, None) => { let tx = tx.to_computed_value(context); result.push(computed_value::ComputedOperation::Translate( tx, computed::length::LengthOrPercentage::zero(), 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 ty = ty.to_computed_value(context); result.push(computed_value::ComputedOperation::Translate( @@ -1282,77 +1280,77 @@ ${helpers.predefined_type( ty, computed::length::Length::new(0))); } - TranslateX(ref tx) => { + SpecifiedOperation::TranslateX(ref tx) => { let tx = tx.to_computed_value(context); result.push(computed_value::ComputedOperation::Translate( tx, computed::length::LengthOrPercentage::zero(), computed::length::Length::new(0))); } - TranslateY(ref ty) => { + SpecifiedOperation::TranslateY(ref ty) => { let ty = ty.to_computed_value(context); result.push(computed_value::ComputedOperation::Translate( computed::length::LengthOrPercentage::zero(), ty, computed::length::Length::new(0))); } - TranslateZ(ref tz) => { + SpecifiedOperation::TranslateZ(ref tz) => { let tz = tz.to_computed_value(context); result.push(computed_value::ComputedOperation::Translate( computed::length::LengthOrPercentage::zero(), computed::length::LengthOrPercentage::zero(), tz)); } - Translate3D(ref tx, ref ty, ref tz) => { + SpecifiedOperation::Translate3D(ref tx, ref ty, ref tz) => { let tx = tx.to_computed_value(context); let ty = ty.to_computed_value(context); let tz = tz.to_computed_value(context); result.push(computed_value::ComputedOperation::Translate(tx, ty, tz)); } - Scale(factor, None) => { + SpecifiedOperation::Scale(factor, None) => { let factor = factor.to_computed_value(context); 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 sy = sy.to_computed_value(context); result.push(computed_value::ComputedOperation::Scale(sx, sy, 1.0)); } - ScaleX(sx) => { + SpecifiedOperation::ScaleX(sx) => { let sx = sx.to_computed_value(context); result.push(computed_value::ComputedOperation::Scale(sx, 1.0, 1.0)); } - ScaleY(sy) => { + SpecifiedOperation::ScaleY(sy) => { let sy = sy.to_computed_value(context); result.push(computed_value::ComputedOperation::Scale(1.0, sy, 1.0)); } - ScaleZ(sz) => { + SpecifiedOperation::ScaleZ(sz) => { let sz = sz.to_computed_value(context); 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 sy = sy.to_computed_value(context); let sz = sz.to_computed_value(context); result.push(computed_value::ComputedOperation::Scale(sx, sy, sz)); } - Rotate(theta) => { + SpecifiedOperation::Rotate(theta) => { let theta = theta.to_computed_value(context); 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); 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); 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); 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 ay = ay.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(); 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); 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_y = theta_y.to_computed_value(context); 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); 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); 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))); } - InterpolateMatrix { ref from_list, ref to_list, progress } => { + SpecifiedOperation::InterpolateMatrix { ref from_list, ref to_list, progress } => { result.push(computed_value::ComputedOperation::InterpolateMatrix { from_list: from_list.to_computed_value(context), to_list: to_list.to_computed_value(context), 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 { from_list: from_list.to_computed_value(context), to_list: to_list.to_computed_value(context), diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index 949b3b7911c..097297bc9f4 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -9,6 +9,20 @@ use std::fmt; use style_traits::{HasViewportPercentage, ToCss}; 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 { + pub a: T, + pub b: T, + pub c: T, + pub d: T, + pub e: U, + pub f: U, +} + /// A generic transform origin. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)] @@ -37,10 +51,6 @@ pub enum TimingFunction { Frames(Integer), } -impl HasViewportPercentage for TimingFunction { - fn has_viewport_percentage(&self) -> bool { false } -} - define_css_keyword_enum! { TimingKeyword: "linear" => Linear, "ease" => Ease, @@ -67,6 +77,10 @@ impl TransformOrigin { } } +impl HasViewportPercentage for TimingFunction { + fn has_viewport_percentage(&self) -> bool { false } +} + impl TimingFunction { /// `ease` #[inline] From 3f27654d97eb684206d614d87ce4b12b08dc1ca5 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 11 Jul 2017 14:58:04 +0200 Subject: [PATCH 03/12] Derive ToCss for specified values of background-repeat --- .../properties/longhand/background.mako.rs | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/components/style/properties/longhand/background.mako.rs b/components/style/properties/longhand/background.mako.rs index 9e4a7c82856..2c75d43dd05 100644 --- a/components/style/properties/longhand/background.mako.rs +++ b/components/style/properties/longhand/background.mako.rs @@ -46,8 +46,8 @@ ${helpers.predefined_type("background-image", "ImageLayer", "round" => Round, "no-repeat" => NoRepeat); - #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] + #[derive(Clone, Debug, PartialEq, ToCss)] pub enum SpecifiedValue { RepeatX, RepeatY, @@ -80,22 +80,6 @@ ${helpers.predefined_type("background-image", "ImageLayer", } } } - impl ToCss for SpecifiedValue { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - SpecifiedValue::RepeatX => dest.write_str("repeat-x"), - SpecifiedValue::RepeatY => dest.write_str("repeat-y"), - SpecifiedValue::Other(horizontal, vertical) => { - horizontal.to_css(dest)?; - if let Some(vertical) = vertical { - dest.write_str(" ")?; - vertical.to_css(dest)?; - } - Ok(()) - } - } - } - } #[inline] pub fn get_initial_value() -> computed_value::T { From 7995a9ed51f95d5cdc9b75c8c30cb019f972014f Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 11 Jul 2017 14:59:17 +0200 Subject: [PATCH 04/12] Derive ToCss for font-weight descriptors --- components/style/font_face.rs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/components/style/font_face.rs b/components/style/font_face.rs index 04554ca81ae..b180e1e7fe2 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -75,7 +75,7 @@ add_impls_for_keyword_enum!(FontDisplay); /// A font-weight value for a @font-face rule. /// The font-weight CSS property specifies the weight or boldness of the font. #[cfg(feature = "gecko")] -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, Eq, PartialEq, ToCss)] pub enum FontWeight { /// Numeric font weights for fonts that provide more than just normal and bold. Weight(font_weight::T), @@ -85,17 +85,6 @@ pub enum FontWeight { Bold, } -#[cfg(feature = "gecko")] -impl ToCss for FontWeight { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - FontWeight::Normal => dest.write_str("normal"), - FontWeight::Bold => dest.write_str("bold"), - FontWeight::Weight(ref weight) => weight.to_css(dest), - } - } -} - #[cfg(feature = "gecko")] impl Parse for FontWeight { fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) From 21ecf4769352f7326240571bdccf27aa18597207 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 11 Jul 2017 15:00:38 +0200 Subject: [PATCH 05/12] Derive ToCss for counter_style::Negative --- components/style/counter_style/mod.rs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/components/style/counter_style/mod.rs b/components/style/counter_style/mod.rs index a2b681dc262..5ca39da05ca 100644 --- a/components/style/counter_style/mod.rs +++ b/components/style/counter_style/mod.rs @@ -380,7 +380,7 @@ impl Symbol { } /// https://drafts.csswg.org/css-counter-styles/#counter-style-negative -#[derive(Debug, Clone)] +#[derive(Debug, Clone, ToCss)] pub struct Negative(pub Symbol, pub Option); impl Parse for Negative { @@ -392,17 +392,6 @@ impl Parse for Negative { } } -impl ToCss for Negative { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - self.0.to_css(dest)?; - if let Some(ref symbol) = self.1 { - dest.write_char(' ')?; - symbol.to_css(dest)? - } - Ok(()) - } -} - /// https://drafts.csswg.org/css-counter-styles/#counter-style-range /// /// Empty Vec represents 'auto' From ec289fbe6a7ad657133c3919dd6e0687599c864e Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 11 Jul 2017 15:32:59 +0200 Subject: [PATCH 06/12] Derive some more ToCss implementations --- .../style/properties/longhand/font.mako.rs | 29 ++----------------- .../style/properties/longhand/text.mako.rs | 13 +-------- components/style/values/generics/text.rs | 25 +--------------- components/style/values/specified/color.rs | 8 +---- 4 files changed, 5 insertions(+), 70 deletions(-) diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 8a1251d9c6e..950c18baaab 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -405,8 +405,8 @@ ${helpers.single_keyword_system("font-variant-caps", no_viewport_percentage!(SpecifiedValue); - #[derive(Debug, Clone, PartialEq, Eq, Copy)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] + #[derive(Clone, Copy, Debug, Eq, PartialEq, ToCss)] pub enum SpecifiedValue { Normal, Bold, @@ -416,19 +416,6 @@ ${helpers.single_keyword_system("font-variant-caps", System(SystemFont), } - impl ToCss for SpecifiedValue { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - SpecifiedValue::Normal => dest.write_str("normal"), - SpecifiedValue::Bold => dest.write_str("bold"), - SpecifiedValue::Bolder => dest.write_str("bolder"), - SpecifiedValue::Lighter => dest.write_str("lighter"), - SpecifiedValue::Weight(weight) => weight.to_css(dest), - SpecifiedValue::System(sys) => sys.to_css(dest), - } - } - } - /// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { @@ -1008,7 +995,7 @@ ${helpers.single_keyword_system("font-variant-caps", no_viewport_percentage!(SpecifiedValue); - #[derive(Copy, Clone, Debug, PartialEq)] + #[derive(Clone, Copy, Debug, PartialEq, ToCss)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum SpecifiedValue { None, @@ -1016,18 +1003,6 @@ ${helpers.single_keyword_system("font-variant-caps", System(SystemFont), } - impl ToCss for SpecifiedValue { - fn to_css(&self, dest: &mut W) -> fmt::Result - where W: fmt::Write, - { - match *self { - SpecifiedValue::None => dest.write_str("none"), - SpecifiedValue::Number(number) => number.to_css(dest), - SpecifiedValue::System(sys) => sys.to_css(dest), - } - } - } - impl ToComputedValue for SpecifiedValue { type ComputedValue = computed_value::T; diff --git a/components/style/properties/longhand/text.mako.rs b/components/style/properties/longhand/text.mako.rs index f6b17d0865c..a7b30aafa5e 100644 --- a/components/style/properties/longhand/text.mako.rs +++ b/components/style/properties/longhand/text.mako.rs @@ -27,8 +27,8 @@ String(Box), } - #[derive(PartialEq, Eq, Clone, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] + #[derive(Clone, Debug, Eq, PartialEq, ToCss)] pub struct SpecifiedValue { pub first: Side, pub second: Option @@ -130,17 +130,6 @@ } } } - - impl ToCss for SpecifiedValue { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - self.first.to_css(dest)?; - if let Some(ref second) = self.second { - dest.write_str(" ")?; - second.to_css(dest)?; - } - Ok(()) - } - } ${helpers.single_keyword("unicode-bidi", diff --git a/components/style/values/generics/text.rs b/components/style/values/generics/text.rs index cb6230be633..a560f564940 100644 --- a/components/style/values/generics/text.rs +++ b/components/style/values/generics/text.rs @@ -13,7 +13,7 @@ use style_traits::{ToCss, ParseError}; /// A generic value for the `initial-letter` property. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] +#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)] pub enum InitialLetter { /// `normal` Normal, @@ -29,29 +29,6 @@ impl InitialLetter { } } -impl ToCss for InitialLetter -where - N: ToCss, - I: ToCss, -{ - fn to_css(&self, dest: &mut W) -> fmt::Result - where - W: fmt::Write, - { - match *self { - InitialLetter::Normal => dest.write_str("normal"), - InitialLetter::Specified(ref size, ref sink) => { - size.to_css(dest)?; - if let Some(ref sink) = *sink { - dest.write_str(" ")?; - sink.to_css(dest)?; - } - Ok(()) - }, - } - } -} - /// A generic spacing value for the `letter-spacing` and `word-spacing` properties. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)] diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index f4aa6cda1c9..46539ed10fb 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -299,7 +299,7 @@ impl ToComputedValue for Color { /// Specified color value, but resolved to just RGBA for computed value /// with value from color property at the same context. -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq, ToCss)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct RGBAColor(pub Color); @@ -311,12 +311,6 @@ impl Parse for RGBAColor { } } -impl ToCss for RGBAColor { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - self.0.to_css(dest) - } -} - impl ToComputedValue for RGBAColor { type ComputedValue = RGBA; From a3af32155fe74ab886862a56a75af06dee9ea9d5 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 11 Jul 2017 15:55:02 +0200 Subject: [PATCH 07/12] Introduce #[css(comma)] --- .../style/properties/longhand/font.mako.rs | 4 -- components/style/values/generics/text.rs | 3 +- components/style_derive/to_css.rs | 70 +++++++++++-------- 3 files changed, 43 insertions(+), 34 deletions(-) diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 950c18baaab..51af5169988 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -399,8 +399,6 @@ ${helpers.single_keyword_system("font-variant-caps", <%helpers:longhand name="font-weight" need_clone="True" animation_value_type="ComputedValue" spec="https://drafts.csswg.org/css-fonts/#propdef-font-weight"> - use std::fmt; - use style_traits::ToCss; use properties::longhands::system_font::SystemFont; no_viewport_percentage!(SpecifiedValue); @@ -990,8 +988,6 @@ ${helpers.single_keyword_system("font-variant-caps", <%helpers:longhand products="gecko" name="font-size-adjust" animation_value_type="ComputedValue" spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust"> use properties::longhands::system_font::SystemFont; - use std::fmt; - use style_traits::ToCss; no_viewport_percentage!(SpecifiedValue); diff --git a/components/style/values/generics/text.rs b/components/style/values/generics/text.rs index a560f564940..64b2e4c9c10 100644 --- a/components/style/values/generics/text.rs +++ b/components/style/values/generics/text.rs @@ -8,8 +8,7 @@ use app_units::Au; use cssparser::Parser; use parser::ParserContext; use properties::animated_properties::Animatable; -use std::fmt; -use style_traits::{ToCss, ParseError}; +use style_traits::ParseError; /// A generic value for the `initial-letter` property. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] diff --git a/components/style_derive/to_css.rs b/components/style_derive/to_css.rs index 550da7d38e1..9bc19dc0695 100644 --- a/components/style_derive/to_css.rs +++ b/components/style_derive/to_css.rs @@ -17,6 +17,47 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens { let style = synstructure::BindStyle::Ref.into(); let match_body = synstructure::each_variant(&input, &style, |bindings, variant| { let mut identifier = to_css_identifier(variant.ident.as_ref()); + let mut css_attrs = variant.attrs.iter().filter(|attr| attr.name() == "css"); + let (is_function, use_comma) = css_attrs.next().map_or((false, false), |attr| { + match attr.value { + syn::MetaItem::List(ref ident, ref items) if ident.as_ref() == "css" => { + let mut nested = items.iter(); + let mut is_function = false; + let mut use_comma = false; + for attr in nested.by_ref() { + match *attr { + syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref ident)) => { + match ident.as_ref() { + "function" => { + if is_function { + panic!("repeated `#[css(function)]` attribute"); + } + is_function = true; + }, + "comma" => { + if use_comma { + panic!("repeated `#[css(comma)]` attribute"); + } + use_comma = true; + }, + _ => panic!("only `#[css(function | comma)]` is supported for now"), + } + }, + _ => panic!("only `#[css()]` is supported for now"), + } + } + if nested.next().is_some() { + panic!("only `#[css()]` or `#[css()]` is supported for now") + } + (is_function, use_comma) + }, + _ => panic!("only `#[css(...)]` is supported for now"), + } + }); + if css_attrs.next().is_some() { + panic!("only a single `#[css(...)]` attribute is supported for now"); + } + let separator = if use_comma { ", " } else { " " }; let mut expr = if !bindings.is_empty() { let mut expr = quote! {}; for binding in bindings { @@ -29,7 +70,7 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens { }; } quote! {{ - let mut writer = ::style_traits::values::SequenceWriter::new(&mut *dest, " "); + let mut writer = ::style_traits::values::SequenceWriter::new(&mut *dest, #separator); #expr Ok(()) }} @@ -38,33 +79,6 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens { ::std::fmt::Write::write_str(dest, #identifier) } }; - let mut css_attrs = variant.attrs.iter().filter(|attr| attr.name() == "css"); - let is_function = css_attrs.next().map_or(false, |attr| { - match attr.value { - syn::MetaItem::List(ref ident, ref items) if ident.as_ref() == "css" => { - let mut nested = items.iter(); - let is_function = nested.next().map_or(false, |attr| { - match *attr { - syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref ident)) => { - if ident.as_ref() != "function" { - panic!("only `#[css(function)]` is supported for now") - } - true - }, - _ => panic!("only `#[css()]` is supported for now"), - } - }); - if nested.next().is_some() { - panic!("only `#[css()]` or `#[css()]` is supported for now") - } - is_function - }, - _ => panic!("only `#[css(...)]` is supported for now"), - } - }); - if css_attrs.next().is_some() { - panic!("only a single `#[css(...)]` attribute is supported for now"); - } if is_function { identifier.push_str("("); expr = quote! { From 50c46ae0e1657f3c1b4842d1993fb671c3c6d5e8 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 12 Jul 2017 10:10:33 +0200 Subject: [PATCH 08/12] Clean up conditional compilation in Image::parse --- components/style/values/specified/image.rs | 36 ++++++++-------------- 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index 80b7d867856..1684cc7ecd9 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -125,22 +125,17 @@ pub type ColorStop = GenericColorStop; /// Specified values for `moz-image-rect` /// -moz-image-rect(, top, right, bottom, left); -pub type ImageRect = GenericImageRect; +pub type MozImageRect = GenericMozImageRect; impl Parse for Image { + #[cfg_attr(not(feature = "gecko"), allow(unused_mut))] fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - #[cfg(feature = "gecko")] - { - if let Ok(mut url) = input.try(|input| SpecifiedUrl::parse(context, input)) { - url.build_image_value(); - return Ok(GenericImage::Url(url)); - } - } - #[cfg(feature = "servo")] - { - if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) { - return Ok(GenericImage::Url(url)); - } + if let Ok(mut url) = input.try(|input| SpecifiedUrl::parse(context, input)) { + #[cfg(feature = "gecko")] + { + url.build_image_value(); + } + return Ok(GenericImage::Url(url)); } if let Ok(gradient) = input.try(|i| Gradient::parse(context, i)) { return Ok(GenericImage::Gradient(gradient)); @@ -151,20 +146,13 @@ impl Parse for Image { return Ok(GenericImage::PaintWorklet(paint_worklet)); } } - #[cfg(feature = "gecko")] - { - if let Ok(mut image_rect) = input.try(|input| ImageRect::parse(context, input)) { + if let Ok(mut image_rect) = input.try(|input| ImageRect::parse(context, input)) { + #[cfg(feature = "gecko")] + { image_rect.url.build_image_value(); - return Ok(GenericImage::Rect(image_rect)); } + return Ok(GenericImage::Rect(image_rect)); } - #[cfg(feature = "servo")] - { - if let Ok(image_rect) = input.try(|input| ImageRect::parse(context, input)) { - return Ok(GenericImage::Rect(image_rect)); - } - } - Ok(GenericImage::Element(Image::parse_element(input)?)) } } From 907d629ca45b4ee1dfbeae0f4e2fded8feb67b91 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 12 Jul 2017 10:11:28 +0200 Subject: [PATCH 09/12] Rename ImageRect to MozImageRect --- components/style/gecko/conversions.rs | 4 ++-- components/style/values/computed/image.rs | 8 ++++---- components/style/values/computed/mod.rs | 2 +- components/style/values/generics/image.rs | 8 ++++---- components/style/values/specified/image.rs | 12 ++++++------ components/style/values/specified/mod.rs | 2 +- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index bc3dd20d6cb..d29f3a0979d 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -370,7 +370,7 @@ impl nsStyleImage { pub unsafe fn into_image(self: &nsStyleImage) -> Option { use gecko_bindings::bindings::Gecko_GetImageElement; use gecko_bindings::structs::nsStyleImageType; - use values::computed::{NumberOrPercentage, ImageRect}; + use values::computed::{NumberOrPercentage, MozImageRect}; match self.mType { nsStyleImageType::eStyleImageType_Null => { @@ -387,7 +387,7 @@ impl nsStyleImage { NumberOrPercentage::from_gecko_style_coord(&rect.data_at(2)), NumberOrPercentage::from_gecko_style_coord(&rect.data_at(3))) { (Some(top), Some(right), Some(bottom), Some(left)) => - Some(GenericImage::Rect(ImageRect { url, top, right, bottom, left } )), + Some(GenericImage::Rect(MozImageRect { url, top, right, bottom, left } )), _ => { debug_assert!(false, "mCropRect could not convert to NumberOrPercentage"); None diff --git a/components/style/values/computed/image.rs b/components/style/values/computed/image.rs index 1e2b694d51d..2037640ef64 100644 --- a/components/style/values/computed/image.rs +++ b/components/style/values/computed/image.rs @@ -17,7 +17,7 @@ use values::computed::position::Position; use values::generics::image::{CompatMode, ColorStop as GenericColorStop, EndingShape as GenericEndingShape}; use values::generics::image::{Gradient as GenericGradient, GradientItem as GenericGradientItem}; use values::generics::image::{Image as GenericImage, GradientKind as GenericGradientKind}; -use values::generics::image::{ImageRect as GenericImageRect, LineDirection as GenericLineDirection}; +use values::generics::image::{LineDirection as GenericLineDirection, MozImageRect as GenericMozImageRect}; use values::specified::image::{Gradient as SpecifiedGradient, LineDirection as SpecifiedLineDirection}; use values::specified::image::{GradientKind as SpecifiedGradientKind}; use values::specified::position::{X, Y}; @@ -27,7 +27,7 @@ pub type ImageLayer = Either; /// Computed values for an image according to CSS-IMAGES. /// https://drafts.csswg.org/css-images/#image-values -pub type Image = GenericImage; +pub type Image = GenericImage; /// Computed values for a CSS gradient. /// https://drafts.csswg.org/css-images/#gradients @@ -71,8 +71,8 @@ pub type GradientItem = GenericGradientItem; /// A computed color stop. pub type ColorStop = GenericColorStop; -/// Computed values for ImageRect. -pub type ImageRect = GenericImageRect; +/// Computed values for `-moz-image-rect(...)`. +pub type MozImageRect = GenericMozImageRect; impl GenericLineDirection for LineDirection { fn points_downwards(&self) -> bool { diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 9b08cd6e2bb..db63c87cbb1 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -30,7 +30,7 @@ pub use self::border::{BorderRadius, BorderCornerRadius}; pub use self::color::{Color, RGBAColor}; pub use self::effects::{BoxShadow, Filter, SimpleShadow}; pub use self::flex::FlexBasis; -pub use self::image::{Gradient, GradientItem, ImageLayer, LineDirection, Image, ImageRect}; +pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect}; #[cfg(feature = "gecko")] pub use self::gecko::ScrollSnapPoint; pub use self::rect::LengthOrNumberRect; diff --git a/components/style/values/generics/image.rs b/components/style/values/generics/image.rs index 78d011beac0..25b5b96aebb 100644 --- a/components/style/values/generics/image.rs +++ b/components/style/values/generics/image.rs @@ -18,13 +18,13 @@ use values::specified::url::SpecifiedUrl; /// [image]: https://drafts.csswg.org/css-images/#image-values #[derive(Clone, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -pub enum Image { +pub enum Image { /// A `` image. Url(SpecifiedUrl), /// A `` image. Gradient(Gradient), /// A `-moz-image-rect` image - Rect(ImageRect), + Rect(MozImageRect), /// A `-moz-element(# )` Element(Atom), /// A paint worklet image. @@ -157,7 +157,7 @@ impl ToCss for PaintWorklet { #[derive(Clone, Debug, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[allow(missing_docs)] -pub struct ImageRect { +pub struct MozImageRect { pub url: SpecifiedUrl, pub top: NumberOrPercentage, pub bottom: NumberOrPercentage, @@ -330,7 +330,7 @@ impl fmt::Debug for ColorStop } } -impl ToCss for ImageRect +impl ToCss for MozImageRect where C: ToCss, { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index 1684cc7ecd9..a5503ba62fb 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -24,8 +24,8 @@ use values::computed::{Context, Position as ComputedPosition, ToComputedValue}; use values::generics::image::{Circle, CompatMode, Ellipse, ColorStop as GenericColorStop}; use values::generics::image::{EndingShape as GenericEndingShape, Gradient as GenericGradient}; use values::generics::image::{GradientItem as GenericGradientItem, GradientKind as GenericGradientKind}; -use values::generics::image::{Image as GenericImage, ImageRect as GenericImageRect}; -use values::generics::image::{LineDirection as GenericsLineDirection, ShapeExtent}; +use values::generics::image::{Image as GenericImage, LineDirection as GenericsLineDirection}; +use values::generics::image::{MozImageRect as GenericMozImageRect, ShapeExtent}; use values::generics::image::PaintWorklet; use values::generics::position::Position as GenericPosition; use values::specified::{Angle, Color, Length, LengthOrPercentage}; @@ -38,7 +38,7 @@ pub type ImageLayer = Either; /// Specified values for an image according to CSS-IMAGES. /// https://drafts.csswg.org/css-images/#image-values -pub type Image = GenericImage; +pub type Image = GenericImage; /// Specified values for a CSS gradient. /// https://drafts.csswg.org/css-images/#gradients @@ -146,7 +146,7 @@ impl Parse for Image { return Ok(GenericImage::PaintWorklet(paint_worklet)); } } - if let Ok(mut image_rect) = input.try(|input| ImageRect::parse(context, input)) { + if let Ok(mut image_rect) = input.try(|input| MozImageRect::parse(context, input)) { #[cfg(feature = "gecko")] { image_rect.url.build_image_value(); @@ -885,7 +885,7 @@ impl Parse for PaintWorklet { } } -impl Parse for ImageRect { +impl Parse for MozImageRect { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { input.try(|i| i.expect_function_matching("-moz-image-rect"))?; input.parse_nested_block(|i| { @@ -900,7 +900,7 @@ impl Parse for ImageRect { i.expect_comma()?; let left = NumberOrPercentage::parse_non_negative(context, i)?; - Ok(ImageRect { + Ok(MozImageRect { url: url, top: top, right: right, diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 7539bd575b0..a5e20879af9 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -37,7 +37,7 @@ pub use self::flex::FlexBasis; #[cfg(feature = "gecko")] pub use self::gecko::ScrollSnapPoint; pub use self::image::{ColorStop, EndingShape as GradientEndingShape, Gradient}; -pub use self::image::{GradientItem, GradientKind, Image, ImageRect, ImageLayer}; +pub use self::image::{GradientItem, GradientKind, Image, ImageLayer, MozImageRect}; pub use self::length::{AbsoluteLength, CalcLengthOrPercentage, CharacterWidth}; pub use self::length::{FontRelativeLength, Length, LengthOrNone, LengthOrNumber}; pub use self::length::{LengthOrPercentage, LengthOrPercentageOrAuto}; From c2e746004a3a6a295876198312b4d04533c07727 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 12 Jul 2017 10:13:04 +0200 Subject: [PATCH 10/12] Derive ToCss for MozImageRect --- components/style/values/generics/image.rs | 25 ++++------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/components/style/values/generics/image.rs b/components/style/values/generics/image.rs index 25b5b96aebb..874912aeaf8 100644 --- a/components/style/values/generics/image.rs +++ b/components/style/values/generics/image.rs @@ -154,14 +154,15 @@ impl ToCss for PaintWorklet { /// Values for `moz-image-rect`. /// /// `-moz-image-rect(, top, right, bottom, left);` -#[derive(Clone, Debug, PartialEq, ToComputedValue)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[css(comma, function)] +#[derive(Clone, Debug, PartialEq, ToComputedValue, ToCss)] pub struct MozImageRect { pub url: SpecifiedUrl, pub top: NumberOrPercentage, - pub bottom: NumberOrPercentage, pub right: NumberOrPercentage, + pub bottom: NumberOrPercentage, pub left: NumberOrPercentage, } @@ -329,21 +330,3 @@ impl fmt::Debug for ColorStop Ok(()) } } - -impl ToCss for MozImageRect - where C: ToCss, -{ - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - dest.write_str("-moz-image-rect(")?; - self.url.to_css(dest)?; - dest.write_str(", ")?; - self.top.to_css(dest)?; - dest.write_str(", ")?; - self.right.to_css(dest)?; - dest.write_str(", ")?; - self.bottom.to_css(dest)?; - dest.write_str(", ")?; - self.left.to_css(dest)?; - dest.write_str(")") - } -} From 7bc9a95b46399023600671a4bff7a23722e46cb0 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 12 Jul 2017 10:50:55 +0200 Subject: [PATCH 11/12] Rename MinMax to Minmax --- components/style/gecko/conversions.rs | 4 ++-- components/style/values/generics/grid.rs | 16 ++++++++-------- components/style/values/specified/grid.rs | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index d29f3a0979d..6314069cb18 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -815,7 +815,7 @@ impl TrackSize { if min == max { TrackSize::Breadth(max) } else { - TrackSize::MinMax(min, max) + TrackSize::Minmax(min, max) } } @@ -836,7 +836,7 @@ impl TrackSize { breadth.to_gecko_style_coord(gecko_min); breadth.to_gecko_style_coord(gecko_max); }, - TrackSize::MinMax(ref min, ref max) => { + TrackSize::Minmax(ref min, ref max) => { min.to_gecko_style_coord(gecko_min); max.to_gecko_style_coord(gecko_max); }, diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index a53402f9b3f..68049274c12 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -213,7 +213,7 @@ pub enum TrackSize { /// and a flexible `` /// /// https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-minmax - MinMax(TrackBreadth, TrackBreadth), + Minmax(TrackBreadth, TrackBreadth), /// A `fit-content` function. /// /// https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-fit-content @@ -231,7 +231,7 @@ impl TrackSize { // minmax(, ) or minmax(, ), // and since both variants are a subset of minmax(, ), we only // need to make sure that they're fixed. So, we don't have to modify the parsing function. - TrackSize::MinMax(ref breadth_1, ref breadth_2) => { + TrackSize::Minmax(ref breadth_1, ref breadth_2) => { if breadth_1.is_fixed() { return true // the second value is always a } @@ -263,7 +263,7 @@ impl ToCss for TrackSize { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match *self { TrackSize::Breadth(ref b) => b.to_css(dest), - TrackSize::MinMax(ref infexible, ref flexible) => { + TrackSize::Minmax(ref infexible, ref flexible) => { dest.write_str("minmax(")?; infexible.to_css(dest)?; dest.write_str(", ")?; @@ -289,11 +289,11 @@ impl ToComputedValue for TrackSize { // outside `minmax()` expands to `mimmax(auto, )` // https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-flex TrackBreadth::Flex(f) => - TrackSize::MinMax(TrackBreadth::Keyword(TrackKeyword::Auto), TrackBreadth::Flex(f)), + TrackSize::Minmax(TrackBreadth::Keyword(TrackKeyword::Auto), TrackBreadth::Flex(f)), _ => TrackSize::Breadth(b.to_computed_value(context)), }, - TrackSize::MinMax(ref b_1, ref b_2) => - TrackSize::MinMax(b_1.to_computed_value(context), b_2.to_computed_value(context)), + TrackSize::Minmax(ref b_1, ref b_2) => + TrackSize::Minmax(b_1.to_computed_value(context), b_2.to_computed_value(context)), TrackSize::FitContent(ref lop) => TrackSize::FitContent(lop.to_computed_value(context)), } } @@ -303,8 +303,8 @@ impl ToComputedValue for TrackSize { match *computed { TrackSize::Breadth(ref b) => TrackSize::Breadth(ToComputedValue::from_computed_value(b)), - TrackSize::MinMax(ref b_1, ref b_2) => - TrackSize::MinMax(ToComputedValue::from_computed_value(b_1), + TrackSize::Minmax(ref b_1, ref b_2) => + TrackSize::Minmax(ToComputedValue::from_computed_value(b_1), ToComputedValue::from_computed_value(b_2)), TrackSize::FitContent(ref lop) => TrackSize::FitContent(ToComputedValue::from_computed_value(lop)), diff --git a/components/style/values/specified/grid.rs b/components/style/values/specified/grid.rs index 50d88fee175..be0ced6cd56 100644 --- a/components/style/values/specified/grid.rs +++ b/components/style/values/specified/grid.rs @@ -68,7 +68,7 @@ impl Parse for TrackSize { }; input.expect_comma()?; - Ok(TrackSize::MinMax(inflexible_breadth, TrackBreadth::parse(context, input)?)) + Ok(TrackSize::Minmax(inflexible_breadth, TrackBreadth::parse(context, input)?)) }); } From d03bcfa8b39db47d34dd7f9b7447e6632e42cfba Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 12 Jul 2017 10:51:38 +0200 Subject: [PATCH 12/12] Derive ToCss for TrackSize --- components/style/values/generics/grid.rs | 26 ++++-------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index 68049274c12..b627231ecd5 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -200,12 +200,12 @@ impl ToComputedValue for TrackBreadth { } } -#[derive(Clone, Debug, HasViewportPercentage, PartialEq)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] /// A `` type for explicit grid track sizing. Like ``, this is /// generic only to avoid code bloat. It only takes `` /// /// https://drafts.csswg.org/css-grid/#typedef-track-size +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToCss)] pub enum TrackSize { /// A flexible `` Breadth(TrackBreadth), @@ -213,10 +213,12 @@ pub enum TrackSize { /// and a flexible `` /// /// https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-minmax + #[css(comma, function)] Minmax(TrackBreadth, TrackBreadth), /// A `fit-content` function. /// /// https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-fit-content + #[css(function)] FitContent(L), } @@ -259,26 +261,6 @@ impl TrackSize { } } -impl ToCss for TrackSize { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - TrackSize::Breadth(ref b) => b.to_css(dest), - TrackSize::Minmax(ref infexible, ref flexible) => { - dest.write_str("minmax(")?; - infexible.to_css(dest)?; - dest.write_str(", ")?; - flexible.to_css(dest)?; - dest.write_str(")") - }, - TrackSize::FitContent(ref lop) => { - dest.write_str("fit-content(")?; - lop.to_css(dest)?; - dest.write_str(")") - }, - } - } -} - impl ToComputedValue for TrackSize { type ComputedValue = TrackSize;