[librsvg] rsvg_handle_get_node_geometry(): Port to Rust



commit ef31c69cf593ecdf83ca6b8bfc22372e8de5bebd
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Dec 18 18:57:47 2018 -0600

    rsvg_handle_get_node_geometry(): Port to Rust
    
    Also added `impl From<cairo::Rectangle> for RsvgRectangle`.

 librsvg/rsvg-handle.c             | 52 +++++++---------------
 rsvg_internals/src/drawing_ctx.rs | 51 ++++-----------------
 rsvg_internals/src/handle.rs      | 94 ++++++++++++++++++++++++++++++++++++++-
 rsvg_internals/src/lib.rs         |  7 +--
 4 files changed, 118 insertions(+), 86 deletions(-)
---
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index d9fd3f16..a252f396 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -176,6 +176,11 @@ extern RsvgDrawingCtx *rsvg_handle_create_drawing_ctx_for_node(RsvgHandle *handl
                                                                RsvgDimensionData *dimensions,
                                                                RsvgNode *node,
                                                                gboolean is_testing);
+extern gboolean rsvg_handle_get_node_geometry(RsvgHandle *handle,
+                                              RsvgNode *node,
+                                              RsvgRectangle *ink_rect,
+                                              RsvgRectangle *logical_rect);
+
 
 /* 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! */
@@ -188,9 +193,6 @@ gboolean rsvg_node_svg_get_size (RsvgNode *node, double dpi_x, double dpi_y, int
 /* Defined in rsvg_internals/src/drawing_ctx.rs */
 extern void rsvg_drawing_ctx_free (RsvgDrawingCtx *draw_ctx);
 extern gboolean rsvg_drawing_ctx_draw_node_from_stack (RsvgDrawingCtx *ctx) G_GNUC_WARN_UNUSED_RESULT;
-extern void rsvg_drawing_ctx_get_geometry (RsvgDrawingCtx *ctx,
-                                           RsvgRectangle *ink_rect,
-                                           RsvgRectangle *logical_rect);
 
 struct RsvgHandlePrivate {
     RsvgSizeFunc size_func;
@@ -1126,39 +1128,6 @@ rsvg_handle_get_dimensions (RsvgHandle * handle, RsvgDimensionData * dimension_d
     }
 }
 
-static gboolean
-get_node_geometry(RsvgHandle *handle, RsvgNode *node, RsvgRectangle *ink_rect, RsvgRectangle *logical_rect)
-{
-    RsvgDimensionData dimensions;
-    cairo_surface_t *target;
-    cairo_t *cr;
-    RsvgDrawingCtx *draw;
-    gboolean res = FALSE;
-
-    g_assert (node != NULL);
-
-    rsvg_handle_get_dimensions (handle, &dimensions);
-    if (dimensions.width == 0 || dimensions.height == 0)
-        return res;
-
-    target = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 1, 1);
-    cr = cairo_create (target);
-
-    draw = rsvg_handle_create_drawing_ctx_for_node (handle, cr, &dimensions, node, handle->priv->is_testing);
-
-    /* FIXME: expose this as a RenderingError in the public API */
-    res = rsvg_drawing_ctx_draw_node_from_stack (draw);
-    if (res) {
-        rsvg_drawing_ctx_get_geometry (draw, ink_rect, logical_rect);
-    }
-
-    rsvg_drawing_ctx_free (draw);
-    cairo_destroy (cr);
-    cairo_surface_destroy (target);
-
-    return res;
-}
-
 /**
  * rsvg_handle_get_dimensions_sub:
  * @handle: A #RsvgHandle
@@ -1256,7 +1225,7 @@ rsvg_handle_get_geometry_sub (RsvgHandle * handle, RsvgRectangle * ink_rect, Rsv
                                        &root_width, &root_height);
 
     if (id || !has_size) {
-        res = get_node_geometry (handle, node ? node : root, &ink_r, &logical_r);
+        res = rsvg_handle_get_node_geometry (handle, node ? node : root, &ink_r, &logical_r);
         if (!res) {
             goto out;
         }
@@ -1607,6 +1576,15 @@ rsvg_handle_internal_set_testing (RsvgHandle *handle, gboolean testing)
     rsvg_handle_update_font_map_for_testing (handle);
 }
 
+G_GNUC_INTERNAL
+gboolean rsvg_handle_get_is_testing (RsvgHandle *handle);
+
+gboolean
+rsvg_handle_get_is_testing (RsvgHandle *handle)
+{
+    return handle->priv->is_testing;
+}
+
 /* This one is defined in the C code, because the prototype has varargs
  * and we can't handle those from Rust :(
  */
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index 2229c58a..b8a436af 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -1073,7 +1073,7 @@ pub extern "C" fn rsvg_drawing_ctx_draw_node_from_stack(
     }
 }
 
-#[derive(Clone, Copy, Debug, PartialEq)]
+#[derive(Default, Clone, Copy, Debug, PartialEq)]
 #[repr(C)]
 pub struct RsvgRectangle {
     pub x: f64,
@@ -1082,48 +1082,13 @@ pub struct RsvgRectangle {
     pub height: f64,
 }
 
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_drawing_ctx_get_geometry(
-    raw_draw_ctx: *const DrawingCtx,
-    ink_rect: *mut RsvgRectangle,
-    logical_rect: *mut RsvgRectangle,
-) {
-    assert!(!raw_draw_ctx.is_null());
-    let draw_ctx = &*raw_draw_ctx;
-
-    assert!(!ink_rect.is_null());
-    assert!(!logical_rect.is_null());
-
-    let ink_rect: &mut RsvgRectangle = &mut *ink_rect;
-    let logical_rect: &mut RsvgRectangle = &mut *logical_rect;
-
-    match draw_ctx.get_bbox().ink_rect {
-        Some(r) => {
-            ink_rect.x = r.x;
-            ink_rect.y = r.y;
-            ink_rect.width = r.width;
-            ink_rect.height = r.height;
-        }
-        None => {
-            ink_rect.x = 0.0;
-            ink_rect.y = 0.0;
-            ink_rect.width = 0.0;
-            ink_rect.height = 0.0;
-        }
-    }
-
-    match draw_ctx.get_bbox().rect {
-        Some(r) => {
-            logical_rect.x = r.x;
-            logical_rect.y = r.y;
-            logical_rect.width = r.width;
-            logical_rect.height = r.height;
-        }
-        None => {
-            logical_rect.x = 0.0;
-            logical_rect.y = 0.0;
-            logical_rect.width = 0.0;
-            logical_rect.height = 0.0;
+impl From<cairo::Rectangle> for RsvgRectangle {
+    fn from(r: cairo::Rectangle) -> RsvgRectangle {
+        RsvgRectangle {
+            x: r.x,
+            y: r.y,
+            width: r.width,
+            height: r.height,
         }
     }
 }
diff --git a/rsvg_internals/src/handle.rs b/rsvg_internals/src/handle.rs
index f5200190..8b769ced 100644
--- a/rsvg_internals/src/handle.rs
+++ b/rsvg_internals/src/handle.rs
@@ -1,4 +1,5 @@
 use std::cell::{Cell, Ref, RefCell};
+use std::mem;
 use std::ptr;
 use std::rc::Rc;
 use std::slice;
@@ -17,7 +18,7 @@ use allowed_url::AllowedUrl;
 use css::{self, CssStyles};
 use defs::{Fragment, Href};
 use dpi::Dpi;
-use drawing_ctx::DrawingCtx;
+use drawing_ctx::{DrawingCtx, RsvgRectangle};
 use error::{set_gerror, LoadingError};
 use io;
 use load::LoadContext;
@@ -225,6 +226,56 @@ impl Handle {
 
         draw_ctx
     }
+
+    fn get_node_geometry(
+        &mut self,
+        handle: *mut RsvgHandle,
+        node: &RsvgNode,
+    ) -> Result<(RsvgRectangle, RsvgRectangle), ()> {
+        let mut dimensions = unsafe { mem::zeroed() };
+
+        unsafe {
+            rsvg_handle_get_dimensions(handle, &mut dimensions);
+        }
+
+        if dimensions.width == 0 || dimensions.height == 0 {
+            return Err(());
+        }
+
+        let target = ImageSurface::create(cairo::Format::Rgb24, 1, 1).map_err(|_| ())?;
+
+        let cr = cairo::Context::new(&target);
+
+        let mut draw_ctx = self.create_drawing_ctx_for_node(
+            handle,
+            &cr,
+            &dimensions,
+            Some(node),
+            is_testing(handle),
+        );
+
+        let svg_ref = self.svg.borrow();
+        let svg = svg_ref.as_ref().unwrap();
+
+        let root = svg.tree.root();
+
+        draw_ctx
+            .draw_node_from_stack(&root.get_cascaded_values(), &root, false)
+            .map_err(|_| ())?;
+
+        let bbox = draw_ctx.get_bbox();
+
+        let ink_rect = bbox
+            .ink_rect
+            .map(|r| RsvgRectangle::from(r))
+            .unwrap_or_else(|| RsvgRectangle::default());
+        let logical_rect = bbox
+            .rect
+            .map(|r| RsvgRectangle::from(r))
+            .unwrap_or_else(|| RsvgRectangle::default());
+
+        Ok((ink_rect, logical_rect))
+    }
 }
 
 // Keep these in sync with rsvg.h:RsvgHandleFlags
@@ -269,6 +320,14 @@ extern "C" {
     ) -> *mut RsvgHandle;
 
     fn rsvg_handle_get_rust(handle: *const RsvgHandle) -> *mut Handle;
+
+    fn rsvg_handle_get_is_testing(handle: *const RsvgHandle) -> glib_sys::gboolean;
+
+    fn rsvg_handle_get_dimensions(handle: *mut RsvgHandle, dimensions: *mut RsvgDimensionData);
+}
+
+fn is_testing(handle: *const RsvgHandle) -> bool {
+    unsafe { from_glib(rsvg_handle_get_is_testing(handle)) }
 }
 
 pub fn lookup_node(handle: *const RsvgHandle, fragment: &Fragment) -> Option<Rc<Node>> {
@@ -731,3 +790,36 @@ pub unsafe extern "C" fn rsvg_handle_create_drawing_ctx_for_node(
 
     Box::into_raw(Box::new(draw_ctx))
 }
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_get_node_geometry(
+    handle: *mut RsvgHandle,
+    node: *const RsvgNode,
+    out_ink_rect: *mut RsvgRectangle,
+    out_logical_rect: *mut RsvgRectangle,
+) -> glib_sys::gboolean {
+    let rhandle = get_rust_handle(handle);
+
+    assert!(!node.is_null());
+    let node = &*node;
+
+    assert!(!out_ink_rect.is_null());
+    assert!(!out_logical_rect.is_null());
+
+    let out_ink_rect = &mut *out_ink_rect;
+    let out_logical_rect = &mut *out_logical_rect;
+
+    match rhandle.get_node_geometry(handle, node) {
+        Ok((ink_rect, logical_rect)) => {
+            *out_ink_rect = ink_rect;
+            *out_logical_rect = logical_rect;
+            true.to_glib()
+        }
+
+        Err(()) => {
+            *out_ink_rect = mem::zeroed();
+            *out_logical_rect = mem::zeroed();
+            false.to_glib()
+        }
+    }
+}
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index ad809e8a..21d6277c 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -35,15 +35,12 @@ extern crate lazy_static;
 
 pub use color::{rsvg_css_parse_color, ColorKind, ColorSpec};
 
-pub use drawing_ctx::{
-    rsvg_drawing_ctx_draw_node_from_stack,
-    rsvg_drawing_ctx_free,
-    rsvg_drawing_ctx_get_geometry,
-};
+pub use drawing_ctx::{rsvg_drawing_ctx_draw_node_from_stack, rsvg_drawing_ctx_free};
 
 pub use handle::{
     rsvg_handle_create_drawing_ctx_for_node,
     rsvg_handle_defs_lookup,
+    rsvg_handle_get_node_geometry,
     rsvg_handle_rust_close,
     rsvg_handle_rust_free,
     rsvg_handle_rust_get_base_gfile,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]