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