[librsvg: 5/6] (#346): Return Cairo errors from filters



commit 0a847cce14d776fcd60f6fb1c311e92991bd42ad
Author: Ivan Molodetskikh <yalterz gmail com>
Date:   Tue Sep 25 12:00:30 2018 +0300

    (#346): Return Cairo errors from filters
    
    https://gitlab.gnome.org/GNOME/librsvg/issues/346

 rsvg_internals/src/drawing_ctx.rs     |  2 +-
 rsvg_internals/src/filters/context.rs |  6 +--
 rsvg_internals/src/filters/mod.rs     | 81 ++++++++++++++++++-----------------
 3 files changed, 44 insertions(+), 45 deletions(-)
---
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index fd2aa020..0a021352 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -492,7 +492,7 @@ impl<'a> DrawingCtx<'a> {
 
                 if !filter_node.is_in_error() {
                     // FIXME: deal with out of memory here
-                    Ok(filters::render(&filter_node, values, &output, self))
+                    filters::render(&filter_node, values, &output, self)
                 } else {
                     Ok(child_surface.clone())
                 }
diff --git a/rsvg_internals/src/filters/context.rs b/rsvg_internals/src/filters/context.rs
index 0bb26052..5b7ac446 100644
--- a/rsvg_internals/src/filters/context.rs
+++ b/rsvg_internals/src/filters/context.rs
@@ -380,11 +380,9 @@ impl FilterContext {
     /// The returned surface is in the sRGB color space.
     // TODO: sRGB conversion should probably be done by the caller.
     #[inline]
-    pub fn into_output(self) -> Result<SharedImageSurface, FilterError> {
+    pub fn into_output(self) -> Result<SharedImageSurface, cairo::Status> {
         match self.last_result {
-            Some(FilterOutput { surface, bounds }) => {
-                surface.to_srgb(bounds).map_err(FilterError::CairoError)
-            }
+            Some(FilterOutput { surface, bounds }) => surface.to_srgb(bounds),
             None => {
                 let empty_surface = cairo::ImageSurface::create(
                     cairo::Format::ARgb32,
diff --git a/rsvg_internals/src/filters/mod.rs b/rsvg_internals/src/filters/mod.rs
index 84068201..a2a3ec11 100644
--- a/rsvg_internals/src/filters/mod.rs
+++ b/rsvg_internals/src/filters/mod.rs
@@ -8,7 +8,7 @@ use owning_ref::RcRef;
 use attributes::Attribute;
 use coord_units::CoordUnits;
 use drawing_ctx::DrawingCtx;
-use error::ValueErrorKind;
+use error::{RenderingError, ValueErrorKind};
 use handle::RsvgHandle;
 use length::{Length, LengthDir, LengthUnit};
 use node::{NodeResult, NodeTrait, NodeType, RsvgNode};
@@ -235,7 +235,7 @@ pub fn render(
     computed_from_node_being_filtered: &ComputedValues,
     source: &cairo::ImageSurface,
     draw_ctx: &mut DrawingCtx<'_>,
-) -> cairo::ImageSurface {
+) -> Result<cairo::ImageSurface, RenderingError> {
     let filter_node = &*filter_node;
     assert_eq!(filter_node.get_type(), NodeType::Filter);
     assert!(!filter_node.is_in_error());
@@ -246,13 +246,13 @@ pub fn render(
         cairo::Format::ARgb32,
         source.get_width(),
         source.get_height(),
-    ).unwrap();
+    )?;
     {
         let cr = cairo::Context::new(&source_surface);
         cr.set_source_surface(source, 0f64, 0f64);
         cr.paint();
     }
-    let source_surface = SharedImageSurface::new(source_surface, SurfaceType::SRgb).unwrap();
+    let source_surface = SharedImageSurface::new(source_surface, SurfaceType::SRgb)?;
 
     let mut filter_ctx = FilterContext::new(
         filter_node,
@@ -264,14 +264,10 @@ pub fn render(
     // If paffine is non-invertible, we won't draw anything. Also bbox combining in bounds
     // computations will panic due to non-invertible martrix.
     if filter_ctx.paffine().try_invert().is_err() {
-        return filter_ctx
-            .into_output()
-            .expect("could not create an empty surface to return from a filter")
-            .into_image_surface()
-            .expect("could not convert filter output into an ImageSurface");
+        return Ok(filter_ctx.into_output()?.into_image_surface()?);
     }
 
-    filter_node
+    let primitives = filter_node
         .children()
         // Skip nodes in error.
         .filter(|c| {
@@ -340,39 +336,44 @@ pub fn render(
                 }).ok();
 
             rr.map(|rr| (rr, linear_rgb))
-        }).for_each(|(rr, linear_rgb)| {
-            let mut render = |filter_ctx: &mut FilterContext| {
-                if let Err(err) = rr
-                    .render(rr.owner(), filter_ctx, draw_ctx)
-                    .and_then(|result| filter_ctx.store_result(result))
-                {
-                    rsvg_log!(
-                        "(filter primitive {} returned an error: {})",
-                        rr.owner().get_human_readable_name(),
-                        err
-                    );
-                }
-            };
+        });
 
-            let start = Instant::now();
+    for (rr, linear_rgb) in primitives {
+        let mut render = |filter_ctx: &mut FilterContext| {
+            if let Err(err) = rr
+                .render(rr.owner(), filter_ctx, draw_ctx)
+                .and_then(|result| filter_ctx.store_result(result))
+            {
+                rsvg_log!(
+                    "(filter primitive {} returned an error: {})",
+                    rr.owner().get_human_readable_name(),
+                    err
+                );
 
-            if rr.is_affected_by_color_interpolation_filters() && linear_rgb {
-                filter_ctx.with_linear_rgb(render);
-            } else {
-                render(&mut filter_ctx);
+                // Exit early on Cairo errors. Continue rendering otherwise.
+                if let FilterError::CairoError(status) = err {
+                    return Err(status);
+                }
             }
 
-            let elapsed = start.elapsed();
-            rsvg_log!(
-                "(rendered filter primitive {} in\n    {} seconds)",
-                rr.owner().get_human_readable_name(),
-                elapsed.as_secs() as f64 + f64::from(elapsed.subsec_nanos()) / 1e9
-            );
-        });
+            Ok(())
+        };
+
+        let start = Instant::now();
+
+        if rr.is_affected_by_color_interpolation_filters() && linear_rgb {
+            filter_ctx.with_linear_rgb(render)?;
+        } else {
+            render(&mut filter_ctx)?;
+        }
+
+        let elapsed = start.elapsed();
+        rsvg_log!(
+            "(rendered filter primitive {} in\n    {} seconds)",
+            rr.owner().get_human_readable_name(),
+            elapsed.as_secs() as f64 + f64::from(elapsed.subsec_nanos()) / 1e9
+        );
+    }
 
-    filter_ctx
-        .into_output()
-        .expect("could not create an empty surface to return from a filter")
-        .into_image_surface()
-        .expect("could not convert filter output into an ImageSurface")
+    Ok(filter_ctx.into_output()?.into_image_surface()?)
 }


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