1#![allow(unused)]
2
3use crate::geom::lerp;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
7#[serde(rename_all = "kebab-case")]
8pub enum Color {
9 Gray(u8),
10 Rgb(u8, u8, u8),
11}
12
13impl Color {
14 pub fn gray(&self) -> u8 {
15 match *self {
16 Color::Gray(level) => level,
17 Color::Rgb(red, green, blue) => {
18 (red as f32 * 0.2126 + green as f32 * 0.7152 + blue as f32 * 0.0722) as u8
19 }
20 }
21 }
22
23 pub fn rgb(&self) -> [u8; 3] {
24 match *self {
25 Color::Gray(level) => [level; 3],
26 Color::Rgb(red, green, blue) => [red, green, blue],
27 }
28 }
29
30 pub fn from_rgb(rgb: &[u8]) -> Color {
31 Color::Rgb(rgb[0], rgb[1], rgb[2])
32 }
33
34 pub fn apply<F>(&self, f: F) -> Color
35 where
36 F: Fn(u8) -> u8,
37 {
38 match *self {
39 Color::Gray(level) => Color::Gray(f(level)),
40 Color::Rgb(red, green, blue) => Color::Rgb(f(red), f(green), f(blue)),
41 }
42 }
43
44 pub fn lerp(&self, color: Color, alpha: f32) -> Color {
45 match (*self, color) {
46 (Color::Gray(l1), Color::Gray(l2)) => {
47 Color::Gray(lerp(l1 as f32, l2 as f32, alpha) as u8)
48 }
49 (Color::Rgb(red, green, blue), Color::Gray(level)) => Color::Rgb(
50 lerp(red as f32, level as f32, alpha) as u8,
51 lerp(green as f32, level as f32, alpha) as u8,
52 lerp(blue as f32, level as f32, alpha) as u8,
53 ),
54 (Color::Gray(level), Color::Rgb(red, green, blue)) => Color::Rgb(
55 lerp(level as f32, red as f32, alpha) as u8,
56 lerp(level as f32, green as f32, alpha) as u8,
57 lerp(level as f32, blue as f32, alpha) as u8,
58 ),
59 (Color::Rgb(r1, g1, b1), Color::Rgb(r2, g2, b2)) => Color::Rgb(
60 lerp(r1 as f32, r2 as f32, alpha) as u8,
61 lerp(g1 as f32, g2 as f32, alpha) as u8,
62 lerp(b1 as f32, b2 as f32, alpha) as u8,
63 ),
64 }
65 }
66
67 pub fn invert(&mut self) {
68 match self {
69 Color::Gray(level) => *level = 255 - *level,
70 Color::Rgb(red, green, blue) => {
71 *red = 255 - *red;
72 *green = 255 - *green;
73 *blue = 255 - *blue;
74 }
75 }
76 }
77
78 pub fn shift(&mut self, drift: u8) {
79 match self {
80 Color::Gray(level) => *level = level.saturating_sub(drift),
81 Color::Rgb(red, green, blue) => {
82 *red = red.saturating_sub(drift);
83 *green = green.saturating_sub(drift);
84 *blue = blue.saturating_sub(drift);
85 }
86 }
87 }
88}
89
90macro_rules! gray {
91 ($a:expr) => {
92 $crate::color::Color::Gray($a)
93 };
94}
95
96pub const GRAY00: Color = gray!(0x00);
97pub const GRAY01: Color = gray!(0x11);
98pub const GRAY02: Color = gray!(0x22);
99pub const GRAY03: Color = gray!(0x33);
100pub const GRAY04: Color = gray!(0x44);
101pub const GRAY05: Color = gray!(0x55);
102pub const GRAY06: Color = gray!(0x66);
103pub const GRAY07: Color = gray!(0x77);
104pub const GRAY08: Color = gray!(0x88);
105pub const GRAY09: Color = gray!(0x99);
106pub const GRAY10: Color = gray!(0xAA);
107pub const GRAY11: Color = gray!(0xBB);
108pub const GRAY12: Color = gray!(0xCC);
109pub const GRAY13: Color = gray!(0xDD);
110pub const GRAY14: Color = gray!(0xEE);
111pub const GRAY15: Color = gray!(0xFF);
112
113pub const BLACK: Color = GRAY00;
114pub const WHITE: Color = GRAY15;
115
116pub const TEXT_NORMAL: [Color; 3] = [WHITE, BLACK, GRAY08];
117pub const TEXT_BUMP_SMALL: [Color; 3] = [GRAY14, BLACK, GRAY07];
118pub const TEXT_BUMP_LARGE: [Color; 3] = [GRAY11, BLACK, BLACK];
119
120pub const TEXT_INVERTED_SOFT: [Color; 3] = [GRAY05, WHITE, WHITE];
121pub const TEXT_INVERTED_HARD: [Color; 3] = [BLACK, WHITE, GRAY06];
122
123pub const SEPARATOR_NORMAL: Color = GRAY10;
124pub const SEPARATOR_STRONG: Color = GRAY07;
125
126pub const KEYBOARD_BG: Color = GRAY12;
127pub const BATTERY_FILL: Color = GRAY12;
128pub const READING_PROGRESS: Color = GRAY07;
129
130pub const PROGRESS_FULL: Color = GRAY05;
131pub const PROGRESS_EMPTY: Color = GRAY13;
132pub const PROGRESS_VALUE: Color = GRAY06;