use ratatui_core::style::{Color, Style};
#[cfg(feature = "serde")]
use serde::de::{Error, MapAccess, SeqAccess, Visitor};
#[cfg(feature = "serde")]
use serde::ser::SerializeStruct;
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::borrow::Cow;
#[cfg(feature = "serde")]
use std::fmt::Formatter;
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct Palette {
pub name: Cow<'static, str>,
pub text_light: Color,
pub text_bright: Color,
pub text_dark: Color,
pub text_black: Color,
pub white: [Color; 8],
pub black: [Color; 8],
pub gray: [Color; 8],
pub red: [Color; 8],
pub orange: [Color; 8],
pub yellow: [Color; 8],
pub limegreen: [Color; 8],
pub green: [Color; 8],
pub bluegreen: [Color; 8],
pub cyan: [Color; 8],
pub blue: [Color; 8],
pub deepblue: [Color; 8],
pub purple: [Color; 8],
pub magenta: [Color; 8],
pub redpink: [Color; 8],
pub primary: [Color; 8],
pub secondary: [Color; 8],
}
#[cfg(feature = "serde")]
impl Serialize for Palette {
fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut pal = ser.serialize_struct("Palette", 22)?;
pal.serialize_field("name", &self.name)?;
pal.serialize_field("text_light", &self.text_light)?;
pal.serialize_field("text_bright", &self.text_bright)?;
pal.serialize_field("text_dark", &self.text_dark)?;
pal.serialize_field("text_black", &self.text_black)?;
pal.serialize_field("white", &self.white)?;
pal.serialize_field("black", &self.black)?;
pal.serialize_field("gray", &self.gray)?;
pal.serialize_field("red", &self.red)?;
pal.serialize_field("orange", &self.orange)?;
pal.serialize_field("yellow", &self.yellow)?;
pal.serialize_field("limegreen", &self.limegreen)?;
pal.serialize_field("green", &self.green)?;
pal.serialize_field("bluegreen", &self.bluegreen)?;
pal.serialize_field("cyan", &self.cyan)?;
pal.serialize_field("blue", &self.blue)?;
pal.serialize_field("deepblue", &self.deepblue)?;
pal.serialize_field("purple", &self.purple)?;
pal.serialize_field("magenta", &self.magenta)?;
pal.serialize_field("redpink", &self.redpink)?;
pal.serialize_field("primary", &self.primary)?;
pal.serialize_field("secondary", &self.secondary)?;
pal.end()
}
}
#[cfg(feature = "serde")]
struct PaletteVisitor;
#[cfg(feature = "serde")]
impl<'de> Visitor<'de> for PaletteVisitor {
type Value = Palette;
fn expecting(&self, f: &mut Formatter) -> std::fmt::Result {
write!(f, "struct Palette")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut pal = Palette::default();
pal.name = seq
.next_element::<Cow<'static, str>>()?
.ok_or(A::Error::invalid_length(0, &"Palette.name"))?;
pal.text_light = seq
.next_element::<Color>()?
.ok_or(A::Error::invalid_length(0, &"Palette.text_light"))?;
pal.text_bright = seq
.next_element::<Color>()?
.ok_or(A::Error::invalid_length(0, &"Palette.text_bright"))?;
pal.text_dark = seq
.next_element::<Color>()?
.ok_or(A::Error::invalid_length(0, &"Palette.text_dark"))?;
pal.text_black = seq
.next_element::<Color>()?
.ok_or(A::Error::invalid_length(0, &"Palette.text_black"))?;
pal.white = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.white"))?;
pal.black = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.black"))?;
pal.gray = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.gray"))?;
pal.red = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.red"))?;
pal.orange = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.orange"))?;
pal.yellow = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.yellow"))?;
pal.limegreen = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.limegreen"))?;
pal.green = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.green"))?;
pal.bluegreen = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.bluegreen"))?;
pal.cyan = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.cyan"))?;
pal.blue = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.blue"))?;
pal.deepblue = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.deepblue"))?;
pal.purple = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.purple"))?;
pal.magenta = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.magenta"))?;
pal.redpink = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.redpink"))?;
pal.primary = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.primary"))?;
pal.secondary = seq
.next_element::<[Color; 8]>()?
.ok_or(A::Error::invalid_length(0, &"Palette.secondary"))?;
Ok(pal)
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut pal = Palette::default();
while let Some(key) = map.next_key::<&str>()? {
match key {
"name" => pal.name = map.next_value::<Cow<'static, str>>()?,
"text_light" => pal.text_light = map.next_value::<Color>()?,
"text_bright" => pal.text_bright = map.next_value::<Color>()?,
"text_dark" => pal.text_dark = map.next_value::<Color>()?,
"text_black" => pal.text_black = map.next_value::<Color>()?,
"white" => pal.white = map.next_value::<[Color; 8]>()?,
"black" => pal.black = map.next_value::<[Color; 8]>()?,
"gray" => pal.gray = map.next_value::<[Color; 8]>()?,
"red" => pal.red = map.next_value::<[Color; 8]>()?,
"orange" => pal.orange = map.next_value::<[Color; 8]>()?,
"yellow" => pal.yellow = map.next_value::<[Color; 8]>()?,
"limegreen" => pal.limegreen = map.next_value::<[Color; 8]>()?,
"green" => pal.green = map.next_value::<[Color; 8]>()?,
"bluegreen" => pal.bluegreen = map.next_value::<[Color; 8]>()?,
"cyan" => pal.cyan = map.next_value::<[Color; 8]>()?,
"blue" => pal.blue = map.next_value::<[Color; 8]>()?,
"deepblue" => pal.deepblue = map.next_value::<[Color; 8]>()?,
"purple" => pal.purple = map.next_value::<[Color; 8]>()?,
"magenta" => pal.magenta = map.next_value::<[Color; 8]>()?,
"redpink" => pal.redpink = map.next_value::<[Color; 8]>()?,
"primary" => pal.primary = map.next_value::<[Color; 8]>()?,
"secondary" => pal.secondary = map.next_value::<[Color; 8]>()?,
_ => {}
}
}
Ok(pal)
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for Palette {
fn deserialize<D>(des: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
const FIELDS: &'static [&'static str] = &[
"name",
"text_light",
"text_bright",
"text_dark",
"text_black",
"white",
"black",
"gray",
"red",
"orange",
"yellow",
"limegreen",
"green",
"bluegreen",
"cyan",
"blue",
"deepblue",
"purple",
"magenta",
"redpink",
"primary",
"secondary",
];
des.deserialize_struct("Palette", FIELDS, PaletteVisitor)
}
}
#[derive(Debug)]
pub enum TextColorRating {
Light,
Dark,
}
#[derive(Debug)]
pub enum Contrast {
High,
Normal,
}
impl Palette {
pub const BRIGHT_0: usize = 0;
pub const BRIGHT_1: usize = 1;
pub const BRIGHT_2: usize = 2;
pub const BRIGHT_3: usize = 3;
pub const DARK_0: usize = 4;
pub const DARK_1: usize = 5;
pub const DARK_2: usize = 6;
pub const DARK_3: usize = 7;
pub fn white(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.white[n], contrast)
}
pub fn black(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.black[n], contrast)
}
pub fn gray(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.gray[n], contrast)
}
pub fn red(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.red[n], contrast)
}
pub fn orange(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.orange[n], contrast)
}
pub fn yellow(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.yellow[n], contrast)
}
pub fn limegreen(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.limegreen[n], contrast)
}
pub fn green(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.green[n], contrast)
}
pub fn bluegreen(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.bluegreen[n], contrast)
}
pub fn cyan(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.cyan[n], contrast)
}
pub fn blue(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.blue[n], contrast)
}
pub fn deepblue(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.deepblue[n], contrast)
}
pub fn purple(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.purple[n], contrast)
}
pub fn magenta(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.magenta[n], contrast)
}
pub fn redpink(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.redpink[n], contrast)
}
pub fn primary(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.primary[n], contrast)
}
pub fn secondary(&self, n: usize, contrast: Contrast) -> Style {
self.style(self.secondary[n], contrast)
}
}
impl Palette {
pub fn style(&self, color: Color, contrast: Contrast) -> Style {
match contrast {
Contrast::High => self.high_contrast(color),
Contrast::Normal => self.normal_contrast(color),
}
}
pub fn high_contrast(&self, color: Color) -> Style {
match Self::rate_text_color(color) {
None => Style::reset(),
Some(TextColorRating::Light) => Style::new().bg(color).fg(self.text_bright),
Some(TextColorRating::Dark) => Style::new().bg(color).fg(self.text_black),
}
}
pub fn normal_contrast(&self, color: Color) -> Style {
match Self::rate_text_color(color) {
None => Style::reset(),
Some(TextColorRating::Light) => Style::new().bg(color).fg(self.text_light),
Some(TextColorRating::Dark) => Style::new().bg(color).fg(self.text_dark),
}
}
pub fn normal_contrast_color(&self, bg: Color, text_colors: &[Color]) -> Style {
let mut color0 = text_colors[0];
let mut color1 = text_colors[0];
let mut contrast1 = Self::contrast_bt_srgb(color1, bg);
for text_color in text_colors {
let test = Self::contrast_bt_srgb(*text_color, bg);
if test > contrast1 {
color0 = color1;
color1 = *text_color;
contrast1 = test;
}
}
Style::new().bg(bg).fg(color0)
}
pub fn high_contrast_color(&self, bg: Color, text_colors: &[Color]) -> Style {
let mut color0 = text_colors[0];
let mut color1 = text_colors[0];
let mut contrast1 = Self::contrast_bt_srgb(color1, bg);
for text_color in text_colors {
let test = Self::contrast_bt_srgb(*text_color, bg);
if test > contrast1 {
color0 = color1;
color1 = *text_color;
contrast1 = test;
}
}
_ = color0;
Style::new().bg(bg).fg(color1)
}
pub(crate) const fn luminance_bt(color: Color) -> f32 {
let (r, g, b) = Self::color2rgb(color);
0.2126f32 * ((r as f32) / 255f32)
+ 0.7152f32 * ((g as f32) / 255f32)
+ 0.0722f32 * ((b as f32) / 255f32)
}
pub(crate) fn luminance_bt_srgb(color: Color) -> f32 {
let (r, g, b) = Self::color2rgb(color);
0.2126f32 * ((r as f32) / 255f32).powf(2.2f32)
+ 0.7152f32 * ((g as f32) / 255f32).powf(2.2f32)
+ 0.0722f32 * ((b as f32) / 255f32).powf(2.2f32)
}
pub(crate) fn contrast_bt_srgb(color: Color, color2: Color) -> f32 {
let lum1 = Self::luminance_bt_srgb(color);
let lum2 = Self::luminance_bt_srgb(color2);
(lum1 - lum2).abs()
}
pub fn rate_text_color(color: Color) -> Option<TextColorRating> {
match color {
Color::Reset => None,
Color::Black => Some(TextColorRating::Light), Color::Red => Some(TextColorRating::Light), Color::Green => Some(TextColorRating::Light), Color::Yellow => Some(TextColorRating::Light), Color::Blue => Some(TextColorRating::Light), Color::Magenta => Some(TextColorRating::Light), Color::Cyan => Some(TextColorRating::Light), Color::Gray => Some(TextColorRating::Dark), Color::DarkGray => Some(TextColorRating::Light), Color::LightRed => Some(TextColorRating::Dark), Color::LightGreen => Some(TextColorRating::Dark), Color::LightYellow => Some(TextColorRating::Dark), Color::LightBlue => Some(TextColorRating::Light), Color::LightMagenta => Some(TextColorRating::Dark), Color::LightCyan => Some(TextColorRating::Dark), Color::White => Some(TextColorRating::Dark), c => {
let lum = Self::luminance_bt(c);
if lum >= 0.4117f32 {
Some(TextColorRating::Dark)
} else {
Some(TextColorRating::Light)
}
}
}
}
pub const fn darken(color: Color, scale_to: u8) -> Color {
let (r, g, b) = Self::color2rgb(color);
Color::Rgb(
Self::scale_to(r, scale_to),
Self::scale_to(g, scale_to),
Self::scale_to(b, scale_to),
)
}
pub const fn grayscale(color: Color) -> Color {
let lum = Self::luminance_bt(color);
let gray = lum * 255f32;
Color::Rgb(gray as u8, gray as u8, gray as u8)
}
pub const fn color32(c0: u32) -> Color {
let r0 = (c0 >> 16) as u8;
let g0 = (c0 >> 8) as u8;
let b0 = c0 as u8;
Color::Rgb(r0, g0, b0)
}
pub const fn interpolate(c0: u32, c1: u32, dark_scale_to: u8) -> [Color; 8] {
const fn i1(a: u8, b: u8) -> u8 {
if a < b {
a + (b - a) / 3
} else {
a - (a - b) / 3
}
}
const fn i2(a: u8, b: u8) -> u8 {
if a < b {
b - (b - a) / 3
} else {
b + (a - b) / 3
}
}
let r0 = (c0 >> 16) as u8;
let g0 = (c0 >> 8) as u8;
let b0 = c0 as u8;
let r3 = (c1 >> 16) as u8;
let g3 = (c1 >> 8) as u8;
let b3 = c1 as u8;
let r1 = i1(r0, r3);
let g1 = i1(g0, g3);
let b1 = i1(b0, b3);
let r2 = i2(r0, r3);
let g2 = i2(g0, g3);
let b2 = i2(b0, b3);
let r4 = Self::scale_to(r0, dark_scale_to);
let g4 = Self::scale_to(g0, dark_scale_to);
let b4 = Self::scale_to(b0, dark_scale_to);
let r5 = Self::scale_to(r1, dark_scale_to);
let g5 = Self::scale_to(g1, dark_scale_to);
let b5 = Self::scale_to(b1, dark_scale_to);
let r6 = Self::scale_to(r2, dark_scale_to);
let g6 = Self::scale_to(g2, dark_scale_to);
let b6 = Self::scale_to(b2, dark_scale_to);
let r7 = Self::scale_to(r3, dark_scale_to);
let g7 = Self::scale_to(g3, dark_scale_to);
let b7 = Self::scale_to(b3, dark_scale_to);
[
Color::Rgb(r0, g0, b0),
Color::Rgb(r1, g1, b1),
Color::Rgb(r2, g2, b2),
Color::Rgb(r3, g3, b3),
Color::Rgb(r4, g4, b4),
Color::Rgb(r5, g5, b5),
Color::Rgb(r6, g6, b6),
Color::Rgb(r7, g7, b7),
]
}
pub const fn scale_to(v: u8, scale_to: u8) -> u8 {
(((v as u16) * scale_to as u16) / 255u16) as u8
}
pub const fn color2rgb(color: Color) -> (u8, u8, u8) {
match color {
Color::Black => (0x00, 0x00, 0x00),
Color::Red => (0xaa, 0x00, 0x00),
Color::Green => (0x00, 0xaa, 0x00),
Color::Yellow => (0xaa, 0x55, 0x00),
Color::Blue => (0x00, 0x00, 0xaa),
Color::Magenta => (0xaa, 0x00, 0xaa),
Color::Cyan => (0x00, 0xaa, 0xaa),
Color::Gray => (0xaa, 0xaa, 0xaa),
Color::DarkGray => (0x55, 0x55, 0x55),
Color::LightRed => (0xff, 0x55, 0x55),
Color::LightGreen => (0x55, 0xff, 0x55),
Color::LightYellow => (0xff, 0xff, 0x55),
Color::LightBlue => (0x55, 0x55, 0xff),
Color::LightMagenta => (0xff, 0x55, 0xff),
Color::LightCyan => (0x55, 0xff, 0xff),
Color::White => (0xff, 0xff, 0xff),
Color::Rgb(r, g, b) => (r, g, b),
Color::Indexed(i) => {
const VGA256: [(u8, u8, u8); 256] = [
(0x00, 0x00, 0x00),
(0x80, 0x00, 0x00),
(0x00, 0x80, 0x00),
(0x80, 0x80, 0x00),
(0x00, 0x00, 0x80),
(0x80, 0x00, 0x80),
(0x00, 0x80, 0x80),
(0xc0, 0xc0, 0xc0),
(0x80, 0x80, 0x80),
(0xff, 0x00, 0x00),
(0x00, 0xff, 0x00),
(0xff, 0xff, 0x00),
(0x00, 0x00, 0xff),
(0xff, 0x00, 0xff),
(0x00, 0xff, 0xff),
(0xff, 0xff, 0xff),
(0x00, 0x00, 0x00),
(0x00, 0x00, 0x5f),
(0x00, 0x00, 0x87),
(0x00, 0x00, 0xaf),
(0x00, 0x00, 0xd7),
(0x00, 0x00, 0xff),
(0x00, 0x5f, 0x00),
(0x00, 0x5f, 0x5f),
(0x00, 0x5f, 0x87),
(0x00, 0x5f, 0xaf),
(0x00, 0x5f, 0xd7),
(0x00, 0x5f, 0xff),
(0x00, 0x87, 0x00),
(0x00, 0x87, 0x5f),
(0x00, 0x87, 0x87),
(0x00, 0x87, 0xaf),
(0x00, 0x87, 0xd7),
(0x00, 0x87, 0xff),
(0x00, 0xaf, 0x00),
(0x00, 0xaf, 0x5f),
(0x00, 0xaf, 0x87),
(0x00, 0xaf, 0xaf),
(0x00, 0xaf, 0xd7),
(0x00, 0xaf, 0xff),
(0x00, 0xd7, 0x00),
(0x00, 0xd7, 0x5f),
(0x00, 0xd7, 0x87),
(0x00, 0xd7, 0xaf),
(0x00, 0xd7, 0xd7),
(0x00, 0xd7, 0xff),
(0x00, 0xff, 0x00),
(0x00, 0xff, 0x5f),
(0x00, 0xff, 0x87),
(0x00, 0xff, 0xaf),
(0x00, 0xff, 0xd7),
(0x00, 0xff, 0xff),
(0x5f, 0x00, 0x00),
(0x5f, 0x00, 0x5f),
(0x5f, 0x00, 0x87),
(0x5f, 0x00, 0xaf),
(0x5f, 0x00, 0xd7),
(0x5f, 0x00, 0xff),
(0x5f, 0x5f, 0x00),
(0x5f, 0x5f, 0x5f),
(0x5f, 0x5f, 0x87),
(0x5f, 0x5f, 0xaf),
(0x5f, 0x5f, 0xd7),
(0x5f, 0x5f, 0xff),
(0x5f, 0x87, 0x00),
(0x5f, 0x87, 0x5f),
(0x5f, 0x87, 0x87),
(0x5f, 0x87, 0xaf),
(0x5f, 0x87, 0xd7),
(0x5f, 0x87, 0xff),
(0x5f, 0xaf, 0x00),
(0x5f, 0xaf, 0x5f),
(0x5f, 0xaf, 0x87),
(0x5f, 0xaf, 0xaf),
(0x5f, 0xaf, 0xd7),
(0x5f, 0xaf, 0xff),
(0x5f, 0xd7, 0x00),
(0x5f, 0xd7, 0x5f),
(0x5f, 0xd7, 0x87),
(0x5f, 0xd7, 0xaf),
(0x5f, 0xd7, 0xd7),
(0x5f, 0xd7, 0xff),
(0x5f, 0xff, 0x00),
(0x5f, 0xff, 0x5f),
(0x5f, 0xff, 0x87),
(0x5f, 0xff, 0xaf),
(0x5f, 0xff, 0xd7),
(0x5f, 0xff, 0xff),
(0x87, 0x00, 0x00),
(0x87, 0x00, 0x5f),
(0x87, 0x00, 0x87),
(0x87, 0x00, 0xaf),
(0x87, 0x00, 0xd7),
(0x87, 0x00, 0xff),
(0x87, 0x5f, 0x00),
(0x87, 0x5f, 0x5f),
(0x87, 0x5f, 0x87),
(0x87, 0x5f, 0xaf),
(0x87, 0x5f, 0xd7),
(0x87, 0x5f, 0xff),
(0x87, 0x87, 0x00),
(0x87, 0x87, 0x5f),
(0x87, 0x87, 0x87),
(0x87, 0x87, 0xaf),
(0x87, 0x87, 0xd7),
(0x87, 0x87, 0xff),
(0x87, 0xaf, 0x00),
(0x87, 0xaf, 0x5f),
(0x87, 0xaf, 0x87),
(0x87, 0xaf, 0xaf),
(0x87, 0xaf, 0xd7),
(0x87, 0xaf, 0xff),
(0x87, 0xd7, 0x00),
(0x87, 0xd7, 0x5f),
(0x87, 0xd7, 0x87),
(0x87, 0xd7, 0xaf),
(0x87, 0xd7, 0xd7),
(0x87, 0xd7, 0xff),
(0x87, 0xff, 0x00),
(0x87, 0xff, 0x5f),
(0x87, 0xff, 0x87),
(0x87, 0xff, 0xaf),
(0x87, 0xff, 0xd7),
(0x87, 0xff, 0xff),
(0xaf, 0x00, 0x00),
(0xaf, 0x00, 0x5f),
(0xaf, 0x00, 0x87),
(0xaf, 0x00, 0xaf),
(0xaf, 0x00, 0xd7),
(0xaf, 0x00, 0xff),
(0xaf, 0x5f, 0x00),
(0xaf, 0x5f, 0x5f),
(0xaf, 0x5f, 0x87),
(0xaf, 0x5f, 0xaf),
(0xaf, 0x5f, 0xd7),
(0xaf, 0x5f, 0xff),
(0xaf, 0x87, 0x00),
(0xaf, 0x87, 0x5f),
(0xaf, 0x87, 0x87),
(0xaf, 0x87, 0xaf),
(0xaf, 0x87, 0xd7),
(0xaf, 0x87, 0xff),
(0xaf, 0xaf, 0x00),
(0xaf, 0xaf, 0x5f),
(0xaf, 0xaf, 0x87),
(0xaf, 0xaf, 0xaf),
(0xaf, 0xaf, 0xd7),
(0xaf, 0xaf, 0xff),
(0xaf, 0xd7, 0x00),
(0xaf, 0xd7, 0x5f),
(0xaf, 0xd7, 0x87),
(0xaf, 0xd7, 0xaf),
(0xaf, 0xd7, 0xd7),
(0xaf, 0xd7, 0xff),
(0xaf, 0xff, 0x00),
(0xaf, 0xff, 0x5f),
(0xaf, 0xff, 0x87),
(0xaf, 0xff, 0xaf),
(0xaf, 0xff, 0xd7),
(0xaf, 0xff, 0xff),
(0xd7, 0x00, 0x00),
(0xd7, 0x00, 0x5f),
(0xd7, 0x00, 0x87),
(0xd7, 0x00, 0xaf),
(0xd7, 0x00, 0xd7),
(0xd7, 0x00, 0xff),
(0xd7, 0x5f, 0x00),
(0xd7, 0x5f, 0x5f),
(0xd7, 0x5f, 0x87),
(0xd7, 0x5f, 0xaf),
(0xd7, 0x5f, 0xd7),
(0xd7, 0x5f, 0xff),
(0xd7, 0x87, 0x00),
(0xd7, 0x87, 0x5f),
(0xd7, 0x87, 0x87),
(0xd7, 0x87, 0xaf),
(0xd7, 0x87, 0xd7),
(0xd7, 0x87, 0xff),
(0xd7, 0xaf, 0x00),
(0xd7, 0xaf, 0x5f),
(0xd7, 0xaf, 0x87),
(0xd7, 0xaf, 0xaf),
(0xd7, 0xaf, 0xd7),
(0xd7, 0xaf, 0xff),
(0xd7, 0xd7, 0x00),
(0xd7, 0xd7, 0x5f),
(0xd7, 0xd7, 0x87),
(0xd7, 0xd7, 0xaf),
(0xd7, 0xd7, 0xd7),
(0xd7, 0xd7, 0xff),
(0xd7, 0xff, 0x00),
(0xd7, 0xff, 0x5f),
(0xd7, 0xff, 0x87),
(0xd7, 0xff, 0xaf),
(0xd7, 0xff, 0xd7),
(0xd7, 0xff, 0xff),
(0xff, 0x00, 0x00),
(0xff, 0x00, 0x5f),
(0xff, 0x00, 0x87),
(0xff, 0x00, 0xaf),
(0xff, 0x00, 0xd7),
(0xff, 0x00, 0xff),
(0xff, 0x5f, 0x00),
(0xff, 0x5f, 0x5f),
(0xff, 0x5f, 0x87),
(0xff, 0x5f, 0xaf),
(0xff, 0x5f, 0xd7),
(0xff, 0x5f, 0xff),
(0xff, 0x87, 0x00),
(0xff, 0x87, 0x5f),
(0xff, 0x87, 0x87),
(0xff, 0x87, 0xaf),
(0xff, 0x87, 0xd7),
(0xff, 0x87, 0xff),
(0xff, 0xaf, 0x00),
(0xff, 0xaf, 0x5f),
(0xff, 0xaf, 0x87),
(0xff, 0xaf, 0xaf),
(0xff, 0xaf, 0xd7),
(0xff, 0xaf, 0xff),
(0xff, 0xd7, 0x00),
(0xff, 0xd7, 0x5f),
(0xff, 0xd7, 0x87),
(0xff, 0xd7, 0xaf),
(0xff, 0xd7, 0xd7),
(0xff, 0xd7, 0xff),
(0xff, 0xff, 0x00),
(0xff, 0xff, 0x5f),
(0xff, 0xff, 0x87),
(0xff, 0xff, 0xaf),
(0xff, 0xff, 0xd7),
(0xff, 0xff, 0xff),
(0x08, 0x08, 0x08),
(0x12, 0x12, 0x12),
(0x1c, 0x1c, 0x1c),
(0x26, 0x26, 0x26),
(0x30, 0x30, 0x30),
(0x3a, 0x3a, 0x3a),
(0x44, 0x44, 0x44),
(0x4e, 0x4e, 0x4e),
(0x58, 0x58, 0x58),
(0x62, 0x62, 0x62),
(0x6c, 0x6c, 0x6c),
(0x76, 0x76, 0x76),
(0x80, 0x80, 0x80),
(0x8a, 0x8a, 0x8a),
(0x94, 0x94, 0x94),
(0x9e, 0x9e, 0x9e),
(0xa8, 0xa8, 0xa8),
(0xb2, 0xb2, 0xb2),
(0xbc, 0xbc, 0xbc),
(0xc6, 0xc6, 0xc6),
(0xd0, 0xd0, 0xd0),
(0xda, 0xda, 0xda),
(0xe4, 0xe4, 0xe4),
(0xee, 0xee, 0xee),
];
VGA256[i as usize]
}
Color::Reset => (0, 0, 0),
}
}
}