[librsvg: 1/21] WIP: (#487) Begin implementing transform as property This change adds TransformProperty, Function, a




commit a03f188905902351060ab54c143419f6eea0d0fb
Author: Madds H <madds hollandart io>
Date:   Wed Aug 4 00:01:27 2021 -0500

    WIP: (#487) Begin implementing transform as property
    This change adds TransformProperty, Function, and parser to transform.rs
    It also adds the TransformProperty to properties macros
    
    Current Errors: Macro in Properties requires #derive(Clone, Debug)
    but 'type' cannot implement them, not sure how to fix aside from
    changing `TransformProperty::List(TransformList)` to
    `::List(Vec<TransformList>)`, which doesn't look pretty
    
    Not quite done implementing the parser, and the names of the functions
    there need changed to be consistent.
    
    Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/576>

 src/properties.rs    |   3 ++
 src/property_defs.rs |  11 ++++
 src/transform.rs     | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 155 insertions(+), 1 deletion(-)
---
diff --git a/src/properties.rs b/src/properties.rs
index 510efd7c..9d9e1096 100644
--- a/src/properties.rs
+++ b/src/properties.rs
@@ -27,6 +27,7 @@ use crate::error::*;
 use crate::parsers::{Parse, ParseValue};
 use crate::property_macros::Property;
 use crate::transform::Transform;
+use crate::transform::TransformProperty;
 use crate::xml::Attributes;
 
 // Re-export the actual properties so they are easy to find from a single place `properties::*`.
@@ -424,6 +425,7 @@ make_properties! {
         "text-anchor"                 => text_anchor                 : TextAnchor,
         "text-decoration"             => text_decoration             : TextDecoration,
         "text-rendering"              => text_rendering              : TextRendering,
+        "transform"                   => transform_property          : TransformProperty,
         "unicode-bidi"                => unicode_bidi                : UnicodeBidi,
         "visibility"                  => visibility                  : Visibility,
         "writing-mode"                => writing_mode                : WritingMode,
@@ -636,6 +638,7 @@ impl SpecifiedValues {
         compute!(TextAnchor, text_anchor);
         compute!(TextDecoration, text_decoration);
         compute!(TextRendering, text_rendering);
+        compute!(TransformProperty, transform_property);
         compute!(UnicodeBidi, unicode_bidi);
         compute!(Visibility, visibility);
         compute!(WritingMode, writing_mode);
diff --git a/src/property_defs.rs b/src/property_defs.rs
index 05b667a5..c12653be 100644
--- a/src/property_defs.rs
+++ b/src/property_defs.rs
@@ -49,6 +49,7 @@ use crate::parsers::Parse;
 use crate::properties::ComputedValues;
 use crate::property_macros::Property;
 use crate::rect::Rect;
+use crate::transform::TransformProperty;
 use crate::unit_interval::UnitInterval;
 
 make_property!(
@@ -985,6 +986,16 @@ make_property!(
     "geometricPrecision" => GeometricPrecision,
 );
 
+make_property!(
+    /// `transform` property.
+    ///
+    /// https://www.w3.org/TR/css-transforms-1/#transform-property
+    Transform,
+    default: TransformProperty::None,
+    inherits_automatically: false,
+    newtype_parse: TransformProperty,
+);
+
 make_property!(
     /// `unicode-bidi` property.
     ///
diff --git a/src/transform.rs b/src/transform.rs
index db77a3de..b1665f63 100644
--- a/src/transform.rs
+++ b/src/transform.rs
@@ -2,7 +2,7 @@
 //!
 //! This module handles `transform` values [per the SVG specification][spec].
 //!
-//! [spec]:  https://www.w3.org/TR/SVG11/coords.html#TransformAttribute
+//! [spec]:  https://www.w3.org/TR/SVG11/coords.html#TransformAttribute and 
https://www.w3.org/TR/css-transforms-1/#transform-property
 
 use cssparser::{Parser, Token};
 
@@ -11,6 +11,94 @@ use crate::error::*;
 use crate::parsers::{optional_comma, Parse};
 use crate::rect::Rect;
 
+// https://www.w3.org/TR/css-transforms-1/#transform-property
+#[derive(Debug, Clone)]
+pub enum TransformProperty {
+    None,
+    List(TransformList),
+}
+
+#[derive(Debug, Clone)]
+pub type TransformList = Vec<TransformFunction>;
+
+// https://www.w3.org/TR/css-transforms-1/#typedef-transform-function
+#[derive(Debug, Clone)]
+enum TransformFunction {
+    Matrix(),
+    Translate(),
+    TranslateX(),
+    TranslateY(),
+    Scale(),
+    ScaleX(),
+    ScaleY(),
+    Rotate(),
+    Skew(),
+    SkewX(),
+    SkewY(),
+}
+
+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))
+    }
+}
+
+fn parse_transform_prop_function_list<'i>(
+    parser: &mut Parser<'i, '_>,
+) -> Result<TransformList, ParseError<'i>> {
+    //TODO: What does this need to be set to?
+    let mut t = TransformFunction::Translate();
+
+    loop {
+        if parser.is_exhausted() {
+            break;
+        }
+        t = parse_transform_prop_function_command(parser)?.post_transform(&t);
+    }
+
+    Ok(t)
+}
+
+fn parse_transform_prop_function_command<'i>(
+    parser: &mut Parser<'i, '_>,
+) -> Result<TransformFunction, ParseError<'i>> {
+    let loc = parser.current_source_location();
+
+    match parser.next()?.clone() {
+        Token::Function(ref name) => parse_transform_prop_function_name(name, parser),
+        tok => Err(loc.new_unexpected_token_error(tok.clone())),
+    }
+}
+
+fn parse_transform_function_internal<'i>(
+    name: &str,
+    parser: &mut Parser<'i, '_>,
+) -> Result<Transform, ParseError<'i>> {
+    let loc = parser.current_source_location();
+
+    match name {
+        "matrix" => parse_matrix_args(parser),
+        "translate" => parse_translate_args(parser),
+        "translateX" => parse_translate_x_args(parser),
+        "translateY" => parse_translate_y_args(parser),
+        "scale" => parse_scale_args(parser),
+        "scaleX" => parse_scale_x_args(parser),
+        "scaleY" => parse_scale_y_args(parser),
+        "rotate" => parse_rotate_args(parser),
+        "skew" => parse_skew_args(parser),
+        "skewX" => parse_skew_x_args(parser),
+        "skewY" => parse_skew_y_args(parser),
+        _ => Err(loc.new_custom_error(ValueErrorKind::parse_error(
+            "expected matrix|translate|translateX|translateY|scale|scaleX|scaleY|rotate|skewX|skewY",
+        ))),
+    }
+}
+
 #[derive(Debug, Copy, Clone, PartialEq)]
 pub struct Transform {
     pub xx: f64,
@@ -307,6 +395,22 @@ fn parse_translate_args<'i>(parser: &mut Parser<'i, '_>) -> Result<Transform, Pa
     })
 }
 
+fn parse_translate_x_args<'i>(parser: &mut Parser<'i, '_>) -> Result<Transform, ParseError<'i>> {
+    parser.parse_nested_block(|p| {
+        let tx = f64::parse(p)?;
+
+        Ok(Transform::new_translate(tx, 0.0))
+    })
+}
+
+fn parse_translate_y_args<'i>(parser: &mut Parser<'i, '_>) -> Result<Transform, ParseError<'i>> {
+    parser.parse_nested_block(|p| {
+        let ty = f64::parse(p)?;
+
+        Ok(Transform::new_translate(0.0, ty))
+    })
+}
+
 fn parse_scale_args<'i>(parser: &mut Parser<'i, '_>) -> Result<Transform, ParseError<'i>> {
     parser.parse_nested_block(|p| {
         let x = f64::parse(p)?;
@@ -322,6 +426,22 @@ fn parse_scale_args<'i>(parser: &mut Parser<'i, '_>) -> Result<Transform, ParseE
     })
 }
 
+fn parse_scale_x_args<'i>(parser: &mut Parser<'i, '_>) -> Result<Transform, ParseError<'i>> {
+    parser.parse_nested_block(|p| {
+        let x = f64::parse(p)?;
+
+        Ok(Transform::new_scale(x, 0.0))
+    })
+}
+
+fn parse_scale_y_args<'i>(parser: &mut Parser<'i, '_>) -> Result<Transform, ParseError<'i>> {
+    parser.parse_nested_block(|p| {
+        let y = f64::parse(p)?;
+
+        Ok(Transform::new_scale(0.0, y))
+    })
+}
+
 fn parse_rotate_args<'i>(parser: &mut Parser<'i, '_>) -> Result<Transform, ParseError<'i>> {
     parser.parse_nested_block(|p| {
         let angle = Angle::from_degrees(f64::parse(p)?);
@@ -344,6 +464,21 @@ fn parse_rotate_args<'i>(parser: &mut Parser<'i, '_>) -> Result<Transform, Parse
     })
 }
 
+fn parse_skew_args<'i>(parser: &mut Parser<'i, '_>) -> Result<Transform, ParseError<'i>> {
+    parser.parse_nested_block(|p| {
+        let ax = Angle::from_degrees(f64::parse(p)?);
+
+        let ay = Angle::from_degrees(
+            p.try_parse(|p| {
+                optional_comma(p);
+                f64::parse(p)
+            })
+            .unwrap_or(0.0),
+        );
+        Ok(Transform::new_skew(ax, ay))
+    })
+}
+
 fn parse_skew_x_args<'i>(parser: &mut Parser<'i, '_>) -> Result<Transform, ParseError<'i>> {
     parser.parse_nested_block(|p| {
         let angle = Angle::from_degrees(f64::parse(p)?);
@@ -588,3 +723,8 @@ mod tests {
         assert_transform_eq(&parse_transform("").unwrap(), &Transform::identity());
     }
 }
+
+#[test]
+fn test_parse_transform_property() {
+    // TODO for madds: put your tests in here
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]