[librsvg] image.rs: Move NodeImage over to Rust. Yay!
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] image.rs: Move NodeImage over to Rust. Yay!
- Date: Tue, 26 Sep 2017 00:40:30 +0000 (UTC)
commit 6c66c98e2d529372db180b32d1a5a7199547174e
Author: Federico Mena Quintero <federico gnome org>
Date: Mon Sep 25 19:14:23 2017 -0500
image.rs: Move NodeImage over to Rust. Yay!
Makefile.am | 1 +
rsvg-base.c | 4 +-
rsvg-image.c | 213 -----------------------------------------------------
rsvg-image.h | 55 --------------
rust/src/image.rs | 126 +++++++++++++++++++++++++++++++
rust/src/lib.rs | 5 +
6 files changed, 134 insertions(+), 270 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 7203bcf..3525902 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -79,6 +79,7 @@ RUST_SOURCES = \
rust/src/error.rs \
rust/src/gradient.rs \
rust/src/handle.rs \
+ rust/src/image.rs \
rust/src/length.rs \
rust/src/lib.rs \
rust/src/marker.rs \
diff --git a/rsvg-base.c b/rsvg-base.c
index e6a6192..392344d 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -316,7 +316,7 @@ static const NodeCreator node_creators[] = {
/* "glyph", TRUE, */
/* "glyphRef", TRUE, */
/* "hkern", FALSE, */
- { "image", TRUE, rsvg_new_image },
+ { "image", TRUE, rsvg_node_image_new },
{ "line", TRUE, rsvg_node_line_new },
{ "linearGradient", TRUE, rsvg_node_linear_gradient_new },
{ "marker", TRUE, rsvg_node_marker_new },
@@ -336,7 +336,7 @@ static const NodeCreator node_creators[] = {
{ "stop", TRUE, rsvg_node_stop_new },
/* "style", FALSE, */
{ "subImage", FALSE, rsvg_node_group_new },
- { "subImageRef", FALSE, rsvg_new_image },
+ { "subImageRef", FALSE, rsvg_node_image_new },
{ "svg", TRUE, rsvg_node_svg_new },
{ "switch", TRUE, rsvg_node_switch_new },
{ "symbol", TRUE, rsvg_node_symbol_new },
diff --git a/rust/src/image.rs b/rust/src/image.rs
new file mode 100644
index 0000000..6b415e4
--- /dev/null
+++ b/rust/src/image.rs
@@ -0,0 +1,126 @@
+use libc;
+use cairo;
+use cairo_sys;
+use glib;
+use glib::translate::*;
+use glib_sys;
+use std::cell::{Cell, RefCell};
+use std::ptr;
+
+use drawing_ctx;
+use drawing_ctx::RsvgDrawingCtx;
+
+use aspect_ratio::*;
+use handle::RsvgHandle;
+use length::*;
+use node::*;
+use property_bag;
+use property_bag::RsvgPropertyBag;
+
+struct NodeImage {
+ aspect: Cell<AspectRatio>,
+ x: Cell<RsvgLength>,
+ y: Cell<RsvgLength>,
+ w: Cell<RsvgLength>,
+ h: Cell<RsvgLength>,
+ surface: RefCell<Option<cairo::ImageSurface>>
+}
+
+impl NodeImage {
+ fn new () -> NodeImage {
+ NodeImage {
+ aspect: Cell::new (AspectRatio::default ()),
+ x: Cell::new (RsvgLength::default ()),
+ y: Cell::new (RsvgLength::default ()),
+ w: Cell::new (RsvgLength::default ()),
+ h: Cell::new (RsvgLength::default ()),
+ surface: RefCell::new (None)
+ }
+ }
+}
+
+impl NodeTrait for NodeImage {
+ fn set_atts (&self, _: &RsvgNode, handle: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult
{
+ self.x.set (property_bag::parse_or_default (pbag, "x", LengthDir::Horizontal, None)?);
+ self.y.set (property_bag::parse_or_default (pbag, "y", LengthDir::Vertical, None)?);
+ self.w.set (property_bag::parse_or_default (pbag, "width", LengthDir::Horizontal,
+ Some(RsvgLength::check_nonnegative))?);
+ self.h.set (property_bag::parse_or_default (pbag, "height", LengthDir::Vertical,
+ Some(RsvgLength::check_nonnegative))?);
+ self.aspect.set (property_bag::parse_or_default (pbag, "preserveAspectRatio", (), None)?);
+
+ let mut href = property_bag::lookup (pbag, "xlink:href");
+
+ if href.is_none() {
+ // "path" is used by some older adobe illustrator versions
+ href = property_bag::lookup (pbag, "path");
+ }
+
+ if let Some(href) = href {
+ extern "C" { fn rsvg_cairo_surface_new_from_href
+ (handle: *const RsvgHandle,
+ href: *const libc::c_char,
+ error: *mut *mut glib_sys::GError) -> *mut cairo_sys::cairo_surface_t;
+ }
+
+ let mut error = ptr::null_mut();
+
+ let raw_surface = unsafe { rsvg_cairo_surface_new_from_href (handle,
+ href.to_glib_none().0,
+ &mut error) };
+ if !raw_surface.is_null() {
+ *self.surface.borrow_mut() = Some(unsafe { cairo::ImageSurface::from_raw_full
(raw_surface).unwrap() });
+ } else {
+ let _: glib::Error = unsafe { from_glib_full(error) }; // FIXME: we should note that the
image couldn't be loaded
+ }
+ }
+
+ Ok (())
+ }
+
+ fn draw (&self, node: &RsvgNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
+ if let Some(ref surface) = *self.surface.borrow() {
+ let x = self.x.get().normalize(draw_ctx);
+ let y = self.y.get().normalize(draw_ctx);
+ let w = self.w.get().normalize(draw_ctx);
+ let h = self.h.get().normalize(draw_ctx);
+
+ let state = node.get_state();
+
+ drawing_ctx::state_reinherit_top(draw_ctx, state, dominate);
+ drawing_ctx::push_discrete_layer(draw_ctx);
+
+ let aspect = self.aspect.get();
+
+ if !drawing_ctx::state_is_overflow(state) {
+ match aspect.align {
+ Align::Aligned { align: _,
+ fit: FitMode::Slice } => {
+ drawing_ctx::add_clipping_rect(draw_ctx, x, y, w, h);
+ },
+
+ _ => ()
+ }
+ }
+
+ let (x, y, w, h) = aspect.compute (surface.get_width() as f64,
+ surface.get_height() as f64,
+ x, y, w, h);
+
+ drawing_ctx::render_surface(draw_ctx, &surface, x, y, w, h);
+
+ drawing_ctx::pop_discrete_layer(draw_ctx);
+ }
+ }
+
+ fn get_c_impl (&self) -> *const RsvgCNodeImpl {
+ unreachable! ();
+ }
+}
+
+#[no_mangle]
+pub extern fn rsvg_node_image_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
+ boxed_node_new (NodeType::Image,
+ raw_parent,
+ Box::new (NodeImage::new ()))
+}
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 3bb6dbe..2533e22 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -50,6 +50,10 @@ pub use length::{
rsvg_length_hand_normalize,
};
+pub use image::{
+ rsvg_node_image_new,
+};
+
pub use marker::{
rsvg_node_marker_new,
};
@@ -132,6 +136,7 @@ mod drawing_ctx;
mod error;
mod gradient;
mod handle;
+mod image;
mod length;
mod marker;
mod node;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]