Move NodeStop over to Rust. Yay!

This reimplements gradient_add_color_stops_from_node() in Rust based on
the old C code.
parent 660d55a5
......@@ -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 },
......
......@@ -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;
}
......
......@@ -209,152 +209,12 @@ 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)
{
......
......@@ -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
......
......@@ -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]
......
......@@ -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
};
......
......@@ -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 ()
}
......
......@@ -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
}
......
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