[librsvg] marker.rs: Fully implement markers in Rust. rsvg-marker.c is gone!
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] marker.rs: Fully implement markers in Rust. rsvg-marker.c is gone!
- Date: Mon, 27 Feb 2017 22:52:21 +0000 (UTC)
commit 6dd4ffd62f9d68799d1b2372a05422440fa0d279
Author: Federico Mena Quintero <federico gnome org>
Date: Mon Feb 27 16:37:59 2017 -0600
marker.rs: Fully implement markers in Rust. rsvg-marker.c is gone!
Makefile.am | 1 -
rsvg-marker.c | 214 ----------------------------------------------------
rsvg-marker.h | 8 --
rust/src/marker.rs | 140 ++++++++++++++++++++++++++++++----
4 files changed, 123 insertions(+), 240 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 6a243eb..1250183 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,7 +37,6 @@ librsvg_@RSVG_API_MAJOR_VERSION@_la_SOURCES = \
rsvg-base-file-util.c \
rsvg-filter.c \
rsvg-filter.h \
- rsvg-marker.c \
rsvg-marker.h \
rsvg-mask.c \
rsvg-mask.h \
diff --git a/rsvg-marker.h b/rsvg-marker.h
index 8a6e392..fd19cf0 100644
--- a/rsvg-marker.h
+++ b/rsvg-marker.h
@@ -30,18 +30,10 @@
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);
-
G_END_DECLS
#endif /* RSVG_MARKER_H */
diff --git a/rust/src/marker.rs b/rust/src/marker.rs
index 8145710..b12a211 100644
--- a/rust/src/marker.rs
+++ b/rust/src/marker.rs
@@ -1,7 +1,11 @@
+extern crate glib;
extern crate libc;
extern crate cairo;
extern crate cairo_sys;
+use self::glib::translate::*;
+use self::cairo::MatrixTrait;
+
use std::cell::Cell;
use std::f64::consts::*;
use std::fmt;
@@ -9,6 +13,7 @@ use std::ptr;
use std::str::FromStr;
use aspect_ratio::*;
+use drawing_ctx;
use drawing_ctx::RsvgDrawingCtx;
use handle::RsvgHandle;
use length::*;
@@ -123,6 +128,88 @@ impl NodeMarker {
// per the spec
RsvgLength::parse ("3", LengthDir::Both)
}
+
+ fn render (&self,
+ c_node: *const RsvgNode,
+ draw_ctx: *const RsvgDrawingCtx,
+ xpos: f64,
+ ypos: f64,
+ computed_angle: f64,
+ line_width: f64) {
+ let marker_width = self.width.get ().normalize (draw_ctx);
+ let marker_height = self.height.get ().normalize (draw_ctx);
+
+ let mut affine = cairo::Matrix::identity ();
+ affine.translate (xpos, ypos);
+
+ affine = cairo::Matrix::multiply (&affine, &drawing_ctx::get_current_state_affine (draw_ctx));
+
+ let rotation: f64;
+
+ match self.orient.get () {
+ MarkerOrient::Auto => { rotation = computed_angle; },
+ MarkerOrient::Degrees (d) => { rotation = d * PI / 180.0; }
+ }
+
+ affine.rotate (rotation);
+
+ if self.units.get () == MarkerUnits::StrokeWidth {
+ affine.scale (line_width, line_width);
+ }
+
+ let vbox = self.vbox.get ();
+
+ if vbox.active {
+ let (_, _, w, h) = self.aspect.get ().compute (vbox.rect.width, vbox.rect.height,
+ 0.0, 0.0,
+ marker_width, marker_height);
+
+ affine.scale (w / vbox.rect.width, h / vbox.rect.height);
+
+ drawing_ctx::push_view_box (draw_ctx, vbox.rect.width, vbox.rect.height);
+ }
+
+ affine.translate (-self.ref_x.get ().normalize (draw_ctx),
+ -self.ref_y.get ().normalize (draw_ctx));
+
+ drawing_ctx::state_push (draw_ctx);
+
+ let state = drawing_ctx::get_current_state (draw_ctx);
+ drawing_ctx::state_reinit (state);
+ drawing_ctx::state_reconstruct (state, c_node);
+
+ drawing_ctx::set_current_state_affine (draw_ctx, affine);
+
+ drawing_ctx::push_discrete_layer (draw_ctx);
+
+ let state = drawing_ctx::get_current_state (draw_ctx);
+
+ if !drawing_ctx::state_is_overflow (state) {
+ if vbox.active {
+ drawing_ctx::add_clipping_rect (draw_ctx,
+ vbox.rect.x,
+ vbox.rect.y,
+ vbox.rect.width,
+ vbox.rect.height);
+ } else {
+ drawing_ctx::add_clipping_rect (draw_ctx,
+ 0.0,
+ 0.0,
+ marker_width,
+ marker_height);
+ }
+ }
+
+ drawing_ctx::node_draw_children (draw_ctx, c_node, -1); // dominate=-1 so it won't reinherit state /
push a layer
+
+ drawing_ctx::pop_discrete_layer (draw_ctx);
+
+ drawing_ctx::state_pop (draw_ctx);
+
+ if vbox.active {
+ drawing_ctx::pop_view_box (draw_ctx);
+ }
+ }
}
impl NodeTrait for NodeMarker {
@@ -485,10 +572,10 @@ fn angle_from_vector (vx: f64, vy: f64) -> f64 {
fn bisect_angles (incoming: f64, outgoing: f64) -> f64 {
let half_delta: f64;
-
+
half_delta = (outgoing - incoming) * 0.5;
- if FRAC_PI_2 < half_delta.abs () {
+ if FRAC_PI_2 < half_delta.abs () {
normalize_angle (incoming + half_delta - PI)
} else {
normalize_angle (incoming + half_delta)
@@ -496,12 +583,6 @@ fn bisect_angles (incoming: f64, outgoing: f64) -> f64 {
}
extern "C" {
- fn rsvg_marker_render (marker_name: *const libc::c_char,
- xpos: f64,
- ypos: f64,
- orient: f64,
- linewidth: f64,
- draw_ctx: *const RsvgDrawingCtx);
fn rsvg_get_normalized_stroke_width (draw_ctx: *const RsvgDrawingCtx) -> f64;
fn rsvg_get_start_marker (draw_ctx: *const RsvgDrawingCtx) -> *const libc::c_char;
@@ -514,10 +595,35 @@ enum SubpathState {
InSubpath
}
+fn render_marker_by_name (draw_ctx: *const RsvgDrawingCtx,
+ marker_name: *const libc::c_char,
+ xpos: f64,
+ ypos: f64,
+ computed_angle: f64,
+ line_width: f64) {
+ if marker_name.is_null () {
+ return;
+ }
+
+ let name = unsafe { String::from_glib_none (marker_name) };
+
+ let c_node = drawing_ctx::acquire_node_of_type (draw_ctx, &name, NodeType::Marker);
+
+ if c_node.is_null () {
+ return;
+ }
+
+ let node: &RsvgNode = unsafe { & *c_node };
+
+ node.with_impl (|marker: &NodeMarker| marker.render (c_node, draw_ctx, xpos, ypos, computed_angle,
line_width));
+
+ drawing_ctx::release_node (draw_ctx, c_node);
+}
+
fn render_marker_at_start_of_segment (segment: &Segment,
marker_name: *const libc::c_char,
orient: f64,
- linewidth: f64,
+ line_width: f64,
draw_ctx: *const RsvgDrawingCtx) {
let xpos: f64;
let ypos: f64;
@@ -534,13 +640,13 @@ fn render_marker_at_start_of_segment (segment: &Segment,
}
}
- unsafe { rsvg_marker_render (marker_name, xpos, ypos, orient, linewidth, draw_ctx); }
+ render_marker_by_name (draw_ctx, marker_name, xpos, ypos, orient, line_width);
}
fn render_marker_at_end_of_segment (segment: &Segment,
marker_name: *const libc::c_char,
orient: f64,
- linewidth: f64,
+ line_width: f64,
draw_ctx: *const RsvgDrawingCtx) {
let xpos: f64;
let ypos: f64;
@@ -557,12 +663,12 @@ fn render_marker_at_end_of_segment (segment: &Segment,
}
}
- unsafe { rsvg_marker_render (marker_name, xpos, ypos, orient, linewidth, draw_ctx); }
+ render_marker_by_name (draw_ctx, marker_name, xpos, ypos, orient, line_width);
}
pub fn render_markers_for_path_builder (builder: &RsvgPathBuilder,
draw_ctx: *const RsvgDrawingCtx) {
-
+
let linewidth: f64 = unsafe { rsvg_get_normalized_stroke_width (draw_ctx) };
if linewidth == 0.0 {
@@ -908,7 +1014,7 @@ mod tests {
/* Sequence of moveto; should generate degenerate points.
*
- * This test is not enabled right now! We create the
+ * This test is not enabled right now! We create the
* path fixtures with Cairo, and Cairo compresses
* sequences of moveto into a single one. So, we can't
* really test this, as we don't get the fixture we want.
@@ -969,17 +1075,17 @@ mod tests {
#[test]
fn curves_with_loops_and_coincident_ends_have_directionality () {
- let (v1x, v1y, v2x, v2y) =
+ let (v1x, v1y, v2x, v2y) =
super::get_segment_directionalities (&curve (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 1.0, 2.0)).unwrap ();
assert_eq! ((2.0, 2.0), (v1x, v1y));
assert_eq! ((-4.0, -4.0), (v2x, v2y));
- let (v1x, v1y, v2x, v2y) =
+ let (v1x, v1y, v2x, v2y) =
super::get_segment_directionalities (&curve (1.0, 2.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0)).unwrap ();
assert_eq! ((2.0, 2.0), (v1x, v1y));
assert_eq! ((-2.0, -2.0), (v2x, v2y));
- let (v1x, v1y, v2x, v2y) =
+ let (v1x, v1y, v2x, v2y) =
super::get_segment_directionalities (&curve (1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 1.0, 2.0)).unwrap ();
assert_eq! ((2.0, 2.0), (v1x, v1y));
assert_eq! ((-2.0, -2.0), (v2x, v2y));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]