Skip to main content

esoc_chart/
figure.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2//! Figure: top-level chart container.
3
4use crate::axes::Axes;
5use crate::error::Result;
6use crate::render::render_figure;
7use crate::theme::Theme;
8
9/// A figure is the top-level container for one or more plot areas.
10pub struct Figure {
11    /// Figure width in pixels.
12    pub width: f64,
13    /// Figure height in pixels.
14    pub height: f64,
15    /// Figure title.
16    pub title: Option<String>,
17    /// Theme.
18    pub theme: Theme,
19    /// Plot areas.
20    pub(crate) axes: Vec<Axes>,
21}
22
23impl Figure {
24    /// Create a new figure with default dimensions.
25    pub fn new() -> Self {
26        Self {
27            width: 800.0,
28            height: 600.0,
29            title: None,
30            theme: Theme::default(),
31            axes: Vec::new(),
32        }
33    }
34
35    /// Set the figure size.
36    pub fn size(mut self, width: f64, height: f64) -> Self {
37        self.width = width;
38        self.height = height;
39        self
40    }
41
42    /// Set the figure title.
43    pub fn title(mut self, title: impl Into<String>) -> Self {
44        self.title = Some(title.into());
45        self
46    }
47
48    /// Set the theme.
49    pub fn theme(mut self, theme: Theme) -> Self {
50        self.theme = theme;
51        self
52    }
53
54    /// Add a new axes (plot area) and return a mutable reference to it.
55    pub fn add_axes(&mut self) -> &mut Axes {
56        self.axes.push(Axes::new());
57        self.axes.last_mut().unwrap()
58    }
59
60    /// Render to an SVG string.
61    pub fn to_svg(&self) -> Result<String> {
62        let canvas = render_figure(self)?;
63        let svg = esoc_gfx::backend::svg::render_svg(&canvas)?;
64        Ok(svg)
65    }
66
67    /// Save as an SVG file.
68    pub fn save_svg(&self, path: &str) -> Result<()> {
69        let svg = self.to_svg()?;
70        std::fs::write(path, svg)?;
71        Ok(())
72    }
73
74    /// Render to PNG bytes (requires `png` feature).
75    #[cfg(feature = "png")]
76    pub fn to_png(&self) -> Result<Vec<u8>> {
77        use esoc_gfx::backend::RenderBackend;
78        let canvas = render_figure(self)?;
79        let bytes = esoc_gfx::backend::png::PngBackend
80            .render(&canvas)
81            .map_err(crate::error::ChartError::Gfx)?;
82        Ok(bytes)
83    }
84
85    /// Save as a PNG file (requires `png` feature).
86    #[cfg(feature = "png")]
87    pub fn save_png(&self, path: &str) -> Result<()> {
88        let bytes = self.to_png()?;
89        std::fs::write(path, bytes)?;
90        Ok(())
91    }
92}
93
94impl Default for Figure {
95    fn default() -> Self {
96        Self::new()
97    }
98}