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, })) } }