use egui::{Color32, TextFormat};
#[derive(Debug, Clone, PartialEq)]
pub struct EguiAnsiTheme {
pub default_format: TextFormat,
pub default_foreground: Color32,
pub default_background: Color32,
pub palette: [Color32; 256],
pub underline_width: f32,
pub strikethrough_width: f32,
pub faint_opacity: f32,
pub bold_is_bright: bool,
}
impl Default for EguiAnsiTheme {
fn default() -> Self {
let default_foreground = Color32::from_rgb(229, 229, 229);
let default_format = TextFormat {
color: default_foreground,
background: Color32::TRANSPARENT,
..Default::default()
};
Self {
default_format,
default_foreground,
default_background: Color32::BLACK,
palette: Self::xterm_palette(),
underline_width: 1.0,
strikethrough_width: 1.0,
faint_opacity: 0.6,
bold_is_bright: true,
}
}
}
impl EguiAnsiTheme {
#[must_use]
pub fn xterm() -> Self {
Self::default()
}
#[must_use]
pub fn xterm_palette() -> [Color32; 256] {
build_palette([
Color32::from_rgb(0, 0, 0),
Color32::from_rgb(205, 0, 0),
Color32::from_rgb(0, 205, 0),
Color32::from_rgb(205, 205, 0),
Color32::from_rgb(0, 0, 238),
Color32::from_rgb(205, 0, 205),
Color32::from_rgb(0, 205, 205),
Color32::from_rgb(229, 229, 229),
Color32::from_rgb(127, 127, 127),
Color32::from_rgb(255, 0, 0),
Color32::from_rgb(0, 255, 0),
Color32::from_rgb(255, 255, 0),
Color32::from_rgb(92, 92, 255),
Color32::from_rgb(255, 0, 255),
Color32::from_rgb(0, 255, 255),
Color32::from_rgb(255, 255, 255),
])
}
}
fn build_palette(system_colors: [Color32; 16]) -> [Color32; 256] {
let mut palette = [Color32::BLACK; 256];
palette[..16].copy_from_slice(&system_colors);
for code in 16u8..=231 {
let value = code - 16;
let r = value / 36;
let g = (value % 36) / 6;
let b = value % 6;
palette[code as usize] =
Color32::from_rgb(cube_component(r), cube_component(g), cube_component(b));
}
for code in 232u8..=255 {
let gray = 8 + (code - 232) * 10;
palette[code as usize] = Color32::from_rgb(gray, gray, gray);
}
palette
}
fn cube_component(component: u8) -> u8 {
if component == 0 {
0
} else {
55 + component * 40
}
}