svg_renderer.rs

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