[librsvg] Move NodeStop over to Rust. Yay!



commit 59bec0b08d30bb59976d7f2eb6e4277cdf23fb58
Author: Federico Mena Quintero <federico gnome org>
Date:   Fri Jun 2 09:53:02 2017 -0500

    Move NodeStop over to Rust.  Yay!
    
    This reimplements gradient_add_color_stops_from_node() in Rust based on
    the old C code.

 rsvg-base.c          |    2 +-
 rsvg-cairo-draw.c    |   31 +----------
 rsvg-paint-server.c  |  140 --------------------------------------------------
 rsvg-paint-server.h  |   17 ++----
 rust/src/gradient.rs |   31 ++++++++----
 rust/src/lib.rs      |    2 +-
 rust/src/node.rs     |    4 ++
 rust/src/stop.rs     |    4 +-
 8 files changed, 36 insertions(+), 195 deletions(-)
---
diff --git a/rsvg-base.c b/rsvg-base.c
index 6cc74c7..5205424 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -321,7 +321,7 @@ static const NodeCreator node_creators[] = {
     { "rect",                TRUE,  rsvg_node_rect_new },
     /* "script",             FALSE, */
     /* "set",                FALSE, */
-    { "stop",                TRUE,  rsvg_new_stop },
+    { "stop",                TRUE,  rsvg_node_stop_new },
     /* "style",              FALSE, */
     { "subImage",            FALSE, rsvg_node_group_new },
     { "subImageRef",         FALSE, rsvg_new_image },
diff --git a/rsvg-cairo-draw.c b/rsvg-cairo-draw.c
index 0e2de5e..d240987 100644
--- a/rsvg-cairo-draw.c
+++ b/rsvg-cairo-draw.c
@@ -42,33 +42,6 @@
 #include <pango/pangocairo.h>
 #include <pango/pangofc-fontmap.h>
 
-static gboolean
-add_color_stop_to_gradient (RsvgNode *node, gpointer data)
-{
-    Gradient *gradient = data;
-    RsvgGradientStop *stop;
-
-    if (rsvg_node_get_type (node) != RSVG_NODE_TYPE_STOP)
-        return TRUE; /* just ignore this node */
-
-    stop = rsvg_rust_cnode_get_impl (node);
-
-    if (!stop->is_valid) {
-        /* Don't add any more stops. */
-        return FALSE;
-    }
-
-    gradient_add_color_stop (gradient, stop->offset, stop->rgba);
-
-    return TRUE;
-}
-
-static void
-add_color_stops_to_gradient (Gradient *gradient, RsvgNode *node)
-{
-    rsvg_node_foreach_child (node, add_color_stop_to_gradient, gradient);
-}
-
 static Gradient *
 linear_gradient_to_rust (RsvgNode *node)
 {
@@ -87,7 +60,7 @@ linear_gradient_to_rust (RsvgNode *node)
                                     linear->hasspread ? &linear->spread : NULL,
                                     linear->fallback);
 
-    add_color_stops_to_gradient (gradient, node);
+    gradient_add_color_stops_from_node (gradient, node);
 
     return gradient;
 }
@@ -111,7 +84,7 @@ radial_gradient_to_rust (RsvgNode *node)
                                     radial->hasspread ? &radial->spread : NULL,
                                     radial->fallback);
 
-    add_color_stops_to_gradient (gradient, node);
+    gradient_add_color_stops_from_node (gradient, node);
 
     return gradient;
 }
diff --git a/rsvg-paint-server.c b/rsvg-paint-server.c
index 05ad241..3e94ae2 100644
--- a/rsvg-paint-server.c
+++ b/rsvg-paint-server.c
@@ -210,151 +210,11 @@ rsvg_paint_server_unref (RsvgPaintServer * ps)
 }
 
 static void
-rsvg_stop_set_atts (RsvgNode *node, gpointer impl, RsvgHandle *handle, RsvgPropertyBag *atts)
-{
-    RsvgGradientStop *stop = impl;
-    const char *value;
-    RsvgState *state;
-    RsvgState *inherited_state;
-    int opacity;
-    guint32 color;
-
-    state = rsvg_node_get_state (node);
-
-    if ((value = rsvg_property_bag_lookup (atts, "offset"))) {
-        /* either a number [0,1] or a percentage */
-        RsvgLength length = rsvg_length_parse (value, LENGTH_DIR_BOTH);
-
-        if (length.unit == LENGTH_UNIT_DEFAULT || length.unit == LENGTH_UNIT_PERCENT) {
-            double offset;
-
-            offset = length.length;
-
-            if (offset < 0.0)
-                offset = 0.0;
-            else if (offset > 1.0)
-                offset = 1.0;
-
-            stop->offset = offset;
-            stop->is_valid = TRUE;
-        } else {
-            /* Only default and percent values are allowed */
-            stop->is_valid = FALSE;
-        }
-    }
-    if ((value = rsvg_property_bag_lookup (atts, "style")))
-        rsvg_parse_style (handle, state, value);
-
-    rsvg_parse_style_pairs (state, atts);
-
-    inherited_state = rsvg_state_new ();
-    rsvg_state_reconstruct (inherited_state, node);
-
-    if (state->has_stop_color) {
-        switch (state->stop_color.kind) {
-        case RSVG_CSS_COLOR_SPEC_INHERIT:
-            switch (inherited_state->stop_color.kind) {
-            case RSVG_CSS_COLOR_SPEC_INHERIT:
-                color = 0;
-                break;
-
-            case RSVG_CSS_COLOR_SPEC_CURRENT_COLOR:
-                color = inherited_state->current_color;
-                break;
-
-            case RSVG_CSS_COLOR_SPEC_ARGB:
-                color = inherited_state->stop_color.argb;
-                break;
-
-            case RSVG_CSS_COLOR_PARSE_ERROR:
-                color = 0;
-                break;
-
-            default:
-                g_assert_not_reached ();
-                return;
-            }
-            break;
-
-        case RSVG_CSS_COLOR_SPEC_CURRENT_COLOR:
-            color = inherited_state->current_color;
-            break;
-
-        case RSVG_CSS_COLOR_SPEC_ARGB:
-            color = state->stop_color.argb & 0x00ffffff;
-            break;
-
-        case RSVG_CSS_COLOR_PARSE_ERROR:
-            color = 0;
-            break;
-
-        default:
-            g_assert_not_reached ();
-            return;
-        }
-    } else {
-        color = 0;
-    }
-
-    if (state->has_stop_opacity) {
-        switch (state->stop_opacity.kind) {
-        case RSVG_OPACITY_SPECIFIED:
-            opacity = state->stop_opacity.opacity;
-            break;
-
-        case RSVG_OPACITY_INHERIT:
-            switch (inherited_state->stop_opacity.kind) {
-            case RSVG_OPACITY_SPECIFIED:
-                opacity = inherited_state->stop_opacity.opacity;
-                break;
-
-            case RSVG_OPACITY_INHERIT:
-                opacity = 0xff;
-                break;
-
-            default:
-                g_assert_not_reached ();
-                return;
-            }
-            break;
-
-        default:
-            g_assert_not_reached ();
-            return;
-        }
-    } else {
-        opacity = 0xff;
-    }
-
-    stop->rgba = (color << 8) | opacity;
-
-    rsvg_state_free (inherited_state);
-}
-
-static void
 rsvg_paint_server_draw (RsvgNode *node, gpointer impl, RsvgDrawingCtx *ctx, int dominate)
 {
     /* nothing; paint servers are handled specially */
 }
 
-RsvgNode *
-rsvg_new_stop (const char *element_name, RsvgNode *parent)
-{
-    RsvgGradientStop *stop = g_new0 (RsvgGradientStop, 1);
-
-    stop->offset = 0;
-    stop->rgba = 0xff000000;
-    stop->is_valid = FALSE;
-
-    return rsvg_rust_cnode_new (RSVG_NODE_TYPE_STOP,
-                                parent,
-                                rsvg_state_new (),
-                                stop,
-                                rsvg_stop_set_atts,
-                                rsvg_paint_server_draw,
-                                g_free);
-}
-
 static void
 rsvg_linear_gradient_set_atts (RsvgNode *node, gpointer impl, RsvgHandle *handle, RsvgPropertyBag *atts)
 {
diff --git a/rsvg-paint-server.h b/rsvg-paint-server.h
index dc152e9..7022ed4 100644
--- a/rsvg-paint-server.h
+++ b/rsvg-paint-server.h
@@ -32,8 +32,6 @@
 
 G_BEGIN_DECLS 
 
-typedef struct _RsvgGradientStop RsvgGradientStop;
-typedef struct _RsvgGradientStops RsvgGradientStops;
 typedef struct _RsvgLinearGradient RsvgLinearGradient;
 typedef struct _RsvgRadialGradient RsvgRadialGradient;
 typedef struct _RsvgSolidColor RsvgSolidColor;
@@ -42,12 +40,6 @@ typedef struct _RsvgPaintServer RsvgPaintServer;
 
 typedef struct _RsvgPSCtx RsvgPSCtx;
 
-struct _RsvgGradientStop {
-    double offset;
-    guint32 rgba;
-    gboolean is_valid;
-};
-
 struct _RsvgLinearGradient {
     gboolean obj_bbox;
     cairo_matrix_t affine; /* user space to actual at time of gradient def */
@@ -111,9 +103,8 @@ void gradient_destroy (Gradient *gradient);
 
 /* Implemented in rust/src/gradient.rs */
 G_GNUC_INTERNAL
-void gradient_add_color_stop (Gradient *gradient,
-                              double    offset,
-                              guint32   rgba);
+void gradient_add_color_stops_from_node (Gradient *gradient,
+                                         RsvgNode *node);
 
 /* Implemented in rust/src/gradient.rs */
 G_GNUC_INTERNAL
@@ -179,8 +170,10 @@ G_GNUC_INTERNAL
 RsvgNode *rsvg_new_linear_gradient  (const char *element_name, RsvgNode *parent);
 G_GNUC_INTERNAL
 RsvgNode *rsvg_new_radial_gradient  (const char *element_name, RsvgNode *parent);
+
+/* Implemented in rust/src/stop.rs */
 G_GNUC_INTERNAL
-RsvgNode *rsvg_new_stop                (const char *element_name, RsvgNode *parent);
+RsvgNode *rsvg_node_stop_new (const char *element_name, RsvgNode *parent);
 
 
 G_END_DECLS
diff --git a/rust/src/gradient.rs b/rust/src/gradient.rs
index 071ff67..102dc0f 100644
--- a/rust/src/gradient.rs
+++ b/rust/src/gradient.rs
@@ -6,15 +6,13 @@ extern crate glib;
 
 use self::glib::translate::*;
 
-use length::*;
-
+use bbox::*;
 use drawing_ctx;
 use drawing_ctx::RsvgDrawingCtx;
-use node::RsvgNode;
+use length::*;
+use node::*;
 use paint_server::*;
-
-use bbox::*;
-
+use stop::*;
 use util::*;
 
 use self::cairo::MatrixTrait;
@@ -600,14 +598,27 @@ pub unsafe extern fn gradient_destroy (raw_gradient: *mut Gradient) {
 }
 
 #[no_mangle]
-pub extern fn gradient_add_color_stop (raw_gradient: *mut Gradient,
-                                       offset:       f64,
-                                       rgba:         u32) {
+pub extern fn gradient_add_color_stops_from_node (raw_gradient: *mut Gradient,
+                                                  raw_node:     *const RsvgNode) {
     assert! (!raw_gradient.is_null ());
+    assert! (!raw_node.is_null ());
 
     let gradient: &mut Gradient = unsafe { &mut (*raw_gradient) };
+    let node: &RsvgNode = unsafe { & *raw_node };
+
+    for child in &*node.children.borrow () {
+        if child.get_type () != NodeType::Stop {
+            continue; // just ignore this child; we are only interested in gradient stops
+        }
 
-    gradient.add_color_stop (offset, rgba);
+        if child.get_result ().is_err () {
+            break; // don't add any more stops
+        }
+
+        child.with_impl (|stop: &NodeStop| {
+            gradient.add_color_stop (stop.get_offset (), stop.get_rgba ());
+        });
+    }
 }
 
 #[no_mangle]
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index e789e13..a2adbb8 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -42,7 +42,7 @@ pub use gradient::{
     gradient_linear_new,
     gradient_radial_new,
     gradient_destroy,
-    gradient_add_color_stop,
+    gradient_add_color_stops_from_node,
     gradient_resolve_fallbacks_and_set_pattern
 };
 
diff --git a/rust/src/node.rs b/rust/src/node.rs
index 3f3c63d..8d7a5fc 100644
--- a/rust/src/node.rs
+++ b/rust/src/node.rs
@@ -192,6 +192,10 @@ impl Node {
         *self.result.borrow_mut () = Err (error);
     }
 
+    pub fn get_result (&self) -> NodeResult {
+        self.result.borrow ().clone ()
+    }
+
     pub fn get_c_impl (&self) -> *const RsvgCNodeImpl {
         self.node_impl.get_c_impl ()
     }
diff --git a/rust/src/stop.rs b/rust/src/stop.rs
index 26763af..22420f0 100644
--- a/rust/src/stop.rs
+++ b/rust/src/stop.rs
@@ -16,7 +16,7 @@ use property_bag;
 use property_bag::*;
 use state::RsvgState;
 
-struct NodeStop {
+pub struct NodeStop {
     offset: Cell<f64>,
     rgba: Cell<u32>
 }
@@ -148,7 +148,7 @@ impl NodeTrait for NodeStop {
         Ok (())
     }
 
-    fn draw (&self, node: &RsvgNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
+    fn draw (&self, _: &RsvgNode, _: *const RsvgDrawingCtx, _: i32) {
         // nothing; paint servers are handled specially
     }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]