From 8ff49c46a42f6f62e97fc0f54fa9c570c1b6ce05 Mon Sep 17 00:00:00 2001 From: Adrien Burgun Date: Sun, 31 Jul 2022 17:13:10 +0200 Subject: [PATCH] :sparkles: Merge in output SVG --- src/export.rs | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/src/export.rs b/src/export.rs index c7c0122..7537777 100644 --- a/src/export.rs +++ b/src/export.rs @@ -3,7 +3,7 @@ use usvg::{ NodeExt, Options, }; -use xmltree::{Element}; +use xmltree::{XMLNode, Element}; use std::path::{PathBuf}; use std::collections::HashSet; @@ -48,7 +48,7 @@ impl From for ExportError { } } -pub fn get_new_bbox(svg: &Tree) -> Option<(f64, f64, f64, f64)> { +fn get_new_bbox(svg: &Tree) -> Option<(f64, f64, f64, f64)> { let bbox = svg.root().calculate_bbox()?; // FIXME: remove once https://github.com/RazrFalcon/resvg/issues/528 is fixed @@ -101,6 +101,45 @@ pub fn resize(svg_str: String) -> Result { } } +/// Finds all the `` in the svg and combines them all into one +pub fn combine_defs(svg_str: String) -> Result { + let mut svg_xml = get_xml(&svg_str)?; + + let mut defs = Vec::new(); + + fn collect_defs(element: &mut Element, defs: &mut Vec) { + for child in std::mem::take(&mut element.children) { + match child { + XMLNode::Element(child) if child.name == "defs" => { + defs.push(child); + } + mut child => { + if let XMLNode::Element(ref mut child) = &mut child { + collect_defs(child, defs); + } + element.children.push(child); + } + } + } + } + + collect_defs(&mut svg_xml, &mut defs); + + let mut defs_element = Element::new("defs"); + defs_element.children = defs + .into_iter() + .map(|def| { + def.children.into_iter().filter(|child| matches!(child, XMLNode::Element(_))) + }) + .flatten() + .collect::>(); + defs_element.attributes.insert("id".to_string(), "defs".to_string()); + + svg_xml.children.insert(0, XMLNode::Element(defs_element)); + + xml_to_str(&svg_xml) +} + pub fn export( mut svg_str: String, output_dir: &PathBuf, @@ -111,6 +150,8 @@ pub fn export( svg_str = resize(svg_str)?; } + svg_str = combine_defs(svg_str)?; + mkdirp::mkdirp(output_dir.join("vector")).unwrap(); let output = output_dir.join(&format!("vector/{}.svg", output_name));