[librsvg: 1/2] Apply width, height when `<use>`ing an `<svg>`




commit ffbec91a10f98584e960dfb29c996ba0856b18d4
Author: Michael Howell <michael notriddle com>
Date:   Fri Sep 2 17:08:55 2022 -0700

    Apply width, height when `<use>`ing an `<svg>`
    
    Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/739>

 src/drawing_ctx.rs                                 | 29 ++++++++++++++--------
 src/structure.rs                                   |  8 ++++++
 .../bugs-reftests/875-svg-use-width-height-ref.svg |  4 +++
 .../bugs-reftests/875-svg-use-width-height.svg     |  9 +++++++
 tests/src/reference.rs                             |  6 +++++
 5 files changed, 45 insertions(+), 11 deletions(-)
---
diff --git a/src/drawing_ctx.rs b/src/drawing_ctx.rs
index 836f434fc..e7f0b3bfa 100644
--- a/src/drawing_ctx.rs
+++ b/src/drawing_ctx.rs
@@ -1678,16 +1678,27 @@ impl DrawingCtx {
 
         let use_element = node.borrow_element();
 
-        let res = if is_element_of_type!(child, Symbol) {
-            // if the <use> references a <symbol>, it gets handled specially
+        let defines_a_viewport = if is_element_of_type!(child, Symbol) {
+            let symbol = borrow_element_as!(child, Symbol);
+            Some((symbol.get_viewbox(), symbol.get_preserve_aspect_ratio()))
+        } else if is_element_of_type!(child, Svg) {
+            let svg = borrow_element_as!(child, Svg);
+            Some((svg.get_viewbox(), svg.get_preserve_aspect_ratio()))
+        } else {
+            None
+        };
+
+        let res = if let Some((viewbox, preserve_aspect_ratio)) = defines_a_viewport {
+            // <symbol> and <svg> define a viewport, as described in the specification:
+            // https://www.w3.org/TR/SVG2/struct.html#UseElement
+            // https://gitlab.gnome.org/GNOME/librsvg/-/issues/875#note_1482705
 
             let elt = child.borrow_element();
 
-            let symbol = borrow_element_as!(child, Symbol);
-            let symbol_values = elt.get_computed_values();
+            let values = elt.get_computed_values();
 
             // FIXME: do we need to look at preserveAspectRatio.slice, like in draw_image()?
-            let clip_mode = if !symbol_values.is_overflow() {
+            let clip_mode = if !values.is_overflow() {
                 ClipMode::ClipToViewport
             } else {
                 ClipMode::NoClip
@@ -1708,12 +1719,8 @@ impl DrawingCtx {
                 clipping,
                 None,
                 &mut |an, dc, _transform| {
-                    let _params = dc.push_new_viewport(
-                        symbol.get_viewbox(),
-                        use_rect,
-                        symbol.get_preserve_aspect_ratio(),
-                        clip_mode,
-                    );
+                    let _params =
+                        dc.push_new_viewport(viewbox, use_rect, preserve_aspect_ratio, clip_mode);
 
                     child.draw_children(
                         an,
diff --git a/src/structure.rs b/src/structure.rs
index da42551a2..425cdb599 100644
--- a/src/structure.rs
+++ b/src/structure.rs
@@ -213,6 +213,14 @@ impl Svg {
         Rect::new(nx, ny, nx + nw, ny + nh)
     }
 
+    pub fn get_viewbox(&self) -> Option<ViewBox> {
+        self.vbox
+    }
+
+    pub fn get_preserve_aspect_ratio(&self) -> AspectRatio {
+        self.preserve_aspect_ratio
+    }
+
     fn push_viewport(
         &self,
         node: &Node,
diff --git a/tests/fixtures/reftests/bugs-reftests/875-svg-use-width-height-ref.svg 
b/tests/fixtures/reftests/bugs-reftests/875-svg-use-width-height-ref.svg
new file mode 100644
index 000000000..a68e5c3ab
--- /dev/null
+++ b/tests/fixtures/reftests/bugs-reftests/875-svg-use-width-height-ref.svg
@@ -0,0 +1,4 @@
+<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"; xmlns:xlink="http://www.w3.org/1999/xlink";>
+  <rect fill="none" stroke="green" stroke-width="5" width="100%" height="100%"/>
+  <rect x="45%" y="45%" width="10%" height="10%" fill="red"/>
+</svg>
diff --git a/tests/fixtures/reftests/bugs-reftests/875-svg-use-width-height.svg 
b/tests/fixtures/reftests/bugs-reftests/875-svg-use-width-height.svg
new file mode 100644
index 000000000..54da0bc1f
--- /dev/null
+++ b/tests/fixtures/reftests/bugs-reftests/875-svg-use-width-height.svg
@@ -0,0 +1,9 @@
+<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"; xmlns:xlink="http://www.w3.org/1999/xlink";>
+  <defs>
+    <svg id="a">
+      <rect width="100%" height="100%" fill="red"/>
+    </svg>
+  </defs>
+  <rect fill="none" stroke="green" stroke-width="5" width="100%" height="100%"/>
+  <use xlink:href="#a" x="45%" y="45%" width="10%" height="10%"/>
+</svg>
diff --git a/tests/src/reference.rs b/tests/src/reference.rs
index 00d6428c1..a00cb0cef 100644
--- a/tests/src/reference.rs
+++ b/tests/src/reference.rs
@@ -412,3 +412,9 @@ test_svg_reference!(
     "tests/fixtures/reftests/bugs-reftests/92-symbol-clip.svg",
     "tests/fixtures/reftests/bugs-reftests/92-symbol-clip-ref.svg"
 );
+
+test_svg_reference!(
+    bug_875_svg_use_width_height,
+    "tests/fixtures/reftests/bugs-reftests/875-svg-use-width-height.svg",
+    "tests/fixtures/reftests/bugs-reftests/875-svg-use-width-height-ref.svg"
+);


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