svg_renderer.rs

 1use crate::{AssetSource, DevicePixels, IsZero, Result, SharedString, Size};
 2use anyhow::anyhow;
 3use std::hash::Hash;
 4use std::sync::Arc;
 5
 6#[derive(Clone, PartialEq, Hash, Eq)]
 7pub struct RenderSvgParams {
 8    pub(crate) path: SharedString,
 9    pub(crate) size: Size<DevicePixels>,
10}
11
12pub struct SvgRenderer {
13    asset_source: Arc<dyn AssetSource>,
14}
15
16impl SvgRenderer {
17    pub fn new(asset_source: Arc<dyn AssetSource>) -> Self {
18        Self { asset_source }
19    }
20
21    pub fn render(&self, params: &RenderSvgParams) -> Result<Vec<u8>> {
22        if params.size.is_zero() {
23            return Err(anyhow!("can't render at a zero size"));
24        }
25
26        // Load the tree.
27        let bytes = self.asset_source.load(&params.path)?;
28        let tree = usvg::Tree::from_data(&bytes, &usvg::Options::default())?;
29
30        // Render the SVG to a pixmap with the specified width and height.
31        let mut pixmap =
32            tiny_skia::Pixmap::new(params.size.width.into(), params.size.height.into()).unwrap();
33        resvg::render(
34            &tree,
35            usvg::FitTo::Width(params.size.width.into()),
36            pixmap.as_mut(),
37        );
38
39        // Convert the pixmap's pixels into an alpha mask.
40        let alpha_mask = pixmap
41            .pixels()
42            .iter()
43            .map(|p| p.alpha())
44            .collect::<Vec<_>>();
45        Ok(alpha_mask)
46    }
47}