1use resvg::tiny_skia;
7use resvg::usvg;
8
9pub fn parse(data: &[u8]) -> Result<usvg::Tree, String> {
13 usvg::Tree::from_data(data, &usvg::Options::default()).map_err(|e| e.to_string())
14}
15
16pub fn render_png(tree: &usvg::Tree, px: u32) -> Result<Vec<u8>, String> {
20 render_png_padded(tree, px, 0.0)
21}
22
23pub fn render_png_padded(tree: &usvg::Tree, px: u32, pad: f32) -> Result<Vec<u8>, String> {
26 if px == 0 {
27 return Err("zero-size render".into());
28 }
29 let mut pixmap =
30 tiny_skia::Pixmap::new(px, px).ok_or_else(|| "pixmap allocation failed".to_string())?;
31 let size = tree.size();
32 let (w, h) = (size.width(), size.height());
33 if w <= 0.0 || h <= 0.0 {
34 return Err("SVG has a zero-sized viewport".into());
35 }
36 let inner = px as f32 * (1.0 - 2.0 * pad.clamp(0.0, 0.45));
37 let scale = inner / w.max(h);
38 let tx = (px as f32 - w * scale) / 2.0;
39 let ty = (px as f32 - h * scale) / 2.0;
40 let ts = tiny_skia::Transform::from_row(scale, 0.0, 0.0, scale, tx, ty);
41 resvg::render(tree, ts, &mut pixmap.as_mut());
42 pixmap.encode_png().map_err(|e| e.to_string())
43}
44
45pub fn content_bbox(tree: &usvg::Tree) -> Option<tiny_skia::Rect> {
48 let b = tree.root().abs_layer_bounding_box();
49 tiny_skia::Rect::from_xywh(b.x(), b.y(), b.width(), b.height())
50}