[librsvg] rsvg_css_parse_opacity(): Move entirely to Rust. Yay!
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] rsvg_css_parse_opacity(): Move entirely to Rust. Yay!
- Date: Wed, 31 May 2017 13:32:00 +0000 (UTC)
commit fd0f38b44436af67679335240e797e262b36aa4c
Author: Federico Mena Quintero <federico gnome org>
Date: Wed May 31 08:26:47 2017 -0500
rsvg_css_parse_opacity(): Move entirely to Rust. Yay!
We also move RsvgOpacitySpec and RsvgOpacityKind to rsvg-css.h, to keep
them together with RsvgColorSpec/Kind.
Makefile.am | 1 +
rsvg-css.c | 17 -----------
rsvg-css.h | 19 +++++++++++-
rsvg-styles.c | 54 +++++++++++++++++++++++++++--------
rsvg-styles.h | 14 ---------
rust/src/lib.rs | 6 ++++
rust/src/opacity.rs | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 144 insertions(+), 45 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index cb21eac..8ac975f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -82,6 +82,7 @@ RUST_SOURCES = \
rust/src/lib.rs \
rust/src/marker.rs \
rust/src/node.rs \
+ rust/src/opacity.rs \
rust/src/paint_server.rs \
rust/src/parsers.rs \
rust/src/parse_transform.lalrpop \
diff --git a/rsvg-css.c b/rsvg-css.c
index 097472d..ab11247 100644
--- a/rsvg-css.c
+++ b/rsvg-css.c
@@ -113,23 +113,6 @@ RsvgCssColorSpec rsvg_css_parse_color_ (const char *str,
return rsvg_css_parse_color (str, allow_inherit, allow_current_color);
}
-guint
-rsvg_css_parse_opacity (const char *str)
-{
- char *end_ptr = NULL;
- double opacity;
-
- opacity = g_ascii_strtod (str, &end_ptr);
-
- if (((opacity == -HUGE_VAL || opacity == HUGE_VAL) && (ERANGE == errno)) ||
- *end_ptr != '\0')
- opacity = 1.;
-
- opacity = CLAMP (opacity, 0., 1.);
-
- return (guint) floor (opacity * 255. + 0.5);
-}
-
PangoStyle
rsvg_css_parse_font_style (const char *str, gboolean * inherit)
{
diff --git a/rsvg-css.h b/rsvg-css.h
index 1c8beba..719820f 100644
--- a/rsvg-css.h
+++ b/rsvg-css.h
@@ -85,6 +85,23 @@ RsvgCssColorSpec rsvg_css_parse_color (const char *str,
AllowInherit allow_inherit,
AllowCurrentColor allow_current_color);
+/* Keep this in sync with rust/src/opacity.rs:OpacityKind */
+typedef enum {
+ RSVG_OPACITY_INHERIT,
+ RSVG_OPACITY_SPECIFIED,
+ RSVG_OPACITY_PARSE_ERROR
+} RsvgOpacityKind;
+
+/* Keep this in sync with rust/src/opacity.rs:OpacitySpec */
+typedef struct {
+ RsvgOpacityKind kind;
+ guint8 opacity; /* 0..255; only valid if kind == RSVG_OPACITY_SPECIFIED */
+} RsvgOpacitySpec;
+
+/* This is implemented in rust/src/opacity.rs */
+G_GNUC_INTERNAL
+RsvgOpacitySpec rsvg_css_parse_opacity (const char *str);
+
/* This is implemented in rust/src/aspect_ratio.rs */
G_GNUC_INTERNAL
guint32 rsvg_aspect_ratio_parse (const char *str);
@@ -102,8 +119,6 @@ void rsvg_aspect_ratio_compute (guint32 aspect,
G_GNUC_INTERNAL
int rsvg_css_parse_aspect_ratio (const char *str);
G_GNUC_INTERNAL
-guint rsvg_css_parse_opacity (const char *str);
-G_GNUC_INTERNAL
PangoStyle rsvg_css_parse_font_style (const char *str, gboolean * inherit);
G_GNUC_INTERNAL
PangoVariant rsvg_css_parse_font_variant (const char *str, gboolean * inherit);
diff --git a/rsvg-styles.c b/rsvg-styles.c
index 5ef1966..9e7502f 100644
--- a/rsvg-styles.c
+++ b/rsvg-styles.c
@@ -560,9 +560,17 @@ rsvg_parse_style_pair (RsvgState * state,
default:
g_assert_not_reached ();
}
- } else if (g_str_equal (name, "opacity"))
- state->opacity = rsvg_css_parse_opacity (value);
- else if (g_str_equal (name, "flood-color")) {
+ } else if (g_str_equal (name, "opacity")) {
+ RsvgOpacitySpec spec;
+
+ spec = rsvg_css_parse_opacity (value);
+ if (spec.kind == RSVG_OPACITY_SPECIFIED) {
+ state->opacity = spec.opacity;
+ } else {
+ state->opacity = 0;
+ /* FIXME: handle INHERIT and PARSE_ERROR */
+ }
+ } else if (g_str_equal (name, "flood-color")) {
RsvgCssColorSpec spec;
spec = rsvg_css_parse_color (value, ALLOW_INHERIT_YES, ALLOW_CURRENT_COLOR_YES);
@@ -591,7 +599,16 @@ rsvg_parse_style_pair (RsvgState * state,
g_assert_not_reached ();
}
} else if (g_str_equal (name, "flood-opacity")) {
- state->flood_opacity = rsvg_css_parse_opacity (value);
+ RsvgOpacitySpec spec;
+
+ spec = rsvg_css_parse_opacity (value);
+ if (spec.kind == RSVG_OPACITY_SPECIFIED) {
+ state->flood_opacity = spec.opacity;
+ } else {
+ state->flood_opacity = 0;
+ /* FIXME: handle INHERIT and PARSE_ERROR */
+ }
+
state->has_flood_opacity = TRUE;
} else if (g_str_equal (name, "filter")) {
g_free (state->filter);
@@ -708,7 +725,16 @@ rsvg_parse_style_pair (RsvgState * state,
rsvg_paint_server_parse (&state->has_fill_server, value);
rsvg_paint_server_unref (fill);
} else if (g_str_equal (name, "fill-opacity")) {
- state->fill_opacity = rsvg_css_parse_opacity (value);
+ RsvgOpacitySpec spec;
+
+ spec = rsvg_css_parse_opacity (value);
+ if (spec.kind == RSVG_OPACITY_SPECIFIED) {
+ state->fill_opacity = spec.opacity;
+ } else {
+ state->fill_opacity = 0;
+ /* FIXME: handle INHERIT and PARSE_ERROR */
+ }
+
state->has_fill_opacity = TRUE;
} else if (g_str_equal (name, "fill-rule")) {
state->has_fill_rule = TRUE;
@@ -747,7 +773,16 @@ rsvg_parse_style_pair (RsvgState * state,
else
g_warning (_("unknown line cap style %s\n"), value);
} else if (g_str_equal (name, "stroke-opacity")) {
- state->stroke_opacity = rsvg_css_parse_opacity (value);
+ RsvgOpacitySpec spec;
+
+ spec = rsvg_css_parse_opacity (value);
+ if (spec.kind == RSVG_OPACITY_SPECIFIED) {
+ state->stroke_opacity = spec.opacity;
+ } else {
+ state->stroke_opacity = 0;
+ /* FIXME: handle INHERIT and PARSE_ERROR */
+ }
+
state->has_stroke_opacity = TRUE;
} else if (g_str_equal (name, "stroke-linejoin")) {
state->has_join = TRUE;
@@ -852,13 +887,8 @@ rsvg_parse_style_pair (RsvgState * state,
state->has_stop_color = TRUE;
state->stop_color = rsvg_css_parse_color (value, ALLOW_INHERIT_YES, ALLOW_CURRENT_COLOR_YES);
} else if (g_str_equal (name, "stop-opacity")) {
+ state->stop_opacity = rsvg_css_parse_opacity (value);
state->has_stop_opacity = TRUE;
- if (g_str_equal (value, "inherit")) {
- state->stop_opacity.kind = RSVG_OPACITY_INHERIT;
- } else {
- state->stop_opacity.kind = RSVG_OPACITY_SPECIFIED;
- state->stop_opacity.opacity = rsvg_css_parse_opacity (value);
- }
} else if (g_str_equal (name, "marker-start")) {
g_free (state->startMarker);
state->startMarker = rsvg_get_url_string (value, NULL);
diff --git a/rsvg-styles.h b/rsvg-styles.h
index 8dfbc74..2466ed6 100644
--- a/rsvg-styles.h
+++ b/rsvg-styles.h
@@ -62,8 +62,6 @@ typedef enum {
RSVG_ENABLE_BACKGROUND_NEW
} RsvgEnableBackgroundType;
-/* enums and data structures are ABI compatible with libart */
-
typedef struct _RsvgVpathDash RsvgVpathDash;
struct _RsvgVpathDash {
@@ -72,18 +70,6 @@ struct _RsvgVpathDash {
double *dash;
};
-typedef enum {
- RSVG_OPACITY_INHERIT,
- RSVG_OPACITY_SPECIFIED
-} RsvgOpacityKind;
-
-typedef struct {
- RsvgOpacityKind kind;
- guint8 opacity; /* 0..255; only valid if kind == RSVG_OPACITY_SPECIFIED */
-} RsvgOpacitySpec;
-
-/* end libart theft... */
-
struct _RsvgState {
RsvgState *parent;
cairo_matrix_t affine;
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 7dfc25f..a4093a5 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -74,6 +74,12 @@ pub use node::{
rsvg_node_draw_children,
};
+pub use opacity::{
+ OpacityKind,
+ OpacitySpec,
+ rsvg_css_parse_opacity
+};
+
pub use path_builder::{
rsvg_path_builder_add_to_cairo_context
};
diff --git a/rust/src/opacity.rs b/rust/src/opacity.rs
index 51c3bc5..6eaeb7c 100644
--- a/rust/src/opacity.rs
+++ b/rust/src/opacity.rs
@@ -2,18 +2,67 @@
/// https://www.w3.org/TR/SVG/masking.html#OpacityProperty
use ::cssparser::{Parser, Token, NumericValue};
+use ::libc;
use std::str::FromStr;
+use ::glib::translate::*;
+
use parsers::ParseError;
use error::*;
+// Keep this in sync with rsvg-css.h:RsvgOpacityKind
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub enum OpacityKind {
+ Inherit,
+ Specified,
+ ParseError
+}
+
+// Keep this in sync with rsvg-css.h:RsvgOpacitySpec
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub struct OpacitySpec {
+ kind: OpacityKind,
+ opacity: u8
+}
+
+// This is the Rust version of the above
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Opacity {
Inherit,
Specified (f64)
}
+impl From<Result<Opacity, AttributeError>> for OpacitySpec {
+ fn from (result: Result<Opacity, AttributeError>) -> OpacitySpec {
+ match result {
+ Ok (Opacity::Inherit) =>
+ OpacitySpec {
+ kind: OpacityKind::Inherit,
+ opacity: 0
+ },
+
+ Ok (Opacity::Specified (val)) =>
+ OpacitySpec {
+ kind: OpacityKind::Specified,
+ opacity: opacity_to_u8 (val)
+ },
+
+ _ =>
+ OpacitySpec {
+ kind: OpacityKind::ParseError,
+ opacity: 0
+ }
+ }
+ }
+}
+
+fn opacity_to_u8 (val: f64) -> u8 {
+ (val * 255.0 + 0.5).floor () as u8
+}
+
impl FromStr for Opacity {
type Err = AttributeError;
@@ -51,6 +100,13 @@ impl FromStr for Opacity {
}
}
+#[no_mangle]
+pub extern fn rsvg_css_parse_opacity (string: *const libc::c_char) -> OpacitySpec {
+ let s = unsafe { String::from_glib_none (string) };
+
+ OpacitySpec::from (Opacity::from_str (&s))
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -86,4 +142,26 @@ mod tests {
assert! (is_parse_error (&Opacity::from_str ("inherit a million dollars")));
assert! (is_parse_error (&Opacity::from_str ("0.0foo")));
}
+
+ fn parse (s: &str) -> OpacitySpec {
+ rsvg_css_parse_opacity (s.to_glib_none ().0)
+ }
+
+ #[test]
+ fn converts_result_to_opacity_spec () {
+ assert_eq! (parse ("inherit"),
+ OpacitySpec { kind: OpacityKind::Inherit,
+ opacity: 0 });
+
+ assert_eq! (parse ("0"),
+ OpacitySpec { kind: OpacityKind::Specified,
+ opacity: 0 });
+ assert_eq! (parse ("1"),
+ OpacitySpec { kind: OpacityKind::Specified,
+ opacity: 255 });
+
+ assert_eq! (parse ("foo"),
+ OpacitySpec { kind: OpacityKind::ParseError,
+ opacity: 0 });
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]