[librsvg: 9/21] Implement computing to transform and parsing tests Needs reference test
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 9/21] Implement computing to transform and parsing tests Needs reference test
- Date: Tue, 31 Aug 2021 18:37:37 +0000 (UTC)
commit da33f00aae0e3dded6f914016ffeabd9e883dd05
Author: Madds H <madds hollandart io>
Date: Mon Aug 23 00:30:07 2021 -0500
Implement computing to transform and parsing tests
Needs reference test
Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/576>
src/properties.rs | 7 +-
src/transform.rs | 187 +++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 177 insertions(+), 17 deletions(-)
---
diff --git a/src/properties.rs b/src/properties.rs
index 54458c90..3627a842 100644
--- a/src/properties.rs
+++ b/src/properties.rs
@@ -638,7 +638,9 @@ impl SpecifiedValues {
computed.transform = self.transform.unwrap_or_else(|| {
match self.get_property(PropertyId::TransformProperty) {
- ParsedProperty::TransformProperty(SpecifiedValue::Specified(ref t)) => t.to_transform(),
+ ParsedProperty::TransformProperty(SpecifiedValue::Specified(ref t)) => {
+ t.to_transform()
+ }
_ => Transform::identity(),
}
});
@@ -750,7 +752,8 @@ impl SpecifiedValues {
// FIXME: we parse the transform attribute here because we don't yet have
// a better way to distinguish attributes whose values have different
// grammars than properties.
- let transform = Transform::parse_str(value).unwrap_or_else(|_| Transform::default());
+ let transform =
+ Transform::parse_str(value).unwrap_or_else(|_| Transform::default());
self.transform = Some(transform);
}
diff --git a/src/transform.rs b/src/transform.rs
index 1b72fde6..fb4db73f 100644
--- a/src/transform.rs
+++ b/src/transform.rs
@@ -32,15 +32,45 @@ impl Property for TransformProperty {
false
}
- fn compute(&self, v: &ComputedValues) -> Self {
+ fn compute(&self, _v: &ComputedValues) -> Self {
self.clone()
}
}
impl TransformProperty {
pub fn to_transform(&self) -> Transform {
- // TODO for madds - compose the individual functions here into a single matrix
- Transform::identity()
+ // From the spec (https://www.w3.org/TR/css-transforms-1/#current-transformation-matrix):
+ // Start with the identity matrix.
+ // TODO: implement (#685) - Translate by the computed X and Y of transform-origin
+ // Multiply by each of the transform functions in transform property from left to right
+ // TODO: implement - Translate by the negated computed X and Y values of transform-origin
+
+ let mut final_transform = Transform::identity();
+
+ if let TransformProperty::List(l) = self {
+ for f in l.iter() {
+ let t = match f {
+ TransformFunction::Matrix(xx, yx, xy, yy, x0, y0) => {
+ Transform::new_unchecked(*xx, *yx, *xy, *yy, *x0, *y0)
+ }
+ TransformFunction::Translate(h, v) => {
+ Transform::new_translate(h.length, v.length)
+ }
+ TransformFunction::TranslateX(h) => Transform::new_translate(h.length, 0.0),
+ TransformFunction::TranslateY(v) => Transform::new_translate(0.0, v.length),
+ TransformFunction::Scale(x, y) => Transform::new_scale(*x, *y),
+ TransformFunction::ScaleX(x) => Transform::new_scale(*x, 0.0),
+ TransformFunction::ScaleY(y) => Transform::new_scale(0.0, *y),
+ TransformFunction::Rotate(a) => Transform::new_rotate(*a),
+ TransformFunction::Skew(ax, ay) => Transform::new_skew(*ax, *ay),
+ TransformFunction::SkewX(ax) => Transform::new_skew(*ax, Angle::new(0.0)),
+ TransformFunction::SkewY(ay) => Transform::new_skew(Angle::new(0.0), *ay),
+ };
+ final_transform = Transform::multiply(&final_transform, &t);
+ }
+ }
+
+ final_transform
}
}
@@ -62,9 +92,6 @@ pub enum TransformFunction {
impl Parse for TransformProperty {
fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<TransformProperty, ParseError<'i>> {
- // look at the impl Parse later in this file for an example
- let loc = parser.current_source_location();
-
let t = parse_transform_prop_function_list(parser)?;
Ok(TransformProperty::List(t))
@@ -74,7 +101,7 @@ impl Parse for TransformProperty {
fn parse_transform_prop_function_list<'i>(
parser: &mut Parser<'i, '_>,
) -> Result<Vec<TransformFunction>, ParseError<'i>> {
- //TODO: What does this need to be set to? -Should there be a none TransformFunction?
+ //TODO: How do I appease clippy here?
let mut t = TransformFunction::Translate(
Length::<Horizontal>::new(0.0, LengthUnit::Px),
Length::<Vertical>::new(0.0, LengthUnit::Px),
@@ -219,7 +246,7 @@ fn parse_prop_rotate_args<'i>(
parser: &mut Parser<'i, '_>,
) -> Result<TransformFunction, ParseError<'i>> {
parser.parse_nested_block(|p| {
- let angle = Angle::parse(p).unwrap();
+ let angle = Angle::parse(p)?;
Ok(TransformFunction::Rotate(angle))
})
@@ -229,7 +256,7 @@ fn parse_prop_skew_args<'i>(
parser: &mut Parser<'i, '_>,
) -> Result<TransformFunction, ParseError<'i>> {
parser.parse_nested_block(|p| {
- let ax = Angle::parse(p).unwrap();
+ let ax = Angle::parse(p)?;
//let ay = Angle::parse(p);
p.expect_comma()?;
@@ -245,7 +272,7 @@ fn parse_prop_skew_x_args<'i>(
parser: &mut Parser<'i, '_>,
) -> Result<TransformFunction, ParseError<'i>> {
parser.parse_nested_block(|p| {
- let angle = Angle::from_degrees(f64::parse(p)?);
+ let angle = Angle::parse(p)?;
Ok(TransformFunction::SkewX(angle))
})
}
@@ -254,7 +281,7 @@ fn parse_prop_skew_y_args<'i>(
parser: &mut Parser<'i, '_>,
) -> Result<TransformFunction, ParseError<'i>> {
parser.parse_nested_block(|p| {
- let angle = Angle::from_degrees(f64::parse(p)?);
+ let angle = Angle::parse(p)?;
Ok(TransformFunction::SkewY(angle))
})
}
@@ -612,6 +639,10 @@ mod tests {
Transform::parse_str(s)
}
+ fn parse_transform_prop(s: &str) -> Result<TransformProperty, ParseError<'_>> {
+ TransformProperty::parse_str(s)
+ }
+
fn assert_transform_eq(t1: &Transform, t2: &Transform) {
let epsilon = 8.0 * f64::EPSILON; // kind of arbitrary, but allow for some sloppiness
@@ -818,9 +849,135 @@ mod tests {
fn parses_empty() {
assert_transform_eq(&parse_transform("").unwrap(), &Transform::identity());
}
-}
-#[test]
-fn test_parse_transform_property() {
- // TODO for madds: put your tests in here
+ #[test]
+ fn test_parse_transform_property_matrix() {
+ let tp = TransformProperty::List(vec![TransformFunction::Matrix(
+ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
+ )]);
+
+ assert_eq!(&tp, &parse_transform_prop("matrix(1,1,1,1,1,1)").unwrap());
+ assert!(parse_transform_prop("matrix(1 1 1 1 1 1)").is_err());
+ assert!(parse_transform_prop("Matrix(1,1,1,1,1,1)").is_err());
+ }
+
+ #[test]
+ fn test_parse_transform_property_translate() {
+ let tpt = TransformProperty::List(vec![TransformFunction::Translate(
+ Length::<Horizontal>::new(100.0, LengthUnit::Px),
+ Length::<Vertical>::new(100.0, LengthUnit::Px),
+ )]);
+
+ assert_eq!(
+ &tpt,
+ &parse_transform_prop("translate(100px,100px)").unwrap()
+ );
+ assert!(parse_transform_prop("translate(100 100)").is_err());
+ assert!(parse_transform_prop("translate(1px,1px,1px,1px)").is_err());
+ }
+
+ #[test]
+ fn test_parse_transform_property_translate_x() {
+ let tptx = TransformProperty::List(vec![TransformFunction::TranslateX(
+ Length::<Horizontal>::new(100.0, LengthUnit::Px),
+ )]);
+
+ assert_eq!(&tptx, &parse_transform_prop("translateX(100px)").unwrap());
+ assert!(parse_transform_prop("translateX(100 100)").is_err());
+ assert!(parse_transform_prop("translatex(1px)").is_err());
+ assert!(parse_transform_prop("translatex(1rad)").is_err());
+ }
+
+ #[test]
+ fn test_parse_transform_property_translate_y() {
+ let tpty = TransformProperty::List(vec![TransformFunction::TranslateY(
+ Length::<Vertical>::new(100.0, LengthUnit::Px),
+ )]);
+
+ assert_eq!(&tpty, &parse_transform_prop("translateY(100px)").unwrap());
+ assert!(parse_transform_prop("translateY(100 100)").is_err());
+ assert!(parse_transform_prop("translatey(1px)").is_err());
+ assert!(parse_transform_prop("translateY(1%)").is_ok());
+ }
+
+ #[test]
+ fn test_parse_transform_property_scale() {
+ let tps = TransformProperty::List(vec![TransformFunction::Scale(1.0, 10.0)]);
+
+ assert_eq!(&tps, &parse_transform_prop("scale(1,10)").unwrap());
+ assert!(parse_transform_prop("scale(1 10)").is_err());
+ assert!(parse_transform_prop("scale(1px,10px)").is_err());
+ assert!(parse_transform_prop("scale(1%)").is_err());
+ }
+
+ #[test]
+ fn test_parse_transform_property_scale_x() {
+ let tpsx = TransformProperty::List(vec![TransformFunction::ScaleX(10.0)]);
+
+ assert_eq!(&tpsx, &parse_transform_prop("scaleX(10)").unwrap());
+
+ assert!(parse_transform_prop("scaleX(100 100)").is_err());
+ assert!(parse_transform_prop("scalex(10)").is_err());
+ assert!(parse_transform_prop("scaleX(10px)").is_err());
+ }
+
+ #[test]
+ fn test_parse_transform_property_scale_y() {
+ let tpsy = TransformProperty::List(vec![TransformFunction::ScaleY(10.0)]);
+
+ assert_eq!(&tpsy, &parse_transform_prop("scaleY(10)").unwrap());
+ assert!(parse_transform_prop("scaleY(10 1)").is_err());
+ assert!(parse_transform_prop("scaleY(1px)").is_err());
+ }
+
+ #[test]
+ fn test_parse_transform_property_rotate() {
+ let tpr =
+ TransformProperty::List(vec![TransformFunction::Rotate(Angle::from_degrees(100.0))]);
+ match parse_transform_prop("rotate(100deg)") {
+ Err(e) => eprintln!("TEST ERROR: {:?}", e),
+ _ => {}
+ }
+ assert_eq!(&tpr, &parse_transform_prop("rotate(100deg)").unwrap());
+ assert!(parse_transform_prop("rotate(100deg 100)").is_err());
+ assert!(parse_transform_prop("rotate(3px)").is_err());
+ }
+
+ #[test]
+ fn test_parse_transform_property_skew() {
+ let tpsk = TransformProperty::List(vec![TransformFunction::Skew(
+ Angle::from_degrees(90.0),
+ Angle::from_degrees(90.0),
+ )]);
+
+ assert_eq!(&tpsk, &parse_transform_prop("skew(90deg,90deg)").unwrap());
+ assert!(parse_transform_prop("skew(1.0,1.0)").is_ok());
+ assert!(parse_transform_prop("skew(1rad,1rad)").is_ok());
+ assert!(parse_transform_prop("skew(1.0px)").is_err());
+ assert!(parse_transform_prop("skew(1.0,1.0,1deg)").is_err());
+ }
+
+ #[test]
+ fn test_parse_transform_property_skew_x() {
+ let tpskx =
+ TransformProperty::List(vec![TransformFunction::SkewX(Angle::from_degrees(90.0))]);
+
+ assert_eq!(&tpskx, &parse_transform_prop("skewX(90deg)").unwrap());
+ assert!(parse_transform_prop("skewX(1.0)").is_ok());
+ assert!(parse_transform_prop("skewX(1rad)").is_ok());
+ assert!(parse_transform_prop("skewx(1.0)").is_err());
+ assert!(parse_transform_prop("skewX(1.0,1.0)").is_err());
+ }
+
+ #[test]
+ fn test_parse_transform_property_skew_y() {
+ let tpsky =
+ TransformProperty::List(vec![TransformFunction::SkewY(Angle::from_degrees(90.0))]);
+
+ assert_eq!(&tpsky, &parse_transform_prop("skewY(90deg)").unwrap());
+ assert!(parse_transform_prop("skewY(1.0)").is_ok());
+ assert!(parse_transform_prop("skewY(1rad)").is_ok());
+ assert!(parse_transform_prop("skewy(1.0)").is_err());
+ assert!(parse_transform_prop("skewY(1.0,1.0)").is_err());
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]