oxygengine_composite_renderer/
svg_image_asset_protocol.rs1use 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}