SvgDocument

Struct SvgDocument 

Source
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

Source

pub fn new() -> Self

Creates a new SvgDocument with default settings only, without any nodes, symbols, or plots.

Examples found in repository?
examples/sine_curve.rs (line 27)
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
Hide additional examples
examples/xy_gamut_plots.rs (line 45)
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}
Source

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?
examples/sine_curve.rs (line 28)
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
Hide additional examples
examples/xy_gamut_plots.rs (line 46)
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}
Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn add_symbol(self, symbol: impl Into<Symbol>) -> Self

Adds a symbol to the SVG document.

Source

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”.

Source

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?
examples/sine_curve.rs (line 29)
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
Hide additional examples
examples/xy_gamut_plots.rs (line 47)
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}
Source

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.

Source

pub fn calculate_subplots_size_with_margin(&self) -> (u32, u32)

Source

pub fn save(self, filename: &str) -> Result<(), Box<dyn Error>>

Examples found in repository?
examples/sine_curve.rs (line 30)
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
Hide additional examples
examples/xy_gamut_plots.rs (line 48)
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

Source§

fn default() -> SvgDocument

Returns the “default value” for a type. Read more
Source§

impl Rendable for SvgDocument

Source§

fn view_parameters(&self) -> ViewParameters

Returns the current view parameters for the object.
Source§

fn set_view_parameters(&mut self, _view_box: ViewParameters)

Sets the view parameters for the object.
Source§

fn render(&self) -> Document

Renders the object as an SVG element.
Source§

fn set_x(&mut self, x: i32)

Sets the x position of the view box (optional).
Source§

fn set_y(&mut self, y: i32)

Sets the y position of the view box (optional).
Source§

fn width(&self) -> u32

Returns the width of the view box (optional).
Source§

fn set_width(&mut self, width: u32)

Sets the width of the view box (optional).
Source§

fn height(&self) -> u32

Returns the height of the view box (optional).
Source§

fn set_height(&mut self, height: u32)

Sets the height of the view box (optional).
Source§

fn view_box(&mut self) -> (i32, i32, u32, u32)

Source§

fn set_view_box(&mut self, vx: i32, vy: i32, vw: u32, vh: u32)

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<G1, G2> Within<G2> for G1
where G2: Contains<G1>,

Source§

fn is_within(&self, b: &G2) -> bool