RazrFalcon / resvg

An SVG rendering library.
Mozilla Public License 2.0
2.74k stars 220 forks source link

Tree question: Is it possible to append a `usvg::Tree` with another `usvg::Tree` #529

Closed LetsMelon closed 2 years ago

LetsMelon commented 2 years ago

Sorry if the question is silly, but I have no idea what's the best method to append a usvg::Tree with another usvg::Tree.

Let's say we modify the code of examples/minimal.rs to accept two SVG files and combine them into one tree and render them. I tried everything from a loop over rtree.root().descendants() to hack something together with 'thousand' methods, but it wasn't really working.

Modified examples/minimal.rs code:

fn main() {
    let args: Vec<String> = std::env::args().collect();
    if args.len() != 4 {
        println!("Usage:\n\tmultiple <in-1-svg> <in-2-svg> <out-png>");
        return;
    }

    let mut opt = usvg::Options::default();
    opt.fontdb.load_system_fonts();

    // first svg file
    opt.resources_dir = std::fs::canonicalize(&args[1]).ok().and_then(|p| p.parent().map(|p| p.to_path_buf()));
    let svg_data = std::fs::read(&args[1]).unwrap();
    let rtree_1 = usvg::Tree::from_data(&svg_data, &opt.to_ref()).unwrap();

    // second svg file
    opt.resources_dir = std::fs::canonicalize(&args[2]).ok().and_then(|p| p.parent().map(|p| p.to_path_buf()));
    let svg_data = std::fs::read(&args[2]).unwrap();
    let rtree_2 = usvg::Tree::from_data(&svg_data, &opt.to_ref()).unwrap();

    // Help wanted? How to combine the two tree's into on and keep them "grouped"
}
RazrFalcon commented 2 years ago

While you can, you shouldn't. You must treat usvg::Tree as read-only. It's mutable now due to the fact that the tree is based on Rc, which cannot be immutable, kinda. Future resvg updates, hopefully, would have a read-only tree. Or maybe not a tree at all. Will see.

As for now, simply use tree.root().append() and append_to_defs() for each node. If you're looking for some sort of existing solution - there is none.

LetsMelon commented 2 years ago

Yeah I'm kinda exploiting the kinda immutable tree for a project of mine (relevant code). But nevertheless thanks for the fast response.

RazrFalcon commented 2 years ago

As for animations, I would suggest converting usvg::Tree into your own representation. usvg is mainly designed as an SVG preprocessor to remove all the complexity it has. And there are a lot. Also, resvg isn't really validating the input usvg::Tree which may lead to weird bugs.

Also, tiny-skia is too slow for real-time rendering. Hopefully someone would eventually write a decent 2D GPU library. Skia (not tiny-skia) is 400 KLOC for a reason...