mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Clean up parsing code for specified transform values
This commit is contained in:
parent
ee95bda3bf
commit
5f1cb084d0
1 changed files with 156 additions and 248 deletions
|
@ -959,248 +959,176 @@ ${helpers.predefined_type(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow unitless zero angle for rotate() and skew() to align with gecko
|
// 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)
|
fn parse_internal<'i, 't>(
|
||||||
-> Result<SpecifiedValue,ParseError<'i>> {
|
context: &ParserContext,
|
||||||
|
input: &mut Parser<'i, 't>,
|
||||||
|
prefixed: bool,
|
||||||
|
) -> Result<SpecifiedValue,ParseError<'i>> {
|
||||||
|
use style_traits::{Separator, Space};
|
||||||
|
|
||||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok(SpecifiedValue(Vec::new()))
|
return Ok(SpecifiedValue(Vec::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = Vec::new();
|
Ok(SpecifiedValue(Space::parse(input, |input| {
|
||||||
loop {
|
let function = input.expect_function()?;
|
||||||
let name = match input.try(|i| i.expect_function()) {
|
input.parse_nested_block(|input| {
|
||||||
Ok(name) => name,
|
let result = match_ignore_ascii_case! { &function,
|
||||||
Err(_) => break,
|
"matrix" => {
|
||||||
};
|
let a = specified::parse_number(context, input)?;
|
||||||
let valid_fn = match_ignore_ascii_case! {
|
input.expect_comma()?;
|
||||||
&name,
|
let b = specified::parse_number(context, input)?;
|
||||||
"matrix" => {
|
input.expect_comma()?;
|
||||||
input.parse_nested_block(|input| {
|
let c = specified::parse_number(context, input)?;
|
||||||
// Standard matrix parsing.
|
input.expect_comma()?;
|
||||||
|
let d = specified::parse_number(context, input)?;
|
||||||
|
input.expect_comma()?;
|
||||||
if !prefixed {
|
if !prefixed {
|
||||||
let values = input.parse_comma_separated(|input| {
|
// Standard matrix parsing.
|
||||||
specified::parse_number(context, input)
|
let e = 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 {
|
|
||||||
input.expect_comma()?;
|
input.expect_comma()?;
|
||||||
if i < 3 {
|
let f = specified::parse_number(context, input)?;
|
||||||
values.push(specified::parse_number(context, input)?);
|
Ok(SpecifiedOperation::Matrix { a, b, c, d, e, f })
|
||||||
} else {
|
} else {
|
||||||
// -moz-transform accepts LengthOrPercentageOrNumber in the nondiagonal
|
// Non-standard prefixed matrix parsing for -moz-transform.
|
||||||
// homogeneous components. transform accepts only number.
|
let e = LoPoNumber::parse(context, input)?;
|
||||||
lengths.push(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 {
|
"matrix3d" => {
|
||||||
a: values[0],
|
let m11 = specified::parse_number(context, input)?;
|
||||||
b: values[1],
|
input.expect_comma()?;
|
||||||
c: values[2],
|
let m12 = specified::parse_number(context, input)?;
|
||||||
d: values[3],
|
input.expect_comma()?;
|
||||||
e: lengths[0].clone(),
|
let m13 = specified::parse_number(context, input)?;
|
||||||
f: lengths[1].clone(),
|
input.expect_comma()?;
|
||||||
});
|
let m14 = specified::parse_number(context, input)?;
|
||||||
Ok(true)
|
input.expect_comma()?;
|
||||||
})?
|
let m21 = specified::parse_number(context, input)?;
|
||||||
},
|
input.expect_comma()?;
|
||||||
"matrix3d" => {
|
let m22 = specified::parse_number(context, input)?;
|
||||||
input.parse_nested_block(|input| {
|
input.expect_comma()?;
|
||||||
// Standard matrix3d parsing.
|
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 {
|
if !prefixed {
|
||||||
let values = input.parse_comma_separated(|i| specified::parse_number(context, i))?;
|
// Standard matrix3d parsing.
|
||||||
if values.len() != 16 {
|
let m41 = specified::parse_number(context, input)?;
|
||||||
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 {
|
|
||||||
input.expect_comma()?;
|
input.expect_comma()?;
|
||||||
// -moz-transform accepts LengthOrPercentageOrNumber in the nondiagonal
|
let m42 = specified::parse_number(context, input)?;
|
||||||
// homogeneous components. transform accepts only number.
|
input.expect_comma()?;
|
||||||
if i < 11 || i > 13 {
|
let m43 = specified::parse_number(context, input)?;
|
||||||
values.push(specified::parse_number(context, input)?);
|
input.expect_comma()?;
|
||||||
} else if i == 13 {
|
let m44 = specified::parse_number(context, input)?;
|
||||||
// m43
|
Ok(SpecifiedOperation::Matrix3D {
|
||||||
length_or_number = Some(LengthOrNumber::parse(context, input)?);
|
m11, m12, m13, m14,
|
||||||
} else {
|
m21, m22, m23, m24,
|
||||||
// m41 and m42
|
m31, m32, m33, m34,
|
||||||
lops.push(LoPoNumber::parse(context, input)?);
|
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 {
|
"translate" => {
|
||||||
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| {
|
|
||||||
let sx = specified::LengthOrPercentage::parse(context, input)?;
|
let sx = specified::LengthOrPercentage::parse(context, input)?;
|
||||||
if input.try(|input| input.expect_comma()).is_ok() {
|
if input.try(|input| input.expect_comma()).is_ok() {
|
||||||
let sy = specified::LengthOrPercentage::parse(context, input)?;
|
let sy = specified::LengthOrPercentage::parse(context, input)?;
|
||||||
result.push(SpecifiedOperation::Translate(sx, Some(sy)));
|
Ok(SpecifiedOperation::Translate(sx, Some(sy)))
|
||||||
} else {
|
} else {
|
||||||
result.push(SpecifiedOperation::Translate(sx, None));
|
Ok(SpecifiedOperation::Translate(sx, None))
|
||||||
}
|
}
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"translatex" => {
|
||||||
},
|
|
||||||
"translatex" => {
|
|
||||||
input.parse_nested_block(|input| {
|
|
||||||
let tx = specified::LengthOrPercentage::parse(context, input)?;
|
let tx = specified::LengthOrPercentage::parse(context, input)?;
|
||||||
result.push(SpecifiedOperation::TranslateX(tx));
|
Ok(SpecifiedOperation::TranslateX(tx))
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"translatey" => {
|
||||||
},
|
|
||||||
"translatey" => {
|
|
||||||
input.parse_nested_block(|input| {
|
|
||||||
let ty = specified::LengthOrPercentage::parse(context, input)?;
|
let ty = specified::LengthOrPercentage::parse(context, input)?;
|
||||||
result.push(SpecifiedOperation::TranslateY(ty));
|
Ok(SpecifiedOperation::TranslateY(ty))
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"translatez" => {
|
||||||
},
|
|
||||||
"translatez" => {
|
|
||||||
input.parse_nested_block(|input| {
|
|
||||||
let tz = specified::Length::parse(context, input)?;
|
let tz = specified::Length::parse(context, input)?;
|
||||||
result.push(SpecifiedOperation::TranslateZ(tz));
|
Ok(SpecifiedOperation::TranslateZ(tz))
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"translate3d" => {
|
||||||
},
|
|
||||||
"translate3d" => {
|
|
||||||
input.parse_nested_block(|input| {
|
|
||||||
let tx = specified::LengthOrPercentage::parse(context, input)?;
|
let tx = specified::LengthOrPercentage::parse(context, input)?;
|
||||||
input.expect_comma()?;
|
input.expect_comma()?;
|
||||||
let ty = specified::LengthOrPercentage::parse(context, input)?;
|
let ty = specified::LengthOrPercentage::parse(context, input)?;
|
||||||
input.expect_comma()?;
|
input.expect_comma()?;
|
||||||
let tz = specified::Length::parse(context, input)?;
|
let tz = specified::Length::parse(context, input)?;
|
||||||
result.push(SpecifiedOperation::Translate3D(tx, ty, tz));
|
Ok(SpecifiedOperation::Translate3D(tx, ty, tz))
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"scale" => {
|
||||||
},
|
|
||||||
"scale" => {
|
|
||||||
input.parse_nested_block(|input| {
|
|
||||||
let sx = specified::parse_number(context, input)?;
|
let sx = specified::parse_number(context, input)?;
|
||||||
if input.try(|input| input.expect_comma()).is_ok() {
|
if input.try(|input| input.expect_comma()).is_ok() {
|
||||||
let sy = specified::parse_number(context, input)?;
|
let sy = specified::parse_number(context, input)?;
|
||||||
result.push(SpecifiedOperation::Scale(sx, Some(sy)));
|
Ok(SpecifiedOperation::Scale(sx, Some(sy)))
|
||||||
} else {
|
} else {
|
||||||
result.push(SpecifiedOperation::Scale(sx, None));
|
Ok(SpecifiedOperation::Scale(sx, None))
|
||||||
}
|
}
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"scalex" => {
|
||||||
},
|
|
||||||
"scalex" => {
|
|
||||||
input.parse_nested_block(|input| {
|
|
||||||
let sx = specified::parse_number(context, input)?;
|
let sx = specified::parse_number(context, input)?;
|
||||||
result.push(SpecifiedOperation::ScaleX(sx));
|
Ok(SpecifiedOperation::ScaleX(sx))
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"scaley" => {
|
||||||
},
|
|
||||||
"scaley" => {
|
|
||||||
input.parse_nested_block(|input| {
|
|
||||||
let sy = specified::parse_number(context, input)?;
|
let sy = specified::parse_number(context, input)?;
|
||||||
result.push(SpecifiedOperation::ScaleY(sy));
|
Ok(SpecifiedOperation::ScaleY(sy))
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"scalez" => {
|
||||||
},
|
|
||||||
"scalez" => {
|
|
||||||
input.parse_nested_block(|input| {
|
|
||||||
let sz = specified::parse_number(context, input)?;
|
let sz = specified::parse_number(context, input)?;
|
||||||
result.push(SpecifiedOperation::ScaleZ(sz));
|
Ok(SpecifiedOperation::ScaleZ(sz))
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"scale3d" => {
|
||||||
},
|
|
||||||
"scale3d" => {
|
|
||||||
input.parse_nested_block(|input| {
|
|
||||||
let sx = specified::parse_number(context, input)?;
|
let sx = specified::parse_number(context, input)?;
|
||||||
input.expect_comma()?;
|
input.expect_comma()?;
|
||||||
let sy = specified::parse_number(context, input)?;
|
let sy = specified::parse_number(context, input)?;
|
||||||
input.expect_comma()?;
|
input.expect_comma()?;
|
||||||
let sz = specified::parse_number(context, input)?;
|
let sz = specified::parse_number(context, input)?;
|
||||||
result.push(SpecifiedOperation::Scale3D(sx, sy, sz));
|
Ok(SpecifiedOperation::Scale3D(sx, sy, sz))
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"rotate" => {
|
||||||
},
|
|
||||||
"rotate" => {
|
|
||||||
input.parse_nested_block(|input| {
|
|
||||||
let theta = specified::Angle::parse_with_unitless(context, input)?;
|
let theta = specified::Angle::parse_with_unitless(context, input)?;
|
||||||
result.push(SpecifiedOperation::Rotate(theta));
|
Ok(SpecifiedOperation::Rotate(theta))
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"rotatex" => {
|
||||||
},
|
|
||||||
"rotatex" => {
|
|
||||||
input.parse_nested_block(|input| {
|
|
||||||
let theta = specified::Angle::parse_with_unitless(context, input)?;
|
let theta = specified::Angle::parse_with_unitless(context, input)?;
|
||||||
result.push(SpecifiedOperation::RotateX(theta));
|
Ok(SpecifiedOperation::RotateX(theta))
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"rotatey" => {
|
||||||
},
|
|
||||||
"rotatey" => {
|
|
||||||
input.parse_nested_block(|input| {
|
|
||||||
let theta = specified::Angle::parse_with_unitless(context, input)?;
|
let theta = specified::Angle::parse_with_unitless(context, input)?;
|
||||||
result.push(SpecifiedOperation::RotateY(theta));
|
Ok(SpecifiedOperation::RotateY(theta))
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"rotatez" => {
|
||||||
},
|
|
||||||
"rotatez" => {
|
|
||||||
input.parse_nested_block(|input| {
|
|
||||||
let theta = specified::Angle::parse_with_unitless(context, input)?;
|
let theta = specified::Angle::parse_with_unitless(context, input)?;
|
||||||
result.push(SpecifiedOperation::RotateZ(theta));
|
Ok(SpecifiedOperation::RotateZ(theta))
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"rotate3d" => {
|
||||||
},
|
|
||||||
"rotate3d" => {
|
|
||||||
input.parse_nested_block(|input| {
|
|
||||||
let ax = specified::parse_number(context, input)?;
|
let ax = specified::parse_number(context, input)?;
|
||||||
input.expect_comma()?;
|
input.expect_comma()?;
|
||||||
let ay = specified::parse_number(context, input)?;
|
let ay = specified::parse_number(context, input)?;
|
||||||
|
@ -1208,56 +1136,36 @@ ${helpers.predefined_type(
|
||||||
let az = specified::parse_number(context, input)?;
|
let az = specified::parse_number(context, input)?;
|
||||||
input.expect_comma()?;
|
input.expect_comma()?;
|
||||||
let theta = specified::Angle::parse_with_unitless(context, input)?;
|
let theta = specified::Angle::parse_with_unitless(context, input)?;
|
||||||
// TODO(gw): Check the axis can be normalized!!
|
// TODO(gw): Check that the axis can be normalized.
|
||||||
result.push(SpecifiedOperation::Rotate3D(ax, ay, az, theta));
|
Ok(SpecifiedOperation::Rotate3D(ax, ay, az, theta))
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"skew" => {
|
||||||
},
|
let ax = specified::Angle::parse_with_unitless(context, input)?;
|
||||||
"skew" => {
|
|
||||||
input.parse_nested_block(|input| {
|
|
||||||
let theta_x = specified::Angle::parse_with_unitless(context, input)?;
|
|
||||||
if input.try(|input| input.expect_comma()).is_ok() {
|
if input.try(|input| input.expect_comma()).is_ok() {
|
||||||
let theta_y = specified::Angle::parse_with_unitless(context, input)?;
|
let ay = specified::Angle::parse_with_unitless(context, input)?;
|
||||||
result.push(SpecifiedOperation::Skew(theta_x, Some(theta_y)));
|
Ok(SpecifiedOperation::Skew(ax, Some(ay)))
|
||||||
} else {
|
} else {
|
||||||
result.push(SpecifiedOperation::Skew(theta_x, None));
|
Ok(SpecifiedOperation::Skew(ax, None))
|
||||||
}
|
}
|
||||||
Ok(true)
|
},
|
||||||
})?
|
"skewx" => {
|
||||||
},
|
let theta = specified::Angle::parse_with_unitless(context, input)?;
|
||||||
"skewx" => {
|
Ok(SpecifiedOperation::SkewX(theta))
|
||||||
input.parse_nested_block(|input| {
|
},
|
||||||
let theta_x = specified::Angle::parse_with_unitless(context, input)?;
|
"skewy" => {
|
||||||
result.push(SpecifiedOperation::SkewX(theta_x));
|
let theta = specified::Angle::parse_with_unitless(context, input)?;
|
||||||
Ok(true)
|
Ok(SpecifiedOperation::SkewY(theta))
|
||||||
})?
|
},
|
||||||
},
|
"perspective" => {
|
||||||
"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| {
|
|
||||||
let d = specified::Length::parse_non_negative(context, input)?;
|
let d = specified::Length::parse_non_negative(context, input)?;
|
||||||
result.push(SpecifiedOperation::Perspective(d));
|
Ok(SpecifiedOperation::Perspective(d))
|
||||||
Ok(true)
|
},
|
||||||
})?
|
_ => Err(()),
|
||||||
},
|
};
|
||||||
_ => false
|
result
|
||||||
};
|
.map_err(|()| StyleParseError::UnexpectedFunction(function).into())
|
||||||
if !valid_fn {
|
})
|
||||||
return Err(StyleParseError::UnexpectedFunction(name).into());
|
})?))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !result.is_empty() {
|
|
||||||
Ok(SpecifiedValue(result))
|
|
||||||
} else {
|
|
||||||
Err(StyleParseError::UnspecifiedError.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses `transform` property.
|
/// Parses `transform` property.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue