[librsvg] shapes.rs: NodeCircle fully implemented in Rust!
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] shapes.rs: NodeCircle fully implemented in Rust!
- Date: Tue, 21 Feb 2017 00:08:22 +0000 (UTC)
commit e36a432082d2e6c281891c9b5832c30ac3f7089d
Author: Federico Mena Quintero <federico gnome org>
Date: Mon Feb 20 18:07:04 2017 -0600
shapes.rs: NodeCircle fully implemented in Rust!
rsvg-base.c | 2 +-
rsvg-shapes.c | 94 ----------------------------------------------------
rsvg-shapes.h | 6 ++-
rust/src/lib.rs | 1 +
rust/src/shapes.rs | 83 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 89 insertions(+), 97 deletions(-)
---
diff --git a/rsvg-base.c b/rsvg-base.c
index 9671d63..df3119b 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -260,7 +260,7 @@ static const NodeCreator node_creators[] = {
/* "animateColor", FALSE, */
/* "animateMotion", FALSE, */
/* "animateTransform", FALSE, */
- { "circle", TRUE, rsvg_new_circle },
+ { "circle", TRUE, rsvg_node_circle_new },
{ "clipPath", TRUE, rsvg_new_clip_path },
/* "color-profile", FALSE, */
{ "conicalGradient", TRUE, rsvg_new_radial_gradient },
diff --git a/rsvg-shapes.c b/rsvg-shapes.c
index 5ba3f59..0a74f58 100644
--- a/rsvg-shapes.c
+++ b/rsvg-shapes.c
@@ -167,100 +167,6 @@ rsvg_new_polyline (const char *element_name, RsvgNode *parent)
return rsvg_new_any_poly (RSVG_NODE_TYPE_POLYLINE, parent);
}
-typedef struct _RsvgNodeCircle RsvgNodeCircle;
-
-struct _RsvgNodeCircle {
- RsvgLength cx, cy, r;
-};
-
-static void
-rsvg_node_circle_set_atts (RsvgNode *node, gpointer impl, RsvgHandle *handle, RsvgPropertyBag *atts)
-{
- RsvgNodeCircle *circle = impl;
- const char *value;
-
- if ((value = rsvg_property_bag_lookup (atts, "cx")))
- circle->cx = rsvg_length_parse (value, LENGTH_DIR_HORIZONTAL);
- if ((value = rsvg_property_bag_lookup (atts, "cy")))
- circle->cy = rsvg_length_parse (value, LENGTH_DIR_VERTICAL);
- if ((value = rsvg_property_bag_lookup (atts, "r")))
- circle->r = rsvg_length_parse (value, LENGTH_DIR_BOTH);
-}
-
-static void
-rsvg_node_circle_draw (RsvgNode *node, gpointer impl, RsvgDrawingCtx *ctx, int dominate)
-{
- RsvgNodeCircle *circle = impl;
- double cx, cy, r;
- RsvgPathBuilder *builder;
-
- cx = rsvg_length_normalize (&circle->cx, ctx);
- cy = rsvg_length_normalize (&circle->cy, ctx);
- r = rsvg_length_normalize (&circle->r, ctx);
-
- if (r <= 0)
- return;
-
- /* approximate a circle using 4 bezier curves */
-
- builder = rsvg_path_builder_new ();
-
- rsvg_path_builder_move_to (builder, cx + r, cy);
-
- rsvg_path_builder_curve_to (builder,
- cx + r, cy + r * RSVG_ARC_MAGIC,
- cx + r * RSVG_ARC_MAGIC, cy + r,
- cx, cy + r);
-
- rsvg_path_builder_curve_to (builder,
- cx - r * RSVG_ARC_MAGIC, cy + r,
- cx - r, cy + r * RSVG_ARC_MAGIC,
- cx - r, cy);
-
- rsvg_path_builder_curve_to (builder,
- cx - r, cy - r * RSVG_ARC_MAGIC,
- cx - r * RSVG_ARC_MAGIC, cy - r,
- cx, cy - r);
-
- rsvg_path_builder_curve_to (builder,
- cx + r * RSVG_ARC_MAGIC, cy - r,
- cx + r, cy - r * RSVG_ARC_MAGIC,
- cx + r, cy);
-
- rsvg_path_builder_close_path (builder);
-
- rsvg_state_reinherit_top (ctx, rsvg_node_get_state (node), dominate);
-
- rsvg_render_path_builder (ctx, builder);
-
- rsvg_path_builder_destroy (builder);
-}
-
-static void
-rsvg_node_circle_free (gpointer impl)
-{
- RsvgNodeCircle *circle = impl;
-
- g_free (circle);
-}
-
-RsvgNode *
-rsvg_new_circle (const char *element_name, RsvgNode *parent)
-{
- RsvgNodeCircle *circle;
-
- circle = g_new0 (RsvgNodeCircle, 1);
- circle->cx = circle->cy = circle->r = rsvg_length_parse ("0", LENGTH_DIR_BOTH);
-
- return rsvg_rust_cnode_new (RSVG_NODE_TYPE_CIRCLE,
- parent,
- rsvg_state_new (),
- circle,
- rsvg_node_circle_set_atts,
- rsvg_node_circle_draw,
- rsvg_node_circle_free);
-}
-
typedef struct _RsvgNodeEllipse RsvgNodeEllipse;
struct _RsvgNodeEllipse {
diff --git a/rsvg-shapes.h b/rsvg-shapes.h
index b7cef55..3d21ee4 100644
--- a/rsvg-shapes.h
+++ b/rsvg-shapes.h
@@ -48,13 +48,15 @@ RsvgNode *rsvg_node_line_new (const char *element_name, RsvgNode *parent);
G_GNUC_INTERNAL
RsvgNode *rsvg_node_rect_new (const char *element_name, RsvgNode *parent);
+/* Implemented in rust/src/shapes.rs */
+G_GNUC_INTERNAL
+RsvgNode *rsvg_node_circle_new (const char *element_name, RsvgNode *parent);
+
G_GNUC_INTERNAL
RsvgNode *rsvg_new_polygon (const char *element_name, RsvgNode *parent);
G_GNUC_INTERNAL
RsvgNode *rsvg_new_polyline (const char *element_name, RsvgNode *parent);
G_GNUC_INTERNAL
-RsvgNode *rsvg_new_circle (const char *element_name, RsvgNode *parent);
-G_GNUC_INTERNAL
RsvgNode *rsvg_new_ellipse (const char *element_name, RsvgNode *parent);
G_END_DECLS
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 1ceb665..e0047da 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -79,6 +79,7 @@ pub use pattern::{
};
pub use shapes::{
+ rsvg_node_circle_new,
rsvg_node_line_new,
rsvg_node_path_new,
rsvg_node_rect_new,
diff --git a/rust/src/shapes.rs b/rust/src/shapes.rs
index 830a81e..b91da3d 100644
--- a/rust/src/shapes.rs
+++ b/rust/src/shapes.rs
@@ -346,6 +346,81 @@ impl NodeTrait for NodeRect {
}
}
+/***** NodeCircle *****/
+
+struct NodeCircle {
+ cx: Cell<RsvgLength>,
+ cy: Cell<RsvgLength>,
+ r: Cell<RsvgLength>
+}
+
+impl NodeCircle {
+ fn new () -> NodeCircle {
+ NodeCircle {
+ cx: Cell::new (RsvgLength::default ()),
+ cy: Cell::new (RsvgLength::default ()),
+ r: Cell::new (RsvgLength::default ()),
+ }
+ }
+}
+
+impl NodeTrait for NodeCircle {
+ fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) {
+ self.cx.set (property_bag::lookup (pbag, "cx").map_or (RsvgLength::default (),
+ |v| RsvgLength::parse (&v,
LengthDir::Horizontal)));
+
+ self.cy.set (property_bag::lookup (pbag, "cy").map_or (RsvgLength::default (),
+ |v| RsvgLength::parse (&v,
LengthDir::Vertical)));
+
+ self.r.set (property_bag::lookup (pbag, "r").map_or (RsvgLength::default (),
+ |v| RsvgLength::parse (&v, LengthDir::Both)));
+ }
+
+ fn draw (&self, node: &RsvgNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
+ let cx = self.cx.get ().normalize (draw_ctx);
+ let cy = self.cy.get ().normalize (draw_ctx);
+ let r = self.r.get ().normalize (draw_ctx);
+
+ // Per the spec, r must be nonnegative
+ if r <= 0.0 {
+ return;
+ }
+
+ // 4/3 * (1-cos 45°)/sin 45° = 4/3 * sqrt(2) - 1
+ let arc_magic: f64 = 0.5522847498;
+
+ // approximate a circle using 4 Bézier curves
+
+ let mut builder = RsvgPathBuilder::new ();
+
+ builder.move_to (cx + r, cy);
+
+ builder.curve_to (cx + r, cy + r * arc_magic,
+ cx + r * arc_magic, cy + r,
+ cx, cy + r);
+
+ builder.curve_to (cx - r * arc_magic, cy + r,
+ cx - r, cy + r * arc_magic,
+ cx - r, cy);
+
+ builder.curve_to (cx - r, cy - r * arc_magic,
+ cx - r * arc_magic, cy - r,
+ cx, cy - r);
+
+ builder.curve_to (cx + r * arc_magic, cy - r,
+ cx + r, cy - r * arc_magic,
+ cx + r, cy);
+
+ builder.close_path ();
+
+ render_path_builder (&builder, draw_ctx, node.get_state (), dominate, false);
+ }
+
+ fn get_c_impl (&self) -> *const RsvgCNodeImpl {
+ ptr::null ()
+ }
+}
+
/***** C Prototypes *****/
#[no_mangle]
@@ -371,3 +446,11 @@ pub extern fn rsvg_node_rect_new (_: *const libc::c_char, raw_parent: *const Rsv
drawing_ctx::state_new (),
Box::new (NodeRect::new ()))))
}
+
+#[no_mangle]
+pub extern fn rsvg_node_circle_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
+ box_node (Rc::new (Node::new (NodeType::Circle,
+ parent_ptr_to_weak (raw_parent),
+ drawing_ctx::state_new (),
+ Box::new (NodeCircle::new ()))))
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]