[librsvg: 7/14] handle: move the size_func in the rust handle



commit 845b41c4d212079d8db1ec7bca4cba06cc36ab38
Author: Paolo Borelli <pborelli gnome org>
Date:   Sat Jan 5 14:36:57 2019 +0100

    handle: move the size_func in the rust handle
    
    This requires creating and intermediate closure struct

 librsvg/rsvg-handle.c        | 74 +++++++++++++++++++++++++++++++-------------
 rsvg_internals/src/handle.rs | 56 +++++++++++++++++++++++++++++++++
 rsvg_internals/src/lib.rs    |  2 ++
 3 files changed, 111 insertions(+), 21 deletions(-)
---
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index ba962389..4710c462 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -171,11 +171,53 @@ extern gboolean rsvg_handle_rust_render_cairo_sub (RsvgHandle *handle,
                                                    const char *id);
 extern GdkPixbuf *rsvg_handle_rust_get_pixbuf_sub (RsvgHandle *handle, const char *id);
 
-struct RsvgHandlePrivate {
-    RsvgSizeFunc size_func;
-    gpointer user_data;
-    GDestroyNotify user_data_destroy;
+typedef struct {
+    RsvgSizeFunc func;
+    gpointer data;
+    GDestroyNotify data_destroy;
+} RsvgSizeClosure;
+
+static RsvgSizeClosure *
+rsvg_size_closure_new (RsvgSizeFunc func, gpointer data, GDestroyNotify data_destroy)
+{
+    RsvgSizeClosure *closure;
+
+    closure = g_new0(RsvgSizeClosure, 1);
+    closure->func = func;
+    closure->data = data;
+    closure->data_destroy = data_destroy;
+
+    return closure;
+}
+
+G_GNUC_INTERNAL
+void rsvg_size_closure_free (RsvgSizeClosure *closure);
+
+void
+rsvg_size_closure_free (RsvgSizeClosure *closure)
+{
+    if (closure && closure->data && closure->data_destroy) {
+        (*closure->data_destroy) (closure->data);
+    }
+
+    g_free (closure);
+}
 
+G_GNUC_INTERNAL
+void rsvg_size_closure_call (RsvgSizeClosure *closure, int *width, int *height);
+
+void
+rsvg_size_closure_call (RsvgSizeClosure *closure, int *width, int *height)
+{
+    if (closure && closure->func) {
+        (*closure->func) (width, height, closure->data);
+    }
+}
+
+extern void rsvg_handle_rust_set_size_closure (RsvgHandleRust *raw_handle, RsvgSizeClosure *closure);
+extern void rsvg_handle_rust_call_size_closure (RsvgHandleRust *raw_handle, int *width, int *height);
+
+struct RsvgHandlePrivate {
     gchar *base_uri; // Keep this here; since rsvg_handle_get_base_uri() returns a const char *
 
     gboolean in_loop;          /* see get_dimension() */
@@ -217,11 +259,6 @@ rsvg_handle_dispose (GObject *instance)
 {
     RsvgHandle *self = (RsvgHandle *) instance;
 
-    if (self->priv->user_data_destroy) {
-        (*self->priv->user_data_destroy) (self->priv->user_data);
-        self->priv->user_data_destroy = NULL;
-    }
-
     g_clear_pointer (&self->priv->base_uri, g_free);
     g_clear_pointer (&self->priv->rust_handle, rsvg_handle_rust_free);
 
@@ -1048,9 +1085,8 @@ rsvg_handle_get_dimensions_sub (RsvgHandle * handle, RsvgDimensionData * dimensi
     dimension_data->em = dimension_data->width;
     dimension_data->ex = dimension_data->height;
 
-    if (handle->priv->size_func)
-        (*handle->priv->size_func) (&dimension_data->width, &dimension_data->height,
-                                    handle->priv->user_data);
+    rsvg_handle_rust_call_size_closure (handle->priv->rust_handle, &dimension_data->width, 
&dimension_data->height);
+
     return TRUE;
 }
 
@@ -1123,8 +1159,7 @@ rsvg_handle_get_position_sub (RsvgHandle * handle, RsvgPositionData * position_d
     width = ink_r.width;
     height = ink_r.height;
 
-    if (handle->priv->size_func)
-        (*handle->priv->size_func) (&width, &height, handle->priv->user_data);
+    rsvg_handle_rust_call_size_closure (handle->priv->rust_handle, &width, &height);
 
     return TRUE;
 }
@@ -1286,16 +1321,13 @@ rsvg_handle_set_dpi_x_y (RsvgHandle * handle, double dpi_x, double dpi_y)
 void
 rsvg_handle_set_size_callback (RsvgHandle * handle,
                                RsvgSizeFunc size_func,
-                               gpointer user_data, GDestroyNotify user_data_destroy)
+                               gpointer user_data,
+                               GDestroyNotify user_data_destroy)
 {
     g_return_if_fail (RSVG_IS_HANDLE (handle));
 
-    if (handle->priv->user_data_destroy)
-        (*handle->priv->user_data_destroy) (handle->priv->user_data);
-
-    handle->priv->size_func = size_func;
-    handle->priv->user_data = user_data;
-    handle->priv->user_data_destroy = user_data_destroy;
+    rsvg_handle_rust_set_size_closure (handle->priv->rust_handle,
+                                       rsvg_size_closure_new (size_func, user_data, user_data_destroy));
 }
 
 /**
diff --git a/rsvg_internals/src/handle.rs b/rsvg_internals/src/handle.rs
index f247dc2c..fe5f2e4e 100644
--- a/rsvg_internals/src/handle.rs
+++ b/rsvg_internals/src/handle.rs
@@ -42,6 +42,23 @@ pub struct RsvgHandle {
     _private: [u8; 0],
 }
 
+// A *const RsvgSizeClosure is just an opaque pointer we get from C
+#[repr(C)]
+pub struct RsvgSizeClosure {
+    _private: [u8; 0],
+}
+
+#[allow(improper_ctypes)]
+extern "C" {
+    fn rsvg_size_closure_free(closure: *mut RsvgSizeClosure);
+
+    fn rsvg_size_closure_call(
+        closure: *const RsvgSizeClosure,
+        width: *mut libc::c_int,
+        height: *mut libc::c_int,
+    );
+}
+
 // Keep in sync with rsvg.h:RsvgDimensionData
 #[repr(C)]
 pub struct RsvgDimensionData {
@@ -79,6 +96,7 @@ pub struct Handle {
     load_options: Cell<LoadOptions>,
     load_state: Cell<LoadState>,
     load: RefCell<Option<LoadContext>>,
+    size_closure: *mut RsvgSizeClosure,
     is_testing: Cell<bool>,
 }
 
@@ -91,6 +109,7 @@ impl Handle {
             load_options: Cell::new(LoadOptions::default()),
             load_state: Cell::new(LoadState::Start),
             load: RefCell::new(None),
+            size_closure: ptr::null_mut(),
             is_testing: Cell::new(false),
         }
     }
@@ -462,6 +481,16 @@ impl Handle {
     }
 }
 
+impl Drop for Handle {
+    fn drop(&mut self) {
+        if !self.size_closure.is_null() {
+            unsafe {
+                rsvg_size_closure_free(self.size_closure);
+            }
+        }
+    }
+}
+
 // Keep these in sync with rsvg.h:RsvgHandleFlags
 const RSVG_HANDLE_FLAG_UNLIMITED: u32 = 1 << 0;
 const RSVG_HANDLE_FLAG_KEEP_IMAGE_DATA: u32 = 1 << 1;
@@ -796,6 +825,33 @@ pub unsafe extern "C" fn rsvg_handle_rust_set_flags(raw_handle: *const Handle, f
     rhandle.load_options.set(LoadOptions::from_flags(flags));
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_rust_set_size_closure(
+    raw_handle: *mut Handle,
+    closure: *mut RsvgSizeClosure,
+) {
+    let rhandle = &mut *raw_handle;
+
+    if !rhandle.size_closure.is_null() {
+        rsvg_size_closure_free(rhandle.size_closure);
+    }
+
+    rhandle.size_closure = closure;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_rust_call_size_closure(
+    raw_handle: *const Handle,
+    width: *mut libc::c_int,
+    height: *mut libc::c_int,
+) {
+    let rhandle = &*raw_handle;
+
+    if !rhandle.size_closure.is_null() {
+        rsvg_size_closure_call(rhandle.size_closure, width, height);
+    }
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn rsvg_handle_rust_set_testing(
     raw_handle: *const Handle,
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 60303056..ea5d3db8 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -37,6 +37,7 @@ extern crate lazy_static;
 pub use color::{rsvg_css_parse_color, ColorKind, ColorSpec};
 
 pub use handle::{
+    rsvg_handle_rust_call_size_closure,
     rsvg_handle_rust_close,
     rsvg_handle_rust_free,
     rsvg_handle_rust_get_base_gfile,
@@ -55,6 +56,7 @@ pub use handle::{
     rsvg_handle_rust_set_dpi_x,
     rsvg_handle_rust_set_dpi_y,
     rsvg_handle_rust_set_flags,
+    rsvg_handle_rust_set_size_closure,
     rsvg_handle_rust_set_testing,
     rsvg_handle_rust_write,
 };


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