[librsvg] rsvg_handle_render_cairo_sub(): Port to Rust
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] rsvg_handle_render_cairo_sub(): Port to Rust
- Date: Thu, 20 Dec 2018 22:50:58 +0000 (UTC)
commit b930b1a77c400390ae3a189aaf67aa861fe5f067
Author: Federico Mena Quintero <federico gnome org>
Date: Thu Dec 20 16:17:23 2018 -0600
rsvg_handle_render_cairo_sub(): Port to Rust
This adds a couple of new error cases to RenderingError.
librsvg/rsvg-handle.c | 46 +++--------------------
rsvg_internals/src/defs.rs | 2 +-
rsvg_internals/src/error.rs | 10 +++++
rsvg_internals/src/handle.rs | 89 ++++++++++++++++++++++++++++++++++++++++----
rsvg_internals/src/lib.rs | 1 +
5 files changed, 100 insertions(+), 48 deletions(-)
---
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index 6242f2d0..c79cda0e 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -178,7 +178,10 @@ extern gboolean rsvg_handle_rust_get_geometry_sub (RsvgHandle *handle,
RsvgRectangle *out_ink_rect,
RsvgRectangle *out_logical_rect,
const char *id);
-extern gboolean rsvg_handle_rust_has_sub(RsvgHandle *handle, const char *id);
+extern gboolean rsvg_handle_rust_has_sub (RsvgHandle *handle, const char *id);
+extern gboolean rsvg_handle_rust_render_cairo_sub (RsvgHandle *handle,
+ cairo_t *cr,
+ const char *id);
/* Implemented in rust/src/node.rs */
/* Call this as node = rsvg_node_unref (node); Then node will be NULL and you don't own it anymore! */
@@ -1024,51 +1027,14 @@ is_loaded (RsvgHandle *handle)
gboolean
rsvg_handle_render_cairo_sub (RsvgHandle * handle, cairo_t * cr, const char *id)
{
- RsvgDimensionData dimensions;
- RsvgDrawingCtx *draw;
- RsvgNode *drawsub = NULL;
- cairo_status_t status;
- gboolean res;
-
g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
+ g_return_val_if_fail (cr != NULL, FALSE);
if (!is_loaded (handle)) {
return FALSE;
}
- status = cairo_status (cr);
-
- if (status != CAIRO_STATUS_SUCCESS) {
- g_warning ("cannot render on a cairo_t with a failure status (status=%d, %s)",
- (int) status,
- cairo_status_to_string (status));
- return FALSE;
- }
-
- if (id && *id)
- drawsub = rsvg_handle_defs_lookup (handle, id);
-
- if (drawsub == NULL && id != NULL) {
- g_warning ("element id=\"%s\" does not exist", id);
- /* todo: there's no way to signal that @id doesn't exist */
- return FALSE;
- }
-
- rsvg_handle_get_dimensions (handle, &dimensions);
- if (dimensions.width == 0 || dimensions.height == 0)
- return FALSE;
-
- cairo_save (cr);
-
- draw = rsvg_handle_create_drawing_ctx_for_node (handle, cr, &dimensions, drawsub,
handle->priv->is_testing);
- res = rsvg_drawing_ctx_draw_node_from_stack (draw);
-
- rsvg_drawing_ctx_free (draw);
- drawsub = rsvg_node_unref (drawsub);
-
- cairo_restore (cr);
-
- return res;
+ return rsvg_handle_rust_render_cairo_sub (handle, cr, id);
}
/**
diff --git a/rsvg_internals/src/defs.rs b/rsvg_internals/src/defs.rs
index 373e8e22..91591297 100644
--- a/rsvg_internals/src/defs.rs
+++ b/rsvg_internals/src/defs.rs
@@ -122,7 +122,7 @@ impl fmt::Display for Fragment {
}
/// Errors returned when creating an `Href` out of a string
-#[derive(Debug, PartialEq)]
+#[derive(Debug, Clone, PartialEq)]
pub enum HrefError {
/// The href is an invalid URI or has empty components.
ParseError,
diff --git a/rsvg_internals/src/error.rs b/rsvg_internals/src/error.rs
index 5d6856cc..5c82c96f 100644
--- a/rsvg_internals/src/error.rs
+++ b/rsvg_internals/src/error.rs
@@ -10,6 +10,7 @@ use glib_sys;
use libc;
use attributes::Attribute;
+use defs::HrefError;
use parsers::ParseError;
/// A simple error which refers to an attribute's value
@@ -90,11 +91,20 @@ impl<'a> From<BasicParseError<'a>> for ValueErrorKind {
}
}
+#[derive(Clone)]
+pub enum DefsLookupErrorKind {
+ HrefError(HrefError),
+ CannotLookupExternalReferences,
+ NotFound,
+}
+
#[derive(Clone)]
pub enum RenderingError {
Cairo(cairo::Status),
CircularReference,
InstancingLimit,
+ InvalidId(DefsLookupErrorKind),
+ SvgHasNoSize,
}
impl From<cairo::Status> for RenderingError {
diff --git a/rsvg_internals/src/handle.rs b/rsvg_internals/src/handle.rs
index 5b7c47f6..e9bc584a 100644
--- a/rsvg_internals/src/handle.rs
+++ b/rsvg_internals/src/handle.rs
@@ -16,10 +16,10 @@ use url::Url;
use allowed_url::AllowedUrl;
use css::{self, CssStyles};
-use defs::{Fragment, Href, HrefError};
+use defs::{Fragment, Href};
use dpi::Dpi;
use drawing_ctx::{DrawingCtx, RsvgRectangle};
-use error::{set_gerror, LoadingError};
+use error::{set_gerror, DefsLookupErrorKind, LoadingError, RenderingError};
use io;
use load::LoadContext;
use node::{box_node, Node, RsvgNode};
@@ -228,6 +228,7 @@ impl Handle {
draw_ctx
}
+ // FIXME: return proper errors
fn get_node_geometry(
&mut self,
handle: *mut RsvgHandle,
@@ -278,6 +279,7 @@ impl Handle {
Ok((ink_rect, logical_rect))
}
+ // FIXME: return proper errors
fn get_geometry_sub(
&mut self,
handle: *mut RsvgHandle,
@@ -365,14 +367,67 @@ impl Handle {
}
fn has_sub(&mut self, handle: *const RsvgHandle, name: &str) -> bool {
+ // FIXME: return a proper error; only NotFound should map to false
self.defs_lookup(handle, name).is_ok()
}
-}
-enum DefsLookupErrorKind {
- HrefError(HrefError),
- CannotLookupExternalReferences,
- NotFound,
+ fn render_cairo_sub(
+ &mut self,
+ handle: *mut RsvgHandle,
+ cr: &cairo::Context,
+ id: Option<&str>,
+ ) -> Result<(), RenderingError> {
+ let status = cr.status();
+ if status != Status::Success {
+ let msg = format!(
+ "cannot render on a cairo_t with a failure status (status={:?})",
+ status,
+ );
+
+ rsvg_g_warning(&msg);
+ return Err(RenderingError::Cairo(status));
+ }
+
+ let node = if let Some(id) = id {
+ Some(
+ self.defs_lookup(handle, id)
+ .map_err(|e| RenderingError::InvalidId(e))?,
+ )
+ } else {
+ None
+ };
+
+ let mut dimensions = unsafe { mem::zeroed() };
+
+ unsafe {
+ rsvg_handle_get_dimensions(handle, &mut dimensions);
+ }
+
+ if dimensions.width == 0 || dimensions.height == 0 {
+ return Err(RenderingError::SvgHasNoSize);
+ }
+
+ cr.save();
+
+ let mut draw_ctx = self.create_drawing_ctx_for_node(
+ handle,
+ cr,
+ &dimensions,
+ node.as_ref(),
+ is_testing(handle),
+ );
+
+ let svg_ref = self.svg.borrow();
+ let svg = svg_ref.as_ref().unwrap();
+
+ let root = svg.tree.root();
+
+ let res = draw_ctx.draw_node_from_stack(&root.get_cascaded_values(), &root, false);
+
+ cr.restore();
+
+ res
+ }
}
// Keep these in sync with rsvg.h:RsvgHandleFlags
@@ -878,3 +933,23 @@ pub unsafe extern "C" fn rsvg_handle_rust_has_sub(
rhandle.has_sub(handle, &id).to_glib()
}
}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_rust_render_cairo_sub(
+ handle: *mut RsvgHandle,
+ cr: *mut cairo_sys::cairo_t,
+ id: *const libc::c_char,
+) -> glib_sys::gboolean {
+ let rhandle = get_rust_handle(handle);
+ let cr = from_glib_none(cr);
+ let id: Option<String> = from_glib_none(id);
+
+ match rhandle.render_cairo_sub(handle, &cr, id.as_ref().map(String::as_str)) {
+ Ok(()) => true.to_glib(),
+
+ Err(_) => {
+ // FIXME: return a proper error code to the public API
+ false.to_glib()
+ }
+ }
+}
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index e55b35a7..f3416f63 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -51,6 +51,7 @@ pub use handle::{
rsvg_handle_rust_has_sub,
rsvg_handle_rust_new,
rsvg_handle_rust_read_stream_sync,
+ rsvg_handle_rust_render_cairo_sub,
rsvg_handle_rust_set_base_url,
rsvg_handle_rust_set_dpi_x,
rsvg_handle_rust_set_dpi_y,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]