deft 0.15.0

Cross platform ui framework
use anyhow::Error;
use resvg::usvg::Tree;
use resvg::{tiny_skia, usvg, RenderOptions};
use skia_safe::Color;
use skia_safe::{surfaces, AlphaType, Canvas, ColorType, ImageInfo};
use std::fs;
use std::sync::{Arc, Mutex};

pub struct SvgState {
    tree: Tree,
    options: RenderOptions,
}

#[derive(Clone)]
pub struct SvgObject {
    state: Arc<Mutex<SvgState>>,
}

impl SvgObject {
    pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
        let options = usvg::Options::default();
        let tree = Tree::from_data(bytes, &options)?;
        let options = RenderOptions::default();
        Ok(Self {
            state: Arc::new(Mutex::new(SvgState { tree, options })),
        })
    }

    pub fn from_file(file: &str) -> Result<Self, Error> {
        let data = fs::read(file)?;
        Self::from_bytes(&data)
    }
    pub fn container_size(&self) -> (f32, f32) {
        let state = self.state.lock().unwrap();
        let size = state.tree.size();
        (size.width(), size.height())
    }

    pub fn set_color(&self, color: Color) {
        let mut state = self.state.lock().unwrap();
        let color = tiny_skia::Color::from_rgba8(color.r(), color.g(), color.b(), color.a());
        state.options.set_color(color);
    }

    pub fn render(&self, canvas: &Canvas, scale: f32) {
        let state = self.state.lock().unwrap();
        let pixmap_size = state.tree.size().to_int_size().scale_by(scale).unwrap();
        let mut pixmap = tiny_skia::Pixmap::new(pixmap_size.width(), pixmap_size.height()).unwrap();
        resvg::render(
            &state.tree,
            tiny_skia::Transform::from_scale(scale, scale),
            &mut pixmap.as_mut(),
            &state.options,
        );

        let width = pixmap_size.width() as i32;
        let height = pixmap_size.height() as i32;
        let bi = ImageInfo::new(
            (width, height),
            ColorType::RGBA8888,
            AlphaType::Premul,
            None,
        );
        let mut surface = surfaces::wrap_pixels(&bi, pixmap.data_mut(), None, None).unwrap();
        let img = surface.image_snapshot();
        canvas.save();
        canvas.scale((1.0 / scale, 1.0 / scale));
        canvas.draw_image(&img, (0.0, 0.0), None);
        canvas.restore();
    }
}