rat_theme2/
palette.rs

1use ratatui_core::style::{Color, Style};
2
3/// Color palette.
4///
5/// This provides the palette used for a theme.
6///
7/// The ideas packed in here are
8/// * provide two colors for highlighting and accents.
9/// * I always want some white, black and gray.
10/// * I don't want to miss out anything, so go once
11///   round the hue in HSV. Take steps of 30° then we
12///   hit pretty much anything interesting.
13/// * Just one variant of each color is not enough, make it 4.
14/// * Background colors need extra considerations. Extend to 8.
15///
16#[derive(Debug, Default, Clone)]
17pub struct Palette {
18    pub white: [Color; 8],
19    pub black: [Color; 8],
20    pub gray: [Color; 8],
21
22    pub red: [Color; 8],
23    pub orange: [Color; 8],
24    pub yellow: [Color; 8],
25    pub limegreen: [Color; 8],
26    pub green: [Color; 8],
27    pub bluegreen: [Color; 8],
28    pub cyan: [Color; 8],
29    pub blue: [Color; 8],
30    pub deepblue: [Color; 8],
31    pub purple: [Color; 8],
32    pub magenta: [Color; 8],
33    pub redpink: [Color; 8],
34
35    pub primary: [Color; 8],
36    pub secondary: [Color; 8],
37}
38
39/// Contrast rating for the text-color that should be used.
40#[derive(Debug)]
41pub enum TextColorRating {
42    /// Use light/white text for the given background.
43    Light,
44    /// Use dark/black text for the given background.
45    Dark,
46}
47
48/// Used to create a high contrast or normal contrast style.
49#[derive(Debug)]
50pub enum Contrast {
51    High,
52    Normal,
53}
54
55impl Palette {
56    /// Color index for a bright variant of the base color.
57    /// Brightness increases with the number.
58    pub const BRIGHT_0: usize = 0;
59    /// Color index for a bright variant of the base color.
60    /// Brightness increases with the number.
61    pub const BRIGHT_1: usize = 1;
62    /// Color index for a bright variant of the base color.
63    /// Brightness increases with the number.
64    pub const BRIGHT_2: usize = 2;
65    /// Color index for a bright variant of the base color.
66    /// Brightness increases with the number.
67    pub const BRIGHT_3: usize = 3;
68    /// Color index for a dark variant of the base color.
69    /// Brightness increases with the number.
70    pub const DARK_0: usize = 4;
71    /// Color index for a dark variant of the base color.
72    /// Brightness increases with the number.
73    pub const DARK_1: usize = 5;
74    /// Color index for a dark variant of the base color.
75    /// Brightness increases with the number.
76    pub const DARK_2: usize = 6;
77    /// Color index for a dark variant of the base color.
78    /// Brightness increases with the number.
79    pub const DARK_3: usize = 7;
80
81    /// Create a style from the given white shade.
82    /// n is `0..=3`
83    pub fn white(&self, n: usize, contrast: Contrast) -> Style {
84        self.style(self.white[n], contrast)
85    }
86
87    /// Create a style from the given black shade.
88    /// n is `0..=3`
89    pub fn black(&self, n: usize, contrast: Contrast) -> Style {
90        self.style(self.black[n], contrast)
91    }
92
93    /// Create a style from the given gray shade.
94    /// n is `0..=3`
95    pub fn gray(&self, n: usize, contrast: Contrast) -> Style {
96        self.style(self.gray[n], contrast)
97    }
98
99    /// Create a style from the given red shade.
100    /// n is `0..=3`
101    pub fn red(&self, n: usize, contrast: Contrast) -> Style {
102        self.style(self.red[n], contrast)
103    }
104
105    /// Create a style from the given orange shade.
106    /// n is `0..=3`
107    pub fn orange(&self, n: usize, contrast: Contrast) -> Style {
108        self.style(self.orange[n], contrast)
109    }
110
111    /// Create a style from the given yellow shade.
112    /// n is `0..=3`
113    pub fn yellow(&self, n: usize, contrast: Contrast) -> Style {
114        self.style(self.yellow[n], contrast)
115    }
116
117    /// Create a style from the given limegreen shade.
118    /// n is `0..=3`
119    pub fn limegreen(&self, n: usize, contrast: Contrast) -> Style {
120        self.style(self.limegreen[n], contrast)
121    }
122
123    /// Create a style from the given green shade.
124    /// n is `0..=3`
125    pub fn green(&self, n: usize, contrast: Contrast) -> Style {
126        self.style(self.green[n], contrast)
127    }
128
129    /// Create a style from the given bluegreen shade.
130    /// n is `0..=3`
131    pub fn bluegreen(&self, n: usize, contrast: Contrast) -> Style {
132        self.style(self.bluegreen[n], contrast)
133    }
134
135    /// Create a style from the given cyan shade.
136    /// n is `0..=3`
137    pub fn cyan(&self, n: usize, contrast: Contrast) -> Style {
138        self.style(self.cyan[n], contrast)
139    }
140
141    /// Create a style from the given blue shade.
142    /// n is `0..=3`
143    pub fn blue(&self, n: usize, contrast: Contrast) -> Style {
144        self.style(self.blue[n], contrast)
145    }
146
147    /// Create a style from the given deepblue shade.
148    /// n is `0..=3`
149    pub fn deepblue(&self, n: usize, contrast: Contrast) -> Style {
150        self.style(self.deepblue[n], contrast)
151    }
152
153    /// Create a style from the given purple shade.
154    /// n is `0..=3`
155    pub fn purple(&self, n: usize, contrast: Contrast) -> Style {
156        self.style(self.purple[n], contrast)
157    }
158
159    /// Create a style from the given magenta shade.
160    /// n is `0..=3`
161    pub fn magenta(&self, n: usize, contrast: Contrast) -> Style {
162        self.style(self.magenta[n], contrast)
163    }
164
165    /// Create a style from the given redpink shade.
166    /// n is `0..=3`
167    pub fn redpink(&self, n: usize, contrast: Contrast) -> Style {
168        self.style(self.redpink[n], contrast)
169    }
170
171    /// Create a style from the given primary shade.
172    /// n is `0..=3`
173    pub fn primary(&self, n: usize, contrast: Contrast) -> Style {
174        self.style(self.primary[n], contrast)
175    }
176
177    /// Create a style from the given secondary shade.
178    /// n is `0..=3`
179    pub fn secondary(&self, n: usize, contrast: Contrast) -> Style {
180        self.style(self.secondary[n], contrast)
181    }
182}
183
184impl Palette {
185    /// Create a style with the given background color and
186    /// contrast.
187    pub fn style(&self, color: Color, contrast: Contrast) -> Style {
188        match contrast {
189            Contrast::High => self.high_contrast(color),
190            Contrast::Normal => self.normal_contrast(color),
191        }
192    }
193
194    /// Create a style with the given background color.
195    /// Uses `white[3]` or `black[0]` for the foreground,
196    /// based on `rate_text_color`.
197    pub fn high_contrast(&self, color: Color) -> Style {
198        match Self::rate_text_color(color) {
199            None => Style::reset(),
200            Some(TextColorRating::Light) => Style::new().bg(color).fg(self.white[3]),
201            Some(TextColorRating::Dark) => Style::new().bg(color).fg(self.black[0]),
202        }
203    }
204
205    /// Create a style with the given background color.
206    /// Uses `white[0]` or `black[3]` for the foreground,
207    /// based on `rate_text_color`.
208    pub fn normal_contrast(&self, color: Color) -> Style {
209        match Self::rate_text_color(color) {
210            None => Style::reset(),
211            Some(TextColorRating::Light) => Style::new().bg(color).fg(self.white[0]),
212            Some(TextColorRating::Dark) => Style::new().bg(color).fg(self.black[3]),
213        }
214    }
215
216    /// This gives back a [TextColorRating] for the given background.
217    ///
218    /// This converts RGB to grayscale and takes the grayscale value
219    /// of VGA cyan as threshold, which is about 105 out of 255.
220    /// This point is a bit arbitrary, just based on what I
221    /// perceive as acceptable. But it produces a good reading
222    /// contrast in my experience.
223    ///
224    /// For the named colors it takes the VGA equivalent as a base.
225    /// For indexed colors it splits the range in half as an estimate.
226    pub const fn rate_text_color(color: Color) -> Option<TextColorRating> {
227        match color {
228            Color::Reset => None,
229            Color::Black => Some(TextColorRating::Light), //0
230            Color::Red => Some(TextColorRating::Light),   //1
231            Color::Green => Some(TextColorRating::Light), //2
232            Color::Yellow => Some(TextColorRating::Light), //3
233            Color::Blue => Some(TextColorRating::Light),  //4
234            Color::Magenta => Some(TextColorRating::Light), //5
235            Color::Cyan => Some(TextColorRating::Light),  //6
236            Color::Gray => Some(TextColorRating::Dark),   //7
237            Color::DarkGray => Some(TextColorRating::Light), //8
238            Color::LightRed => Some(TextColorRating::Dark), //9
239            Color::LightGreen => Some(TextColorRating::Dark), //10
240            Color::LightYellow => Some(TextColorRating::Dark), //11
241            Color::LightBlue => Some(TextColorRating::Light), //12
242            Color::LightMagenta => Some(TextColorRating::Dark), //13
243            Color::LightCyan => Some(TextColorRating::Dark), //14
244            Color::White => Some(TextColorRating::Dark),  //15
245            Color::Rgb(r, g, b) => {
246                // The formula used in the GIMP is Y = 0.3R + 0.59G + 0.11B;
247                // That's also Rec.ITU-R BT.601-7
248                // let grey = r as f32 * 0.2989f32 + g as f32 * 0.5870f32 + b as f32 * 0.1140f32;
249
250                // Another standard BT.709. Works better with green.
251                let grey = r as f32 * 0.2126f32 + g as f32 * 0.7152f32 + b as f32 * 0.0722f32;
252                if grey >= 105f32 {
253                    Some(TextColorRating::Dark)
254                } else {
255                    Some(TextColorRating::Light)
256                }
257            }
258            Color::Indexed(n) => match n {
259                0..=6 => Some(TextColorRating::Light),
260                7 => Some(TextColorRating::Dark),
261                8 => Some(TextColorRating::Light),
262                9..=11 => Some(TextColorRating::Dark),
263                12 => Some(TextColorRating::Light),
264                13..=15 => Some(TextColorRating::Dark),
265                v @ 16..=231 => {
266                    if (v - 16) % 36 < 18 {
267                        Some(TextColorRating::Light)
268                    } else {
269                        Some(TextColorRating::Dark)
270                    }
271                }
272                v @ 232..=255 => {
273                    if (v - 232) % 24 < 12 {
274                        Some(TextColorRating::Light)
275                    } else {
276                        Some(TextColorRating::Dark)
277                    }
278                }
279            },
280        }
281    }
282
283    /// Reduces the range of the given color from 0..255
284    /// to 0..scale_to.
285    ///
286    /// This gives a true dark equivalent which can be used
287    /// as a background for a dark theme.
288    pub const fn darken(color: Color, scale_to: u8) -> Color {
289        let (r, g, b) = Self::color2rgb(color);
290        Color::Rgb(
291            Self::scale_to(r, scale_to),
292            Self::scale_to(g, scale_to),
293            Self::scale_to(b, scale_to),
294        )
295    }
296
297    /// Converts the given color to an equivalent grayscale.
298    pub const fn grayscale(color: Color) -> Color {
299        let (r, g, b) = Self::color2rgb(color);
300        // The formula used in the GIMP is Y = 0.3R + 0.59G + 0.11B;
301        let gray = r as f32 * 0.3f32 + g as f32 * 0.59f32 + b as f32 * 0.11f32;
302        Color::Rgb(gray as u8, gray as u8, gray as u8)
303    }
304
305    /// Calculates a linear interpolation for the two colors
306    /// and fills the first 4 colors with it.
307    /// The next 4 colors are scaled down versions using dark_scale_to.
308    pub const fn interpolate(c0: u32, c1: u32, dark_scale_to: u8) -> [Color; 8] {
309        // 1/3
310        const fn i1(a: u8, b: u8) -> u8 {
311            if a < b {
312                a + (b - a) / 3
313            } else {
314                a - (a - b) / 3
315            }
316        }
317        // 2/3
318        const fn i2(a: u8, b: u8) -> u8 {
319            if a < b {
320                b - (b - a) / 3
321            } else {
322                b + (a - b) / 3
323            }
324        }
325
326        let r0 = (c0 >> 16) as u8;
327        let g0 = (c0 >> 8) as u8;
328        let b0 = c0 as u8;
329
330        let r3 = (c1 >> 16) as u8;
331        let g3 = (c1 >> 8) as u8;
332        let b3 = c1 as u8;
333
334        let r1 = i1(r0, r3);
335        let g1 = i1(g0, g3);
336        let b1 = i1(b0, b3);
337
338        let r2 = i2(r0, r3);
339        let g2 = i2(g0, g3);
340        let b2 = i2(b0, b3);
341
342        // dark
343        let r4 = Self::scale_to(r0, dark_scale_to);
344        let g4 = Self::scale_to(g0, dark_scale_to);
345        let b4 = Self::scale_to(b0, dark_scale_to);
346
347        let r5 = Self::scale_to(r1, dark_scale_to);
348        let g5 = Self::scale_to(g1, dark_scale_to);
349        let b5 = Self::scale_to(b1, dark_scale_to);
350
351        let r6 = Self::scale_to(r2, dark_scale_to);
352        let g6 = Self::scale_to(g2, dark_scale_to);
353        let b6 = Self::scale_to(b2, dark_scale_to);
354
355        let r7 = Self::scale_to(r3, dark_scale_to);
356        let g7 = Self::scale_to(g3, dark_scale_to);
357        let b7 = Self::scale_to(b3, dark_scale_to);
358
359        [
360            Color::Rgb(r0, g0, b0),
361            Color::Rgb(r1, g1, b1),
362            Color::Rgb(r2, g2, b2),
363            Color::Rgb(r3, g3, b3),
364            Color::Rgb(r4, g4, b4),
365            Color::Rgb(r5, g5, b5),
366            Color::Rgb(r6, g6, b6),
367            Color::Rgb(r7, g7, b7),
368        ]
369    }
370
371    /// Scale the u8 down to scale_to.
372    pub const fn scale_to(v: u8, scale_to: u8) -> u8 {
373        (((v as u16) * scale_to as u16) / 255u16) as u8
374    }
375
376    /// Gives back the rgb for any ratatui Color.
377    /// Has the indexed and the named colors too.
378    pub const fn color2rgb(color: Color) -> (u8, u8, u8) {
379        match color {
380            Color::Black => (0x00, 0x00, 0x00),
381            Color::Red => (0xaa, 0x00, 0x00),
382            Color::Green => (0x00, 0xaa, 0x00),
383            Color::Yellow => (0xaa, 0x55, 0x00),
384            Color::Blue => (0x00, 0x00, 0xaa),
385            Color::Magenta => (0xaa, 0x00, 0xaa),
386            Color::Cyan => (0x00, 0xaa, 0xaa),
387            Color::Gray => (0xaa, 0xaa, 0xaa),
388            Color::DarkGray => (0x55, 0x55, 0x55),
389            Color::LightRed => (0xff, 0x55, 0x55),
390            Color::LightGreen => (0x55, 0xff, 0x55),
391            Color::LightYellow => (0xff, 0xff, 0x55),
392            Color::LightBlue => (0x55, 0x55, 0xff),
393            Color::LightMagenta => (0xff, 0x55, 0xff),
394            Color::LightCyan => (0x55, 0xff, 0xff),
395            Color::White => (0xff, 0xff, 0xff),
396            Color::Rgb(r, g, b) => (r, g, b),
397            Color::Indexed(i) => {
398                const VGA256: [(u8, u8, u8); 256] = [
399                    (0x00, 0x00, 0x00),
400                    (0x80, 0x00, 0x00),
401                    (0x00, 0x80, 0x00),
402                    (0x80, 0x80, 0x00),
403                    (0x00, 0x00, 0x80),
404                    (0x80, 0x00, 0x80),
405                    (0x00, 0x80, 0x80),
406                    (0xc0, 0xc0, 0xc0),
407                    (0x80, 0x80, 0x80),
408                    (0xff, 0x00, 0x00),
409                    (0x00, 0xff, 0x00),
410                    (0xff, 0xff, 0x00),
411                    (0x00, 0x00, 0xff),
412                    (0xff, 0x00, 0xff),
413                    (0x00, 0xff, 0xff),
414                    (0xff, 0xff, 0xff),
415                    (0x00, 0x00, 0x00),
416                    (0x00, 0x00, 0x5f),
417                    (0x00, 0x00, 0x87),
418                    (0x00, 0x00, 0xaf),
419                    (0x00, 0x00, 0xd7),
420                    (0x00, 0x00, 0xff),
421                    (0x00, 0x5f, 0x00),
422                    (0x00, 0x5f, 0x5f),
423                    (0x00, 0x5f, 0x87),
424                    (0x00, 0x5f, 0xaf),
425                    (0x00, 0x5f, 0xd7),
426                    (0x00, 0x5f, 0xff),
427                    (0x00, 0x87, 0x00),
428                    (0x00, 0x87, 0x5f),
429                    (0x00, 0x87, 0x87),
430                    (0x00, 0x87, 0xaf),
431                    (0x00, 0x87, 0xd7),
432                    (0x00, 0x87, 0xff),
433                    (0x00, 0xaf, 0x00),
434                    (0x00, 0xaf, 0x5f),
435                    (0x00, 0xaf, 0x87),
436                    (0x00, 0xaf, 0xaf),
437                    (0x00, 0xaf, 0xd7),
438                    (0x00, 0xaf, 0xff),
439                    (0x00, 0xd7, 0x00),
440                    (0x00, 0xd7, 0x5f),
441                    (0x00, 0xd7, 0x87),
442                    (0x00, 0xd7, 0xaf),
443                    (0x00, 0xd7, 0xd7),
444                    (0x00, 0xd7, 0xff),
445                    (0x00, 0xff, 0x00),
446                    (0x00, 0xff, 0x5f),
447                    (0x00, 0xff, 0x87),
448                    (0x00, 0xff, 0xaf),
449                    (0x00, 0xff, 0xd7),
450                    (0x00, 0xff, 0xff),
451                    (0x5f, 0x00, 0x00),
452                    (0x5f, 0x00, 0x5f),
453                    (0x5f, 0x00, 0x87),
454                    (0x5f, 0x00, 0xaf),
455                    (0x5f, 0x00, 0xd7),
456                    (0x5f, 0x00, 0xff),
457                    (0x5f, 0x5f, 0x00),
458                    (0x5f, 0x5f, 0x5f),
459                    (0x5f, 0x5f, 0x87),
460                    (0x5f, 0x5f, 0xaf),
461                    (0x5f, 0x5f, 0xd7),
462                    (0x5f, 0x5f, 0xff),
463                    (0x5f, 0x87, 0x00),
464                    (0x5f, 0x87, 0x5f),
465                    (0x5f, 0x87, 0x87),
466                    (0x5f, 0x87, 0xaf),
467                    (0x5f, 0x87, 0xd7),
468                    (0x5f, 0x87, 0xff),
469                    (0x5f, 0xaf, 0x00),
470                    (0x5f, 0xaf, 0x5f),
471                    (0x5f, 0xaf, 0x87),
472                    (0x5f, 0xaf, 0xaf),
473                    (0x5f, 0xaf, 0xd7),
474                    (0x5f, 0xaf, 0xff),
475                    (0x5f, 0xd7, 0x00),
476                    (0x5f, 0xd7, 0x5f),
477                    (0x5f, 0xd7, 0x87),
478                    (0x5f, 0xd7, 0xaf),
479                    (0x5f, 0xd7, 0xd7),
480                    (0x5f, 0xd7, 0xff),
481                    (0x5f, 0xff, 0x00),
482                    (0x5f, 0xff, 0x5f),
483                    (0x5f, 0xff, 0x87),
484                    (0x5f, 0xff, 0xaf),
485                    (0x5f, 0xff, 0xd7),
486                    (0x5f, 0xff, 0xff),
487                    (0x87, 0x00, 0x00),
488                    (0x87, 0x00, 0x5f),
489                    (0x87, 0x00, 0x87),
490                    (0x87, 0x00, 0xaf),
491                    (0x87, 0x00, 0xd7),
492                    (0x87, 0x00, 0xff),
493                    (0x87, 0x5f, 0x00),
494                    (0x87, 0x5f, 0x5f),
495                    (0x87, 0x5f, 0x87),
496                    (0x87, 0x5f, 0xaf),
497                    (0x87, 0x5f, 0xd7),
498                    (0x87, 0x5f, 0xff),
499                    (0x87, 0x87, 0x00),
500                    (0x87, 0x87, 0x5f),
501                    (0x87, 0x87, 0x87),
502                    (0x87, 0x87, 0xaf),
503                    (0x87, 0x87, 0xd7),
504                    (0x87, 0x87, 0xff),
505                    (0x87, 0xaf, 0x00),
506                    (0x87, 0xaf, 0x5f),
507                    (0x87, 0xaf, 0x87),
508                    (0x87, 0xaf, 0xaf),
509                    (0x87, 0xaf, 0xd7),
510                    (0x87, 0xaf, 0xff),
511                    (0x87, 0xd7, 0x00),
512                    (0x87, 0xd7, 0x5f),
513                    (0x87, 0xd7, 0x87),
514                    (0x87, 0xd7, 0xaf),
515                    (0x87, 0xd7, 0xd7),
516                    (0x87, 0xd7, 0xff),
517                    (0x87, 0xff, 0x00),
518                    (0x87, 0xff, 0x5f),
519                    (0x87, 0xff, 0x87),
520                    (0x87, 0xff, 0xaf),
521                    (0x87, 0xff, 0xd7),
522                    (0x87, 0xff, 0xff),
523                    (0xaf, 0x00, 0x00),
524                    (0xaf, 0x00, 0x5f),
525                    (0xaf, 0x00, 0x87),
526                    (0xaf, 0x00, 0xaf),
527                    (0xaf, 0x00, 0xd7),
528                    (0xaf, 0x00, 0xff),
529                    (0xaf, 0x5f, 0x00),
530                    (0xaf, 0x5f, 0x5f),
531                    (0xaf, 0x5f, 0x87),
532                    (0xaf, 0x5f, 0xaf),
533                    (0xaf, 0x5f, 0xd7),
534                    (0xaf, 0x5f, 0xff),
535                    (0xaf, 0x87, 0x00),
536                    (0xaf, 0x87, 0x5f),
537                    (0xaf, 0x87, 0x87),
538                    (0xaf, 0x87, 0xaf),
539                    (0xaf, 0x87, 0xd7),
540                    (0xaf, 0x87, 0xff),
541                    (0xaf, 0xaf, 0x00),
542                    (0xaf, 0xaf, 0x5f),
543                    (0xaf, 0xaf, 0x87),
544                    (0xaf, 0xaf, 0xaf),
545                    (0xaf, 0xaf, 0xd7),
546                    (0xaf, 0xaf, 0xff),
547                    (0xaf, 0xd7, 0x00),
548                    (0xaf, 0xd7, 0x5f),
549                    (0xaf, 0xd7, 0x87),
550                    (0xaf, 0xd7, 0xaf),
551                    (0xaf, 0xd7, 0xd7),
552                    (0xaf, 0xd7, 0xff),
553                    (0xaf, 0xff, 0x00),
554                    (0xaf, 0xff, 0x5f),
555                    (0xaf, 0xff, 0x87),
556                    (0xaf, 0xff, 0xaf),
557                    (0xaf, 0xff, 0xd7),
558                    (0xaf, 0xff, 0xff),
559                    (0xd7, 0x00, 0x00),
560                    (0xd7, 0x00, 0x5f),
561                    (0xd7, 0x00, 0x87),
562                    (0xd7, 0x00, 0xaf),
563                    (0xd7, 0x00, 0xd7),
564                    (0xd7, 0x00, 0xff),
565                    (0xd7, 0x5f, 0x00),
566                    (0xd7, 0x5f, 0x5f),
567                    (0xd7, 0x5f, 0x87),
568                    (0xd7, 0x5f, 0xaf),
569                    (0xd7, 0x5f, 0xd7),
570                    (0xd7, 0x5f, 0xff),
571                    (0xd7, 0x87, 0x00),
572                    (0xd7, 0x87, 0x5f),
573                    (0xd7, 0x87, 0x87),
574                    (0xd7, 0x87, 0xaf),
575                    (0xd7, 0x87, 0xd7),
576                    (0xd7, 0x87, 0xff),
577                    (0xd7, 0xaf, 0x00),
578                    (0xd7, 0xaf, 0x5f),
579                    (0xd7, 0xaf, 0x87),
580                    (0xd7, 0xaf, 0xaf),
581                    (0xd7, 0xaf, 0xd7),
582                    (0xd7, 0xaf, 0xff),
583                    (0xd7, 0xd7, 0x00),
584                    (0xd7, 0xd7, 0x5f),
585                    (0xd7, 0xd7, 0x87),
586                    (0xd7, 0xd7, 0xaf),
587                    (0xd7, 0xd7, 0xd7),
588                    (0xd7, 0xd7, 0xff),
589                    (0xd7, 0xff, 0x00),
590                    (0xd7, 0xff, 0x5f),
591                    (0xd7, 0xff, 0x87),
592                    (0xd7, 0xff, 0xaf),
593                    (0xd7, 0xff, 0xd7),
594                    (0xd7, 0xff, 0xff),
595                    (0xff, 0x00, 0x00),
596                    (0xff, 0x00, 0x5f),
597                    (0xff, 0x00, 0x87),
598                    (0xff, 0x00, 0xaf),
599                    (0xff, 0x00, 0xd7),
600                    (0xff, 0x00, 0xff),
601                    (0xff, 0x5f, 0x00),
602                    (0xff, 0x5f, 0x5f),
603                    (0xff, 0x5f, 0x87),
604                    (0xff, 0x5f, 0xaf),
605                    (0xff, 0x5f, 0xd7),
606                    (0xff, 0x5f, 0xff),
607                    (0xff, 0x87, 0x00),
608                    (0xff, 0x87, 0x5f),
609                    (0xff, 0x87, 0x87),
610                    (0xff, 0x87, 0xaf),
611                    (0xff, 0x87, 0xd7),
612                    (0xff, 0x87, 0xff),
613                    (0xff, 0xaf, 0x00),
614                    (0xff, 0xaf, 0x5f),
615                    (0xff, 0xaf, 0x87),
616                    (0xff, 0xaf, 0xaf),
617                    (0xff, 0xaf, 0xd7),
618                    (0xff, 0xaf, 0xff),
619                    (0xff, 0xd7, 0x00),
620                    (0xff, 0xd7, 0x5f),
621                    (0xff, 0xd7, 0x87),
622                    (0xff, 0xd7, 0xaf),
623                    (0xff, 0xd7, 0xd7),
624                    (0xff, 0xd7, 0xff),
625                    (0xff, 0xff, 0x00),
626                    (0xff, 0xff, 0x5f),
627                    (0xff, 0xff, 0x87),
628                    (0xff, 0xff, 0xaf),
629                    (0xff, 0xff, 0xd7),
630                    (0xff, 0xff, 0xff),
631                    (0x08, 0x08, 0x08),
632                    (0x12, 0x12, 0x12),
633                    (0x1c, 0x1c, 0x1c),
634                    (0x26, 0x26, 0x26),
635                    (0x30, 0x30, 0x30),
636                    (0x3a, 0x3a, 0x3a),
637                    (0x44, 0x44, 0x44),
638                    (0x4e, 0x4e, 0x4e),
639                    (0x58, 0x58, 0x58),
640                    (0x62, 0x62, 0x62),
641                    (0x6c, 0x6c, 0x6c),
642                    (0x76, 0x76, 0x76),
643                    (0x80, 0x80, 0x80),
644                    (0x8a, 0x8a, 0x8a),
645                    (0x94, 0x94, 0x94),
646                    (0x9e, 0x9e, 0x9e),
647                    (0xa8, 0xa8, 0xa8),
648                    (0xb2, 0xb2, 0xb2),
649                    (0xbc, 0xbc, 0xbc),
650                    (0xc6, 0xc6, 0xc6),
651                    (0xd0, 0xd0, 0xd0),
652                    (0xda, 0xda, 0xda),
653                    (0xe4, 0xe4, 0xe4),
654                    (0xee, 0xee, 0xee),
655                ];
656                VGA256[i as usize]
657            }
658            Color::Reset => (0, 0, 0),
659        }
660    }
661}