rat_theme4/
palette.rs

1use ratatui::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#[derive(Debug, Default, Clone, Copy)]
16pub struct Palette {
17    pub name: &'static str,
18
19    pub text_light: Color,
20    pub text_bright: Color,
21    pub text_dark: Color,
22    pub text_black: Color,
23
24    pub white: [Color; 8],
25    pub black: [Color; 8],
26    pub gray: [Color; 8],
27
28    pub red: [Color; 8],
29    pub orange: [Color; 8],
30    pub yellow: [Color; 8],
31    pub limegreen: [Color; 8],
32    pub green: [Color; 8],
33    pub bluegreen: [Color; 8],
34    pub cyan: [Color; 8],
35    pub blue: [Color; 8],
36    pub deepblue: [Color; 8],
37    pub purple: [Color; 8],
38    pub magenta: [Color; 8],
39    pub redpink: [Color; 8],
40
41    pub primary: [Color; 8],
42    pub secondary: [Color; 8],
43}
44
45/// Contrast rating for the text-color that should be used.
46#[derive(Debug)]
47pub enum TextColorRating {
48    /// Use light/white text for the given background.
49    Light,
50    /// Use dark/black text for the given background.
51    Dark,
52}
53
54impl Palette {
55    /// Color index for a bright variant of the base color.
56    /// Brightness increases with the number.
57    pub const C0: usize = 0;
58    /// Color index for a bright variant of the base color.
59    /// Brightness increases with the number.
60    pub const C1: usize = 1;
61    /// Color index for a bright variant of the base color.
62    /// Brightness increases with the number.
63    pub const C2: usize = 2;
64    /// Color index for a bright variant of the base color.
65    /// Brightness increases with the number.
66    pub const C3: usize = 3;
67    /// Color index for a dark variant of the base color.
68    /// Brightness increases with the number.
69    pub const D0: usize = 4;
70    /// Color index for a dark variant of the base color.
71    /// Brightness increases with the number.
72    pub const D1: usize = 5;
73    /// Color index for a dark variant of the base color.
74    /// Brightness increases with the number.
75    pub const D2: usize = 6;
76    /// Color index for a dark variant of the base color.
77    /// Brightness increases with the number.
78    pub const D3: usize = 7;
79
80    /// Create a style from the given white shade.
81    /// n is `0..=3`
82    pub fn white(&self, n: usize) -> Style {
83        self.normal_contrast(self.white[n])
84    }
85
86    /// Create a style from the given black shade.
87    /// n is `0..=3`
88    pub fn black(&self, n: usize) -> Style {
89        self.normal_contrast(self.black[n])
90    }
91
92    /// Create a style from the given gray shade.
93    /// n is `0..=3`
94    pub fn gray(&self, n: usize) -> Style {
95        self.normal_contrast(self.gray[n])
96    }
97
98    /// Create a style from the given red shade.
99    /// n is `0..=3`
100    pub fn red(&self, n: usize) -> Style {
101        self.normal_contrast(self.red[n])
102    }
103
104    /// Create a style from the given orange shade.
105    /// n is `0..=3`
106    pub fn orange(&self, n: usize) -> Style {
107        self.normal_contrast(self.orange[n])
108    }
109
110    /// Create a style from the given yellow shade.
111    /// n is `0..=3`
112    pub fn yellow(&self, n: usize) -> Style {
113        self.normal_contrast(self.yellow[n])
114    }
115
116    /// Create a style from the given limegreen shade.
117    /// n is `0..=3`
118    pub fn limegreen(&self, n: usize) -> Style {
119        self.normal_contrast(self.limegreen[n])
120    }
121
122    /// Create a style from the given green shade.
123    /// n is `0..=3`
124    pub fn green(&self, n: usize) -> Style {
125        self.normal_contrast(self.green[n])
126    }
127
128    /// Create a style from the given bluegreen shade.
129    /// n is `0..=3`
130    pub fn bluegreen(&self, n: usize) -> Style {
131        self.normal_contrast(self.bluegreen[n])
132    }
133
134    /// Create a style from the given cyan shade.
135    /// n is `0..=3`
136    pub fn cyan(&self, n: usize) -> Style {
137        self.normal_contrast(self.cyan[n])
138    }
139
140    /// Create a style from the given blue shade.
141    /// n is `0..=3`
142    pub fn blue(&self, n: usize) -> Style {
143        self.normal_contrast(self.blue[n])
144    }
145
146    /// Create a style from the given deepblue shade.
147    /// n is `0..=3`
148    pub fn deepblue(&self, n: usize) -> Style {
149        self.normal_contrast(self.deepblue[n])
150    }
151
152    /// Create a style from the given purple shade.
153    /// n is `0..=3`
154    pub fn purple(&self, n: usize) -> Style {
155        self.normal_contrast(self.purple[n])
156    }
157
158    /// Create a style from the given magenta shade.
159    /// n is `0..=3`
160    pub fn magenta(&self, n: usize) -> Style {
161        self.normal_contrast(self.magenta[n])
162    }
163
164    /// Create a style from the given redpink shade.
165    /// n is `0..=3`
166    pub fn redpink(&self, n: usize) -> Style {
167        self.normal_contrast(self.redpink[n])
168    }
169
170    /// Create a style from the given white shade.
171    /// n is `0..=3`
172    pub fn fg_white(&self, n: usize) -> Style {
173        Style::new().fg(self.white[n])
174    }
175
176    /// Create a style from the given black shade.
177    /// n is `0..=3`
178    pub fn fg_black(&self, n: usize) -> Style {
179        Style::new().fg(self.black[n])
180    }
181
182    /// Create a style from the given gray shade.
183    /// n is `0..=3`
184    pub fn fg_gray(&self, n: usize) -> Style {
185        Style::new().fg(self.gray[n])
186    }
187
188    /// Create a style from the given red shade.
189    /// n is `0..=3`
190    pub fn fg_red(&self, n: usize) -> Style {
191        Style::new().fg(self.red[n])
192    }
193
194    /// Create a style from the given orange shade.
195    /// n is `0..=3`
196    pub fn fg_orange(&self, n: usize) -> Style {
197        Style::new().fg(self.orange[n])
198    }
199
200    /// Create a style from the given yellow shade.
201    /// n is `0..=3`
202    pub fn fg_yellow(&self, n: usize) -> Style {
203        Style::new().fg(self.yellow[n])
204    }
205
206    /// Create a style from the given limegreen shade.
207    /// n is `0..=3`
208    pub fn fg_limegreen(&self, n: usize) -> Style {
209        Style::new().fg(self.limegreen[n])
210    }
211
212    /// Create a style from the given green shade.
213    /// n is `0..=3`
214    pub fn fg_green(&self, n: usize) -> Style {
215        Style::new().fg(self.green[n])
216    }
217
218    /// Create a style from the given bluegreen shade.
219    /// n is `0..=3`
220    pub fn fg_bluegreen(&self, n: usize) -> Style {
221        Style::new().fg(self.bluegreen[n])
222    }
223
224    /// Create a style from the given cyan shade.
225    /// n is `0..=3`
226    pub fn fg_cyan(&self, n: usize) -> Style {
227        Style::new().fg(self.cyan[n])
228    }
229
230    /// Create a style from the given blue shade.
231    /// n is `0..=3`
232    pub fn fg_blue(&self, n: usize) -> Style {
233        Style::new().fg(self.blue[n])
234    }
235
236    /// Create a style from the given deepblue shade.
237    /// n is `0..=3`
238    pub fn fg_deepblue(&self, n: usize) -> Style {
239        Style::new().fg(self.deepblue[n])
240    }
241
242    /// Create a style from the given purple shade.
243    /// n is `0..=3`
244    pub fn fg_purple(&self, n: usize) -> Style {
245        Style::new().fg(self.purple[n])
246    }
247
248    /// Create a style from the given magenta shade.
249    /// n is `0..=3`
250    pub fn fg_magenta(&self, n: usize) -> Style {
251        Style::new().fg(self.magenta[n])
252    }
253
254    /// Create a style from the given redpink shade.
255    /// n is `0..=3`
256    pub fn fg_redpink(&self, n: usize) -> Style {
257        Style::new().fg(self.redpink[n])
258    }
259
260    /// Create a style from the given primary shade.
261    /// n is `0..=3`
262    pub fn primary(&self, n: usize) -> Style {
263        self.normal_contrast(self.primary[n])
264    }
265
266    /// Create a style from the given secondary shade.
267    /// n is `0..=3`
268    pub fn secondary(&self, n: usize) -> Style {
269        self.normal_contrast(self.secondary[n])
270    }
271
272    /// Create a style from the given white shade.
273    /// n is `0..=3`
274    pub fn bg_white(&self, n: usize) -> Style {
275        Style::new().bg(self.white[n])
276    }
277
278    /// Create a style from the given black shade.
279    /// n is `0..=3`
280    pub fn bg_black(&self, n: usize) -> Style {
281        Style::new().bg(self.black[n])
282    }
283
284    /// Create a style from the given gray shade.
285    /// n is `0..=3`
286    pub fn bg_gray(&self, n: usize) -> Style {
287        Style::new().bg(self.gray[n])
288    }
289
290    /// Create a style from the given red shade.
291    /// n is `0..=3`
292    pub fn bg_red(&self, n: usize) -> Style {
293        Style::new().bg(self.red[n])
294    }
295
296    /// Create a style from the given orange shade.
297    /// n is `0..=3`
298    pub fn bg_orange(&self, n: usize) -> Style {
299        Style::new().bg(self.orange[n])
300    }
301
302    /// Create a style from the given yellow shade.
303    /// n is `0..=3`
304    pub fn bg_yellow(&self, n: usize) -> Style {
305        Style::new().bg(self.yellow[n])
306    }
307
308    /// Create a style from the given limegreen shade.
309    /// n is `0..=3`
310    pub fn bg_limegreen(&self, n: usize) -> Style {
311        Style::new().bg(self.limegreen[n])
312    }
313
314    /// Create a style from the given green shade.
315    /// n is `0..=3`
316    pub fn bg_green(&self, n: usize) -> Style {
317        Style::new().bg(self.green[n])
318    }
319
320    /// Create a style from the given bluegreen shade.
321    /// n is `0..=3`
322    pub fn bg_bluegreen(&self, n: usize) -> Style {
323        Style::new().bg(self.bluegreen[n])
324    }
325
326    /// Create a style from the given cyan shade.
327    /// n is `0..=3`
328    pub fn bg_cyan(&self, n: usize) -> Style {
329        Style::new().bg(self.cyan[n])
330    }
331
332    /// Create a style from the given blue shade.
333    /// n is `0..=3`
334    pub fn bg_blue(&self, n: usize) -> Style {
335        Style::new().bg(self.blue[n])
336    }
337
338    /// Create a style from the given deepblue shade.
339    /// n is `0..=3`
340    pub fn bg_deepblue(&self, n: usize) -> Style {
341        Style::new().bg(self.deepblue[n])
342    }
343
344    /// Create a style from the given purple shade.
345    /// n is `0..=3`
346    pub fn bg_purple(&self, n: usize) -> Style {
347        Style::new().bg(self.purple[n])
348    }
349
350    /// Create a style from the given magenta shade.
351    /// n is `0..=3`
352    pub fn bg_magenta(&self, n: usize) -> Style {
353        Style::new().bg(self.magenta[n])
354    }
355
356    /// Create a style from the given redpink shade.
357    /// n is `0..=3`
358    pub fn bg_redpink(&self, n: usize) -> Style {
359        Style::new().bg(self.redpink[n])
360    }
361
362    /// Create a style from the given primary shade.
363    /// n is `0..=3`
364    pub fn bg_primary(&self, n: usize) -> Style {
365        Style::new().bg(self.primary[n])
366    }
367
368    /// Create a style from the given secondary shade.
369    /// n is `0..=3`
370    pub fn bg_secondary(&self, n: usize) -> Style {
371        Style::new().bg(self.secondary[n])
372    }
373
374    pub fn text_light(&self) -> Style {
375        Style::new().fg(self.text_light)
376    }
377
378    pub fn text_bright(&self) -> Style {
379        Style::new().fg(self.text_bright)
380    }
381
382    pub fn text_dark(&self) -> Style {
383        Style::new().fg(self.text_dark)
384    }
385
386    pub fn text_black(&self) -> Style {
387        Style::new().fg(self.text_black)
388    }
389}
390
391impl Palette {
392    /// Create a style with the given background color.
393    /// Uses `white[3]` or `black[0]` for the foreground,
394    /// based on `rate_text_color`.
395    pub fn high_contrast(&self, color: Color) -> Style {
396        match Self::rate_text_color(color) {
397            None => Style::reset(),
398            Some(TextColorRating::Light) => Style::new().bg(color).fg(self.text_bright),
399            Some(TextColorRating::Dark) => Style::new().bg(color).fg(self.text_black),
400        }
401    }
402
403    /// Create a style with the given background color.
404    /// Uses text_light or text_dark for the foreground,
405    /// based on `rate_text_color`.
406    pub fn normal_contrast(&self, color: Color) -> Style {
407        match Self::rate_text_color(color) {
408            None => Style::reset(),
409            Some(TextColorRating::Light) => Style::new().bg(color).fg(self.text_light),
410            Some(TextColorRating::Dark) => Style::new().bg(color).fg(self.text_dark),
411        }
412    }
413
414    /// Pick a color from the choice with a good contrast to the
415    /// given background.
416    pub fn normal_contrast_color(&self, bg: Color, text: &[Color]) -> Style {
417        let mut color0 = text[0];
418        let mut color1 = text[0];
419        let mut contrast1 = Self::contrast_bt_srgb(color1, bg);
420
421        for text_color in text {
422            let test = Self::contrast_bt_srgb(*text_color, bg);
423            if test > contrast1 {
424                color0 = color1;
425                color1 = *text_color;
426                contrast1 = test;
427            }
428        }
429
430        Style::new().bg(bg).fg(color0)
431    }
432
433    /// Pick a color from the choice with the best contrast to the
434    /// given background.
435    pub fn high_contrast_color(&self, bg: Color, text: &[Color]) -> Style {
436        let mut color0 = text[0];
437        let mut color1 = text[0];
438        let mut contrast1 = Self::contrast_bt_srgb(color1, bg);
439
440        for text_color in text {
441            let test = Self::contrast_bt_srgb(*text_color, bg);
442            if test > contrast1 {
443                color0 = color1;
444                color1 = *text_color;
445                contrast1 = test;
446            }
447        }
448        // don't use the second brightest.
449        _ = color0;
450
451        Style::new().bg(bg).fg(color1)
452    }
453
454    // /// Gives the luminance according to Rec.ITU-R BT.601-7.
455    // const fn luminance_itu(color: Color) -> f32 {
456    //     let (r, g, b) = Self::color2rgb(color);
457    //     0.2989f32 * (r as f32) / 255f32
458    //         + 0.5870f32 * (g as f32) / 255f32
459    //         + 0.1140f32 * (b as f32) / 255f32
460    // }
461    //
462    // /// Gives the luminance according to Rec.ITU-R BT.601-7.
463    // fn luminance_itu_srgb(color: Color) -> f32 {
464    //     let (r, g, b) = Self::color2rgb(color);
465    //     0.2989f32 * (r as f32) / 255f32
466    //         + 0.5870f32 * (g as f32) / 255f32
467    //         + 0.1140f32 * (b as f32) / 255f32
468    // }
469    //
470    // /// Contrast between two colors.
471    // fn contrast_itu_srgb(color: Color, color2: Color) -> f32 {
472    //     let lum1 = Self::luminance_itu_srgb(color);
473    //     let lum2 = Self::luminance_itu_srgb(color2);
474    //     (lum1 + 0.05f32) / (lum2 + 0.05f32)
475    // }
476
477    /// Gives the luminance according to BT.709.
478    pub(crate) const fn luminance_bt(color: Color) -> f32 {
479        let (r, g, b) = Self::color2rgb(color);
480        0.2126f32 * ((r as f32) / 255f32)
481            + 0.7152f32 * ((g as f32) / 255f32)
482            + 0.0722f32 * ((b as f32) / 255f32)
483    }
484
485    /// Gives the luminance according to BT.709.
486    pub(crate) fn luminance_bt_srgb(color: Color) -> f32 {
487        let (r, g, b) = Self::color2rgb(color);
488        0.2126f32 * ((r as f32) / 255f32).powf(2.2f32)
489            + 0.7152f32 * ((g as f32) / 255f32).powf(2.2f32)
490            + 0.0722f32 * ((b as f32) / 255f32).powf(2.2f32)
491    }
492
493    /// Contrast between two colors.
494    pub(crate) fn contrast_bt_srgb(color: Color, color2: Color) -> f32 {
495        let lum1 = Self::luminance_bt_srgb(color);
496        let lum2 = Self::luminance_bt_srgb(color2);
497        (lum1 - lum2).abs()
498        // Don't use this prescribed method.
499        // The abs diff comes out better.
500        // (lum1 + 0.05f32) / (lum2 + 0.05f32)
501    }
502
503    /// This gives back a [TextColorRating] for the given background.
504    ///
505    /// This converts RGB to grayscale and takes the grayscale value
506    /// of VGA cyan as threshold, which is about 105 out of 255.
507    /// This point is a bit arbitrary, just based on what I
508    /// perceive as acceptable. But it produces a good reading
509    /// contrast in my experience.
510    ///
511    /// For the named colors it takes the VGA equivalent as a base.
512    /// For indexed colors it splits the range in half as an estimate.
513    pub(crate) fn rate_text_color(color: Color) -> Option<TextColorRating> {
514        match color {
515            Color::Reset => None,
516            Color::Black => Some(TextColorRating::Light), //0
517            Color::Red => Some(TextColorRating::Light),   //1
518            Color::Green => Some(TextColorRating::Light), //2
519            Color::Yellow => Some(TextColorRating::Light), //3
520            Color::Blue => Some(TextColorRating::Light),  //4
521            Color::Magenta => Some(TextColorRating::Light), //5
522            Color::Cyan => Some(TextColorRating::Light),  //6
523            Color::Gray => Some(TextColorRating::Dark),   //7
524            Color::DarkGray => Some(TextColorRating::Light), //8
525            Color::LightRed => Some(TextColorRating::Dark), //9
526            Color::LightGreen => Some(TextColorRating::Dark), //10
527            Color::LightYellow => Some(TextColorRating::Dark), //11
528            Color::LightBlue => Some(TextColorRating::Light), //12
529            Color::LightMagenta => Some(TextColorRating::Dark), //13
530            Color::LightCyan => Some(TextColorRating::Dark), //14
531            Color::White => Some(TextColorRating::Dark),  //15
532            c => {
533                let lum = Self::luminance_bt(c);
534                if lum >= 0.4117f32 {
535                    Some(TextColorRating::Dark)
536                } else {
537                    Some(TextColorRating::Light)
538                }
539            }
540        }
541    }
542
543    /// Reduces the range of the given color from 0..255
544    /// to 0..scale_to.
545    ///
546    /// This gives a true dark equivalent which can be used
547    /// as a background for a dark theme.
548    pub const fn darken(color: Color, scale_to: u8) -> Color {
549        let (r, g, b) = Self::color2rgb(color);
550        Color::Rgb(
551            Self::scale_to(r, scale_to),
552            Self::scale_to(g, scale_to),
553            Self::scale_to(b, scale_to),
554        )
555    }
556
557    /// Converts the given color to an equivalent grayscale.
558    pub const fn grayscale(color: Color) -> Color {
559        let lum = Self::luminance_bt(color);
560        let gray = lum * 255f32;
561        Color::Rgb(gray as u8, gray as u8, gray as u8)
562    }
563
564    /// Color from u32
565    pub const fn color32(c0: u32) -> Color {
566        let r0 = (c0 >> 16) as u8;
567        let g0 = (c0 >> 8) as u8;
568        let b0 = c0 as u8;
569        Color::Rgb(r0, g0, b0)
570    }
571
572    /// Calculates a linear interpolation for the two colors
573    /// and fills the first 4 colors with it.
574    /// The next 4 colors are scaled down versions using dark_scale_to.
575    pub const fn interpolate(c0: u32, c1: u32, dark_scale_to: u8) -> [Color; 8] {
576        // 1/3
577        const fn i1(a: u8, b: u8) -> u8 {
578            if a < b {
579                a + (b - a) / 3
580            } else {
581                a - (a - b) / 3
582            }
583        }
584        // 2/3
585        const fn i2(a: u8, b: u8) -> u8 {
586            if a < b {
587                b - (b - a) / 3
588            } else {
589                b + (a - b) / 3
590            }
591        }
592
593        let r0 = (c0 >> 16) as u8;
594        let g0 = (c0 >> 8) as u8;
595        let b0 = c0 as u8;
596
597        let r3 = (c1 >> 16) as u8;
598        let g3 = (c1 >> 8) as u8;
599        let b3 = c1 as u8;
600
601        let r1 = i1(r0, r3);
602        let g1 = i1(g0, g3);
603        let b1 = i1(b0, b3);
604
605        let r2 = i2(r0, r3);
606        let g2 = i2(g0, g3);
607        let b2 = i2(b0, b3);
608
609        // dark
610        let r4 = Self::scale_to(r0, dark_scale_to);
611        let g4 = Self::scale_to(g0, dark_scale_to);
612        let b4 = Self::scale_to(b0, dark_scale_to);
613
614        let r5 = Self::scale_to(r1, dark_scale_to);
615        let g5 = Self::scale_to(g1, dark_scale_to);
616        let b5 = Self::scale_to(b1, dark_scale_to);
617
618        let r6 = Self::scale_to(r2, dark_scale_to);
619        let g6 = Self::scale_to(g2, dark_scale_to);
620        let b6 = Self::scale_to(b2, dark_scale_to);
621
622        let r7 = Self::scale_to(r3, dark_scale_to);
623        let g7 = Self::scale_to(g3, dark_scale_to);
624        let b7 = Self::scale_to(b3, dark_scale_to);
625
626        [
627            Color::Rgb(r0, g0, b0),
628            Color::Rgb(r1, g1, b1),
629            Color::Rgb(r2, g2, b2),
630            Color::Rgb(r3, g3, b3),
631            Color::Rgb(r4, g4, b4),
632            Color::Rgb(r5, g5, b5),
633            Color::Rgb(r6, g6, b6),
634            Color::Rgb(r7, g7, b7),
635        ]
636    }
637
638    /// Scale the u8 down to scale_to.
639    pub const fn scale_to(v: u8, scale_to: u8) -> u8 {
640        (((v as u16) * scale_to as u16) / 255u16) as u8
641    }
642
643    /// Gives back the rgb for any ratatui Color.
644    /// Has the indexed and the named colors too.
645    pub const fn color2rgb(color: Color) -> (u8, u8, u8) {
646        match color {
647            Color::Black => (0x00, 0x00, 0x00),
648            Color::Red => (0xaa, 0x00, 0x00),
649            Color::Green => (0x00, 0xaa, 0x00),
650            Color::Yellow => (0xaa, 0x55, 0x00),
651            Color::Blue => (0x00, 0x00, 0xaa),
652            Color::Magenta => (0xaa, 0x00, 0xaa),
653            Color::Cyan => (0x00, 0xaa, 0xaa),
654            Color::Gray => (0xaa, 0xaa, 0xaa),
655            Color::DarkGray => (0x55, 0x55, 0x55),
656            Color::LightRed => (0xff, 0x55, 0x55),
657            Color::LightGreen => (0x55, 0xff, 0x55),
658            Color::LightYellow => (0xff, 0xff, 0x55),
659            Color::LightBlue => (0x55, 0x55, 0xff),
660            Color::LightMagenta => (0xff, 0x55, 0xff),
661            Color::LightCyan => (0x55, 0xff, 0xff),
662            Color::White => (0xff, 0xff, 0xff),
663            Color::Rgb(r, g, b) => (r, g, b),
664            Color::Indexed(i) => {
665                const VGA256: [(u8, u8, u8); 256] = [
666                    (0x00, 0x00, 0x00),
667                    (0x80, 0x00, 0x00),
668                    (0x00, 0x80, 0x00),
669                    (0x80, 0x80, 0x00),
670                    (0x00, 0x00, 0x80),
671                    (0x80, 0x00, 0x80),
672                    (0x00, 0x80, 0x80),
673                    (0xc0, 0xc0, 0xc0),
674                    (0x80, 0x80, 0x80),
675                    (0xff, 0x00, 0x00),
676                    (0x00, 0xff, 0x00),
677                    (0xff, 0xff, 0x00),
678                    (0x00, 0x00, 0xff),
679                    (0xff, 0x00, 0xff),
680                    (0x00, 0xff, 0xff),
681                    (0xff, 0xff, 0xff),
682                    (0x00, 0x00, 0x00),
683                    (0x00, 0x00, 0x5f),
684                    (0x00, 0x00, 0x87),
685                    (0x00, 0x00, 0xaf),
686                    (0x00, 0x00, 0xd7),
687                    (0x00, 0x00, 0xff),
688                    (0x00, 0x5f, 0x00),
689                    (0x00, 0x5f, 0x5f),
690                    (0x00, 0x5f, 0x87),
691                    (0x00, 0x5f, 0xaf),
692                    (0x00, 0x5f, 0xd7),
693                    (0x00, 0x5f, 0xff),
694                    (0x00, 0x87, 0x00),
695                    (0x00, 0x87, 0x5f),
696                    (0x00, 0x87, 0x87),
697                    (0x00, 0x87, 0xaf),
698                    (0x00, 0x87, 0xd7),
699                    (0x00, 0x87, 0xff),
700                    (0x00, 0xaf, 0x00),
701                    (0x00, 0xaf, 0x5f),
702                    (0x00, 0xaf, 0x87),
703                    (0x00, 0xaf, 0xaf),
704                    (0x00, 0xaf, 0xd7),
705                    (0x00, 0xaf, 0xff),
706                    (0x00, 0xd7, 0x00),
707                    (0x00, 0xd7, 0x5f),
708                    (0x00, 0xd7, 0x87),
709                    (0x00, 0xd7, 0xaf),
710                    (0x00, 0xd7, 0xd7),
711                    (0x00, 0xd7, 0xff),
712                    (0x00, 0xff, 0x00),
713                    (0x00, 0xff, 0x5f),
714                    (0x00, 0xff, 0x87),
715                    (0x00, 0xff, 0xaf),
716                    (0x00, 0xff, 0xd7),
717                    (0x00, 0xff, 0xff),
718                    (0x5f, 0x00, 0x00),
719                    (0x5f, 0x00, 0x5f),
720                    (0x5f, 0x00, 0x87),
721                    (0x5f, 0x00, 0xaf),
722                    (0x5f, 0x00, 0xd7),
723                    (0x5f, 0x00, 0xff),
724                    (0x5f, 0x5f, 0x00),
725                    (0x5f, 0x5f, 0x5f),
726                    (0x5f, 0x5f, 0x87),
727                    (0x5f, 0x5f, 0xaf),
728                    (0x5f, 0x5f, 0xd7),
729                    (0x5f, 0x5f, 0xff),
730                    (0x5f, 0x87, 0x00),
731                    (0x5f, 0x87, 0x5f),
732                    (0x5f, 0x87, 0x87),
733                    (0x5f, 0x87, 0xaf),
734                    (0x5f, 0x87, 0xd7),
735                    (0x5f, 0x87, 0xff),
736                    (0x5f, 0xaf, 0x00),
737                    (0x5f, 0xaf, 0x5f),
738                    (0x5f, 0xaf, 0x87),
739                    (0x5f, 0xaf, 0xaf),
740                    (0x5f, 0xaf, 0xd7),
741                    (0x5f, 0xaf, 0xff),
742                    (0x5f, 0xd7, 0x00),
743                    (0x5f, 0xd7, 0x5f),
744                    (0x5f, 0xd7, 0x87),
745                    (0x5f, 0xd7, 0xaf),
746                    (0x5f, 0xd7, 0xd7),
747                    (0x5f, 0xd7, 0xff),
748                    (0x5f, 0xff, 0x00),
749                    (0x5f, 0xff, 0x5f),
750                    (0x5f, 0xff, 0x87),
751                    (0x5f, 0xff, 0xaf),
752                    (0x5f, 0xff, 0xd7),
753                    (0x5f, 0xff, 0xff),
754                    (0x87, 0x00, 0x00),
755                    (0x87, 0x00, 0x5f),
756                    (0x87, 0x00, 0x87),
757                    (0x87, 0x00, 0xaf),
758                    (0x87, 0x00, 0xd7),
759                    (0x87, 0x00, 0xff),
760                    (0x87, 0x5f, 0x00),
761                    (0x87, 0x5f, 0x5f),
762                    (0x87, 0x5f, 0x87),
763                    (0x87, 0x5f, 0xaf),
764                    (0x87, 0x5f, 0xd7),
765                    (0x87, 0x5f, 0xff),
766                    (0x87, 0x87, 0x00),
767                    (0x87, 0x87, 0x5f),
768                    (0x87, 0x87, 0x87),
769                    (0x87, 0x87, 0xaf),
770                    (0x87, 0x87, 0xd7),
771                    (0x87, 0x87, 0xff),
772                    (0x87, 0xaf, 0x00),
773                    (0x87, 0xaf, 0x5f),
774                    (0x87, 0xaf, 0x87),
775                    (0x87, 0xaf, 0xaf),
776                    (0x87, 0xaf, 0xd7),
777                    (0x87, 0xaf, 0xff),
778                    (0x87, 0xd7, 0x00),
779                    (0x87, 0xd7, 0x5f),
780                    (0x87, 0xd7, 0x87),
781                    (0x87, 0xd7, 0xaf),
782                    (0x87, 0xd7, 0xd7),
783                    (0x87, 0xd7, 0xff),
784                    (0x87, 0xff, 0x00),
785                    (0x87, 0xff, 0x5f),
786                    (0x87, 0xff, 0x87),
787                    (0x87, 0xff, 0xaf),
788                    (0x87, 0xff, 0xd7),
789                    (0x87, 0xff, 0xff),
790                    (0xaf, 0x00, 0x00),
791                    (0xaf, 0x00, 0x5f),
792                    (0xaf, 0x00, 0x87),
793                    (0xaf, 0x00, 0xaf),
794                    (0xaf, 0x00, 0xd7),
795                    (0xaf, 0x00, 0xff),
796                    (0xaf, 0x5f, 0x00),
797                    (0xaf, 0x5f, 0x5f),
798                    (0xaf, 0x5f, 0x87),
799                    (0xaf, 0x5f, 0xaf),
800                    (0xaf, 0x5f, 0xd7),
801                    (0xaf, 0x5f, 0xff),
802                    (0xaf, 0x87, 0x00),
803                    (0xaf, 0x87, 0x5f),
804                    (0xaf, 0x87, 0x87),
805                    (0xaf, 0x87, 0xaf),
806                    (0xaf, 0x87, 0xd7),
807                    (0xaf, 0x87, 0xff),
808                    (0xaf, 0xaf, 0x00),
809                    (0xaf, 0xaf, 0x5f),
810                    (0xaf, 0xaf, 0x87),
811                    (0xaf, 0xaf, 0xaf),
812                    (0xaf, 0xaf, 0xd7),
813                    (0xaf, 0xaf, 0xff),
814                    (0xaf, 0xd7, 0x00),
815                    (0xaf, 0xd7, 0x5f),
816                    (0xaf, 0xd7, 0x87),
817                    (0xaf, 0xd7, 0xaf),
818                    (0xaf, 0xd7, 0xd7),
819                    (0xaf, 0xd7, 0xff),
820                    (0xaf, 0xff, 0x00),
821                    (0xaf, 0xff, 0x5f),
822                    (0xaf, 0xff, 0x87),
823                    (0xaf, 0xff, 0xaf),
824                    (0xaf, 0xff, 0xd7),
825                    (0xaf, 0xff, 0xff),
826                    (0xd7, 0x00, 0x00),
827                    (0xd7, 0x00, 0x5f),
828                    (0xd7, 0x00, 0x87),
829                    (0xd7, 0x00, 0xaf),
830                    (0xd7, 0x00, 0xd7),
831                    (0xd7, 0x00, 0xff),
832                    (0xd7, 0x5f, 0x00),
833                    (0xd7, 0x5f, 0x5f),
834                    (0xd7, 0x5f, 0x87),
835                    (0xd7, 0x5f, 0xaf),
836                    (0xd7, 0x5f, 0xd7),
837                    (0xd7, 0x5f, 0xff),
838                    (0xd7, 0x87, 0x00),
839                    (0xd7, 0x87, 0x5f),
840                    (0xd7, 0x87, 0x87),
841                    (0xd7, 0x87, 0xaf),
842                    (0xd7, 0x87, 0xd7),
843                    (0xd7, 0x87, 0xff),
844                    (0xd7, 0xaf, 0x00),
845                    (0xd7, 0xaf, 0x5f),
846                    (0xd7, 0xaf, 0x87),
847                    (0xd7, 0xaf, 0xaf),
848                    (0xd7, 0xaf, 0xd7),
849                    (0xd7, 0xaf, 0xff),
850                    (0xd7, 0xd7, 0x00),
851                    (0xd7, 0xd7, 0x5f),
852                    (0xd7, 0xd7, 0x87),
853                    (0xd7, 0xd7, 0xaf),
854                    (0xd7, 0xd7, 0xd7),
855                    (0xd7, 0xd7, 0xff),
856                    (0xd7, 0xff, 0x00),
857                    (0xd7, 0xff, 0x5f),
858                    (0xd7, 0xff, 0x87),
859                    (0xd7, 0xff, 0xaf),
860                    (0xd7, 0xff, 0xd7),
861                    (0xd7, 0xff, 0xff),
862                    (0xff, 0x00, 0x00),
863                    (0xff, 0x00, 0x5f),
864                    (0xff, 0x00, 0x87),
865                    (0xff, 0x00, 0xaf),
866                    (0xff, 0x00, 0xd7),
867                    (0xff, 0x00, 0xff),
868                    (0xff, 0x5f, 0x00),
869                    (0xff, 0x5f, 0x5f),
870                    (0xff, 0x5f, 0x87),
871                    (0xff, 0x5f, 0xaf),
872                    (0xff, 0x5f, 0xd7),
873                    (0xff, 0x5f, 0xff),
874                    (0xff, 0x87, 0x00),
875                    (0xff, 0x87, 0x5f),
876                    (0xff, 0x87, 0x87),
877                    (0xff, 0x87, 0xaf),
878                    (0xff, 0x87, 0xd7),
879                    (0xff, 0x87, 0xff),
880                    (0xff, 0xaf, 0x00),
881                    (0xff, 0xaf, 0x5f),
882                    (0xff, 0xaf, 0x87),
883                    (0xff, 0xaf, 0xaf),
884                    (0xff, 0xaf, 0xd7),
885                    (0xff, 0xaf, 0xff),
886                    (0xff, 0xd7, 0x00),
887                    (0xff, 0xd7, 0x5f),
888                    (0xff, 0xd7, 0x87),
889                    (0xff, 0xd7, 0xaf),
890                    (0xff, 0xd7, 0xd7),
891                    (0xff, 0xd7, 0xff),
892                    (0xff, 0xff, 0x00),
893                    (0xff, 0xff, 0x5f),
894                    (0xff, 0xff, 0x87),
895                    (0xff, 0xff, 0xaf),
896                    (0xff, 0xff, 0xd7),
897                    (0xff, 0xff, 0xff),
898                    (0x08, 0x08, 0x08),
899                    (0x12, 0x12, 0x12),
900                    (0x1c, 0x1c, 0x1c),
901                    (0x26, 0x26, 0x26),
902                    (0x30, 0x30, 0x30),
903                    (0x3a, 0x3a, 0x3a),
904                    (0x44, 0x44, 0x44),
905                    (0x4e, 0x4e, 0x4e),
906                    (0x58, 0x58, 0x58),
907                    (0x62, 0x62, 0x62),
908                    (0x6c, 0x6c, 0x6c),
909                    (0x76, 0x76, 0x76),
910                    (0x80, 0x80, 0x80),
911                    (0x8a, 0x8a, 0x8a),
912                    (0x94, 0x94, 0x94),
913                    (0x9e, 0x9e, 0x9e),
914                    (0xa8, 0xa8, 0xa8),
915                    (0xb2, 0xb2, 0xb2),
916                    (0xbc, 0xbc, 0xbc),
917                    (0xc6, 0xc6, 0xc6),
918                    (0xd0, 0xd0, 0xd0),
919                    (0xda, 0xda, 0xda),
920                    (0xe4, 0xe4, 0xe4),
921                    (0xee, 0xee, 0xee),
922                ];
923                VGA256[i as usize]
924            }
925            Color::Reset => (0, 0, 0),
926        }
927    }
928}