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