pub struct SvgDocument { /* private fields */ }Expand description
Represents an SVG document with a specified width and height. It contains clip paths, styles,
layers, and symbols that can be used to create SVG graphics. Although you can directly
manipulate the SVG document, it is recommended to use higher level objects in this library such
as Chart struct for creating scaled charts with x and y axis.
The SvgDocument struct is the main entry point for creating SVG documents in this library.
A SVG-global style sheet can be set using the scss field, which is a string containing SCSS
styles. The styles are compiled to CSS using the grass crate when the SVG document is rendered.
This allows for flexible styling of SVG elements using SCSS syntax, and verified the validity of the SCSS parameters
before rendering. You can append additional SCSS styles using the append_scss method.
Any css file is also a valid SCSS file, so you can use any CSS file as a stylesheet.
The style sheet is embedded in the SVG document as a <style> element, which is
the most convenient way to handle SVG images with styles.
You don’t have to use a global style, you can set styles for individual elements using the
StyleAttr parameter in all the plot element and plot functions.
Implementations§
Source§impl SvgDocument
impl SvgDocument
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates a new SvgDocument with default settings only,
without any nodes, symbols, or plots.
Examples found in repository?
5pub fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let pi = std::f64::consts::PI;
7 let pi2 = 2.0 * pi;
8
9 const N: i32 = 100;
10 let sin: Vec<(f64, f64)> = (0..N)
11 .map(|i| {
12 let x = i as f64 * pi2 / (N as f64 - 1.0);
13 (x, x.sin())
14 })
15 .collect();
16
17 let chart = XYChart::new((600, 300), (..pi2, -1.1..1.1))
18 .x_labels(1.0, 10, None)
19 .y_labels(0.5, 10, None)
20 .x_axis_description("x", None)
21 .y_axis_description("sin(x)", None)
22 .plot_grid(0.2, 0.1, class("fine-grid"))
23 .plot_grid(1.0, 0.5, class("grid"))
24 .plot_poly_line(sin, class("curve"))
25 .plot_poly_line(vec![(0.0, 0.0), (pi2, 0.0)], class("base-line"));
26
27 SvgDocument::new()
28 .append_scss(STYLE)
29 .add_plot(Box::new(chart))
30 .save("docs/img/sine_curve.svg")
31}More examples
20pub fn make_plot(space: RgbSpace) -> Result<(), Box<dyn std::error::Error>> {
21 let observer = Observer::Cie1931; // Use the CIE 1931 observer
22 // let space = RgbSpace::DisplayP3; // Use the sRGB color space
23
24 // Create an XYChromaticity chart with the specified observer and ranges
25 let xy_chromaticity = XYChromaticity::new((775, 875), (-0.025..=0.75, 0.0..=0.875))
26 .ticks(0.01, 0.01, 5, class("fine-grid"))
27 .ticks(0.1, 0.1, 10, class("grid"))
28 .x_labels(0.1, 10, None)
29 .x_axis_description(&format!("{} x", observer.name()), None)
30 .y_labels(0.1, 10, class("y-labels"))
31 .y_axis_description(&format!("{} y", observer.name()), None)
32 .plot_spectral_locus(class("spectral-locus"))
33 .plot_spectral_locus_ticks(440..=650, 10, 15, class("spectral-locus-ticks"))
34 .plot_spectral_locus_ticks(460..=630, 1, 7, class("spectral-locus-ticks"))
35 .plot_spectral_locus_labels(460..=620, 10, 3, class("spectral-locus-labels"))
36 .plot_rgb_gamut(space, None)
37 .plot_planckian_locus(class("planckian"))
38 .plot_planckian_locus_ticks((1500..=7500).step_by(100), 7, class("planckian-ticks-fine"))
39 .plot_planckian_locus_ticks(PLANCKIAN_LABELS_AT.to_vec(), 15, class("planckian-ticks"))
40 .plot_planckian_locus_labels(PLANCKIAN_LABELS_AT.to_vec(), 18, class("planckian-labels"))
41 .plot_grid(0.01, 0.01, class("fine-grid"))
42 .plot_grid(0.1, 0.1, class("grid"));
43
44 // create the plot
45 SvgDocument::new()
46 .append_scss(STYLE)
47 .add_plot(Box::new(xy_chromaticity))
48 .save(format!("docs/img/{}_gamut.svg", space.as_ref().to_lowercase()).as_str())?;
49 Ok(())
50}Sourcepub fn append_scss(self, css: &str) -> Self
pub fn append_scss(self, css: &str) -> Self
Appends SCSS styles to the document’s stylesheet. This method allows you to add additional styles to the existing SCSS content. The styles are compiled to CSS when the document is rendered.
Most covenient is to use a separate SCSS file and include it using the append_scss method
using include_str! macro, which reads the file at compile time.
The SCSS styles are compiled to CSS using the grass crate when the SVG document is rendered,
and embedded in the resulting SVG document as a <style> element.
Using a seperate SCSS file allows you to keep your styles organized and maintainable, and also allows you to edit the styles in a lanaguate aware editor with syntax highlighting and autocompletion.
§Example
// The file in the include_str! macro is just an example, and gives a compile error if the file does not exist.
use colorimetry_plot::svgdoc::SvgDocument;
// Create a new SVG document and append SCSS styles from a file
let svg_doc = SvgDocument::new()
.append_scss(include_str!("path/to/your/styles.scss"));Examples found in repository?
5pub fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let pi = std::f64::consts::PI;
7 let pi2 = 2.0 * pi;
8
9 const N: i32 = 100;
10 let sin: Vec<(f64, f64)> = (0..N)
11 .map(|i| {
12 let x = i as f64 * pi2 / (N as f64 - 1.0);
13 (x, x.sin())
14 })
15 .collect();
16
17 let chart = XYChart::new((600, 300), (..pi2, -1.1..1.1))
18 .x_labels(1.0, 10, None)
19 .y_labels(0.5, 10, None)
20 .x_axis_description("x", None)
21 .y_axis_description("sin(x)", None)
22 .plot_grid(0.2, 0.1, class("fine-grid"))
23 .plot_grid(1.0, 0.5, class("grid"))
24 .plot_poly_line(sin, class("curve"))
25 .plot_poly_line(vec![(0.0, 0.0), (pi2, 0.0)], class("base-line"));
26
27 SvgDocument::new()
28 .append_scss(STYLE)
29 .add_plot(Box::new(chart))
30 .save("docs/img/sine_curve.svg")
31}More examples
20pub fn make_plot(space: RgbSpace) -> Result<(), Box<dyn std::error::Error>> {
21 let observer = Observer::Cie1931; // Use the CIE 1931 observer
22 // let space = RgbSpace::DisplayP3; // Use the sRGB color space
23
24 // Create an XYChromaticity chart with the specified observer and ranges
25 let xy_chromaticity = XYChromaticity::new((775, 875), (-0.025..=0.75, 0.0..=0.875))
26 .ticks(0.01, 0.01, 5, class("fine-grid"))
27 .ticks(0.1, 0.1, 10, class("grid"))
28 .x_labels(0.1, 10, None)
29 .x_axis_description(&format!("{} x", observer.name()), None)
30 .y_labels(0.1, 10, class("y-labels"))
31 .y_axis_description(&format!("{} y", observer.name()), None)
32 .plot_spectral_locus(class("spectral-locus"))
33 .plot_spectral_locus_ticks(440..=650, 10, 15, class("spectral-locus-ticks"))
34 .plot_spectral_locus_ticks(460..=630, 1, 7, class("spectral-locus-ticks"))
35 .plot_spectral_locus_labels(460..=620, 10, 3, class("spectral-locus-labels"))
36 .plot_rgb_gamut(space, None)
37 .plot_planckian_locus(class("planckian"))
38 .plot_planckian_locus_ticks((1500..=7500).step_by(100), 7, class("planckian-ticks-fine"))
39 .plot_planckian_locus_ticks(PLANCKIAN_LABELS_AT.to_vec(), 15, class("planckian-ticks"))
40 .plot_planckian_locus_labels(PLANCKIAN_LABELS_AT.to_vec(), 18, class("planckian-labels"))
41 .plot_grid(0.01, 0.01, class("fine-grid"))
42 .plot_grid(0.1, 0.1, class("grid"));
43
44 // create the plot
45 SvgDocument::new()
46 .append_scss(STYLE)
47 .add_plot(Box::new(xy_chromaticity))
48 .save(format!("docs/img/{}_gamut.svg", space.as_ref().to_lowercase()).as_str())?;
49 Ok(())
50}Sourcepub fn set_margin(self, margin: u32) -> Self
pub fn set_margin(self, margin: u32) -> Self
Sets the margin for the SVG document. The margin is applied to the width and height of the document when calculating the size of sub plots. The default margin is 50 pixels.
Sourcepub fn set_width(self, width: u32) -> Self
pub fn set_width(self, width: u32) -> Self
Sets the width of the SVG document. If not set, the width will be calculated based on the size of the sub plots and the margin. If the width is larger than the maximum allowed size, an error will be printed and the program will exit. The width is set in pixels.
Sourcepub fn set_height(self, height: u32) -> Self
pub fn set_height(self, height: u32) -> Self
Sets the height of the SVG document. If not set, the height will be calculated based on the size of the sub plots and the margin. If the height is larger than the maximum allowed size, an error will be printed and the program will exit. The height is set in pixels.
Sourcepub fn add_clip_path(self, id: String, path: &Path) -> Self
pub fn add_clip_path(self, id: String, path: &Path) -> Self
Adds a path to the SVG document as a clip path with the specified ID.
Sourcepub fn add_symbol(self, symbol: impl Into<Symbol>) -> Self
pub fn add_symbol(self, symbol: impl Into<Symbol>) -> Self
Adds a symbol to the SVG document.
Sourcepub fn add_node(self, node: impl Into<Box<dyn Node>>) -> Self
pub fn add_node(self, node: impl Into<Box<dyn Node>>) -> Self
Adds a node to the SVG document, typically used for headers, footers, or other SVG elements. They will be added to the SVG document as-is, without any transformations or scaling, and placed in front of any other content, into a layer with the id “front”.
Sourcepub fn add_plot(self, svg_sub: Box<dyn Rendable>) -> Self
pub fn add_plot(self, svg_sub: Box<dyn Rendable>) -> Self
Adds a sub plot to the SVG document.
The sub plot must implement the Rendable trait, which allows it to be rendered as an SVG element.
The sub plot will be positioned based on the document’s flow, which is calculated by the flow method.
If the sub plot is larger than the document size, an error will be printed and the program will exit.
Examples found in repository?
5pub fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let pi = std::f64::consts::PI;
7 let pi2 = 2.0 * pi;
8
9 const N: i32 = 100;
10 let sin: Vec<(f64, f64)> = (0..N)
11 .map(|i| {
12 let x = i as f64 * pi2 / (N as f64 - 1.0);
13 (x, x.sin())
14 })
15 .collect();
16
17 let chart = XYChart::new((600, 300), (..pi2, -1.1..1.1))
18 .x_labels(1.0, 10, None)
19 .y_labels(0.5, 10, None)
20 .x_axis_description("x", None)
21 .y_axis_description("sin(x)", None)
22 .plot_grid(0.2, 0.1, class("fine-grid"))
23 .plot_grid(1.0, 0.5, class("grid"))
24 .plot_poly_line(sin, class("curve"))
25 .plot_poly_line(vec![(0.0, 0.0), (pi2, 0.0)], class("base-line"));
26
27 SvgDocument::new()
28 .append_scss(STYLE)
29 .add_plot(Box::new(chart))
30 .save("docs/img/sine_curve.svg")
31}More examples
20pub fn make_plot(space: RgbSpace) -> Result<(), Box<dyn std::error::Error>> {
21 let observer = Observer::Cie1931; // Use the CIE 1931 observer
22 // let space = RgbSpace::DisplayP3; // Use the sRGB color space
23
24 // Create an XYChromaticity chart with the specified observer and ranges
25 let xy_chromaticity = XYChromaticity::new((775, 875), (-0.025..=0.75, 0.0..=0.875))
26 .ticks(0.01, 0.01, 5, class("fine-grid"))
27 .ticks(0.1, 0.1, 10, class("grid"))
28 .x_labels(0.1, 10, None)
29 .x_axis_description(&format!("{} x", observer.name()), None)
30 .y_labels(0.1, 10, class("y-labels"))
31 .y_axis_description(&format!("{} y", observer.name()), None)
32 .plot_spectral_locus(class("spectral-locus"))
33 .plot_spectral_locus_ticks(440..=650, 10, 15, class("spectral-locus-ticks"))
34 .plot_spectral_locus_ticks(460..=630, 1, 7, class("spectral-locus-ticks"))
35 .plot_spectral_locus_labels(460..=620, 10, 3, class("spectral-locus-labels"))
36 .plot_rgb_gamut(space, None)
37 .plot_planckian_locus(class("planckian"))
38 .plot_planckian_locus_ticks((1500..=7500).step_by(100), 7, class("planckian-ticks-fine"))
39 .plot_planckian_locus_ticks(PLANCKIAN_LABELS_AT.to_vec(), 15, class("planckian-ticks"))
40 .plot_planckian_locus_labels(PLANCKIAN_LABELS_AT.to_vec(), 18, class("planckian-labels"))
41 .plot_grid(0.01, 0.01, class("fine-grid"))
42 .plot_grid(0.1, 0.1, class("grid"));
43
44 // create the plot
45 SvgDocument::new()
46 .append_scss(STYLE)
47 .add_plot(Box::new(xy_chromaticity))
48 .save(format!("docs/img/{}_gamut.svg", space.as_ref().to_lowercase()).as_str())?;
49 Ok(())
50}Sourcepub fn flow(&self) -> Vec<(u32, u32)>
pub fn flow(&self) -> Vec<(u32, u32)>
Calculates the positions of the sub plots on the document.
The positions are calculated based on the document’s width and height,
and the size of the sub plots. If there is only one sub plot, it will be centered in the document.
If there are multiple sub plots, the flow is not yet implemented and will return todo!().
The sub plots will not be scaled, but positioned based on the document’s flow.
If the sub plot is larger than the document size, an error will be printed and the program will exit.
§Returns
A vector of tuples containing the x and y positions of each sub plot in the document.
pub fn calculate_subplots_size_with_margin(&self) -> (u32, u32)
Sourcepub fn save(self, filename: &str) -> Result<(), Box<dyn Error>>
pub fn save(self, filename: &str) -> Result<(), Box<dyn Error>>
Examples found in repository?
5pub fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let pi = std::f64::consts::PI;
7 let pi2 = 2.0 * pi;
8
9 const N: i32 = 100;
10 let sin: Vec<(f64, f64)> = (0..N)
11 .map(|i| {
12 let x = i as f64 * pi2 / (N as f64 - 1.0);
13 (x, x.sin())
14 })
15 .collect();
16
17 let chart = XYChart::new((600, 300), (..pi2, -1.1..1.1))
18 .x_labels(1.0, 10, None)
19 .y_labels(0.5, 10, None)
20 .x_axis_description("x", None)
21 .y_axis_description("sin(x)", None)
22 .plot_grid(0.2, 0.1, class("fine-grid"))
23 .plot_grid(1.0, 0.5, class("grid"))
24 .plot_poly_line(sin, class("curve"))
25 .plot_poly_line(vec![(0.0, 0.0), (pi2, 0.0)], class("base-line"));
26
27 SvgDocument::new()
28 .append_scss(STYLE)
29 .add_plot(Box::new(chart))
30 .save("docs/img/sine_curve.svg")
31}More examples
20pub fn make_plot(space: RgbSpace) -> Result<(), Box<dyn std::error::Error>> {
21 let observer = Observer::Cie1931; // Use the CIE 1931 observer
22 // let space = RgbSpace::DisplayP3; // Use the sRGB color space
23
24 // Create an XYChromaticity chart with the specified observer and ranges
25 let xy_chromaticity = XYChromaticity::new((775, 875), (-0.025..=0.75, 0.0..=0.875))
26 .ticks(0.01, 0.01, 5, class("fine-grid"))
27 .ticks(0.1, 0.1, 10, class("grid"))
28 .x_labels(0.1, 10, None)
29 .x_axis_description(&format!("{} x", observer.name()), None)
30 .y_labels(0.1, 10, class("y-labels"))
31 .y_axis_description(&format!("{} y", observer.name()), None)
32 .plot_spectral_locus(class("spectral-locus"))
33 .plot_spectral_locus_ticks(440..=650, 10, 15, class("spectral-locus-ticks"))
34 .plot_spectral_locus_ticks(460..=630, 1, 7, class("spectral-locus-ticks"))
35 .plot_spectral_locus_labels(460..=620, 10, 3, class("spectral-locus-labels"))
36 .plot_rgb_gamut(space, None)
37 .plot_planckian_locus(class("planckian"))
38 .plot_planckian_locus_ticks((1500..=7500).step_by(100), 7, class("planckian-ticks-fine"))
39 .plot_planckian_locus_ticks(PLANCKIAN_LABELS_AT.to_vec(), 15, class("planckian-ticks"))
40 .plot_planckian_locus_labels(PLANCKIAN_LABELS_AT.to_vec(), 18, class("planckian-labels"))
41 .plot_grid(0.01, 0.01, class("fine-grid"))
42 .plot_grid(0.1, 0.1, class("grid"));
43
44 // create the plot
45 SvgDocument::new()
46 .append_scss(STYLE)
47 .add_plot(Box::new(xy_chromaticity))
48 .save(format!("docs/img/{}_gamut.svg", space.as_ref().to_lowercase()).as_str())?;
49 Ok(())
50}Trait Implementations§
Source§impl Default for SvgDocument
impl Default for SvgDocument
Source§fn default() -> SvgDocument
fn default() -> SvgDocument
Source§impl Rendable for SvgDocument
impl Rendable for SvgDocument
Source§fn view_parameters(&self) -> ViewParameters
fn view_parameters(&self) -> ViewParameters
Source§fn set_view_parameters(&mut self, _view_box: ViewParameters)
fn set_view_parameters(&mut self, _view_box: ViewParameters)
Source§fn set_height(&mut self, height: u32)
fn set_height(&mut self, height: u32)
fn view_box(&mut self) -> (i32, i32, u32, u32)
fn set_view_box(&mut self, vx: i32, vy: i32, vw: u32, vh: u32)
Auto Trait Implementations§
impl Freeze for SvgDocument
impl !RefUnwindSafe for SvgDocument
impl !Send for SvgDocument
impl !Sync for SvgDocument
impl Unpin for SvgDocument
impl !UnwindSafe for SvgDocument
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.