[librsvg: 3/5] c_api: move C api functions in the c_api module



commit d01f75ed310b0a7b8d62fc7de65465357f20f535
Author: Paolo Borelli <pborelli gnome org>
Date:   Sun Mar 3 14:13:38 2019 +0100

    c_api: move C api functions in the c_api module
    
    Move all extern C handle functions to c_api. While at it, also
    rename them from rsvg_handle_rust to rsvg_rust_handle which is
    consistent with the other entry points exposed by c_api.

 librsvg/rsvg-handle.c              | 105 ++++---
 rsvg_internals/src/c_api.rs        | 529 +++++++++++++++++++++++++++++++-
 rsvg_internals/src/handle.rs       | 601 +++----------------------------------
 rsvg_internals/src/lib.rs          |  67 ++---
 rsvg_internals/src/pixbuf_utils.rs |   6 +-
 5 files changed, 654 insertions(+), 654 deletions(-)
---
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index c1d4d976..65964670 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -279,60 +279,59 @@
 typedef struct RsvgXmlState RsvgXmlState;
 
 /* Implemented in rsvg_internals/src/handle.rs */
-extern double rsvg_handle_rust_get_dpi_x (RsvgHandle *raw_handle);
-extern double rsvg_handle_rust_get_dpi_y (RsvgHandle *raw_handle);
-extern void rsvg_handle_rust_set_dpi_x (RsvgHandle *raw_handle, double dpi_x);
-extern void rsvg_handle_rust_set_dpi_y (RsvgHandle *raw_handle, double dpi_y);
-extern void rsvg_handle_rust_set_base_url (RsvgHandle *raw_handle, const char *uri);
-extern void rsvg_handle_rust_set_base_gfile (RsvgHandle *raw_handle, GFile *file);
-extern const char *rsvg_handle_rust_get_base_url (RsvgHandle *raw_handle);
-extern GFile *rsvg_handle_rust_get_base_gfile (RsvgHandle *raw_handle);
-extern guint rsvg_handle_rust_get_flags (RsvgHandle *raw_handle);
-extern void rsvg_handle_rust_set_flags (RsvgHandle *raw_handle, guint flags);
-extern guint rsvg_handle_rust_set_testing (RsvgHandle *raw_handle, gboolean testing);
-extern gboolean rsvg_handle_rust_read_stream_sync (RsvgHandle *handle,
+extern double rsvg_rust_handle_get_dpi_x (RsvgHandle *raw_handle);
+extern double rsvg_rust_handle_get_dpi_y (RsvgHandle *raw_handle);
+extern void rsvg_rust_handle_set_dpi_x (RsvgHandle *raw_handle, double dpi_x);
+extern void rsvg_rust_handle_set_dpi_y (RsvgHandle *raw_handle, double dpi_y);
+extern void rsvg_rust_handle_set_base_url (RsvgHandle *raw_handle, const char *uri);
+extern void rsvg_rust_handle_set_base_gfile (RsvgHandle *raw_handle, GFile *file);
+extern const char *rsvg_rust_handle_get_base_url (RsvgHandle *raw_handle);
+extern guint rsvg_rust_handle_get_flags (RsvgHandle *raw_handle);
+extern void rsvg_rust_handle_set_flags (RsvgHandle *raw_handle, guint flags);
+extern guint rsvg_rust_handle_set_testing (RsvgHandle *raw_handle, gboolean testing);
+extern gboolean rsvg_rust_handle_read_stream_sync (RsvgHandle *handle,
                                                    GInputStream *stream,
                                                    GCancellable *cancellable,
                                                    GError **error);
-extern void rsvg_handle_rust_write (RsvgHandle *handle, const guchar *buf, gsize count);
-extern gboolean rsvg_handle_rust_close (RsvgHandle *handle, GError **error);
-extern gboolean rsvg_handle_rust_get_geometry_sub (RsvgHandle *handle,
+extern void rsvg_rust_handle_write (RsvgHandle *handle, const guchar *buf, gsize count);
+extern gboolean rsvg_rust_handle_close (RsvgHandle *handle, GError **error);
+extern gboolean rsvg_rust_handle_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_render_cairo_sub (RsvgHandle *handle,
+extern gboolean rsvg_rust_handle_has_sub (RsvgHandle *handle, const char *id);
+extern gboolean rsvg_rust_handle_render_cairo_sub (RsvgHandle *handle,
                                                    cairo_t *cr,
                                                    const char *id);
-extern GdkPixbuf *rsvg_handle_rust_get_pixbuf_sub (RsvgHandle *handle, const char *id);
-extern void rsvg_handle_rust_get_dimensions (RsvgHandle *handle,
+extern GdkPixbuf *rsvg_rust_handle_get_pixbuf_sub (RsvgHandle *handle, const char *id);
+extern void rsvg_rust_handle_get_dimensions (RsvgHandle *handle,
                                              RsvgDimensionData *dimension_data);
-extern gboolean rsvg_handle_rust_get_dimensions_sub (RsvgHandle *handle,
+extern gboolean rsvg_rust_handle_get_dimensions_sub (RsvgHandle *handle,
                                                      RsvgDimensionData *dimension_data,
                                                      const char *id);
-extern gboolean rsvg_handle_rust_get_position_sub (RsvgHandle *handle,
+extern gboolean rsvg_rust_handle_get_position_sub (RsvgHandle *handle,
                                                    RsvgPositionData *dimension_data,
                                                    const char *id);
-extern void rsvg_handle_rust_set_size_callback (RsvgHandle *raw_handle,
+extern void rsvg_rust_handle_set_size_callback (RsvgHandle *raw_handle,
                                                 RsvgSizeFunc size_func,
                                                 gpointer user_data,
                                                 GDestroyNotify destroy_notify);
-extern RsvgHandle *rsvg_handle_rust_new_with_flags (RsvgHandleFlags flags);
-extern RsvgHandle *rsvg_handle_rust_new_from_file (const char *filename,
+extern RsvgHandle *rsvg_rust_handle_new_with_flags (RsvgHandleFlags flags);
+extern RsvgHandle *rsvg_rust_handle_new_from_file (const char *filename,
                                                    GError **error);
-extern RsvgHandle *rsvg_handle_rust_new_from_gfile_sync (GFile *file,
+extern RsvgHandle *rsvg_rust_handle_new_from_gfile_sync (GFile *file,
                                                          RsvgHandleFlags flags,
                                                          GCancellable *cancellable,
                                                          GError **error);
-extern RsvgHandle *rsvg_handle_rust_new_from_stream_sync (GInputStream *input_stream,
+extern RsvgHandle *rsvg_rust_handle_new_from_stream_sync (GInputStream *input_stream,
                                                           GFile *base_file,
                                                           RsvgHandleFlags flags,
                                                           GCancellable *cancellable,
                                                           GError **error);
-extern RsvgHandle *rsvg_handle_rust_new_from_data (const guint8 *data,
+extern RsvgHandle *rsvg_rust_handle_new_from_data (const guint8 *data,
                                                    gsize data_len,
                                                    GError **error);
-extern void rsvg_handle_rust_get_intrinsic_dimensions (RsvgHandle *handle,
+extern void rsvg_rust_handle_get_intrinsic_dimensions (RsvgHandle *handle,
                                                        gboolean   *out_has_width,
                                                        RsvgLength *out_width,
                                                        gboolean   *out_has_height,
@@ -345,12 +344,12 @@ extern GType rsvg_rust_error_get_type (void);
 extern GType rsvg_rust_handle_flags_get_type (void);
 
 /* Implemented in rsvg_internals/src/c_api.rs */
-extern GType rsvg_handle_rust_get_type (void);
+extern GType rsvg_rust_handle_get_type (void);
 
 GType
 rsvg_handle_get_type (void)
 {
-    return rsvg_handle_rust_get_type ();
+    return rsvg_rust_handle_get_type ();
 }
 
 /**
@@ -418,7 +417,7 @@ rsvg_handle_new_from_data (const guint8 *data, gsize data_len, GError **error)
     g_return_val_if_fail (data_len <= G_MAXSSIZE, NULL);
     g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
-    return rsvg_handle_rust_new_from_data (data, data_len, error);
+    return rsvg_rust_handle_new_from_data (data, data_len, error);
 }
 
 /**
@@ -437,7 +436,7 @@ rsvg_handle_new_from_file (const gchar *filename, GError **error)
     g_return_val_if_fail (filename != NULL, NULL);
     g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
-    return rsvg_handle_rust_new_from_file (filename, error);
+    return rsvg_rust_handle_new_from_file (filename, error);
 }
 
 /**
@@ -453,7 +452,7 @@ rsvg_handle_new_from_file (const gchar *filename, GError **error)
 RsvgHandle *
 rsvg_handle_new_with_flags (RsvgHandleFlags flags)
 {
-    return rsvg_handle_rust_new_with_flags (flags);
+    return rsvg_rust_handle_new_with_flags (flags);
 }
 
 /**
@@ -484,7 +483,7 @@ rsvg_handle_new_from_gfile_sync (GFile          *file,
     g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
     g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
-    return rsvg_handle_rust_new_from_gfile_sync (file, flags, cancellable, error);
+    return rsvg_rust_handle_new_from_gfile_sync (file, flags, cancellable, error);
 }
 
 /**
@@ -518,7 +517,7 @@ rsvg_handle_new_from_stream_sync (GInputStream    *input_stream,
     g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
     g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
-    return rsvg_handle_rust_new_from_stream_sync (input_stream,
+    return rsvg_rust_handle_new_from_stream_sync (input_stream,
                                                   base_file,
                                                   flags,
                                                   cancellable,
@@ -550,7 +549,7 @@ rsvg_handle_write (RsvgHandle *handle, const guchar *buf, gsize count, GError **
     g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
     g_return_val_if_fail ((buf != NULL && count != 0) || (count == 0), FALSE);
 
-    rsvg_handle_rust_write (handle, buf, count);
+    rsvg_rust_handle_write (handle, buf, count);
     return TRUE;
 }
 
@@ -574,7 +573,7 @@ rsvg_handle_close (RsvgHandle *handle, GError **error)
     g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
     g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-    return rsvg_handle_rust_close(handle, error);
+    return rsvg_rust_handle_close(handle, error);
 }
 
 /**
@@ -607,7 +606,7 @@ rsvg_handle_read_stream_sync (RsvgHandle   *handle,
     g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
     g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-    return rsvg_handle_rust_read_stream_sync (handle,
+    return rsvg_rust_handle_read_stream_sync (handle,
                                               stream,
                                               cancellable,
                                               error);
@@ -629,7 +628,7 @@ rsvg_handle_set_base_uri (RsvgHandle *handle, const char *base_uri)
     g_return_if_fail (RSVG_IS_HANDLE (handle));
     g_return_if_fail (base_uri != NULL);
 
-    rsvg_handle_rust_set_base_url (handle, base_uri);
+    rsvg_rust_handle_set_base_url (handle, base_uri);
 }
 
 /**
@@ -650,7 +649,7 @@ rsvg_handle_set_base_gfile (RsvgHandle *handle,
     g_return_if_fail (RSVG_IS_HANDLE (handle));
     g_return_if_fail (G_IS_FILE (base_file));
 
-    rsvg_handle_rust_set_base_gfile (handle, base_file);
+    rsvg_rust_handle_set_base_gfile (handle, base_file);
 }
 
 /**
@@ -667,7 +666,7 @@ rsvg_handle_get_base_uri (RsvgHandle *handle)
 {
     g_return_val_if_fail (RSVG_IS_HANDLE (handle), NULL);
 
-    return rsvg_handle_rust_get_base_url (handle);
+    return rsvg_rust_handle_get_base_url (handle);
 }
 
 /**
@@ -749,7 +748,7 @@ rsvg_handle_render_cairo_sub (RsvgHandle *handle, cairo_t *cr, const char *id)
     g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
     g_return_val_if_fail (cr != NULL, FALSE);
 
-    return rsvg_handle_rust_render_cairo_sub (handle, cr, id);
+    return rsvg_rust_handle_render_cairo_sub (handle, cr, id);
 }
 
 /**
@@ -786,7 +785,7 @@ rsvg_handle_get_dimensions (RsvgHandle *handle, RsvgDimensionData *dimension_dat
     g_return_if_fail (RSVG_IS_HANDLE (handle));
     g_return_if_fail (dimension_data != NULL);
 
-    rsvg_handle_rust_get_dimensions (handle, dimension_data);
+    rsvg_rust_handle_get_dimensions (handle, dimension_data);
 }
 
 /**
@@ -811,7 +810,7 @@ rsvg_handle_get_dimensions_sub (RsvgHandle *handle,
     g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
     g_return_val_if_fail (dimension_data, FALSE);
 
-    return rsvg_handle_rust_get_dimensions_sub (handle, dimension_data, id);
+    return rsvg_rust_handle_get_dimensions_sub (handle, dimension_data, id);
 }
 
 /**
@@ -837,7 +836,7 @@ rsvg_handle_get_geometry_sub (RsvgHandle *handle,
 {
     g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
 
-    return rsvg_handle_rust_get_geometry_sub(handle, ink_rect, logical_rect, id);
+    return rsvg_rust_handle_get_geometry_sub(handle, ink_rect, logical_rect, id);
 }
 
 /**
@@ -862,7 +861,7 @@ rsvg_handle_get_position_sub (RsvgHandle *handle,
     g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
     g_return_val_if_fail (position_data != NULL, FALSE);
 
-    return rsvg_handle_rust_get_position_sub (handle, position_data, id);
+    return rsvg_rust_handle_get_position_sub (handle, position_data, id);
 }
 
 /**
@@ -881,7 +880,7 @@ rsvg_handle_has_sub (RsvgHandle *handle, const char *id)
 {
     g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
 
-    return rsvg_handle_rust_has_sub (handle, id);
+    return rsvg_rust_handle_has_sub (handle, id);
 }
 
 /**
@@ -911,7 +910,7 @@ rsvg_handle_get_pixbuf_sub (RsvgHandle *handle, const char *id)
 {
     g_return_val_if_fail (RSVG_IS_HANDLE (handle), NULL);
 
-    return rsvg_handle_rust_get_pixbuf_sub (handle, id);
+    return rsvg_rust_handle_get_pixbuf_sub (handle, id);
 }
 
 /**
@@ -966,8 +965,8 @@ rsvg_handle_set_dpi_x_y (RsvgHandle *handle, double dpi_x, double dpi_y)
 {
     g_return_if_fail (RSVG_IS_HANDLE (handle));
 
-    rsvg_handle_rust_set_dpi_x (handle, dpi_x);
-    rsvg_handle_rust_set_dpi_y (handle, dpi_y);
+    rsvg_rust_handle_set_dpi_x (handle, dpi_x);
+    rsvg_rust_handle_set_dpi_y (handle, dpi_y);
 }
 
 /**
@@ -1035,7 +1034,7 @@ rsvg_handle_set_size_callback (RsvgHandle *handle,
 {
     g_return_if_fail (RSVG_IS_HANDLE (handle));
 
-    rsvg_handle_rust_set_size_callback (handle,
+    rsvg_rust_handle_set_size_callback (handle,
                                         size_func,
                                         user_data,
                                         user_data_destroy);
@@ -1052,7 +1051,7 @@ rsvg_handle_get_intrinsic_dimensions (RsvgHandle *handle,
 {
     g_return_if_fail (RSVG_IS_HANDLE (handle));
 
-    rsvg_handle_rust_get_intrinsic_dimensions (handle,
+    rsvg_rust_handle_get_intrinsic_dimensions (handle,
                                                out_has_width,
                                                out_width,
                                                out_has_height,
@@ -1074,7 +1073,7 @@ rsvg_handle_internal_set_testing (RsvgHandle *handle, gboolean testing)
 {
     g_return_if_fail (RSVG_IS_HANDLE (handle));
 
-    rsvg_handle_rust_set_testing (handle, testing);
+    rsvg_rust_handle_set_testing (handle, testing);
 }
 
 GType
diff --git a/rsvg_internals/src/c_api.rs b/rsvg_internals/src/c_api.rs
index f699871b..22582e35 100644
--- a/rsvg_internals/src/c_api.rs
+++ b/rsvg_internals/src/c_api.rs
@@ -1,4 +1,9 @@
+use std::ffi::CStr;
+use std::mem;
 use std::ops;
+use std::path::PathBuf;
+use std::ptr;
+use std::slice;
 use std::sync::Once;
 use std::{f64, i32};
 
@@ -15,8 +20,12 @@ use glib::{ParamFlags, ParamSpec, StaticType, ToValue, Type, Value};
 use glib_sys;
 use gobject_sys::{self, GEnumValue, GFlagsValue};
 
-use error::RSVG_ERROR_FAILED;
-use handle::Handle;
+use dpi::Dpi;
+use drawing_ctx::RsvgRectangle;
+use error::{set_gerror, RSVG_ERROR_FAILED};
+use handle::{Handle, LoadFlags, LoadState};
+use length::RsvgLength;
+use url::Url;
 
 mod handle_flags {
     // The following is entirely stolen from the auto-generated code
@@ -77,6 +86,31 @@ mod handle_flags {
 
 pub use self::handle_flags::*;
 
+// Keep in sync with rsvg.h:RsvgDimensionData
+#[repr(C)]
+pub struct RsvgDimensionData {
+    pub width: libc::c_int,
+    pub height: libc::c_int,
+    pub em: f64,
+    pub ex: f64,
+}
+
+// Keep in sync with rsvg.h:RsvgPositionData
+#[repr(C)]
+pub struct RsvgPositionData {
+    pub x: libc::c_int,
+    pub y: libc::c_int,
+}
+
+// Keep in sync with rsvg.h:RsvgSizeFunc
+pub type RsvgSizeFunc = Option<
+    unsafe extern "C" fn(
+        inout_width: *mut libc::c_int,
+        inout_height: *mut libc::c_int,
+        user_data: glib_sys::gpointer,
+    ),
+>;
+
 // Keep this in sync with rsvg.h:RsvgHandleClass
 #[repr(C)]
 pub struct RsvgHandleClass {
@@ -295,7 +329,7 @@ pub fn get_rust_handle<'a>(handle: *const RsvgHandle) -> &'a Handle {
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_get_type() -> glib_sys::GType {
+pub unsafe extern "C" fn rsvg_rust_handle_get_type() -> glib_sys::GType {
     Handle::get_type().to_glib()
 }
 
@@ -380,3 +414,492 @@ pub unsafe extern "C" fn rsvg_rust_handle_flags_get_type() -> glib_sys::GType {
 
     FTYPE
 }
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_set_base_url(
+    raw_handle: *const RsvgHandle,
+    uri: *const libc::c_char,
+) {
+    let rhandle = get_rust_handle(raw_handle);
+
+    assert!(!uri.is_null());
+    let uri: String = from_glib_none(uri);
+
+    rhandle.set_base_url(&uri);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_set_base_gfile(
+    raw_handle: *const RsvgHandle,
+    raw_gfile: *mut gio_sys::GFile,
+) {
+    let rhandle = get_rust_handle(raw_handle);
+
+    assert!(!raw_gfile.is_null());
+
+    let file: gio::File = from_glib_none(raw_gfile);
+
+    rhandle.set_base_gfile(&file);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_get_base_url(
+    raw_handle: *const RsvgHandle,
+) -> *const libc::c_char {
+    let rhandle = get_rust_handle(raw_handle);
+
+    rhandle.get_base_url_as_ptr()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_set_dpi_x(raw_handle: *const RsvgHandle, dpi_x: f64) {
+    let rhandle = get_rust_handle(raw_handle);
+
+    rhandle.dpi.set(Dpi::new(dpi_x, rhandle.dpi.get().y()));
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_get_dpi_x(raw_handle: *const RsvgHandle) -> f64 {
+    let rhandle = get_rust_handle(raw_handle);
+
+    rhandle.dpi.get().x()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_set_dpi_y(raw_handle: *const RsvgHandle, dpi_y: f64) {
+    let rhandle = get_rust_handle(raw_handle);
+
+    rhandle.dpi.set(Dpi::new(rhandle.dpi.get().x(), dpi_y));
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_get_dpi_y(raw_handle: *const RsvgHandle) -> f64 {
+    let rhandle = get_rust_handle(raw_handle);
+
+    rhandle.dpi.get().y()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_get_flags(
+    raw_handle: *const RsvgHandle,
+) -> RsvgHandleFlags {
+    let rhandle = get_rust_handle(raw_handle);
+
+    rhandle.load_flags.get().to_flags().to_glib()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_set_flags(
+    raw_handle: *const RsvgHandle,
+    flags: RsvgHandleFlags,
+) {
+    let rhandle = get_rust_handle(raw_handle);
+
+    rhandle
+        .load_flags
+        .set(LoadFlags::from_flags(from_glib(flags)));
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_set_size_callback(
+    raw_handle: *const RsvgHandle,
+    size_func: RsvgSizeFunc,
+    user_data: glib_sys::gpointer,
+    destroy_notify: glib_sys::GDestroyNotify,
+) {
+    let rhandle = get_rust_handle(raw_handle);
+
+    rhandle.set_size_callback(size_func, user_data, destroy_notify);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_set_testing(
+    raw_handle: *const RsvgHandle,
+    testing: glib_sys::gboolean,
+) {
+    let rhandle = get_rust_handle(raw_handle);
+
+    rhandle.set_testing(from_glib(testing));
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_read_stream_sync(
+    handle: *const RsvgHandle,
+    stream: *mut gio_sys::GInputStream,
+    cancellable: *mut gio_sys::GCancellable,
+    error: *mut *mut glib_sys::GError,
+) -> glib_sys::gboolean {
+    let rhandle = get_rust_handle(handle);
+
+    if rhandle.load_state() != LoadState::Start {
+        panic!("handle must not be already loaded in order to call rsvg_handle_read_stream_sync()",);
+    }
+
+    let stream = from_glib_none(stream);
+    let cancellable: Option<gio::Cancellable> = from_glib_none(cancellable);
+
+    match rhandle.read_stream_sync(&stream, cancellable.as_ref()) {
+        Ok(()) => true.to_glib(),
+
+        Err(e) => {
+            set_gerror(error, 0, &format!("{}", e));
+            false.to_glib()
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_write(
+    handle: *const RsvgHandle,
+    buf: *const u8,
+    count: usize,
+) {
+    let rhandle = get_rust_handle(handle);
+
+    let load_state = rhandle.load_state();
+
+    if !(load_state == LoadState::Start || load_state == LoadState::Loading) {
+        panic!("handle must not be closed in order to write to it");
+    }
+
+    let buffer = slice::from_raw_parts(buf, count);
+
+    rhandle.write(buffer);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_close(
+    handle: *const RsvgHandle,
+    error: *mut *mut glib_sys::GError,
+) -> glib_sys::gboolean {
+    let rhandle = get_rust_handle(handle);
+
+    match rhandle.close() {
+        Ok(()) => true.to_glib(),
+
+        Err(e) => {
+            set_gerror(error, 0, &format!("{}", e));
+            false.to_glib()
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_get_geometry_sub(
+    handle: *const RsvgHandle,
+    out_ink_rect: *mut RsvgRectangle,
+    out_logical_rect: *mut RsvgRectangle,
+    id: *const libc::c_char,
+) -> glib_sys::gboolean {
+    let rhandle = get_rust_handle(handle);
+
+    let id: Option<String> = from_glib_none(id);
+
+    match rhandle.get_geometry_sub(id.as_ref().map(String::as_str)) {
+        Ok((ink_r, logical_r)) => {
+            if !out_ink_rect.is_null() {
+                *out_ink_rect = ink_r;
+            }
+
+            if !out_logical_rect.is_null() {
+                *out_logical_rect = logical_r;
+            }
+
+            true.to_glib()
+        }
+
+        Err(_) => {
+            if !out_ink_rect.is_null() {
+                *out_ink_rect = mem::zeroed();
+            }
+
+            if !out_logical_rect.is_null() {
+                *out_logical_rect = mem::zeroed();
+            }
+
+            // FIXME: return a proper error code to the public API
+            false.to_glib()
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_has_sub(
+    handle: *const RsvgHandle,
+    id: *const libc::c_char,
+) -> glib_sys::gboolean {
+    let rhandle = get_rust_handle(handle);
+
+    if id.is_null() {
+        return false.to_glib();
+    }
+
+    let id: String = from_glib_none(id);
+    // FIXME: return a proper error code to the public API
+    rhandle.has_sub(&id).unwrap_or(false).to_glib()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_render_cairo_sub(
+    handle: *const 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(&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()
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_get_pixbuf_sub(
+    handle: *const RsvgHandle,
+    id: *const libc::c_char,
+) -> *mut gdk_pixbuf_sys::GdkPixbuf {
+    let rhandle = get_rust_handle(handle);
+    let id: Option<String> = from_glib_none(id);
+
+    match rhandle.get_pixbuf_sub(id.as_ref().map(String::as_str)) {
+        Ok(pixbuf) => pixbuf.to_glib_full(),
+        Err(_) => ptr::null_mut(),
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_get_dimensions(
+    handle: *const RsvgHandle,
+    dimension_data: *mut RsvgDimensionData,
+) {
+    let rhandle = get_rust_handle(handle);
+
+    *dimension_data = rhandle.get_dimensions_no_error();
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_get_dimensions_sub(
+    handle: *const RsvgHandle,
+    dimension_data: *mut RsvgDimensionData,
+    id: *const libc::c_char,
+) -> glib_sys::gboolean {
+    let rhandle = get_rust_handle(handle);
+
+    let id: Option<String> = from_glib_none(id);
+
+    match rhandle.get_dimensions_sub(id.as_ref().map(String::as_str)) {
+        Ok(dimensions) => {
+            *dimension_data = dimensions;
+            true.to_glib()
+        }
+
+        Err(_) => {
+            let d = &mut *dimension_data;
+
+            d.width = 0;
+            d.height = 0;
+            d.em = 0.0;
+            d.ex = 0.0;
+
+            // FIXME: return a proper error code to the public API
+            false.to_glib()
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_get_position_sub(
+    handle: *const RsvgHandle,
+    position_data: *mut RsvgPositionData,
+    id: *const libc::c_char,
+) -> glib_sys::gboolean {
+    let rhandle = get_rust_handle(handle);
+
+    let id: Option<String> = from_glib_none(id);
+
+    match rhandle.get_position_sub(id.as_ref().map(String::as_str)) {
+        Ok(position) => {
+            *position_data = position;
+            true.to_glib()
+        }
+
+        Err(_) => {
+            let p = &mut *position_data;
+
+            p.x = 0;
+            p.y = 0;
+
+            // FIXME: return a proper error code to the public API
+            false.to_glib()
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_new_with_flags(flags: u32) -> *const RsvgHandle {
+    let obj: *mut gobject_sys::GObject =
+        glib::Object::new(Handle::get_type(), &[("flags", &flags)])
+            .unwrap()
+            .to_glib_full();
+
+    obj as *mut _
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_new_from_file(
+    filename: *const libc::c_char,
+    error: *mut *mut glib_sys::GError,
+) -> *const RsvgHandle {
+    // This API lets the caller pass a URI, or a file name in the operating system's
+    // encoding.  So, first we'll see if it's UTF-8, and in that case, try the URL version.
+    // Otherwise, we'll try building a path name.
+
+    let cstr = CStr::from_ptr(filename);
+
+    let file = cstr
+        .to_str()
+        .map_err(|_| ())
+        .and_then(|utf8| Url::parse(utf8).map_err(|_| ()))
+        .and_then(|url| Ok(gio::File::new_for_uri(url.as_str())))
+        .unwrap_or_else(|_| gio::File::new_for_path(PathBuf::from_glib_none(filename)));
+
+    rsvg_rust_handle_new_from_gfile_sync(file.to_glib_none().0, 0, ptr::null_mut(), error)
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_new_from_gfile_sync(
+    file: *mut gio_sys::GFile,
+    flags: u32,
+    cancellable: *mut gio_sys::GCancellable,
+    error: *mut *mut glib_sys::GError,
+) -> *const RsvgHandle {
+    let raw_handle = rsvg_rust_handle_new_with_flags(flags);
+
+    let rhandle = get_rust_handle(raw_handle);
+
+    let file = from_glib_none(file);
+    let cancellable: Option<gio::Cancellable> = from_glib_none(cancellable);
+
+    match rhandle.construct_new_from_gfile_sync(&file, cancellable.as_ref()) {
+        Ok(()) => raw_handle,
+
+        Err(e) => {
+            set_gerror(error, 0, &format!("{}", e));
+            gobject_sys::g_object_unref(raw_handle as *mut _);
+            ptr::null_mut()
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_new_from_stream_sync(
+    input_stream: *mut gio_sys::GInputStream,
+    base_file: *mut gio_sys::GFile,
+    flags: u32,
+    cancellable: *mut gio_sys::GCancellable,
+    error: *mut *mut glib_sys::GError,
+) -> *const RsvgHandle {
+    let raw_handle = rsvg_rust_handle_new_with_flags(flags);
+
+    let rhandle = get_rust_handle(raw_handle);
+
+    let base_file: Option<gio::File> = from_glib_none(base_file);
+    let stream = from_glib_none(input_stream);
+    let cancellable: Option<gio::Cancellable> = from_glib_none(cancellable);
+
+    match rhandle.construct_read_stream_sync(&stream, base_file.as_ref(), cancellable.as_ref()) {
+        Ok(()) => raw_handle,
+
+        Err(e) => {
+            set_gerror(error, 0, &format!("{}", e));
+            gobject_sys::g_object_unref(raw_handle as *mut _);
+            ptr::null_mut()
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_new_from_data(
+    data: *mut u8,
+    len: usize,
+    error: *mut *mut glib_sys::GError,
+) -> *const RsvgHandle {
+    // We create the MemoryInputStream without the gtk-rs binding because of this:
+    //
+    // - The binding doesn't provide _new_from_data().  All of the binding's ways to
+    // put data into a MemoryInputStream involve copying the data buffer.
+    //
+    // - We can't use glib::Bytes from the binding either, for the same reason.
+    //
+    // - For now, we are using the other C-visible constructor, so we need a raw pointer to the
+    //   stream, anyway.
+
+    assert!(len <= std::isize::MAX as usize);
+    let len = len as isize;
+
+    let raw_stream = gio_sys::g_memory_input_stream_new_from_data(data, len, None);
+
+    let ret = rsvg_rust_handle_new_from_stream_sync(
+        raw_stream as *mut _,
+        ptr::null_mut(), // base_file
+        0,               // flags
+        ptr::null_mut(), // cancellable
+        error,
+    );
+
+    gobject_sys::g_object_unref(raw_stream as *mut _);
+    ret
+}
+
+unsafe fn set_out_param<T: Copy>(
+    out_has_param: *mut glib_sys::gboolean,
+    out_param: *mut T,
+    value: &Option<T>,
+) {
+    let has_value = if let Some(ref v) = *value {
+        if !out_param.is_null() {
+            *out_param = *v;
+        }
+
+        true
+    } else {
+        false
+    };
+
+    if !out_has_param.is_null() {
+        *out_has_param = has_value.to_glib();
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_get_intrinsic_dimensions(
+    handle: *mut RsvgHandle,
+    out_has_width: *mut glib_sys::gboolean,
+    out_width: *mut RsvgLength,
+    out_has_height: *mut glib_sys::gboolean,
+    out_height: *mut RsvgLength,
+    out_has_viewbox: *mut glib_sys::gboolean,
+    out_viewbox: *mut RsvgRectangle,
+) {
+    let rhandle = get_rust_handle(handle);
+
+    if rhandle.check_is_loaded().is_err() {
+        return;
+    }
+
+    let d = rhandle.get_intrinsic_dimensions();
+
+    let w = d.width.map(|l| l.to_length());
+    let h = d.width.map(|l| l.to_length());
+    let r = d.vbox.map(RsvgRectangle::from);
+
+    set_out_param(out_has_width, out_width, &w);
+    set_out_param(out_has_height, out_height, &h);
+    set_out_param(out_has_viewbox, out_viewbox, &r);
+}
diff --git a/rsvg_internals/src/handle.rs b/rsvg_internals/src/handle.rs
index 3bb156d3..b555dc1c 100644
--- a/rsvg_internals/src/handle.rs
+++ b/rsvg_internals/src/handle.rs
@@ -1,32 +1,21 @@
-use std;
 use std::cell::{Cell, RefCell};
-use std::ffi::{CStr, CString};
-use std::mem;
-use std::path::PathBuf;
+use std::ffi::CString;
 use std::ptr;
 use std::rc::Rc;
-use std::slice;
 
 use cairo::{self, ImageSurface, Status};
-use cairo_sys;
 use gdk_pixbuf::Pixbuf;
-use gdk_pixbuf_sys;
 use gio::{self, FileExt};
-use gio_sys;
-use glib::subclass::types::ObjectSubclass;
-use glib::translate::*;
 use glib::{self, Bytes, Cast};
 use glib_sys;
-use gobject_sys;
 use libc;
 use locale_config::{LanguageRange, Locale};
 
 use allowed_url::{AllowedUrl, Href};
-use c_api::{get_rust_handle, HandleFlags, RsvgHandle, RsvgHandleFlags};
+use c_api::{HandleFlags, RsvgDimensionData, RsvgPositionData, RsvgSizeFunc};
 use dpi::Dpi;
 use drawing_ctx::{DrawingCtx, RsvgRectangle};
-use error::{set_gerror, DefsLookupErrorKind, LoadingError, RenderingError};
-use length::RsvgLength;
+use error::{DefsLookupErrorKind, LoadingError, RenderingError};
 use node::RsvgNode;
 use pixbuf_utils::{empty_pixbuf, pixbuf_from_surface};
 use structure::{IntrinsicDimensions, NodeSvg};
@@ -37,28 +26,6 @@ use util::rsvg_g_warning;
 use xml::XmlState;
 use xml2_load::xml_state_load_from_possibly_compressed_stream;
 
-// A *const RsvgHandle is just an opaque pointer we get from C
-// #[repr(C)]
-// pub struct RsvgHandle {
-//    _private: [u8; 0],
-// }
-
-// Keep in sync with rsvg.h:RsvgDimensionData
-#[repr(C)]
-pub struct RsvgDimensionData {
-    pub width: libc::c_int,
-    pub height: libc::c_int,
-    pub em: f64,
-    pub ex: f64,
-}
-
-// Keep in sync with rsvg.h:RsvgPositionData
-#[repr(C)]
-pub struct RsvgPositionData {
-    pub x: libc::c_int,
-    pub y: libc::c_int,
-}
-
 /// Flags used during loading
 ///
 /// We communicate these to/from the C code with a HandleFlags
@@ -105,15 +72,6 @@ pub enum LoadState {
     ClosedError,
 }
 
-// Keep in sync with rsvg.h:RsvgSizeFunc
-type RsvgSizeFunc = Option<
-    unsafe extern "C" fn(
-        inout_width: *mut libc::c_int,
-        inout_height: *mut libc::c_int,
-        user_data: glib_sys::gpointer,
-    ),
->;
-
 struct SizeCallback {
     size_func: RsvgSizeFunc,
     user_data: glib_sys::gpointer,
@@ -215,7 +173,7 @@ impl Handle {
         }
     }
 
-    fn set_base_gfile(&self, file: &gio::File) {
+    pub fn set_base_gfile(&self, file: &gio::File) {
         if let Some(uri) = file.get_uri() {
             self.set_base_url(&uri);
         } else {
@@ -223,6 +181,26 @@ impl Handle {
         }
     }
 
+    pub fn get_base_url_as_ptr(&self) -> *const libc::c_char {
+        match *self.base_url_cstring.borrow() {
+            None => ptr::null(),
+            Some(ref url) => url.as_ptr(),
+        }
+    }
+
+    pub fn set_size_callback(
+        &self,
+        size_func: RsvgSizeFunc,
+        user_data: glib_sys::gpointer,
+        destroy_notify: glib_sys::GDestroyNotify,
+    ) {
+        *self.size_callback.borrow_mut() = SizeCallback {
+            size_func,
+            user_data,
+            destroy_notify,
+        };
+    }
+
     pub fn read_stream_sync(
         &self,
         stream: &gio::InputStream,
@@ -241,7 +219,7 @@ impl Handle {
         Ok(())
     }
 
-    fn check_is_loaded(self: &Handle) -> Result<(), RenderingError> {
+    pub fn check_is_loaded(self: &Handle) -> Result<(), RenderingError> {
         match self.load_state.get() {
             LoadState::Start => {
                 rsvg_g_warning("RsvgHandle has not been loaded");
@@ -265,6 +243,10 @@ impl Handle {
         }
     }
 
+    pub fn load_state(&self) -> LoadState {
+        self.load_state.get()
+    }
+
     fn load_options(&self) -> LoadOptions {
         LoadOptions::new(
             self.load_flags.get(),
@@ -406,7 +388,10 @@ impl Handle {
         }
     }
 
-    fn get_dimensions_sub(&self, id: Option<&str>) -> Result<RsvgDimensionData, RenderingError> {
+    pub fn get_dimensions_sub(
+        &self,
+        id: Option<&str>,
+    ) -> Result<RsvgDimensionData, RenderingError> {
         self.check_is_loaded()?;
 
         let (ink_r, _) = self.get_geometry_sub(id)?;
@@ -424,7 +409,7 @@ impl Handle {
         })
     }
 
-    fn get_position_sub(&self, id: Option<&str>) -> Result<RsvgPositionData, RenderingError> {
+    pub fn get_position_sub(&self, id: Option<&str>) -> Result<RsvgPositionData, RenderingError> {
         self.check_is_loaded()?;
 
         if let None = id {
@@ -494,7 +479,7 @@ impl Handle {
     }
 
     /// Returns (ink_rect, logical_rect)
-    fn get_geometry_sub(
+    pub fn get_geometry_sub(
         &self,
         id: Option<&str>,
     ) -> Result<(RsvgRectangle, RsvgRectangle), RenderingError> {
@@ -642,7 +627,7 @@ impl Handle {
         res
     }
 
-    fn get_pixbuf_sub(&self, id: Option<&str>) -> Result<Pixbuf, RenderingError> {
+    pub fn get_pixbuf_sub(&self, id: Option<&str>) -> Result<Pixbuf, RenderingError> {
         self.check_is_loaded()?;
 
         let dimensions = self.get_dimensions()?;
@@ -664,7 +649,7 @@ impl Handle {
         pixbuf_from_surface(&surface)
     }
 
-    fn construct_new_from_gfile_sync(
+    pub fn construct_new_from_gfile_sync(
         &self,
         file: &gio::File,
         cancellable: Option<&gio::Cancellable>,
@@ -707,6 +692,10 @@ impl Handle {
     pub fn set_dpi_y(&self, dpi_y: f64) {
         self.dpi.set(Dpi::new(self.dpi.get().x(), dpi_y));
     }
+
+    pub fn set_testing(&self, testing: bool) {
+        self.is_testing.set(testing);
+    }
 }
 
 fn check_cairo_context(cr: &cairo::Context) -> Result<(), RenderingError> {
@@ -767,511 +756,3 @@ fn locale_from_environment() -> Locale {
 
     locale
 }
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_set_base_url(
-    raw_handle: *const RsvgHandle,
-    uri: *const libc::c_char,
-) {
-    let rhandle = get_rust_handle(raw_handle);
-
-    assert!(!uri.is_null());
-    let uri: String = from_glib_none(uri);
-
-    rhandle.set_base_url(&uri);
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_get_base_gfile(
-    raw_handle: *const Handle,
-) -> *mut gio_sys::GFile {
-    let handle = &*raw_handle;
-
-    match *handle.base_url.borrow() {
-        None => ptr::null_mut(),
-        Some(ref url) => gio::File::new_for_uri(url.as_str()).to_glib_full(),
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_set_base_gfile(
-    raw_handle: *const RsvgHandle,
-    raw_gfile: *mut gio_sys::GFile,
-) {
-    let rhandle = get_rust_handle(raw_handle);
-
-    assert!(!raw_gfile.is_null());
-
-    let file: gio::File = from_glib_none(raw_gfile);
-
-    rhandle.set_base_gfile(&file);
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_get_base_url(
-    raw_handle: *const RsvgHandle,
-) -> *const libc::c_char {
-    let rhandle = get_rust_handle(raw_handle);
-
-    match *rhandle.base_url_cstring.borrow() {
-        None => ptr::null(),
-        Some(ref url) => url.as_ptr(),
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_set_dpi_x(raw_handle: *const RsvgHandle, dpi_x: f64) {
-    let rhandle = get_rust_handle(raw_handle);
-
-    rhandle.dpi.set(Dpi::new(dpi_x, rhandle.dpi.get().y()));
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_get_dpi_x(raw_handle: *const RsvgHandle) -> f64 {
-    let rhandle = get_rust_handle(raw_handle);
-
-    rhandle.dpi.get().x()
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_set_dpi_y(raw_handle: *const RsvgHandle, dpi_y: f64) {
-    let rhandle = get_rust_handle(raw_handle);
-
-    rhandle.dpi.set(Dpi::new(rhandle.dpi.get().x(), dpi_y));
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_get_dpi_y(raw_handle: *const RsvgHandle) -> f64 {
-    let rhandle = get_rust_handle(raw_handle);
-
-    rhandle.dpi.get().y()
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_get_flags(
-    raw_handle: *const RsvgHandle,
-) -> RsvgHandleFlags {
-    let rhandle = get_rust_handle(raw_handle);
-
-    rhandle.load_flags.get().to_flags().to_glib()
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_set_flags(
-    raw_handle: *const RsvgHandle,
-    flags: RsvgHandleFlags,
-) {
-    let rhandle = get_rust_handle(raw_handle);
-
-    rhandle
-        .load_flags
-        .set(LoadFlags::from_flags(from_glib(flags)));
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_set_size_callback(
-    raw_handle: *const RsvgHandle,
-    size_func: RsvgSizeFunc,
-    user_data: glib_sys::gpointer,
-    destroy_notify: glib_sys::GDestroyNotify,
-) {
-    let rhandle = get_rust_handle(raw_handle);
-
-    *rhandle.size_callback.borrow_mut() = SizeCallback {
-        size_func,
-        user_data,
-        destroy_notify,
-    };
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_set_testing(
-    raw_handle: *const RsvgHandle,
-    testing: glib_sys::gboolean,
-) {
-    let rhandle = get_rust_handle(raw_handle);
-
-    rhandle.is_testing.set(from_glib(testing));
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_read_stream_sync(
-    handle: *const RsvgHandle,
-    stream: *mut gio_sys::GInputStream,
-    cancellable: *mut gio_sys::GCancellable,
-    error: *mut *mut glib_sys::GError,
-) -> glib_sys::gboolean {
-    let rhandle = get_rust_handle(handle);
-
-    if rhandle.load_state.get() != LoadState::Start {
-        panic!("handle must not be already loaded in order to call rsvg_handle_read_stream_sync()",);
-    }
-
-    let stream = from_glib_none(stream);
-    let cancellable: Option<gio::Cancellable> = from_glib_none(cancellable);
-
-    match rhandle.read_stream_sync(&stream, cancellable.as_ref()) {
-        Ok(()) => true.to_glib(),
-
-        Err(e) => {
-            set_gerror(error, 0, &format!("{}", e));
-            false.to_glib()
-        }
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_write(
-    handle: *const RsvgHandle,
-    buf: *const u8,
-    count: usize,
-) {
-    let rhandle = get_rust_handle(handle);
-
-    let load_state = rhandle.load_state.get();
-
-    if !(load_state == LoadState::Start || load_state == LoadState::Loading) {
-        panic!("handle must not be closed in order to write to it");
-    }
-
-    let buffer = slice::from_raw_parts(buf, count);
-
-    rhandle.write(buffer);
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_close(
-    handle: *const RsvgHandle,
-    error: *mut *mut glib_sys::GError,
-) -> glib_sys::gboolean {
-    let rhandle = get_rust_handle(handle);
-
-    match rhandle.close() {
-        Ok(()) => true.to_glib(),
-
-        Err(e) => {
-            set_gerror(error, 0, &format!("{}", e));
-            false.to_glib()
-        }
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_get_geometry_sub(
-    handle: *const RsvgHandle,
-    out_ink_rect: *mut RsvgRectangle,
-    out_logical_rect: *mut RsvgRectangle,
-    id: *const libc::c_char,
-) -> glib_sys::gboolean {
-    let rhandle = get_rust_handle(handle);
-
-    let id: Option<String> = from_glib_none(id);
-
-    match rhandle.get_geometry_sub(id.as_ref().map(String::as_str)) {
-        Ok((ink_r, logical_r)) => {
-            if !out_ink_rect.is_null() {
-                *out_ink_rect = ink_r;
-            }
-
-            if !out_logical_rect.is_null() {
-                *out_logical_rect = logical_r;
-            }
-
-            true.to_glib()
-        }
-
-        Err(_) => {
-            if !out_ink_rect.is_null() {
-                *out_ink_rect = mem::zeroed();
-            }
-
-            if !out_logical_rect.is_null() {
-                *out_logical_rect = mem::zeroed();
-            }
-
-            // FIXME: return a proper error code to the public API
-            false.to_glib()
-        }
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_has_sub(
-    handle: *const RsvgHandle,
-    id: *const libc::c_char,
-) -> glib_sys::gboolean {
-    let rhandle = get_rust_handle(handle);
-
-    if id.is_null() {
-        return false.to_glib();
-    }
-
-    let id: String = from_glib_none(id);
-    // FIXME: return a proper error code to the public API
-    rhandle.has_sub(&id).unwrap_or(false).to_glib()
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_render_cairo_sub(
-    handle: *const 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(&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()
-        }
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_get_pixbuf_sub(
-    handle: *const RsvgHandle,
-    id: *const libc::c_char,
-) -> *mut gdk_pixbuf_sys::GdkPixbuf {
-    let rhandle = get_rust_handle(handle);
-    let id: Option<String> = from_glib_none(id);
-
-    match rhandle.get_pixbuf_sub(id.as_ref().map(String::as_str)) {
-        Ok(pixbuf) => pixbuf.to_glib_full(),
-        Err(_) => ptr::null_mut(),
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_get_dimensions(
-    handle: *const RsvgHandle,
-    dimension_data: *mut RsvgDimensionData,
-) {
-    let rhandle = get_rust_handle(handle);
-
-    *dimension_data = rhandle.get_dimensions_no_error();
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_get_dimensions_sub(
-    handle: *const RsvgHandle,
-    dimension_data: *mut RsvgDimensionData,
-    id: *const libc::c_char,
-) -> glib_sys::gboolean {
-    let rhandle = get_rust_handle(handle);
-
-    let id: Option<String> = from_glib_none(id);
-
-    match rhandle.get_dimensions_sub(id.as_ref().map(String::as_str)) {
-        Ok(dimensions) => {
-            *dimension_data = dimensions;
-            true.to_glib()
-        }
-
-        Err(_) => {
-            let d = &mut *dimension_data;
-
-            d.width = 0;
-            d.height = 0;
-            d.em = 0.0;
-            d.ex = 0.0;
-
-            // FIXME: return a proper error code to the public API
-            false.to_glib()
-        }
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_get_position_sub(
-    handle: *const RsvgHandle,
-    position_data: *mut RsvgPositionData,
-    id: *const libc::c_char,
-) -> glib_sys::gboolean {
-    let rhandle = get_rust_handle(handle);
-
-    let id: Option<String> = from_glib_none(id);
-
-    match rhandle.get_position_sub(id.as_ref().map(String::as_str)) {
-        Ok(position) => {
-            *position_data = position;
-            true.to_glib()
-        }
-
-        Err(_) => {
-            let p = &mut *position_data;
-
-            p.x = 0;
-            p.y = 0;
-
-            // FIXME: return a proper error code to the public API
-            false.to_glib()
-        }
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_new_with_flags(flags: u32) -> *const RsvgHandle {
-    let obj: *mut gobject_sys::GObject =
-        glib::Object::new(Handle::get_type(), &[("flags", &flags)])
-            .unwrap()
-            .to_glib_full();
-
-    obj as *mut _
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_new_from_file(
-    filename: *const libc::c_char,
-    error: *mut *mut glib_sys::GError,
-) -> *const RsvgHandle {
-    // This API lets the caller pass a URI, or a file name in the operating system's
-    // encoding.  So, first we'll see if it's UTF-8, and in that case, try the URL version.
-    // Otherwise, we'll try building a path name.
-
-    let cstr = CStr::from_ptr(filename);
-
-    let file = cstr
-        .to_str()
-        .map_err(|_| ())
-        .and_then(|utf8| Url::parse(utf8).map_err(|_| ()))
-        .and_then(|url| Ok(gio::File::new_for_uri(url.as_str())))
-        .unwrap_or_else(|_| gio::File::new_for_path(PathBuf::from_glib_none(filename)));
-
-    rsvg_handle_rust_new_from_gfile_sync(file.to_glib_none().0, 0, ptr::null_mut(), error)
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_new_from_gfile_sync(
-    file: *mut gio_sys::GFile,
-    flags: u32,
-    cancellable: *mut gio_sys::GCancellable,
-    error: *mut *mut glib_sys::GError,
-) -> *const RsvgHandle {
-    let raw_handle = rsvg_handle_rust_new_with_flags(flags);
-
-    let rhandle = get_rust_handle(raw_handle);
-
-    let file = from_glib_none(file);
-    let cancellable: Option<gio::Cancellable> = from_glib_none(cancellable);
-
-    match rhandle.construct_new_from_gfile_sync(&file, cancellable.as_ref()) {
-        Ok(()) => raw_handle,
-
-        Err(e) => {
-            set_gerror(error, 0, &format!("{}", e));
-            gobject_sys::g_object_unref(raw_handle as *mut _);
-            ptr::null_mut()
-        }
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_new_from_stream_sync(
-    input_stream: *mut gio_sys::GInputStream,
-    base_file: *mut gio_sys::GFile,
-    flags: u32,
-    cancellable: *mut gio_sys::GCancellable,
-    error: *mut *mut glib_sys::GError,
-) -> *const RsvgHandle {
-    let raw_handle = rsvg_handle_rust_new_with_flags(flags);
-
-    let rhandle = get_rust_handle(raw_handle);
-
-    let base_file: Option<gio::File> = from_glib_none(base_file);
-    let stream = from_glib_none(input_stream);
-    let cancellable: Option<gio::Cancellable> = from_glib_none(cancellable);
-
-    match rhandle.construct_read_stream_sync(&stream, base_file.as_ref(), cancellable.as_ref()) {
-        Ok(()) => raw_handle,
-
-        Err(e) => {
-            set_gerror(error, 0, &format!("{}", e));
-            gobject_sys::g_object_unref(raw_handle as *mut _);
-            ptr::null_mut()
-        }
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_new_from_data(
-    data: *mut u8,
-    len: usize,
-    error: *mut *mut glib_sys::GError,
-) -> *const RsvgHandle {
-    // We create the MemoryInputStream without the gtk-rs binding because of this:
-    //
-    // - The binding doesn't provide _new_from_data().  All of the binding's ways to
-    // put data into a MemoryInputStream involve copying the data buffer.
-    //
-    // - We can't use glib::Bytes from the binding either, for the same reason.
-    //
-    // - For now, we are using the other C-visible constructor, so we need a raw pointer to the
-    //   stream, anyway.
-
-    assert!(len <= std::isize::MAX as usize);
-    let len = len as isize;
-
-    let raw_stream = gio_sys::g_memory_input_stream_new_from_data(data, len, None);
-
-    let ret = rsvg_handle_rust_new_from_stream_sync(
-        raw_stream as *mut _,
-        ptr::null_mut(), // base_file
-        0,               // flags
-        ptr::null_mut(), // cancellable
-        error,
-    );
-
-    gobject_sys::g_object_unref(raw_stream as *mut _);
-    ret
-}
-
-unsafe fn set_out_param<T: Copy>(
-    out_has_param: *mut glib_sys::gboolean,
-    out_param: *mut T,
-    value: &Option<T>,
-) {
-    let has_value = if let Some(ref v) = *value {
-        if !out_param.is_null() {
-            *out_param = *v;
-        }
-
-        true
-    } else {
-        false
-    };
-
-    if !out_has_param.is_null() {
-        *out_has_param = has_value.to_glib();
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rsvg_handle_rust_get_intrinsic_dimensions(
-    handle: *mut RsvgHandle,
-    out_has_width: *mut glib_sys::gboolean,
-    out_width: *mut RsvgLength,
-    out_has_height: *mut glib_sys::gboolean,
-    out_height: *mut RsvgLength,
-    out_has_viewbox: *mut glib_sys::gboolean,
-    out_viewbox: *mut RsvgRectangle,
-) {
-    let rhandle = get_rust_handle(handle);
-
-    if rhandle.check_is_loaded().is_err() {
-        return;
-    }
-
-    let d = rhandle.get_intrinsic_dimensions();
-
-    let w = d.width.map(|l| l.to_length());
-    let h = d.width.map(|l| l.to_length());
-    let r = d.vbox.map(RsvgRectangle::from);
-
-    set_out_param(out_has_width, out_width, &w);
-    set_out_param(out_has_height, out_height, &h);
-    set_out_param(out_has_viewbox, out_viewbox, &r);
-}
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 3258ec83..e19d233a 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -13,7 +13,6 @@ extern crate float_cmp;
 extern crate gdk_pixbuf;
 extern crate gdk_pixbuf_sys;
 extern crate gio;
-extern crate gio_sys;
 extern crate glib_sys;
 extern crate gobject_sys;
 extern crate itertools;
@@ -40,7 +39,37 @@ extern crate glib;
 #[macro_use]
 extern crate lazy_static;
 
-pub use c_api::{rsvg_rust_error_get_type, rsvg_rust_handle_flags_get_type};
+pub use c_api::{
+    rsvg_rust_error_get_type,
+    rsvg_rust_handle_close,
+    rsvg_rust_handle_flags_get_type,
+    rsvg_rust_handle_get_base_url,
+    rsvg_rust_handle_get_dimensions,
+    rsvg_rust_handle_get_dimensions_sub,
+    rsvg_rust_handle_get_dpi_x,
+    rsvg_rust_handle_get_dpi_y,
+    rsvg_rust_handle_get_flags,
+    rsvg_rust_handle_get_geometry_sub,
+    rsvg_rust_handle_get_intrinsic_dimensions,
+    rsvg_rust_handle_get_pixbuf_sub,
+    rsvg_rust_handle_get_position_sub,
+    rsvg_rust_handle_has_sub,
+    rsvg_rust_handle_new_from_data,
+    rsvg_rust_handle_new_from_file,
+    rsvg_rust_handle_new_from_gfile_sync,
+    rsvg_rust_handle_new_from_stream_sync,
+    rsvg_rust_handle_new_with_flags,
+    rsvg_rust_handle_read_stream_sync,
+    rsvg_rust_handle_render_cairo_sub,
+    rsvg_rust_handle_set_base_gfile,
+    rsvg_rust_handle_set_base_url,
+    rsvg_rust_handle_set_dpi_x,
+    rsvg_rust_handle_set_dpi_y,
+    rsvg_rust_handle_set_flags,
+    rsvg_rust_handle_set_size_callback,
+    rsvg_rust_handle_set_testing,
+    rsvg_rust_handle_write,
+};
 
 pub use color::{rsvg_css_parse_color, ColorKind, ColorSpec};
 
@@ -56,39 +85,7 @@ pub use error::{
     RenderingError,
 };
 
-pub use handle::{
-    rsvg_handle_rust_close,
-    rsvg_handle_rust_get_base_gfile,
-    rsvg_handle_rust_get_base_url,
-    rsvg_handle_rust_get_dimensions,
-    rsvg_handle_rust_get_dimensions_sub,
-    rsvg_handle_rust_get_dpi_x,
-    rsvg_handle_rust_get_dpi_y,
-    rsvg_handle_rust_get_flags,
-    rsvg_handle_rust_get_geometry_sub,
-    rsvg_handle_rust_get_intrinsic_dimensions,
-    rsvg_handle_rust_get_pixbuf_sub,
-    rsvg_handle_rust_get_position_sub,
-    rsvg_handle_rust_has_sub,
-    rsvg_handle_rust_new_from_data,
-    rsvg_handle_rust_new_from_file,
-    rsvg_handle_rust_new_from_gfile_sync,
-    rsvg_handle_rust_new_from_stream_sync,
-    rsvg_handle_rust_new_with_flags,
-    rsvg_handle_rust_read_stream_sync,
-    rsvg_handle_rust_render_cairo_sub,
-    rsvg_handle_rust_set_base_gfile,
-    rsvg_handle_rust_set_base_url,
-    rsvg_handle_rust_set_dpi_x,
-    rsvg_handle_rust_set_dpi_y,
-    rsvg_handle_rust_set_flags,
-    rsvg_handle_rust_set_size_callback,
-    rsvg_handle_rust_set_testing,
-    rsvg_handle_rust_write,
-
-    Handle,
-    LoadFlags,
-};
+pub use handle::{Handle, LoadFlags};
 
 pub use length::{Length, LengthUnit};
 
diff --git a/rsvg_internals/src/pixbuf_utils.rs b/rsvg_internals/src/pixbuf_utils.rs
index 913d68cb..cd205645 100644
--- a/rsvg_internals/src/pixbuf_utils.rs
+++ b/rsvg_internals/src/pixbuf_utils.rs
@@ -7,9 +7,9 @@ use glib::translate::*;
 use glib_sys;
 use libc;
 
-use c_api::get_rust_handle;
+use c_api::{get_rust_handle, rsvg_rust_handle_new_from_gfile_sync, RsvgDimensionData};
 use error::{set_gerror, RenderingError};
-use handle::{rsvg_handle_rust_new_from_gfile_sync, Handle, RsvgDimensionData};
+use handle::Handle;
 use rect::IRect;
 use surface_utils::{
     iterators::Pixels,
@@ -189,7 +189,7 @@ fn pixbuf_from_file_with_size_mode(
     unsafe {
         let file = gio_sys::g_file_new_for_path(filename);
 
-        let handle = rsvg_handle_rust_new_from_gfile_sync(file, 0, ptr::null_mut(), error);
+        let handle = rsvg_rust_handle_new_from_gfile_sync(file, 0, ptr::null_mut(), error);
 
         gobject_sys::g_object_unref(file as *mut _);
 


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