tessera_ui_basic_components/
material_icons.rs

1//! Material Design icon content helpers.
2//!
3//! ## Usage
4//!
5//! Use style modules (e.g., [`filled`]) and functions like `home_icon()` to get an
6//! [`IconContent`] that can be passed to [`crate::icon::IconArgs`].
7use std::{collections::HashMap, sync::Arc};
8
9use parking_lot::RwLock;
10
11use crate::{
12    icon::IconContent, image_vector::ImageVectorSource,
13    pipelines::image_vector::command::ImageVectorData,
14};
15
16pub use generated::{ICON_BLOB, filled, outlined, round, sharp, two_tone};
17
18#[allow(missing_docs, clippy::all)]
19mod generated {
20    include!(concat!(env!("OUT_DIR"), "/material_icons.rs"));
21}
22
23type IconCache = HashMap<(&'static str, u32, u32), Arc<ImageVectorData>>;
24
25static ICON_CACHE: std::sync::OnceLock<RwLock<IconCache>> = std::sync::OnceLock::new();
26
27fn cache() -> &'static RwLock<IconCache> {
28    ICON_CACHE.get_or_init(|| RwLock::new(HashMap::new()))
29}
30
31/// Load vector data from the bundled blob with caching.
32pub fn load_icon_bytes(style: &'static str, offset: u32, len: u32) -> Arc<ImageVectorData> {
33    let key = (style, offset, len);
34    if let Some(cached) = cache().read().get(&key) {
35        return cached.clone();
36    }
37
38    let start = offset as usize;
39    let end = start + len as usize;
40    let bytes = Arc::<[u8]>::from(&ICON_BLOB[start..end]);
41    let vector =
42        crate::image_vector::load_image_vector_from_source(&ImageVectorSource::Bytes(bytes))
43            .map(Arc::new)
44            .expect("bundled material icon svg should load");
45
46    cache().write().insert(key, vector.clone());
47    vector
48}
49
50/// Convert loaded vector data into icon content.
51pub fn content_from_data(data: Arc<ImageVectorData>) -> IconContent {
52    IconContent::from(data)
53}