[librsvg/wip/aruiz/rust-pixbuf-loader] eureka!
- From: Alberto Ruiz <aruiz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg/wip/aruiz/rust-pixbuf-loader] eureka!
- Date: Wed, 27 Jul 2022 16:58:31 +0000 (UTC)
commit 9563553cd971fcace83b07a3908140086f58f37e
Author: Alberto Ruiz <aruiz redhat com>
Date: Wed Jul 27 17:58:21 2022 +0100
eureka!
gdk-pixbuf-loader/src/lib.rs | 92 ++++++++++++++++++++++++++------------------
1 file changed, 55 insertions(+), 37 deletions(-)
---
diff --git a/gdk-pixbuf-loader/src/lib.rs b/gdk-pixbuf-loader/src/lib.rs
index ad3f8ae91..06e433ef6 100644
--- a/gdk-pixbuf-loader/src/lib.rs
+++ b/gdk-pixbuf-loader/src/lib.rs
@@ -12,7 +12,7 @@ use libc::{c_char, c_int, c_uint, c_void};
use gio::prelude::MemoryInputStreamExt;
use gio::MemoryInputStream;
use glib::Bytes;
-use librsvg::{Loader, SvgHandle};
+use librsvg::Loader;
#[allow(non_camel_case_types)]
type c_bool = c_int;
@@ -23,7 +23,6 @@ struct SvgContext {
update_func: GdkPixbufModuleUpdatedFunc,
user_data: *mut c_void,
stream: MemoryInputStream,
- handle: SvgHandle,
}
#[no_mangle]
@@ -39,24 +38,15 @@ unsafe extern "C" fn begin_load(
}
let stream = MemoryInputStream::new();
+ let ctx = Box::new(SvgContext {
+ size_func,
+ prep_func,
+ update_func,
+ user_data,
+ stream,
+ });
- match Loader::new().read_stream::<_, gio::File, gio::Cancellable>(&stream, None, None) {
- Ok(handle) => {
- let ctx = SvgContext {
- size_func,
- prep_func,
- update_func,
- user_data,
- stream,
- handle,
- };
- Box::into_raw(Box::new(ctx)) as *mut c_void
- }
- Err(e) => {
- //TODO> Set error
- null_mut()
- }
- }
+ Box::into_raw(ctx) as *mut c_void
}
#[no_mangle]
@@ -78,16 +68,16 @@ unsafe extern "C" fn load_increment(
1
}
-fn argb_to_rgba(data: &mut Vec<u8>, width: i32, height: i32, stride: i32) {
- for i in 0..height as usize {
- let row_index = i * (width as usize * 4) + i * (stride as usize);
+fn argb_to_rgba(data: &mut Vec<u8>, width: usize, height: usize, stride: usize) {
+ assert!((width * 4) >= stride);
+ assert!((stride * height) <= data.len());
+ for i in 0..height {
+ let row_index = i * stride;
for j in 0..width {
- let pixel_index = row_index + (j as usize * 4);
- let tmp = data[pixel_index];
- data[pixel_index] = data[pixel_index + 1];
- data[pixel_index + 1] = data[pixel_index + 2];
- data[pixel_index + 2] = data[pixel_index + 3];
- data[pixel_index + 3] = tmp;
+ let pixel_index = row_index + (j * 4);
+ let tmp = data[pixel_index + 2];
+ data[pixel_index + 2] = data[pixel_index];
+ data[pixel_index] = tmp;
}
}
}
@@ -99,23 +89,41 @@ unsafe extern "C" fn stop_load(user_data: *mut c_void, error: *mut *mut GError)
*error = null_mut();
}
- let renderer = librsvg::CairoRenderer::new(&ctx.handle);
+ 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 => {
- //TODO: Set Error
+ 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 mut surface = match cairo::ImageSurface::create(
+ let surface = match cairo::ImageSurface::create(
cairo::Format::ARgb32,
w.ceil() as i32,
h.ceil() as i32,
) {
Ok(sfc) => sfc,
Err(e) => {
- //TODO: Set Error
+ let gerr = glib::Error::new(gdk_pixbuf::PixbufError::Failed, &e.to_string());
+ *error = gerr.into_raw();
return 0;
}
};
@@ -123,7 +131,8 @@ unsafe extern "C" fn stop_load(user_data: *mut c_void, error: *mut *mut GError)
let cr = match cairo::Context::new(&surface) {
Ok(cr) => cr,
Err(e) => {
- //TODO: Set Error
+ let gerr = glib::Error::new(gdk_pixbuf::PixbufError::Failed, &e.to_string());
+ *error = gerr.into_raw();
return 0;
}
};
@@ -138,7 +147,8 @@ unsafe extern "C" fn stop_load(user_data: *mut c_void, error: *mut *mut GError)
},
) {
Err(e) => {
- //TODO: Set Error
+ let gerr = glib::Error::new(gdk_pixbuf::PixbufError::Failed, &e.to_string());
+ *error = gerr.into_raw();
return 0;
}
_ => {}
@@ -147,16 +157,24 @@ unsafe extern "C" fn stop_load(user_data: *mut c_void, error: *mut *mut GError)
let mut w = w.ceil() as i32;
let mut h = h.ceil() as i32;
- surface.flush();
let stride = surface.stride();
- let sfc_data = surface.data().unwrap();
+ // 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,
+ 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, h, stride);
+ argb_to_rgba(&mut pb_data, w as usize, h as usize, stride as usize);
// Vector length and capacity to rebuild and destroy the vector in destroy_fn
let cb_data = Box::new((pb_data.len(), pb_data.capacity()));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]