[librsvg] transform.rs: Implement rsvg_parse_transform() fully in Rust
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] transform.rs: Implement rsvg_parse_transform() fully in Rust
- Date: Wed, 22 Mar 2017 18:00:25 +0000 (UTC)
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]