[librsvg] transform.rs: Implement rsvg_parse_transform() fully in Rust



commit b9dbe3bdfde71899af9f090b923ad35513006670
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Mar 22 11:01:18 2017 -0600

    transform.rs: Implement rsvg_parse_transform() fully in Rust
    
    And remove it from rsvg-styles.c.  Yay!

 rsvg-styles.c         |  157 -------------------------------------------------
 rsvg-styles.h         |    1 +
 rust/src/lib.rs       |    4 +
 rust/src/transform.rs |   24 ++++++++
 4 files changed, 29 insertions(+), 157 deletions(-)
---
diff --git a/rsvg-styles.c b/rsvg-styles.c
index 1a81f55..e8ce51f 100644
--- a/rsvg-styles.c
+++ b/rsvg-styles.c
@@ -61,21 +61,6 @@ typedef struct _StyleValueData {
     gboolean important;
 } StyleValueData;
 
-/*
- * _rsvg_cairo_matrix_init_shear: Set up a shearing matrix.
- * @dst: Where to store the resulting affine transform.
- * @theta: Shear angle in degrees.
- *
- * Sets up a shearing matrix. In the standard libart coordinate system
- * and a small value for theta, || becomes \\. Horizontal lines remain
- * unchanged.
- **/
-static void
-_rsvg_cairo_matrix_init_shear (cairo_matrix_t *dst, double theta)
-{
-  cairo_matrix_init (dst, 1., 0., tan (theta * M_PI / 180.0), 1., 0., 0);
-}
-
 static StyleValueData *
 style_value_data_new (const gchar *value, gboolean important)
 {
@@ -1302,148 +1287,6 @@ ccss_import_style (CRDocHandler * a_this,
     g_free (mime_type);
 }
 
-/* Parse an SVG transform string into an affine matrix. Reference: SVG
-   working draft dated 1999-07-06, section 8.5. Return TRUE on
-   success. */
-gboolean
-rsvg_parse_transform (cairo_matrix_t *out_matrix, const char *src)
-{
-    cairo_matrix_t dst;
-    int idx;
-    char keyword[32];
-    double args[6];
-    int n_args;
-    guint key_len;
-    cairo_matrix_t affine;
-    cairo_matrix_t inverse;
-
-    cairo_matrix_init_identity (&dst);
-
-    idx = 0;
-    while (src[idx]) {
-        /* skip initial whitespace */
-        while (g_ascii_isspace (src[idx]))
-            idx++;
-
-        if (src[idx] == '\0')
-            break;
-
-        /* parse keyword */
-        for (key_len = 0; key_len < sizeof (keyword); key_len++) {
-            char c;
-
-            c = src[idx];
-            if (g_ascii_isalpha (c) || c == '-')
-                keyword[key_len] = src[idx++];
-            else
-                break;
-        }
-        if (key_len >= sizeof (keyword))
-            return FALSE;
-        keyword[key_len] = '\0';
-
-        /* skip whitespace */
-        while (g_ascii_isspace (src[idx]))
-            idx++;
-
-        if (src[idx] != '(')
-            return FALSE;
-        idx++;
-
-        for (n_args = 0;; n_args++) {
-            char c;
-            char *end_ptr;
-
-            /* skip whitespace */
-            while (g_ascii_isspace (src[idx]))
-                idx++;
-            c = src[idx];
-            if (g_ascii_isdigit (c) || c == '+' || c == '-' || c == '.') {
-                if (n_args == sizeof (args) / sizeof (args[0]))
-                    return FALSE;       /* too many args */
-
-                args[n_args] = g_ascii_strtod (src + idx, &end_ptr);
-                if (errno == ERANGE)
-                    return FALSE; /* overflow / underflow */
-
-                idx = end_ptr - src;
-
-                while (g_ascii_isspace (src[idx]))
-                    idx++;
-
-                /* skip optional comma */
-                if (src[idx] == ',')
-                    idx++;
-            } else if (c == ')')
-                break;
-            else
-                return FALSE;
-        }
-        idx++;
-
-        /* ok, have parsed keyword and args, now modify the transform */
-        if (!strcmp (keyword, "matrix")) {
-            if (n_args != 6)
-                return FALSE;
-
-            cairo_matrix_init (&affine, args[0], args[1], args[2], args[3], args[4], args[5]);
-            cairo_matrix_multiply (&dst, &affine, &dst);
-        } else if (!strcmp (keyword, "translate")) {
-            if (n_args == 1)
-                args[1] = 0;
-            else if (n_args != 2)
-                return FALSE;
-            cairo_matrix_init_translate (&affine, args[0], args[1]);
-            cairo_matrix_multiply (&dst, &affine, &dst);
-        } else if (!strcmp (keyword, "scale")) {
-            if (n_args == 1)
-                args[1] = args[0];
-            else if (n_args != 2)
-                return FALSE;
-            cairo_matrix_init_scale (&affine, args[0], args[1]);
-            cairo_matrix_multiply (&dst, &affine, &dst);
-        } else if (!strcmp (keyword, "rotate")) {
-            if (n_args == 1) {
-
-                cairo_matrix_init_rotate (&affine, args[0] * M_PI / 180.);
-                cairo_matrix_multiply (&dst, &affine, &dst);
-            } else if (n_args == 3) {
-                cairo_matrix_init_translate (&affine, args[1], args[2]);
-                cairo_matrix_multiply (&dst, &affine, &dst);
-
-                cairo_matrix_init_rotate (&affine, args[0] * M_PI / 180.);
-                cairo_matrix_multiply (&dst, &affine, &dst);
-
-                cairo_matrix_init_translate (&affine, -args[1], -args[2]);
-                cairo_matrix_multiply (&dst, &affine, &dst);
-            } else
-                return FALSE;
-        } else if (!strcmp (keyword, "skewX")) {
-            if (n_args != 1)
-                return FALSE;
-            _rsvg_cairo_matrix_init_shear (&affine, args[0]);
-            cairo_matrix_multiply (&dst, &affine, &dst);
-        } else if (!strcmp (keyword, "skewY")) {
-            if (n_args != 1)
-                return FALSE;
-            _rsvg_cairo_matrix_init_shear (&affine, args[0]);
-            /* transpose the affine, given that we know [1] is zero */
-            affine.yx = affine.xy;
-            affine.xy = 0.;
-            cairo_matrix_multiply (&dst, &affine, &dst);
-        } else
-            return FALSE;       /* unknown keyword */
-    }
-
-    inverse = dst;
-    if (cairo_matrix_invert (&inverse) != CAIRO_STATUS_SUCCESS) {
-        return FALSE; /* we got passed an invalid matrix */
-    }
-
-    *out_matrix = dst;
-    return TRUE;
-}
-
 /**
  * rsvg_parse_transform_attr:
  * @ctx: Rsvg context.
diff --git a/rsvg-styles.h b/rsvg-styles.h
index 8d61dde..07f1cbc 100644
--- a/rsvg-styles.h
+++ b/rsvg-styles.h
@@ -230,6 +230,7 @@ G_GNUC_INTERNAL
 void rsvg_parse_style_attrs (RsvgHandle *ctx, RsvgNode *node, const char *tag,
                              const char *klazz, const char *id, RsvgPropertyBag * atts);
 
+/* Implemented in rust/src/transform.rs */
 G_GNUC_INTERNAL
 gboolean rsvg_parse_transform   (cairo_matrix_t *matrix, const char *src) G_GNUC_WARN_UNUSED_RESULT;
 
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 983fafc..dbea38b 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -97,6 +97,10 @@ pub use structure::{
     rsvg_node_switch_new,
 };
 
+pub use transform::{
+    rsvg_parse_transform,
+};
+
 pub use viewbox::{
     RsvgViewBox
 };
diff --git a/rust/src/transform.rs b/rust/src/transform.rs
index 8dd5426..2b52377 100644
--- a/rust/src/transform.rs
+++ b/rust/src/transform.rs
@@ -1,7 +1,10 @@
 extern crate lalrpop_util;
+extern crate glib;
+extern crate libc;
 
 extern crate cairo;
 use self::cairo::MatrixTrait;
+use self::glib::translate::*;
 
 use std::f64::consts::*;
 
@@ -38,6 +41,27 @@ fn make_rotation_matrix (angle_degrees: f64, tx: f64, ty: f64) -> cairo::Matrix
     m
 }
 
+#[no_mangle]
+pub fn rsvg_parse_transform (out_matrix: *mut cairo::Matrix, s: *const libc::c_char) -> bool {
+    assert! (!out_matrix.is_null ());
+    assert! (!s.is_null ());
+
+    let string = unsafe { String::from_glib_none (s) };
+    let matrix: &mut cairo::Matrix = unsafe { &mut *out_matrix };
+
+    match parse_transform (&string) {
+        Ok (m) => {
+            *matrix = m;
+            true
+        },
+
+        Err (_) => {
+            *matrix = cairo::Matrix::identity ();
+            false
+        }
+    }
+}
+
 #[cfg(test)]
 mod test {
     use super::*;


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