Repository: linebender/resvg (language: rust)

Issue:
Transforms and bbox
This SVG doc:
```xml
<svg width="102" height="124" viewBox="0 0 102 124" fill="none" xmlns="http://www.w3.org/2000/svg">
   <rect width="124" height="102" transform="translate(102) rotate(90)" fill="#7B61FF"/>
</svg>
```
...and this code:
```rust
use usvg::NodeExt;

fn main() {
    let tree = usvg::Tree::from_str(
        include_str!("../simplified.svg"),
        &usvg::Options { ..Default::default() }.to_ref(),
    )
    .unwrap();

    let bbox = tree.root().calculate_bbox().unwrap();
    println!(
        "bbox: {}x{}+{}+{}",
        bbox.width(),
        bbox.height(),
        bbox.x(),
        bbox.y()
    );
}
```
reports a bbox of `124x102+0+0`. Since the rect is rotated by 90 degrees, I'd expect a bbox of `102x124+0+0`. `resvg` renders the document honoring the transform (and only sets pixels within 102x124).

Am I misunderstanding bbox? I really want to know the bounds of the pixels that will be painted by a given document, and I know bbox doesn't consider filter bounds (like drop shadows), so I think I need to write an alternative implementation of bbox anyway, so I am really asking if this is a bug that you'd like a fix for, or if this is expected behavior and any "paint bounds" implementation I make should either exist outside of usvg or be a new method.


Discussion / hints:
This change gives me the bbox result I am expecting; 
```diff
diff --git a/usvg/src/lib.rs b/usvg/src/lib.rs
index 739535f..7042e13 100644
--- a/usvg/src/lib.rs
+++ b/usvg/src/lib.rs
@@ -794,7 +794,9 @@ fn calc_node_bbox(
             let mut bbox = PathBbox::new_bbox();

             for child in node.children() {
-                if let Some(c_bbox) = calc_node_bbox(&child, ts) {
+                let mut child_transform = ts.clone();
+                child_transform.append(&child.transform());
+                if let Some(c_bbox) = calc_node_bbox(&child, child_transform) {
                     bbox = bbox.expand(c_bbox);
                 }
             }
```
Looks like a bug to me. This method is not used by the renderer, it's just a utility.
Fill free to send a patch.

Fix patch:
diff --git a/usvg/src/lib.rs b/usvg/src/lib.rs
index 739535fdf..7042e13ba 100644
--- a/usvg/src/lib.rs
+++ b/usvg/src/lib.rs
@@ -794,7 +794,9 @@ fn calc_node_bbox(
             let mut bbox = PathBbox::new_bbox();
 
             for child in node.children() {
-                if let Some(c_bbox) = calc_node_bbox(&child, ts) {
+                let mut child_transform = ts.clone();
+                child_transform.append(&child.transform());
+                if let Some(c_bbox) = calc_node_bbox(&child, child_transform) {
                     bbox = bbox.expand(c_bbox);
                 }
             }


Test patch: