system_theme/theme/
mod.rs

1//! Theme definitions
2mod palette;
3
4#[doc(inline)]
5pub use palette::ThemePalette;
6
7/// Theme scheme
8#[derive(Debug, Default, PartialEq, Clone, Copy)]
9pub enum ThemeScheme {
10    /// Light mode
11    Light,
12    /// Dark mode
13    #[default]
14    Dark,
15}
16
17/// Theme contrast
18#[derive(Debug, Default, PartialEq, Clone, Copy)]
19pub enum ThemeContrast {
20    /// Normal contrast
21    #[default]
22    Normal,
23    /// High contrast
24    High,
25}
26
27/// Theme color
28#[derive(Debug, PartialEq, Clone, Copy)]
29pub struct ThemeColor {
30    /// Red component (0.0 - 1.0)
31    pub red: f32,
32    /// Green component (0.0 - 1.0)
33    pub green: f32,
34    /// Blue component (0.0 - 1.0)
35    pub blue: f32,
36}
37
38impl ThemeColor {
39    /// White color (#FFFFFF)
40    pub const WHITE: Self = Self {
41        red: 1.0,
42        green: 1.0,
43        blue: 1.0,
44    };
45
46    /// Black color (#000000)
47    pub const BLACK: Self = Self {
48        red: 0.0,
49        green: 0.0,
50        blue: 0.0,
51    };
52
53    /// Create a color from RGB 8-bit values.
54    pub const fn from_rgb8(red: u8, green: u8, blue: u8) -> Self {
55        Self {
56            red: red as f32 / 255.0,
57            green: green as f32 / 255.0,
58            blue: blue as f32 / 255.0,
59        }
60    }
61
62    /// Check if a color is dark.
63    pub fn is_dark(&self) -> bool {
64        // Conversion from: https://en.wikipedia.org/wiki/Oklab_color_space#Conversions_between_color_spaces
65
66        // Convert RGB to LMS
67        let l = 0.41222146 * self.red + 0.53633255 * self.green + 0.051445995 * self.blue;
68        let m = 0.2119035 * self.red + 0.6806995 * self.green + 0.10739696 * self.blue;
69        let s = 0.08830246 * self.red + 0.28171885 * self.green + 0.6299787 * self.blue;
70
71        // Convert LMS to Oklab perceptual lightness
72        let oklab_l = 0.21045426 * l.cbrt() + 0.7936178 * m.cbrt() - 0.004072047 * s.cbrt();
73
74        // A color is considered dark if its Oklab perceptual lightness is below half the scale
75        oklab_l < 0.5
76    }
77}
78
79/// Theme kind
80#[derive(Debug, Default, PartialEq, Clone, Copy)]
81pub enum ThemeKind {
82    /// Microsoft Windows
83    Windows,
84    /// Apple MacOS
85    MacOS,
86    /// GTK (GNOME)
87    #[default]
88    Gtk,
89    /// Qt (KDE)
90    Qt,
91}