[librsvg] Port StrokeLinejoin parsing to Rust
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] Port StrokeLinejoin parsing to Rust
- Date: Sun, 25 Mar 2018 00:03:56 +0000 (UTC)
commit 156d4791589b4447d7917991da98f4a9fc31219e
Author: Federico Mena Quintero <federico gnome org>
Date: Wed Mar 21 08:28:17 2018 -0600
Port StrokeLinejoin parsing to Rust
This is an experiment in porting individual property parsers to Rust.
The idea is to drain rsvg_parse_style_pair() gradually.
Right now the C code has a lot of verbosity to handle "inherit" values
and to overlook parsing errors. We will remove all that in the Rust
version.
librsvg/rsvg-styles.c | 31 ++++++++++++++-------
librsvg/rsvg-styles.h | 18 +++++++++++--
rsvg_internals/src/draw.rs | 15 +++++++++--
rsvg_internals/src/lib.rs | 2 ++
rsvg_internals/src/state.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 118 insertions(+), 14 deletions(-)
---
diff --git a/librsvg/rsvg-styles.c b/librsvg/rsvg-styles.c
index cc337bae..453b0a30 100644
--- a/librsvg/rsvg-styles.c
+++ b/librsvg/rsvg-styles.c
@@ -524,6 +524,10 @@ typedef enum {
PAIR_SOURCE_PRESENTATION_ATTRIBUTE
} PairSource;
+/* Defined in rsvg_internals/src/state.rs */
+extern StrokeLinejoin rsvg_stroke_linejoin_get_default(void);
+extern StrokeLinejoinResult rsvg_stroke_linejoin_parse(const char *s);
+
/* Parse a CSS2 style argument, setting the SVG context attributes. */
static void
rsvg_parse_style_pair (RsvgState *state,
@@ -884,15 +888,22 @@ rsvg_parse_style_pair (RsvgState *state,
case RSVG_ATTRIBUTE_STROKE_LINEJOIN:
{
- state->has_join = TRUE;
- if (g_str_equal (value, "miter"))
- state->join = CAIRO_LINE_JOIN_MITER;
- else if (g_str_equal (value, "round"))
- state->join = CAIRO_LINE_JOIN_ROUND;
- else if (g_str_equal (value, "bevel"))
- state->join = CAIRO_LINE_JOIN_BEVEL;
- else
- g_warning (_("unknown line join style %s\n"), value);
+ StrokeLinejoinResult result = rsvg_stroke_linejoin_parse(value);
+
+ if (result.valid) {
+ if (result.linejoin == STROKE_LINEJOIN_INHERIT) {
+ /* FIXME: handle INHERIT */
+ state->has_join = FALSE;
+ state->join = rsvg_stroke_linejoin_get_default ();
+ } else {
+ state->has_join = TRUE;
+ state->join = result.linejoin;
+ }
+ } else {
+ /* FIXME: do error handling */
+ state->has_join = FALSE;
+ state->join = rsvg_stroke_linejoin_get_default ();
+ }
}
break;
@@ -1882,7 +1893,7 @@ rsvg_state_get_line_cap (RsvgState *state)
return state->cap;
}
-cairo_line_join_t
+StrokeLinejoin
rsvg_state_get_line_join (RsvgState *state)
{
return state->join;
diff --git a/librsvg/rsvg-styles.h b/librsvg/rsvg-styles.h
index fe4ad1ca..1642970e 100644
--- a/librsvg/rsvg-styles.h
+++ b/librsvg/rsvg-styles.h
@@ -61,6 +61,20 @@ typedef enum {
RSVG_ENABLE_BACKGROUND_NEW
} RsvgEnableBackgroundType;
+/* Keep in sync with rsvg_internals/src/state.rs:StrokeLinejoin */
+typedef enum {
+ STROKE_LINEJOIN_MITER,
+ STROKE_LINEJOIN_ROUND,
+ STROKE_LINEJOIN_BEVEL,
+ STROKE_LINEJOIN_INHERIT
+} StrokeLinejoin;
+
+/* Keep in sync with rsvg_internals/src/state.rs:StrokeLinejoinResult */
+typedef struct {
+ gboolean valid;
+ StrokeLinejoin linejoin;
+} StrokeLinejoinResult;
+
/* Opaque; defined in rsvg_internals/src/length.rs */
typedef struct RsvgStrokeDasharray RsvgStrokeDasharray;
@@ -99,7 +113,7 @@ struct _RsvgState {
cairo_line_cap_t cap;
gboolean has_cap;
- cairo_line_join_t join;
+ StrokeLinejoin join;
gboolean has_join;
RsvgLength font_size;
@@ -248,7 +262,7 @@ G_GNUC_INTERNAL
cairo_line_cap_t rsvg_state_get_line_cap (RsvgState *state);
G_GNUC_INTERNAL
-cairo_line_join_t rsvg_state_get_line_join (RsvgState *state);
+StrokeLinejoin rsvg_state_get_line_join (RsvgState *state);
G_GNUC_INTERNAL
gboolean rsvg_state_get_cond_true (RsvgState *state);
diff --git a/rsvg_internals/src/draw.rs b/rsvg_internals/src/draw.rs
index 5e74b144..cfc94164 100644
--- a/rsvg_internals/src/draw.rs
+++ b/rsvg_internals/src/draw.rs
@@ -11,7 +11,7 @@ use float_eq_cairo::ApproxEqCairo;
use length::StrokeDasharray;
use paint_server;
use path_builder::RsvgPathBuilder;
-use state::{self, RsvgState};
+use state::{self, RsvgState, StrokeLinejoin};
use text;
pub fn draw_path_builder(draw_ctx: *mut RsvgDrawingCtx, builder: &RsvgPathBuilder, clipping: bool) {
@@ -88,11 +88,22 @@ fn stroke_and_fill(cr: &cairo::Context, draw_ctx: *mut RsvgDrawingCtx) {
cr.new_path();
}
+impl From<StrokeLinejoin> for cairo::LineJoin {
+ fn from(j: StrokeLinejoin) -> cairo::LineJoin {
+ match j {
+ StrokeLinejoin::Miter => cairo::LineJoin::Miter,
+ StrokeLinejoin::Round => cairo::LineJoin::Round,
+ StrokeLinejoin::Bevel => cairo::LineJoin::Bevel,
+ StrokeLinejoin::Inherit => unreachable!(),
+ }
+ }
+}
+
fn setup_cr_for_stroke(cr: &cairo::Context, draw_ctx: *mut RsvgDrawingCtx, state: *mut RsvgState) {
cr.set_line_width(state::get_stroke_width(state).normalize(draw_ctx));
cr.set_miter_limit(state::get_miter_limit(state));
cr.set_line_cap(state::get_line_cap(state));
- cr.set_line_join(state::get_line_join(state));
+ cr.set_line_join(cairo::LineJoin::from(state::get_line_join(state)));
let dash = state::get_stroke_dasharray(state);
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index be3d6a1d..0128416a 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -124,6 +124,8 @@ pub use shapes::{
pub use space::rsvg_xml_space_normalize;
+pub use state::{rsvg_stroke_linejoin_get_default, rsvg_stroke_linejoin_parse};
+
pub use stop::rsvg_node_stop_new;
pub use structure::{
diff --git a/rsvg_internals/src/state.rs b/rsvg_internals/src/state.rs
index 919f630a..4832ad17 100644
--- a/rsvg_internals/src/state.rs
+++ b/rsvg_internals/src/state.rs
@@ -11,6 +11,8 @@ use length::{RsvgLength, StrokeDasharray};
use node::RsvgNode;
use opacity::{Opacity, OpacitySpec};
use paint_server::PaintServer;
+use parsers::Parse;
+use util::utf8_cstr;
pub enum RsvgState {}
@@ -290,3 +292,67 @@ pub fn get_fill_opacity(state: *const RsvgState) -> u8 {
pub fn get_fill_rule(state: *const RsvgState) -> cairo::FillRule {
unsafe { rsvg_state_get_fill_rule(state) }
}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub enum StrokeLinejoin {
+ Miter,
+ Round,
+ Bevel,
+ Inherit,
+}
+
+#[repr(C)]
+pub struct StrokeLinejoinResult {
+ valid: glib_sys::gboolean,
+ linejoin: StrokeLinejoin,
+}
+
+impl Default for StrokeLinejoin {
+ fn default() -> StrokeLinejoin {
+ StrokeLinejoin::Miter
+ }
+}
+
+impl Parse for StrokeLinejoin {
+ type Data = ();
+ type Err = ();
+
+ fn parse(s: &str, _: Self::Data) -> Result<StrokeLinejoin, ()> {
+ match s.trim() {
+ "miter" => Ok(StrokeLinejoin::Miter),
+ "round" => Ok(StrokeLinejoin::Round),
+ "bevel" => Ok(StrokeLinejoin::Bevel),
+ "inherit" => Ok(StrokeLinejoin::Inherit),
+ _ => Err(()),
+ }
+ }
+}
+
+impl From<Result<StrokeLinejoin, ()>> for StrokeLinejoinResult {
+ fn from(v: Result<StrokeLinejoin, ()>) -> StrokeLinejoinResult {
+ match v {
+ Ok(j) => StrokeLinejoinResult {
+ valid: true.to_glib(),
+ linejoin: j,
+ },
+
+ Err(()) => StrokeLinejoinResult {
+ valid: false.to_glib(),
+ linejoin: StrokeLinejoin::default(),
+ },
+ }
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn rsvg_stroke_linejoin_get_default() -> StrokeLinejoin {
+ StrokeLinejoin::default()
+}
+
+#[no_mangle]
+pub extern "C" fn rsvg_stroke_linejoin_parse(s: *const libc::c_char) -> StrokeLinejoinResult {
+ let s = unsafe { utf8_cstr(s) };
+
+ StrokeLinejoinResult::from(StrokeLinejoin::parse(s, ()))
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]