[librsvg: 1/2] (#547): Do not abort rendering if there is a nonexistent image URL



commit 963b4164cb3b943619bb2c970cbb2fcfb5bea313
Author: Federico Mena Quintero <federico gnome org>
Date:   Thu Feb 6 17:11:18 2020 -0600

    (#547): Do not abort rendering if there is a nonexistent image URL
    
    An element like <image xlink:href="nonexistent.png"/> would cause
    rendering to stop at that point and return with an error.  In this
    case we just need to carry on without rendering the image.
    
    Fixes https://gitlab.gnome.org/GNOME/librsvg/issues/547

 librsvg_crate/tests/bugs.rs | 49 ++++++++++++++++++++++++++++++++++++++++++++-
 rsvg_internals/src/image.rs | 26 ++++++++++++++++++------
 2 files changed, 68 insertions(+), 7 deletions(-)
---
diff --git a/librsvg_crate/tests/bugs.rs b/librsvg_crate/tests/bugs.rs
index 7b755d8a..0743ec95 100644
--- a/librsvg_crate/tests/bugs.rs
+++ b/librsvg_crate/tests/bugs.rs
@@ -2,7 +2,9 @@ use cairo;
 
 mod utils;
 
-use self::utils::{load_svg, render_document, SurfaceSize};
+use rsvg_internals::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
+
+use self::utils::{compare_to_surface, load_svg, render_document, SurfaceSize};
 
 // https://gitlab.gnome.org/GNOME/librsvg/issues/496
 #[test]
@@ -28,3 +30,48 @@ fn inf_width() {
     )
     .unwrap();
 }
+
+// https://gitlab.gnome.org/GNOME/librsvg/issues/547
+#[test]
+fn nonexistent_image_shouldnt_cancel_rendering() {
+    let svg = load_svg(
+        br#"<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"; xmlns:xlink="http://www.w3.org/1999/xlink";
+     width="50" height="50">
+  <image xlink:href="nonexistent.png" width="10" height="10"/>
+  <rect x="10" y="10" width="30" height="30" fill="blue"/>
+</svg>
+"#,
+    );
+
+    let output_surf = render_document(
+        &svg,
+        SurfaceSize(50, 50),
+        |_| (),
+        cairo::Rectangle {
+            x: 0.0,
+            y: 0.0,
+            width: 50.0,
+            height: 50.0,
+        },
+    )
+    .unwrap();
+
+    let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 50, 50).unwrap();
+
+    {
+        let cr = cairo::Context::new(&reference_surf);
+
+        cr.rectangle(10.0, 10.0, 30.0, 30.0);
+        cr.set_source_rgba(0.0, 0.0, 1.0, 1.0);
+        cr.fill();
+    }
+
+    let reference_surf = SharedImageSurface::wrap(reference_surf, SurfaceType::SRgb).unwrap();
+
+    compare_to_surface(
+        &output_surf,
+        &reference_surf,
+        "nonexistent_image_shouldnt_cancel_rendering",
+    );
+}
diff --git a/rsvg_internals/src/image.rs b/rsvg_internals/src/image.rs
index 6e282108..340b6bda 100644
--- a/rsvg_internals/src/image.rs
+++ b/rsvg_internals/src/image.rs
@@ -73,16 +73,30 @@ impl NodeTrait for Image {
 
         let rect = self.get_rect(values, &params);
 
-        if rect.is_empty() {
+        if rect.is_empty() || self.href.is_none() {
             return Ok(draw_ctx.empty_bbox());
         }
 
+        let href = self.href.as_ref().unwrap();
+        let url = match *href {
+            Href::PlainUrl(ref url) => url,
+            Href::WithFragment(_) => {
+                rsvg_log!(
+                    "not rendering {} because its xlink:href cannot contain a fragment identifier",
+                    node
+                );
+
+                return Ok(draw_ctx.empty_bbox());
+            }
+        };
+
         draw_ctx.with_discrete_layer(node, acquired_nodes, values, clipping, &mut |an, dc| {
-            let surface = if let Some(Href::PlainUrl(ref url)) = self.href {
-                an.lookup_image(&url)
-                    .map_err(|_| RenderingError::InvalidHref)?
-            } else {
-                return Ok(dc.empty_bbox());
+            let surface = match an.lookup_image(url) {
+                Ok(surf) => surf,
+                Err(e) => {
+                    rsvg_log!("could not load image \"{}\": {}", url, e);
+                    return Ok(dc.empty_bbox());
+                }
             };
 
             let clip_mode = if !values.is_overflow() && self.aspect.is_slice() {


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