[librsvg] Unfinished: Move the rest of rsvg-marker.c to Rust
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] Unfinished: Move the rest of rsvg-marker.c to Rust
- Date: Mon, 27 Feb 2017 22:51:56 +0000 (UTC)
commit fc90f896b813d711964ab289940f574ee5ecf44f
Author: Federico Mena Quintero <federico gnome org>
Date: Mon Feb 27 11:15:17 2017 -0600
Unfinished: Move the rest of rsvg-marker.c to Rust
rsvg-base.c | 2 +-
rsvg-marker.c | 4 +-
rsvg-marker.h | 6 ++
rust/src/marker.rs | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 179 insertions(+), 4 deletions(-)
---
diff --git a/rsvg-base.c b/rsvg-base.c
index 6fb33d3..8d8d9d3 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -307,7 +307,7 @@ static const NodeCreator node_creators[] = {
{ "image", TRUE, rsvg_new_image },
{ "line", TRUE, rsvg_node_line_new },
{ "linearGradient", TRUE, rsvg_new_linear_gradient },
- { "marker", TRUE, rsvg_new_marker },
+ { "marker", TRUE, rsvg_node_marker_new },
{ "mask", TRUE, rsvg_new_mask },
/* "metadata", FALSE, */
/* "missing-glyph", TRUE, */
diff --git a/rsvg-marker.c b/rsvg-marker.c
index 66e7ef7..9747d09 100644
--- a/rsvg-marker.c
+++ b/rsvg-marker.c
@@ -39,7 +39,7 @@
#include <string.h>
#include <math.h>
#include <errno.h>
-
+#if 0
typedef struct _RsvgMarker RsvgMarker;
struct _RsvgMarker {
@@ -111,7 +111,7 @@ rsvg_new_marker (const char *element_name, RsvgNode *parent)
rsvg_node_marker_draw,
g_free);
}
-
+#endif
static gboolean
draw_child (RsvgNode *node, gpointer data)
{
diff --git a/rsvg-marker.h b/rsvg-marker.h
index 1571235..8a6e392 100644
--- a/rsvg-marker.h
+++ b/rsvg-marker.h
@@ -30,8 +30,14 @@
G_BEGIN_DECLS
+#if 0
G_GNUC_INTERNAL
RsvgNode *rsvg_new_marker (const char *element_name, RsvgNode *node);
+#endif
+
+/* Implemented in rust/src/marker.rs */
+G_GNUC_INTERNAL
+RsvgNode *rsvg_node_marker_new (const char *element_name, RsvgNode *parent);
G_GNUC_INTERNAL
void rsvg_marker_render (const char * marker_name, gdouble xpos, gdouble ypos, gdouble orient, gdouble
linewidth, RsvgDrawingCtx * ctx);
diff --git a/rust/src/marker.rs b/rust/src/marker.rs
index d3ea3a3..8145710 100644
--- a/rust/src/marker.rs
+++ b/rust/src/marker.rs
@@ -2,10 +2,171 @@ extern crate libc;
extern crate cairo;
extern crate cairo_sys;
+use std::cell::Cell;
use std::f64::consts::*;
-use path_builder::*;
+use std::fmt;
+use std::ptr;
+use std::str::FromStr;
+
+use aspect_ratio::*;
use drawing_ctx::RsvgDrawingCtx;
+use handle::RsvgHandle;
+use length::*;
+use node::*;
+use path_builder::*;
+use parsers;
+use property_bag;
+use property_bag::*;
use util::*;
+use viewbox::*;
+
+// markerUnits attribute: https://www.w3.org/TR/SVG/painting.html#MarkerElement
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+enum MarkerUnits {
+ UserSpaceOnUse,
+ StrokeWidth
+}
+
+impl Default for MarkerUnits {
+ fn default () -> MarkerUnits {
+ MarkerUnits::StrokeWidth
+ }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+struct MarkerUnitsParseError;
+
+impl fmt::Display for MarkerUnitsParseError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ "string must be \"userSpaceOnUse\" or \"strokeWidth\"".fmt (f)
+ }
+}
+
+impl FromStr for MarkerUnits {
+ type Err = MarkerUnitsParseError;
+
+ fn from_str (s: &str) -> Result <MarkerUnits, MarkerUnitsParseError> {
+ match s {
+ "userSpaceOnUse" => Ok (MarkerUnits::UserSpaceOnUse),
+ "strokeWidth" => Ok (MarkerUnits::StrokeWidth),
+ _ => Err (MarkerUnitsParseError)
+ }
+ }
+}
+
+// orient attribute: https://www.w3.org/TR/SVG/painting.html#MarkerElement
+
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+enum MarkerOrient {
+ Auto,
+ Degrees (f64)
+}
+
+impl Default for MarkerOrient {
+ fn default () -> MarkerOrient {
+ MarkerOrient::Degrees (0.0)
+ }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+struct MarkerOrientParseError;
+
+impl fmt::Display for MarkerOrientParseError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ "string must be \"auto\" or a CSS angle".fmt (f)
+ }
+}
+
+impl FromStr for MarkerOrient {
+ type Err = MarkerOrientParseError;
+
+ fn from_str (s: &str) -> Result <MarkerOrient, MarkerOrientParseError> {
+ match s {
+ "auto" => Ok (MarkerOrient::Auto),
+ _ => parsers::angle_degrees (s).map (
+ |degrees| MarkerOrient::Degrees (degrees) ).map_err (
+ |_| MarkerOrientParseError)
+ }
+ }
+}
+
+// NodeMarker
+
+struct NodeMarker {
+ units: Cell<MarkerUnits>,
+ ref_x: Cell<RsvgLength>,
+ ref_y: Cell<RsvgLength>,
+ width: Cell<RsvgLength>,
+ height: Cell<RsvgLength>,
+ orient: Cell<MarkerOrient>,
+ aspect: Cell<AspectRatio>,
+ vbox: Cell<RsvgViewBox>
+}
+
+impl NodeMarker {
+ fn new () -> NodeMarker {
+ NodeMarker {
+ units: Cell::new (MarkerUnits::default ()),
+ ref_x: Cell::new (RsvgLength::default ()),
+ ref_y: Cell::new (RsvgLength::default ()),
+ width: Cell::new (NodeMarker::get_default_size ()),
+ height: Cell::new (NodeMarker::get_default_size ()),
+ orient: Cell::new (MarkerOrient::default ()),
+ aspect: Cell::new (AspectRatio::default ()),
+ vbox: Cell::new (RsvgViewBox::default ())
+ }
+ }
+
+ fn get_default_size () -> RsvgLength {
+ // per the spec
+ RsvgLength::parse ("3", LengthDir::Both)
+ }
+}
+
+impl NodeTrait for NodeMarker {
+ fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) {
+ self.units.set (property_bag::lookup (pbag, "markerUnits").map_or (MarkerUnits::default (),
+ |v| MarkerUnits::from_str
(&v).unwrap_or (MarkerUnits::default ())));
+
+ self.ref_x.set (property_bag::lookup (pbag, "refX").map_or (RsvgLength::default (),
+ |v| RsvgLength::parse (&v,
LengthDir::Horizontal)));
+ self.ref_y.set (property_bag::lookup (pbag, "refY").map_or (RsvgLength::default (),
+ |v| RsvgLength::parse (&v,
LengthDir::Vertical)));
+
+ self.width.set (property_bag::lookup (pbag, "markerWidth").map_or (NodeMarker::get_default_size (),
+ |v| RsvgLength::parse (&v,
LengthDir::Horizontal)));
+ self.height.set (property_bag::lookup (pbag, "markerHeight").map_or (NodeMarker::get_default_size (),
+ |v| RsvgLength::parse (&v,
LengthDir::Vertical)));
+
+ self.orient.set (property_bag::lookup (pbag, "orient").map_or (MarkerOrient::default (),
+ |v| MarkerOrient::from_str
(&v).unwrap_or (MarkerOrient::default ())));
+
+ self.aspect.set (property_bag::lookup (pbag, "preserveAspectRatio").map_or (AspectRatio::default (),
+ |v|
AspectRatio::from_str (&v).unwrap_or (AspectRatio::default ())));
+
+ self.vbox.set (property_bag::lookup (pbag, "viewBox").map_or (RsvgViewBox::default (),
+ |v| RsvgViewBox::from_str
(&v).unwrap_or (RsvgViewBox::default ())));
+ }
+
+ fn draw (&self, _: &RsvgNode, _: *const RsvgDrawingCtx, _: i32) {
+ // nothing; markers are drawn by their referencing shapes
+ }
+
+ fn get_c_impl (&self) -> *const RsvgCNodeImpl {
+ ptr::null ()
+ }
+}
+
+#[no_mangle]
+pub extern fn rsvg_node_marker_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
+ boxed_node_new (NodeType::Marker,
+ raw_parent,
+ Box::new (NodeMarker::new ()))
+}
+
+// Machinery to figure out marker orientations
#[derive(Debug, PartialEq)]
pub enum Segment {
@@ -854,4 +1015,12 @@ mod tests {
assert_eq! ((40.0, 30.0), (v1x, v1y));
assert_eq! ((40.0, 30.0), (v2x, v2y));
}
+
+ #[test]
+ fn parses_marker_units () {
+ assert_eq! (MarkerUnits::from_str ("foo"), Err (MarkerUnitsParseError));
+
+ assert_eq! (MarkerUnits::from_str ("userSpaceOnUse"), Ok (MarkerUnits::UserSpaceOnUse));
+ assert_eq! (MarkerUnits::from_str ("strokeWidth"), Ok (MarkerUnits::StrokeWidth));
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]