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 }