1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#![forbid(unsafe_code)]
#![warn(missing_docs)]
#![allow(clippy::field_reassign_with_default)]
#![allow(clippy::identity_op)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::uninlined_format_args)]
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::wrong_self_convention)]
pub use tiny_skia;
pub use usvg;
#[cfg(feature = "text")]
pub use usvg_text_layout;
use usvg::NodeExt;
mod clip;
#[cfg(feature = "filter")]
mod filter;
mod image;
mod mask;
mod paint_server;
mod path;
mod render;
pub use crate::render::trim_transparency;
trait OptionLog {
fn log_none<F: FnOnce()>(self, f: F) -> Self;
}
impl<T> OptionLog for Option<T> {
#[inline]
fn log_none<F: FnOnce()>(self, f: F) -> Self {
self.or_else(|| {
f();
None
})
}
}
trait ConvTransform {
fn to_native(&self) -> tiny_skia::Transform;
fn from_native(_: tiny_skia::Transform) -> Self;
}
impl ConvTransform for usvg::Transform {
fn to_native(&self) -> tiny_skia::Transform {
tiny_skia::Transform::from_row(
self.a as f32,
self.b as f32,
self.c as f32,
self.d as f32,
self.e as f32,
self.f as f32,
)
}
fn from_native(ts: tiny_skia::Transform) -> Self {
Self::new(
ts.sx as f64,
ts.ky as f64,
ts.kx as f64,
ts.sy as f64,
ts.tx as f64,
ts.ty as f64,
)
}
}
pub fn render(
tree: &usvg::Tree,
fit_to: usvg::FitTo,
transform: tiny_skia::Transform,
pixmap: tiny_skia::PixmapMut,
) -> Option<()> {
let size = fit_to.fit_to(tree.size.to_screen_size())?;
let mut canvas = render::Canvas::from(pixmap);
canvas.apply_transform(transform);
render::render_to_canvas(tree, size, &mut canvas);
Some(())
}
pub fn render_node(
tree: &usvg::Tree,
node: &usvg::Node,
fit_to: usvg::FitTo,
transform: tiny_skia::Transform,
pixmap: tiny_skia::PixmapMut,
) -> Option<()> {
let node_bbox = if let Some(bbox) = node.calculate_bbox().and_then(|r| r.to_rect()) {
bbox
} else {
log::warn!("Node '{}' has zero size.", node.id());
return None;
};
let vbox = usvg::ViewBox {
rect: node_bbox,
aspect: usvg::AspectRatio::default(),
};
let size = fit_to.fit_to(node_bbox.size().to_screen_size())?;
let mut canvas = render::Canvas::from(pixmap);
canvas.apply_transform(transform);
render::render_node_to_canvas(
tree,
node,
vbox,
size,
&mut render::RenderState::Ok,
&mut canvas,
);
Some(())
}