oxygengine_composite_renderer/
svg_image_asset_protocol.rs

1use crate::core::assets::protocol::{AssetLoadResult, AssetProtocol};
2use std::str::from_utf8;
3use svg::{
4    node::element::tag::{Type, SVG},
5    parser::Event,
6};
7
8pub struct SvgImageAsset {
9    bytes: Vec<u8>,
10    width: usize,
11    height: usize,
12}
13
14impl SvgImageAsset {
15    pub fn bytes(&self) -> &[u8] {
16        &self.bytes
17    }
18
19    pub fn width(&self) -> usize {
20        self.width
21    }
22
23    pub fn height(&self) -> usize {
24        self.height
25    }
26}
27
28pub struct SvgImageAssetProtocol;
29
30impl AssetProtocol for SvgImageAssetProtocol {
31    fn name(&self) -> &str {
32        "svg"
33    }
34
35    fn on_load(&mut self, data: Vec<u8>) -> AssetLoadResult {
36        let content = from_utf8(&data).unwrap();
37        let mut width = 0;
38        let mut height = 0;
39        for event in svg::read(content).unwrap() {
40            if let Event::Tag(SVG, Type::Start, attributes) = event {
41                let mut iter = attributes.get("viewBox").unwrap().split_whitespace();
42                let left = iter.next().unwrap().parse::<isize>().unwrap();
43                let top = iter.next().unwrap().parse::<isize>().unwrap();
44                let right = iter.next().unwrap().parse::<isize>().unwrap();
45                let bottom = iter.next().unwrap().parse::<isize>().unwrap();
46                width = (right - left) as usize;
47                height = (bottom - top) as usize;
48                break;
49            }
50        }
51        let content = content.replace("width=\"100%\"", &format!("width=\"{}\"", width));
52        let content = content.replace("height=\"100%\"", &format!("height=\"{}\"", height));
53        AssetLoadResult::Data(Box::new(SvgImageAsset {
54            bytes: content.into_bytes(),
55            width,
56            height,
57        }))
58    }
59}