use std::collections::HashMap;
use std::sync::Arc;
use egui::ImageSource;
use egui::load::Bytes;
#[derive(Clone, Copy, Debug)]
pub struct SvgStyle {
pub current_color: &'static str,
pub stroke_width: Option<&'static str>,
}
pub struct SvgIconSet {
icons: HashMap<&'static str, Arc<[u8]>>,
uri_prefix: &'static str,
fallback: &'static str,
empty: Arc<[u8]>,
}
impl SvgIconSet {
pub fn new(icons: &'static [(&'static str, &'static [u8])], style: SvgStyle, uri_prefix: &'static str, fallback: &'static str) -> Self {
let mut prepared = HashMap::with_capacity(icons.len());
for &(name, svg) in icons {
let mut text = String::from_utf8_lossy(svg).replace("currentColor", style.current_color);
if let Some(width) = style.stroke_width {
text = text.replace("stroke-width=\"2\"", &format!("stroke-width=\"{width}\""));
}
prepared.insert(name, Arc::from(text.into_bytes()));
}
Self { icons: prepared, uri_prefix, fallback, empty: Arc::from(Vec::new()) }
}
pub fn contains(&self, name: &str) -> bool {
self.icons.contains_key(name)
}
pub fn canonical_name(&self, name: &str) -> Option<&'static str> {
self.icons.get_key_value(name).map(|(&key, _)| key)
}
pub fn source(&self, name: &str) -> ImageSource<'static> {
let bytes = self.icons.get(name).or_else(|| self.icons.get(self.fallback)).unwrap_or(&self.empty);
ImageSource::Bytes { uri: format!("{}{name}.svg", self.uri_prefix).into(), bytes: Bytes::Shared(Arc::clone(bytes)) }
}
}
#[cfg(test)]
mod tests;