[librsvg: 12/25] rsvg_parse_stroke_dasharray(): New function, implemented in Rust
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 12/25] rsvg_parse_stroke_dasharray(): New function, implemented in Rust
- Date: Fri, 2 Feb 2018 00:29:37 +0000 (UTC)
commit 8ebc8675c88791cceaa8040e5d00b1c107b7e0cc
Author: Federico Mena Quintero <federico gnome org>
Date: Mon Jan 29 18:35:11 2018 -0600
rsvg_parse_stroke_dasharray(): New function, implemented in Rust
We use this now instead of the shitty C parser for the
stroke-dasharray attribute. We still need to handle errors and
inheritance.
rsvg-cairo-draw.c | 41 ++++++++++++++++++++++++++++++++--
rsvg-styles.c | 51 +++++-------------------------------------
rsvg-styles.h | 18 ++++++++++-----
rust/src/length.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++---
rust/src/lib.rs | 1 +
5 files changed, 120 insertions(+), 56 deletions(-)
---
diff --git a/rsvg-cairo-draw.c b/rsvg-cairo-draw.c
index 83109f4..c0f9949 100644
--- a/rsvg-cairo-draw.c
+++ b/rsvg-cairo-draw.c
@@ -230,6 +230,43 @@ rsvg_cairo_get_pango_context (RsvgDrawingCtx * ctx)
return context;
}
+static void
+set_stroke_dasharray(cairo_t *cr, RsvgDrawingCtx *ctx, RsvgStrokeDasharray *dash, RsvgLength *dash_offset)
+{
+ double *dashes;
+ int i;
+
+ switch (dash->kind) {
+ case RSVG_STROKE_DASHARRAY_NONE:
+ cairo_set_dash (cr, NULL, 0, 0.0);
+ break;
+
+ case RSVG_STROKE_DASHARRAY_INHERIT:
+ /* FIXME: do inheritance in the caller */
+ cairo_set_dash (cr, NULL, 0, 0.0);
+ break;
+
+ case RSVG_STROKE_DASHARRAY_DASHES:
+ dashes = g_new(double, dash->num_dashes);
+
+ for (i = 0; i < dash->num_dashes; i++) {
+ dashes[i] = rsvg_length_normalize(&dash->dashes[i], ctx);
+ }
+
+ cairo_set_dash (cr,
+ dashes,
+ dash->num_dashes,
+ rsvg_length_normalize (dash_offset, ctx));
+ g_free(dashes);
+ break;
+
+ case RSVG_STROKE_DASHARRAY_ERROR:
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
static void
setup_cr_for_stroke (cairo_t *cr, RsvgDrawingCtx *ctx, RsvgState *state)
{
@@ -237,8 +274,8 @@ setup_cr_for_stroke (cairo_t *cr, RsvgDrawingCtx *ctx, RsvgState *state)
cairo_set_miter_limit (cr, state->miter_limit);
cairo_set_line_cap (cr, (cairo_line_cap_t) state->cap);
cairo_set_line_join (cr, (cairo_line_join_t) state->join);
- cairo_set_dash (cr, state->dash.dashes, state->dash.num_dashes,
- rsvg_length_normalize (&state->dash_offset, ctx));
+
+ set_stroke_dasharray(cr, ctx, &state->dash, &state->dash_offset);
}
void
diff --git a/rsvg-styles.c b/rsvg-styles.c
index d733fef..6667ab0 100644
--- a/rsvg-styles.c
+++ b/rsvg-styles.c
@@ -288,7 +288,7 @@ rsvg_state_clone (RsvgState * dst, const RsvgState * src)
dst->styles = g_hash_table_ref (src->styles);
if (src->dash.num_dashes > 0) {
- dst->dash.dashes = g_new0 (gdouble, src->dash.num_dashes);
+ dst->dash.dashes = g_new0 (RsvgLength, src->dash.num_dashes);
for (i = 0; i < src->dash.num_dashes; i++)
dst->dash.dashes[i] = src->dash.dashes[i];
}
@@ -419,7 +419,7 @@ rsvg_state_inherit_run (RsvgState * dst, const RsvgState * src,
if (dst->has_dash)
g_free (dst->dash.dashes);
- dst->dash.dashes = g_new0 (gdouble, src->dash.num_dashes);
+ dst->dash.dashes = g_new0 (RsvgLength, src->dash.num_dashes);
dst->dash.num_dashes = src->dash.num_dashes;
for (i = 0; i < src->dash.num_dashes; i++)
dst->dash.dashes[i] = src->dash.dashes[i];
@@ -518,6 +518,9 @@ rsvg_state_inherit (RsvgState * dst, const RsvgState * src)
rsvg_state_inherit_run (dst, src, inheritfunction, 1);
}
+/* Defined in rust/src/length.rs */
+extern RsvgStrokeDasharray rsvg_parse_stroke_dasharray(const char *str);
+
/* Parse a CSS2 style argument, setting the SVG context attributes. */
static void
rsvg_parse_style_pair (RsvgState * state,
@@ -956,49 +959,7 @@ rsvg_parse_style_pair (RsvgState * state,
} else if (g_str_equal (name, "stroke-dasharray")) {
state->has_dash = TRUE;
- if (g_str_equal (value, "none")) {
- if (state->dash.num_dashes != 0) {
- /* free any cloned dash data */
- g_free (state->dash.dashes);
- state->dash.dashes = NULL;
- state->dash.num_dashes = 0;
- }
- } else {
- gchar **dashes = g_strsplit (value, ",", -1);
- if (NULL != dashes) {
- gint n_dashes, i;
- gboolean is_even = FALSE;
- gdouble total = 0;
-
- /* count the #dashes */
- for (n_dashes = 0; dashes[n_dashes] != NULL; n_dashes++);
-
- is_even = (n_dashes % 2 == 0);
- state->dash.num_dashes = (is_even ? n_dashes : n_dashes * 2);
- state->dash.dashes = g_new0 (double, state->dash.num_dashes);
-
- /* TODO: handle negative value == error case */
-
- /* the even and base case */
- for (i = 0; i < n_dashes; i++) {
- state->dash.dashes[i] = g_ascii_strtod (dashes[i], NULL);
- total += state->dash.dashes[i];
- }
- /* if an odd number of dashes is found, it gets repeated */
- if (!is_even)
- for (; i < state->dash.num_dashes; i++)
- state->dash.dashes[i] = state->dash.dashes[i - n_dashes];
-
- g_strfreev (dashes);
- /* If the dashes add up to 0, then it should
- be ignored */
- if (total == 0) {
- g_free (state->dash.dashes);
- state->dash.dashes = NULL;
- state->dash.num_dashes = 0;
- }
- }
- }
+ state->dash = rsvg_parse_stroke_dasharray (value);
}
}
diff --git a/rsvg-styles.h b/rsvg-styles.h
index 9089166..b89f2c1 100644
--- a/rsvg-styles.h
+++ b/rsvg-styles.h
@@ -61,12 +61,18 @@ typedef enum {
RSVG_ENABLE_BACKGROUND_NEW
} RsvgEnableBackgroundType;
-typedef struct _RsvgVpathDash RsvgVpathDash;
+typedef enum {
+ RSVG_STROKE_DASHARRAY_NONE,
+ RSVG_STROKE_DASHARRAY_INHERIT,
+ RSVG_STROKE_DASHARRAY_DASHES,
+ RSVG_STROKE_DASHARRAY_ERROR
+} RsvgStrokeDasharrayKind;
-struct _RsvgVpathDash {
+typedef struct {
+ RsvgStrokeDasharrayKind kind;
gsize num_dashes;
- double *dashes;
-};
+ RsvgLength *dashes;
+} RsvgStrokeDasharray;
struct _RsvgState {
RsvgState *parent;
@@ -150,10 +156,10 @@ struct _RsvgState {
gboolean has_cond;
gboolean cond_true;
- RsvgVpathDash dash;
+ RsvgStrokeDasharray dash;
gboolean has_dash;
- gboolean has_dashoffset;
RsvgLength dash_offset;
+ gboolean has_dashoffset;
guint32 current_color;
gboolean has_current_color;
diff --git a/rust/src/length.rs b/rust/src/length.rs
index f9ba3c1..0d658c0 100644
--- a/rust/src/length.rs
+++ b/rust/src/length.rs
@@ -1,8 +1,11 @@
-use ::cssparser::{Parser, ParserInput, Token};
-use ::glib::translate::*;
-use ::libc;
+use cssparser::{Parser, ParserInput, Token};
+use glib_sys;
+use glib::translate::*;
+use libc;
use std::f64::consts::*;
+use std::mem;
+use std::ptr;
use drawing_ctx;
use drawing_ctx::RsvgDrawingCtx;
@@ -290,6 +293,23 @@ fn viewport_percentage (x: f64, y: f64) -> f64 {
(x * x + y * y).sqrt () / SQRT_2
}
+// Keep in sync with rsvg-styles.h:RsvgStrokeDasharrayKind
+#[repr(C)]
+pub enum RsvgStrokeDasharrayKind {
+ None,
+ Inherit,
+ Dashes,
+ Error
+}
+
+// Keep in sync with rsvg-styles.h:RsvgStrokeDasharray
+#[repr(C)]
+pub struct RsvgStrokeDasharray {
+ pub kind: RsvgStrokeDasharrayKind,
+ pub num_dashes: usize,
+ pub dashes: *mut RsvgLength
+}
+
#[derive(Debug)]
enum StrokeDasharray {
None,
@@ -363,6 +383,45 @@ pub extern fn rsvg_length_hand_normalize (raw_length: *const RsvgLength,
length.hand_normalize (pixels_per_inch, width_or_height, font_size)
}
+#[no_mangle]
+pub extern fn rsvg_parse_stroke_dasharray(string: *const libc::c_char) -> RsvgStrokeDasharray {
+ let my_string = unsafe { &String::from_glib_none (string) };
+
+ match parse_stroke_dash_array(my_string) {
+ Ok(StrokeDasharray::None) => RsvgStrokeDasharray {
+ kind: RsvgStrokeDasharrayKind::None,
+ num_dashes: 0,
+ dashes: ptr::null_mut()
+ },
+
+ Ok(StrokeDasharray::Inherit) => RsvgStrokeDasharray {
+ kind: RsvgStrokeDasharrayKind::Inherit,
+ num_dashes: 0,
+ dashes: ptr::null_mut()
+ },
+
+ Ok(StrokeDasharray::Dasharray(ref v)) => RsvgStrokeDasharray {
+ kind: RsvgStrokeDasharrayKind::Dashes,
+ num_dashes: v.len(),
+ dashes: to_c_array(&v)
+ },
+
+ Err(_) => RsvgStrokeDasharray {
+ kind: RsvgStrokeDasharrayKind::Error,
+ num_dashes: 0,
+ dashes: ptr::null_mut()
+ }
+ }
+}
+
+fn to_c_array<T>(v: &[T]) -> *mut T {
+ unsafe {
+ let res = glib_sys::g_malloc(mem::size_of::<T>() * v.len()) as *mut T;
+ ptr::copy_nonoverlapping(v.as_ptr(), res, v.len());
+ res
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index fd308b5..8c6f1b6 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -59,6 +59,7 @@ pub use length::{
rsvg_length_parse,
rsvg_length_normalize,
rsvg_length_hand_normalize,
+ rsvg_parse_stroke_dasharray
};
pub use image::{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]