adic_shape/svg_doc/
svg_doc_display.rs

1use itertools::Itertools;
2use svg::{Document, node::element as svg_el};
3use crate::{AdicEl, DisplayShape};
4
5
6/// For plotting different SVGs
7///
8/// Use this trait when you have a shape and you want to print or save an SVG for it.
9/// The [`create_svg_doc`](Self::create_svg_doc) method returns an [`svg::Document`] for the shape.
10pub trait SvgDocDisplay: DisplayShape {
11
12    /// Create an SVG document for the shape
13    fn create_svg_doc(&self) -> svg::Document {
14
15        let viewbox_str = self.viewbox_str();
16        let style_comps = self.shape_style_els();
17        let svg_comps = self.shape_svg_els();
18
19        // Wrap in svg
20        let document = Document::new()
21            .set("class", self.default_class())
22            .set("viewBox", viewbox_str)
23            .set("xmlns", "http://www.w3.org/2000/svg");
24        style_comps.chain(svg_comps).fold(document, Document::add)
25
26    }
27
28
29    /// Iterator through the style elements for the svg
30    fn shape_style_els(&self) -> impl Iterator<Item=svg_el::Element>;
31
32
33    /// Iterator through all the components of the svg
34    fn shape_svg_els(&self) -> impl Iterator<Item=svg_el::Element> {
35        self.adic_els().map(|adic_el| match adic_el {
36            AdicEl::Circle(c) => svg_el::Element::from({
37                let mut circle = svg_el::Circle::new();
38                if let Some(class) = c.class {
39                    circle = circle.set("class", class);
40                }
41                circle = circle.set("cx", c.cx).set("cy", c.cy).set("r", c.r);
42                circle
43            }),
44            AdicEl::Path(p) => svg_el::Element::from({
45                let mut path = svg_el::Path::new();
46                if let Some(class) = p.class {
47                    path = path.set("class", class);
48                }
49                path = path.set("d", p.d.into_iter().map(String::from).join(" "));
50                path
51            }),
52            AdicEl::Text(t) => svg_el::Element::from({
53                let mut text = svg_el::Text::new(t.content);
54                if let Some(class) = t.class {
55                    text = text.set("class", class);
56                }
57                if let Some(style) = t.style {
58                    text = text.set("style", style);
59                }
60                text = text.set("x", t.x).set("y", t.y).set("dx", t.dx).set("dy", t.dy);
61                text
62            })
63        })
64    }
65
66}