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.
parent ba4c3a96
......@@ -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 \
......
......@@ -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)
{
......
......@@ -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);
......
......@@ -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);
......
......@@ -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;
......
......@@ -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
};
......
......@@ -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 });
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment