raqote_usvg_render/
lib.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5/*!
6[resvg](https://github.com/RazrFalcon/resvg) backend implementation
7using the [raqote](https://github.com/jrmuizel/raqote) library.
8*/
9
10#![doc(html_root_url = "https://docs.rs/resvg-raqote/0.10.0")]
11
12#![warn(missing_docs)]
13
14/// Unwraps `Option` and invokes `return` on `None`.
15macro_rules! try_opt {
16    ($task:expr) => {
17        match $task {
18            Some(v) => v,
19            None => return,
20        }
21    };
22}
23
24/// Unwraps `Option` and invokes `return $ret` on `None`.
25macro_rules! try_opt_or {
26    ($task:expr, $ret:expr) => {
27        match $task {
28            Some(v) => v,
29            None => return $ret,
30        }
31    };
32}
33
34
35use usvg::{NodeExt, ScreenSize};
36use log::warn;
37
38mod clip;
39mod filter;
40mod image;
41mod layers;
42mod mask;
43mod paint_server;
44mod path;
45mod render;
46
47
48/// Rendering options.
49pub struct Options {
50    /// `usvg` preprocessor options.
51    pub usvg: usvg::Options,
52
53    /// Fits the image using specified options.
54    ///
55    /// Does not affect rendering to canvas.
56    pub fit_to: usvg::FitTo,
57
58    /// An image background color.
59    ///
60    /// Sets an image background color. Does not affect rendering to canvas.
61    ///
62    /// `None` equals to transparent.
63    pub background: Option<usvg::Color>,
64}
65
66impl Default for Options {
67    fn default() -> Options {
68        Options {
69            usvg: usvg::Options::default(),
70            fit_to: usvg::FitTo::Original,
71            background: None,
72        }
73    }
74}
75
76
77/// Renders SVG to image.
78pub fn render_to_image(
79    tree: &usvg::Tree,
80    opt: &Options,
81) -> Option<raqote::DrawTarget> {
82    let (mut dt, img_view) = render::create_target(
83        tree.svg_node().size.to_screen_size(),
84        opt,
85    )?;
86
87    // Fill background.
88    if let Some(c) = opt.background {
89        dt.clear(raqote::SolidSource { r: c.red, g: c.green, b: c.blue, a: 255 });
90    }
91
92    render_to_canvas(tree, opt, img_view, &mut dt);
93
94    Some(dt)
95}
96
97/// Renders SVG node to image.
98pub fn render_node_to_image(
99    node: &usvg::Node,
100    opt: &Options,
101) -> Option<raqote::DrawTarget> {
102    let node_bbox = if let Some(bbox) = node.calculate_bbox() {
103        bbox
104    } else {
105        warn!("Node '{}' has a zero size.", node.id());
106        return None;
107    };
108
109    let (mut dt, img_size) = render::create_target(node_bbox.to_screen_size(), opt)?;
110
111    let vbox = usvg::ViewBox {
112        rect: node_bbox,
113        aspect: usvg::AspectRatio::default(),
114    };
115
116    // Fill background.
117    if let Some(c) = opt.background {
118        dt.clear(raqote::SolidSource { r: c.red, g: c.green, b: c.blue, a: 255 });
119    }
120
121    render_node_to_canvas(node, opt, vbox, img_size, &mut dt);
122
123    Some(dt)
124}
125
126/// Renders `tree` onto the canvas.
127///
128/// The caller must guarantee that `img_size` is large enough.
129///
130/// Canvas must not have a transform.
131pub fn render_to_canvas(
132    tree: &usvg::Tree,
133    opt: &Options,
134    img_size: ScreenSize,
135    dt: &mut raqote::DrawTarget,
136) {
137    render_node_to_canvas(&tree.root(), opt, tree.svg_node().view_box, img_size, dt);
138}
139
140/// Renders `node` onto the canvas.
141///
142/// The caller must guarantee that `img_size` is large enough.
143///
144/// Canvas must not have a transform.
145pub fn render_node_to_canvas(
146    node: &usvg::Node,
147    opt: &Options,
148    view_box: usvg::ViewBox,
149    img_size: ScreenSize,
150    dt: &mut raqote::DrawTarget,
151) {
152    render::render_node_to_canvas(node, opt, view_box, img_size, &mut render::RenderState::Ok, dt)
153}