[librsvg] handle: port get_pixbuf_sub to rust
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] handle: port get_pixbuf_sub to rust
- Date: Fri, 28 Dec 2018 17:35:53 +0000 (UTC)
commit 24096468be30c139582793920c2e472d9f825643
Author: Paolo Borelli <pborelli gnome org>
Date: Wed Dec 26 11:56:30 2018 +0100
handle: port get_pixbuf_sub to rust
Cargo.lock | 1 +
librsvg/rsvg-handle.c | 32 ++----------------
librsvg/rsvg-pixbuf.c | 76 ------------------------------------------
librsvg/rsvg-private.h | 3 --
rsvg_internals/Cargo.toml | 1 +
rsvg_internals/src/handle.rs | 79 ++++++++++++++++++++++++++++++++++++++++++--
rsvg_internals/src/lib.rs | 2 ++
7 files changed, 83 insertions(+), 111 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index 8dcf781b..2757a749 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -957,6 +957,7 @@ dependencies = [
"encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"float-cmp 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gdk-pixbuf 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gdk-pixbuf-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index 15b1bdf2..ee790c8c 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -176,6 +176,7 @@ extern gboolean rsvg_handle_rust_has_sub (RsvgHandle *handle, const char *id);
extern gboolean rsvg_handle_rust_render_cairo_sub (RsvgHandle *handle,
cairo_t *cr,
const char *id);
+extern GdkPixbuf *rsvg_handle_rust_get_pixbuf_sub (RsvgHandle *handle, const char *id);
struct RsvgHandlePrivate {
RsvgSizeFunc size_func;
@@ -1241,42 +1242,13 @@ rsvg_handle_has_sub (RsvgHandle *handle,
GdkPixbuf *
rsvg_handle_get_pixbuf_sub (RsvgHandle * handle, const char *id)
{
- RsvgDimensionData dimensions;
- GdkPixbuf *output = NULL;
- cairo_surface_t *surface;
- cairo_t *cr;
-
g_return_val_if_fail (RSVG_IS_HANDLE (handle), NULL);
if (!is_loaded (handle)) {
return NULL;
}
- rsvg_handle_get_dimensions (handle, &dimensions);
- if (!(dimensions.width && dimensions.height))
- return NULL;
-
- surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- dimensions.width, dimensions.height);
- if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) {
- cairo_surface_destroy (surface);
- return NULL;
- }
-
- cr = cairo_create (surface);
-
- if (!rsvg_handle_render_cairo_sub (handle, cr, id)) {
- cairo_destroy (cr);
- cairo_surface_destroy (surface);
- return NULL;
- }
-
- cairo_destroy (cr);
-
- output = rsvg_cairo_surface_to_pixbuf (surface);
- cairo_surface_destroy (surface);
-
- return output;
+ return rsvg_handle_rust_get_pixbuf_sub (handle, id);
}
/**
diff --git a/librsvg/rsvg-pixbuf.c b/librsvg/rsvg-pixbuf.c
index 57877c32..1687cf42 100644
--- a/librsvg/rsvg-pixbuf.c
+++ b/librsvg/rsvg-pixbuf.c
@@ -223,79 +223,3 @@ rsvg_pixbuf_from_file_at_max_size (const gchar * file_name,
return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
}
-
-/* Copied from gtk+/gdk/gdkpixbuf-drawable.c, LGPL 2+.
- *
- * Copyright (C) 1999 Michael Zucchi
- *
- * Authors: Michael Zucchi <zucchi zedzone mmc com au>
- * Cody Russell <bratsche dfw net>
- * Federico Mena-Quintero <federico gimp org>
- */
-
-static void
-convert_alpha (guchar *dest_data,
- int dest_stride,
- guchar *src_data,
- int src_stride,
- int src_x,
- int src_y,
- int width,
- int height)
-{
- int x, y;
-
- src_data += src_stride * src_y + src_x * 4;
-
- for (y = 0; y < height; y++) {
- guint32 *src = (guint32 *) src_data;
-
- for (x = 0; x < width; x++) {
- guint alpha = src[x] >> 24;
-
- if (alpha == 0) {
- dest_data[x * 4 + 0] = 0;
- dest_data[x * 4 + 1] = 0;
- dest_data[x * 4 + 2] = 0;
- } else {
- dest_data[x * 4 + 0] = (((src[x] & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
- dest_data[x * 4 + 1] = (((src[x] & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha;
- dest_data[x * 4 + 2] = (((src[x] & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha;
- }
- dest_data[x * 4 + 3] = alpha;
- }
-
- src_data += src_stride;
- dest_data += dest_stride;
- }
-}
-
-GdkPixbuf *
-rsvg_cairo_surface_to_pixbuf (cairo_surface_t *surface)
-{
- GdkPixbuf *dest;
- int width, height;
-
- /* General sanity checks */
- g_assert (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE);
- g_assert (cairo_image_surface_get_format (surface) == CAIRO_FORMAT_ARGB32);
-
- width = cairo_image_surface_get_width (surface);
- height = cairo_image_surface_get_height (surface);
- if (width == 0 || height == 0)
- return NULL;
-
- dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
- TRUE,
- 8,
- width, height);
-
- convert_alpha (gdk_pixbuf_get_pixels (dest),
- gdk_pixbuf_get_rowstride (dest),
- cairo_image_surface_get_data (surface),
- cairo_image_surface_get_stride (surface),
- 0, 0,
- width, height);
-
- return dest;
-}
diff --git a/librsvg/rsvg-private.h b/librsvg/rsvg-private.h
index 22911e2f..05c5cca7 100644
--- a/librsvg/rsvg-private.h
+++ b/librsvg/rsvg-private.h
@@ -66,9 +66,6 @@ double rsvg_get_default_dpi_x (void);
G_GNUC_INTERNAL
double rsvg_get_default_dpi_y (void);
-G_GNUC_INTERNAL
-GdkPixbuf *rsvg_cairo_surface_to_pixbuf (cairo_surface_t *surface);
-
G_GNUC_INTERNAL
void rsvg_return_if_fail_warning (const char *pretty_function,
const char *expression, GError ** error);
diff --git a/rsvg_internals/Cargo.toml b/rsvg_internals/Cargo.toml
index bf89d050..c9f077c2 100644
--- a/rsvg_internals/Cargo.toml
+++ b/rsvg_internals/Cargo.toml
@@ -28,6 +28,7 @@ downcast-rs = "^1.0.0"
encoding = "0.2.33"
float-cmp = "0.4.0"
gdk-pixbuf = "0.5.0"
+gdk-pixbuf-sys = "0.7.0"
gio = { version="0.5.1", features=["v2_48"] } # per configure.ac
gio-sys = "0.7.0"
glib = "0.6.0"
diff --git a/rsvg_internals/src/handle.rs b/rsvg_internals/src/handle.rs
index 60a80898..1e52fe53 100644
--- a/rsvg_internals/src/handle.rs
+++ b/rsvg_internals/src/handle.rs
@@ -6,7 +6,8 @@ use std::slice;
use cairo::{self, ImageSurface, Status};
use cairo_sys;
-use gdk_pixbuf::{PixbufLoader, PixbufLoaderExt};
+use gdk_pixbuf::{Colorspace, Pixbuf, PixbufLoader, PixbufLoaderExt};
+use gdk_pixbuf_sys;
use gio::{File as GFile, InputStream};
use gio_sys;
use glib::translate::*;
@@ -20,11 +21,16 @@ use defs::{Fragment, Href};
use dpi::Dpi;
use drawing_ctx::{DrawingCtx, RsvgRectangle};
use error::{set_gerror, DefsLookupErrorKind, LoadingError, RenderingError};
+use filters::context::IRect;
use io;
use load::LoadContext;
use node::{Node, RsvgNode};
use structure::NodeSvg;
-use surface_utils::shared_surface::SharedImageSurface;
+use surface_utils::{
+ iterators::Pixels,
+ shared_surface::SharedImageSurface,
+ shared_surface::SurfaceType,
+};
use svg::Svg;
use util::rsvg_g_warning;
use xml::XmlState;
@@ -428,6 +434,60 @@ impl Handle {
res
}
+
+ fn get_pixbuf_sub(
+ &mut self,
+ handle: *mut RsvgHandle,
+ id: Option<&str>,
+ ) -> Result<Pixbuf, RenderingError> {
+ let mut dimensions = unsafe { mem::zeroed() };
+
+ unsafe {
+ rsvg_handle_get_dimensions(handle, &mut dimensions);
+ }
+
+ if dimensions.width == 0 || dimensions.height == 0 {
+ return Err(RenderingError::SvgHasNoSize);
+ }
+
+ let surface =
+ ImageSurface::create(cairo::Format::ARgb32, dimensions.width, dimensions.height)?;
+
+ {
+ let cr = cairo::Context::new(&surface);
+ self.render_cairo_sub(handle, &cr, id)?;
+ }
+
+ let surface = SharedImageSurface::new(surface, SurfaceType::SRgb)?;
+
+ let bounds = IRect {
+ x0: 0,
+ y0: 0,
+ x1: dimensions.width,
+ y1: dimensions.height,
+ };
+
+ let pixbuf = Pixbuf::new(
+ Colorspace::Rgb,
+ true,
+ 8,
+ dimensions.width,
+ dimensions.height,
+ );
+
+ for (x, y, pixel) in Pixels::new(&surface, bounds) {
+ let (r, g, b, a) = if pixel.a == 0 {
+ (0, 0, 0, 0)
+ } else {
+ let pixel = pixel.unpremultiply();
+ (pixel.r, pixel.g, pixel.b, pixel.a)
+ };
+
+ pixbuf.put_pixel(x as i32, y as i32, r, g, b, a);
+ }
+
+ Ok(pixbuf)
+ }
}
// Keep these in sync with rsvg.h:RsvgHandleFlags
@@ -910,3 +970,18 @@ pub unsafe extern "C" fn rsvg_handle_rust_render_cairo_sub(
}
}
}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_rust_get_pixbuf_sub(
+ handle: *mut 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(handle, id.as_ref().map(String::as_str)) {
+ Ok(pixbuf) => pixbuf.to_glib_full(),
+ Err(_) => ptr::null_mut(),
+ }
+}
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 7fb70e79..771c6dd5 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -11,6 +11,7 @@ extern crate downcast_rs;
extern crate encoding;
extern crate float_cmp;
extern crate gdk_pixbuf;
+extern crate gdk_pixbuf_sys;
extern crate gio;
extern crate gio_sys;
extern crate glib;
@@ -44,6 +45,7 @@ pub use handle::{
rsvg_handle_rust_get_flags,
rsvg_handle_rust_get_geometry_sub,
rsvg_handle_rust_get_load_state,
+ rsvg_handle_rust_get_pixbuf_sub,
rsvg_handle_rust_has_sub,
rsvg_handle_rust_new,
rsvg_handle_rust_read_stream_sync,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]