rat_theme3/
palette.rs

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