[librsvg/wip/aruiz/rust-pixbuf-loader] pixbuf loader: remove leaks



commit 9666db61df79cc239cd3e243c691129a2f822f9a
Author: Alberto Ruiz <aruiz redhat com>
Date:   Thu Jul 28 16:34:25 2022 +0100

    pixbuf loader: remove leaks

 gdk-pixbuf-loader/src/lib.rs | 131 +++++++++++++++++--------------------------
 1 file changed, 53 insertions(+), 78 deletions(-)
---
diff --git a/gdk-pixbuf-loader/src/lib.rs b/gdk-pixbuf-loader/src/lib.rs
index 06e433ef6..b784f6629 100644
--- a/gdk-pixbuf-loader/src/lib.rs
+++ b/gdk-pixbuf-loader/src/lib.rs
@@ -7,6 +7,7 @@ use gdk_pixbuf_sys::{
 };
 
 use glib_sys::GError;
+use gobject_sys::GObject;
 use libc::{c_char, c_int, c_uint, c_void};
 
 use gio::prelude::MemoryInputStreamExt;
@@ -89,89 +90,61 @@ unsafe extern "C" fn stop_load(user_data: *mut c_void, error: *mut *mut GError)
         *error = null_mut();
     }
 
-    let handle = match Loader::new().read_stream::<_, gio::File, gio::Cancellable>(
-        &ctx.stream,
-        None,
-        None,
-    ) {
-        Ok(handle) => handle,
-        Err(e) => {
-            let gerr = glib::Error::new(gdk_pixbuf::PixbufError::Failed, &e.to_string());
-            *error = gerr.into_raw();
-            return 0;
-        }
-    };
-
-    let renderer = librsvg::CairoRenderer::new(&handle);
-    let (w, h) = match renderer.intrinsic_size_in_pixels() {
-        Some((w, h)) => (w, h),
-        None => {
-            let gerr = glib::Error::new(
-                gdk_pixbuf::PixbufError::Failed,
-                "Could not get intrinsic size in pixel of Cairo memory surface",
-            );
-            *error = gerr.into_raw();
-            return 0;
-        }
-    };
-
-    let surface = match cairo::ImageSurface::create(
-        cairo::Format::ARgb32,
-        w.ceil() as i32,
-        h.ceil() as i32,
-    ) {
-        Ok(sfc) => sfc,
-        Err(e) => {
-            let gerr = glib::Error::new(gdk_pixbuf::PixbufError::Failed, &e.to_string());
-            *error = gerr.into_raw();
-            return 0;
-        }
-    };
-
-    let cr = match cairo::Context::new(&surface) {
-        Ok(cr) => cr,
-        Err(e) => {
-            let gerr = glib::Error::new(gdk_pixbuf::PixbufError::Failed, &e.to_string());
-            *error = gerr.into_raw();
-            return 0;
-        }
-    };
-
-    match renderer.render_document(
-        &cr,
-        &cairo::Rectangle {
-            x: 0.0,
-            y: 0.0,
-            width: w,
-            height: h,
-        },
-    ) {
-        Err(e) => {
-            let gerr = glib::Error::new(gdk_pixbuf::PixbufError::Failed, &e.to_string());
-            *error = gerr.into_raw();
-            return 0;
-        }
-        _ => {}
-    };
-
-    let mut w = w.ceil() as i32;
-    let mut h = h.ceil() as i32;
+    fn _inner_stop_load(ctx: &Box<SvgContext>) -> Result<(Vec<u8>, i32, i32, i32), String> {
+        let handle = Loader::new()
+            .read_stream::<_, gio::File, gio::Cancellable>(&ctx.stream, None, None)
+            .map_err(|e| e.to_string())?;
+
+        let renderer = librsvg::CairoRenderer::new(&handle);
+        let (w, h) = match renderer.intrinsic_size_in_pixels() {
+            Some((w, h)) => (w, h),
+            None => {
+                return Err(String::from(
+                    "Could not get intrinsic size in pixel of Cairo memory surface",
+                ));
+            }
+        };
+
+        let surface =
+            cairo::ImageSurface::create(cairo::Format::ARgb32, w.ceil() as i32, h.ceil() as i32)
+                .map_err(|e| e.to_string())?;
+
+        let cr = cairo::Context::new(&surface).map_err(|e| e.to_string())?;
+
+        renderer
+            .render_document(
+                &cr,
+                &cairo::Rectangle {
+                    x: 0.0,
+                    y: 0.0,
+                    width: w,
+                    height: h,
+                },
+            )
+            .map_err(|e| e.to_string())?;
+
+        let w = w.ceil() as i32;
+        let h = h.ceil() as i32;
+
+        let stride = surface.stride();
+        // The cairo::Context holds a reference to the surface which needs to be dropped to access the data
+        std::mem::drop(cr);
+        let sfc_data = surface.take_data().map_err(|e| e.to_string())?;
+        let sfc_data = unsafe { std::slice::from_raw_parts(sfc_data.as_ptr(), sfc_data.len()) }; // This is 
just a slice to the canonical data
+                                                                                                 // We need 
it as a mutable vector to move the alpha channel around
+        let pb_data = sfc_data.to_vec();
+
+        Ok((pb_data, w, h, stride))
+    }
 
-    let stride = surface.stride();
-    // The cairo::Context holds a reference to the surface which needs to be dropped to access the data
-    std::mem::drop(cr);
-    let sfc_data = match surface.take_data() {
-        Ok(data) => data,
+    let (mut pb_data, mut w, mut h, stride) = match _inner_stop_load(&ctx) {
+        Ok(r) => r,
         Err(e) => {
             let gerr = glib::Error::new(gdk_pixbuf::PixbufError::Failed, &e.to_string());
             *error = gerr.into_raw();
             return 0;
         }
     };
-    let sfc_data = std::slice::from_raw_parts(sfc_data.as_ptr(), sfc_data.len()); // This is just a slice to 
the canonical data
-
-    // We need it as a mutable vector to move the alpha channel around
-    let mut pb_data = sfc_data.to_vec();
 
     // GDK Pixbuf only support RGBA and Cairo only ARGB32, we swap channels around
     argb_to_rgba(&mut pb_data, w as usize, h as usize, stride as usize);
@@ -181,7 +154,7 @@ unsafe extern "C" fn stop_load(user_data: *mut c_void, error: *mut *mut GError)
 
     // Function to free the pixel data by rebuilding the Vec object
     #[no_mangle]
-    unsafe extern "C" fn destroy_fn(pixels: *mut u8, user_data: *mut c_void) {
+    unsafe extern "C" fn destroy_cb_foo(pixels: *mut u8, user_data: *mut c_void) {
         let data = Box::<(usize, usize)>::from_raw(user_data as *mut (usize, usize));
         Vec::from_raw_parts(pixels, data.0, data.1);
     }
@@ -195,7 +168,7 @@ unsafe extern "C" fn stop_load(user_data: *mut c_void, error: *mut *mut GError)
         w,
         h,
         stride,
-        Some(destroy_fn),
+        Some(destroy_cb_foo),
         Box::into_raw(cb_data) as *mut c_void,
     );
     if let Some(size_func) = ctx.size_func {
@@ -208,6 +181,8 @@ unsafe extern "C" fn stop_load(user_data: *mut c_void, error: *mut *mut GError)
         prep_func(pixbuf, null_mut(), ctx.user_data);
     }
 
+    gobject_sys::g_object_unref(pixbuf as *mut GObject);
+
     1
 }
 


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