1use super::Color;
6
7struct Entry {
8 color: Color,
9 key: &'static str,
10 name: &'static str,
11 stops: &'static [[u8; 3]],
12}
13
14const PALETTE: &[Entry] = &[
15 Entry {
16 color: Color::Accent,
17 key: "accent",
18 name: "Accent",
19 stops: &[[0x2f, 0x5b, 0xea]],
20 },
21 Entry {
22 color: Color::Green,
23 key: "green",
24 name: "Green",
25 stops: &[[0x43, 0xc7, 0x7f]],
26 },
27 Entry {
28 color: Color::Orange,
29 key: "orange",
30 name: "Orange",
31 stops: &[[0xe9, 0xa2, 0x3b]],
32 },
33 Entry {
34 color: Color::Pink,
35 key: "pink",
36 name: "Pink",
37 stops: &[[0xed, 0x78, 0xb5]],
38 },
39 Entry {
40 color: Color::Ibtesam,
41 key: "ibtesam",
42 name: "Ibtesam",
43 stops: &[[0x00, 0xf5, 0xa0], [0x00, 0xd9, 0xf5]],
44 },
45 Entry {
46 color: Color::Lunada,
47 key: "lunada",
48 name: "Lunada",
49 stops: &[[0x54, 0x33, 0xff], [0x20, 0xbd, 0xff], [0xa5, 0xfe, 0xcb]],
50 },
51 Entry {
52 color: Color::Stripe,
53 key: "stripe",
54 name: "Stripe",
55 stops: &[[0x1f, 0xa2, 0xff], [0x12, 0xd8, 0xfa], [0xa6, 0xff, 0xcb]],
56 },
57 Entry {
58 color: Color::Ali,
59 key: "ali",
60 name: "Ali",
61 stops: &[[0xff, 0x4b, 0x1f], [0x1f, 0xdd, 0xff]],
62 },
63 Entry {
64 color: Color::Alihossein,
65 key: "alihossein",
66 name: "Alihossein",
67 stops: &[[0xf7, 0xff, 0x00], [0xdb, 0x36, 0xa4]],
68 },
69 Entry {
70 color: Color::Transfile,
71 key: "transfile",
72 name: "Transfile",
73 stops: &[[0x16, 0xbf, 0xfd], [0xcb, 0x30, 0x66]],
74 },
75 Entry {
76 color: Color::ElectricViolet,
77 key: "electric_violet",
78 name: "Electric Violet",
79 stops: &[[0x47, 0x76, 0xe6], [0x8e, 0x54, 0xe9]],
80 },
81 Entry {
82 color: Color::Martini,
83 key: "martini",
84 name: "Martini",
85 stops: &[[0xfd, 0xfc, 0x47], [0x24, 0xfe, 0x41]],
86 },
87 Entry {
88 color: Color::Superman,
89 key: "superman",
90 name: "Superman",
91 stops: &[[0x00, 0x99, 0xf7], [0xf1, 0x17, 0x12]],
92 },
93 Entry {
94 color: Color::EdsSunsetGradient,
95 key: "eds_sunset_gradient",
96 name: "Ed's Sunset Gradient",
97 stops: &[[0xff, 0x7e, 0x5f], [0xfe, 0xb4, 0x7b]],
98 },
99 Entry {
100 color: Color::SublimeLight,
101 key: "sublime_light",
102 name: "Sublime Light",
103 stops: &[[0xfc, 0x5c, 0x7d], [0x6a, 0x82, 0xfb]],
104 },
105 Entry {
106 color: Color::Argon,
107 key: "argon",
108 name: "Argon",
109 stops: &[
110 [0x03, 0x00, 0x1e],
111 [0x73, 0x03, 0xc0],
112 [0xec, 0x38, 0xbc],
113 [0xfd, 0xef, 0xf9],
114 ],
115 },
116 Entry {
117 color: Color::JShine,
118 key: "j_shine",
119 name: "JShine",
120 stops: &[[0x12, 0xc2, 0xe9], [0xc4, 0x71, 0xed], [0xf6, 0x4f, 0x59]],
121 },
122 Entry {
123 color: Color::Flare,
124 key: "flare",
125 name: "Flare",
126 stops: &[[0xff, 0xf3, 0xb0], [0xf5, 0xaf, 0x19], [0xf1, 0x27, 0x11]],
127 },
128 Entry {
129 color: Color::UltraVoilet,
130 key: "ultra_voilet",
131 name: "Ultra Voilet",
132 stops: &[[0x65, 0x4e, 0xa3], [0xea, 0xaf, 0xc8]],
133 },
134 Entry {
135 color: Color::KyooPal,
136 key: "kyoo_pal",
137 name: "Kyoo Pal",
138 stops: &[[0xdd, 0x3e, 0x54], [0x6b, 0xe5, 0x85]],
139 },
140 Entry {
141 color: Color::KyeMeh,
142 key: "kye_meh",
143 name: "Kye Meh",
144 stops: &[[0x83, 0x60, 0xc3], [0x2e, 0xbf, 0x91]],
145 },
146 Entry {
147 color: Color::Wiretap,
148 key: "wiretap",
149 name: "Wiretap",
150 stops: &[[0x8a, 0x23, 0x87], [0xe9, 0x40, 0x57], [0xf2, 0x71, 0x21]],
151 },
152 Entry {
153 color: Color::Rastafari,
154 key: "rastafari",
155 name: "Rastafari",
156 stops: &[[0x1e, 0x96, 0x00], [0xff, 0xf2, 0x00], [0xff, 0x00, 0x00]],
157 },
158 Entry {
159 color: Color::SinCityRed,
160 key: "sin_city_red",
161 name: "Sin City Red",
162 stops: &[[0xed, 0x21, 0x3a], [0x93, 0x29, 0x1e]],
163 },
164 Entry {
165 color: Color::AzurLane,
166 key: "azur_lane",
167 name: "Azur Lane",
168 stops: &[[0x7f, 0x7f, 0xd5], [0x86, 0xa8, 0xe7], [0x91, 0xea, 0xe4]],
169 },
170 Entry {
171 color: Color::WitchingHour,
172 key: "witching_hour",
173 name: "Witching Hour",
174 stops: &[[0xc3, 0x14, 0x32], [0x24, 0x0b, 0x36]],
175 },
176];
177
178impl Color {
179 pub fn choices() -> impl Iterator<Item = (Self, &'static str, &'static str)> {
181 PALETTE
182 .iter()
183 .map(|entry| (entry.color, entry.key, entry.name))
184 }
185
186 #[must_use]
188 #[allow(
190 clippy::cast_possible_truncation,
191 clippy::cast_sign_loss,
192 clippy::cast_precision_loss
193 )]
194 pub fn sample(self, t: f32, dark: bool) -> [u8; 3] {
195 if self == Self::Accent && dark {
196 return [0x70, 0x88, 0xff];
197 }
198 let stops = PALETTE[self as usize].stops;
199 let position = if t.is_nan() { 0.0 } else { t.clamp(0.0, 1.0) } * (stops.len() - 1) as f32;
200 let index = (position as usize).min(stops.len() - 1);
201 let next = (index + 1).min(stops.len() - 1);
202 let fraction = position - index as f32;
203 std::array::from_fn(|channel| {
204 let start = f32::from(stops[index][channel]);
205 (start + (f32::from(stops[next][channel]) - start) * fraction).round() as u8
206 })
207 }
208}
209
210#[cfg(test)]
211mod tests {
212 use super::*;
213
214 #[test]
215 fn sample_multi_stop_gradient_returns_endpoints_and_interpolation() {
216 let color = Color::Lunada;
218
219 let samples = [0.0, 0.25, 0.5, 0.75, 1.0].map(|t| color.sample(t, false));
221
222 assert_eq!(
224 samples,
225 [
226 [0x54, 0x33, 0xff],
227 [0x3a, 0x78, 0xff],
228 [0x20, 0xbd, 0xff],
229 [0x63, 0xde, 0xe5],
230 [0xa5, 0xfe, 0xcb]
231 ]
232 );
233 }
234}