Skip to main content

deft_resvg/
lib.rs

1// Copyright 2017 the Resvg Authors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4/*!
5[resvg](https://github.com/linebender/resvg) is an SVG rendering library.
6*/
7
8#![forbid(unsafe_code)]
9#![warn(missing_docs)]
10#![allow(clippy::field_reassign_with_default)]
11#![allow(clippy::identity_op)]
12#![allow(clippy::too_many_arguments)]
13#![allow(clippy::uninlined_format_args)]
14#![allow(clippy::upper_case_acronyms)]
15#![allow(clippy::wrong_self_convention)]
16
17pub use tiny_skia;
18pub use usvg;
19
20mod clip;
21mod filter;
22mod geom;
23mod image;
24mod mask;
25mod path;
26mod render;
27
28/// Render options
29pub struct RenderOptions {
30    current_color: tiny_skia::Color,
31}
32
33impl RenderOptions {
34    
35    /// current color
36    pub fn set_color(&mut self, color: tiny_skia::Color) -> &mut Self {
37        self.current_color = color;
38        self
39    }
40}
41
42impl Default for RenderOptions {
43    fn default() -> Self {
44        Self {
45            current_color: tiny_skia::Color::from_rgba8(0, 0, 0, 255),
46        }
47    }
48    
49}
50
51/// Renders a tree onto the pixmap.
52///
53/// `transform` will be used as a root transform.
54/// Can be used to position SVG inside the `pixmap`.
55///
56/// The produced content is in the sRGB color space.
57pub fn render(
58    tree: &usvg::Tree,
59    transform: tiny_skia::Transform,
60    pixmap: &mut tiny_skia::PixmapMut,
61    options: &RenderOptions,
62) {
63    let target_size = tiny_skia::IntSize::from_wh(pixmap.width(), pixmap.height()).unwrap();
64    let max_bbox = tiny_skia::IntRect::from_xywh(
65        -(target_size.width() as i32) * 2,
66        -(target_size.height() as i32) * 2,
67        target_size.width() * 5,
68        target_size.height() * 5,
69    )
70    .unwrap();
71
72    let ctx = render::Context { max_bbox };
73    render::render_nodes(tree.root(), &ctx, transform, pixmap, options);
74}
75
76/// Renders a node onto the pixmap.
77///
78/// `transform` will be used as a root transform.
79/// Can be used to position SVG inside the `pixmap`.
80///
81/// The expected pixmap size can be retrieved from `usvg::Node::abs_layer_bounding_box()`.
82///
83/// Returns `None` when `node` has a zero size.
84///
85/// The produced content is in the sRGB color space.
86pub fn render_node(
87    node: &usvg::Node,
88    mut transform: tiny_skia::Transform,
89    pixmap: &mut tiny_skia::PixmapMut,
90    options: &RenderOptions,
91) -> Option<()> {
92    let bbox = node.abs_layer_bounding_box()?;
93
94    let target_size = tiny_skia::IntSize::from_wh(pixmap.width(), pixmap.height()).unwrap();
95    let max_bbox = tiny_skia::IntRect::from_xywh(
96        -(target_size.width() as i32) * 2,
97        -(target_size.height() as i32) * 2,
98        target_size.width() * 5,
99        target_size.height() * 5,
100    )
101    .unwrap();
102
103    transform = transform.pre_translate(-bbox.x(), -bbox.y());
104
105    let ctx = render::Context { max_bbox };
106    render::render_node(node, &ctx, transform, pixmap, options);
107
108    Some(())
109}
110
111pub(crate) trait OptionLog {
112    fn log_none<F: FnOnce()>(self, f: F) -> Self;
113}
114
115impl<T> OptionLog for Option<T> {
116    #[inline]
117    fn log_none<F: FnOnce()>(self, f: F) -> Self {
118        self.or_else(|| {
119            f();
120            None
121        })
122    }
123}