[librsvg] Move the surface-to-pixbuf code to a separate file



commit adcd3744cd7e2861e9551299efb828e7c06161c9
Author: Federico Mena Quintero <federico gnome org>
Date:   Thu Jan 10 19:00:50 2019 -0600

    Move the surface-to-pixbuf code to a separate file

 Makefile.am                        |  1 +
 rsvg_internals/src/error.rs        |  1 +
 rsvg_internals/src/handle.rs       | 38 ++++-------------------------
 rsvg_internals/src/lib.rs          |  1 +
 rsvg_internals/src/pixbuf_utils.rs | 49 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 56 insertions(+), 34 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index ce2fe885..d83aaaeb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -97,6 +97,7 @@ RUST_SRC =                                                    \
        rsvg_internals/src/path_builder.rs                      \
        rsvg_internals/src/path_parser.rs                       \
        rsvg_internals/src/pattern.rs                           \
+       rsvg_internals/src/pixbuf_utils.rs                      \
        rsvg_internals/src/property_bag.rs                      \
        rsvg_internals/src/property_macros.rs                   \
        rsvg_internals/src/rect.rs                              \
diff --git a/rsvg_internals/src/error.rs b/rsvg_internals/src/error.rs
index 58537172..38064761 100644
--- a/rsvg_internals/src/error.rs
+++ b/rsvg_internals/src/error.rs
@@ -105,6 +105,7 @@ pub enum RenderingError {
     InstancingLimit,
     InvalidId(DefsLookupErrorKind),
     SvgHasNoSize,
+    OutOfMemory,
 }
 
 impl From<cairo::Status> for RenderingError {
diff --git a/rsvg_internals/src/handle.rs b/rsvg_internals/src/handle.rs
index e0adf6ee..a8eb0459 100644
--- a/rsvg_internals/src/handle.rs
+++ b/rsvg_internals/src/handle.rs
@@ -8,7 +8,7 @@ use std::slice;
 
 use cairo::{self, ImageSurface, Status};
 use cairo_sys;
-use gdk_pixbuf::{Colorspace, Pixbuf, PixbufLoader, PixbufLoaderExt};
+use gdk_pixbuf::{Pixbuf, PixbufLoader, PixbufLoaderExt};
 use gdk_pixbuf_sys;
 use gio::{self, FileExt};
 use gio_sys;
@@ -27,13 +27,9 @@ use error::{set_gerror, DefsLookupErrorKind, LoadingError, RenderingError};
 use io;
 use load::LoadContext;
 use node::{Node, RsvgNode};
-use rect::IRect;
+use pixbuf_utils::pixbuf_from_surface;
 use structure::NodeSvg;
-use surface_utils::{
-    iterators::Pixels,
-    shared_surface::SharedImageSurface,
-    shared_surface::SurfaceType,
-};
+use surface_utils::{shared_surface::SharedImageSurface, shared_surface::SurfaceType};
 use svg::Svg;
 use util::rsvg_g_warning;
 
@@ -555,33 +551,7 @@ impl Handle {
 
         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)
+        pixbuf_from_surface(&surface)
     }
 
     fn construct_new_from_gfile_sync(
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index c1c2ff44..ed906bb4 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -116,6 +116,7 @@ mod parsers;
 mod path_builder;
 mod path_parser;
 mod pattern;
+mod pixbuf_utils;
 mod property_bag;
 mod rect;
 mod shapes;
diff --git a/rsvg_internals/src/pixbuf_utils.rs b/rsvg_internals/src/pixbuf_utils.rs
new file mode 100644
index 00000000..a809518a
--- /dev/null
+++ b/rsvg_internals/src/pixbuf_utils.rs
@@ -0,0 +1,49 @@
+use glib::translate::*;
+
+use error::RenderingError;
+use gdk_pixbuf::{Colorspace, Pixbuf};
+use gdk_pixbuf_sys as ffi;
+use rect::IRect;
+use surface_utils::{iterators::Pixels, shared_surface::SharedImageSurface};
+
+// Pixbuf::new() doesn't return out-of-memory errors properly
+// See https://github.com/gtk-rs/gdk-pixbuf/issues/96
+fn pixbuf_new(width: i32, height: i32) -> Result<Pixbuf, RenderingError> {
+    unsafe {
+        let raw_pixbuf =
+            ffi::gdk_pixbuf_new(Colorspace::Rgb.to_glib(), true.to_glib(), 8, width, height);
+
+        if raw_pixbuf.is_null() {
+            return Err(RenderingError::OutOfMemory);
+        }
+
+        Ok(from_glib_full(raw_pixbuf))
+    }
+}
+
+pub fn pixbuf_from_surface(surface: &SharedImageSurface) -> Result<Pixbuf, RenderingError> {
+    let width = surface.width();
+    let height = surface.height();
+
+    let pixbuf = pixbuf_new(width as i32, height as i32)?;
+
+    let bounds = IRect {
+        x0: 0,
+        y0: 0,
+        x1: width,
+        y1: 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)
+}


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