git.lucas.co / cce-status-interface
status bar
git clone https://git.lucas.co/cce-status-interface.git

src/icons.rs (2.3K)

 1 //! Bundled cce-icons glyphs, tinted for the bar.
 2 //!
 3 //! Every symbol the bar draws is a cce-icons glyph: the stat readouts' units,
 4 //! the OSD's, the tray's stand-in for an item that brings no icon of its own,
 5 //! and the in-surface menu's marks and page chevrons. A glyph has to wear
 6 //! the colour of the text beside it — `module { text_color }`, the battery's
 7 //! accent when it is low or charging, the volume's `disabled_color` while
 8 //! muted — and a `Prim::Image` carries alpha but no colour, so the tint is
 9 //! baked into the texture: `cce_ui::upload_icon_tinted`, cached per `(name,
10 //! px, tint)` and keyed on the renderer epoch, so a reconnect (cce-ui
11 //! repairs a lost transport by opening a new session, and a new renderer,
12 //! around the same `Application`) re-uploads rather than drawing ids the
13 //! new renderer never had. Until 2026-10-05 this module rasterized and
14 //! uploaded the SVGs itself through a cache that outlived the renderer, and
15 //! `renderer_init` had to empty it by hand.
16 //!
17 //! The artwork comes from the cce-icons crate via [`cce_ui::icons_dir`]
18 //! (`$CCE_ICONS_DIR`, else `~/projects/cce/cce-icons/svg`). A glyph that is
19 //! missing or unparsable yields `None` — the caller keeps its text readout as
20 //! the fallback — and is logged once per name.
21 
22 use std::collections::HashSet;
23 use std::sync::Mutex;
24 
25 /// `<name>.svg` from cce-icons, `side` LOGICAL px on its longer side, tinted
26 /// `rgb` (raw sRGB, like every text colour here, so a glyph matches the label
27 /// beside it). Returns the image id and the glyph's logical size.
28 pub(crate) fn glyph(name: &str, side: f32, rgb: [u8; 3]) -> Option<(u32, f32, f32)> {
29     let scale = cce_ui::scale::scale_factor();
30     let px = (side * scale).round().max(1.0) as u32;
31     match cce_ui::upload_icon_tinted(name, px, rgb) {
32         Some((image, w, h)) => Some((image, w as f32 / scale, h as f32 / scale)),
33         None => {
34             static WARNED: Mutex<Option<HashSet<String>>> = Mutex::new(None);
35             let mut warned = WARNED.lock().unwrap();
36             if warned.get_or_insert_with(HashSet::new).insert(name.to_string()) {
37                 log::warn!(
38                     "[icons] {}/{name}.svg could not be loaded — drawing without it",
39                     cce_ui::icons_dir()
40                 );
41             }
42             None
43         }
44     }
45 }