clankerdiff-ratatui 0.1.7

Embeddable Ratatui diff review widget
Documentation
use clankerdiff_theme::{ReviewTheme, Rgba};
use ratatui::style::{Color, Style};

#[must_use]
pub const fn composite_color(value: Rgba, background: Rgba) -> Color {
    let value = value.over(background.over(Rgba::new(0, 0, 0, 255)));
    Color::Rgb(value.r, value.g, value.b)
}

#[must_use]
pub const fn page_color(theme: &ReviewTheme, value: Rgba) -> Color {
    composite_color(value, theme.diff.background)
}

#[must_use]
pub fn layered_style(foreground: Rgba, background: Rgba, canvas: Rgba) -> Style {
    let canvas = canvas.over(Rgba::new(0, 0, 0, 255));
    let background = background.over(canvas);
    Style::new()
        .fg(composite_color(foreground, background))
        .bg(composite_color(background, canvas))
}

pub(crate) const fn native_color(value: Rgba, background: Color) -> Color {
    let rgb = match background {
        Color::Rgb(r, g, b) => (r, g, b),
        Color::Red => (128, 0, 0),
        Color::Green => (0, 128, 0),
        Color::Yellow => (128, 128, 0),
        Color::Blue => (0, 0, 128),
        Color::Magenta => (128, 0, 128),
        Color::Cyan => (0, 128, 128),
        Color::Gray => (192, 192, 192),
        Color::DarkGray => (128, 128, 128),
        Color::LightRed => (255, 0, 0),
        Color::LightGreen => (0, 255, 0),
        Color::LightYellow => (255, 255, 0),
        Color::LightBlue => (0, 0, 255),
        Color::LightMagenta => (255, 0, 255),
        Color::LightCyan => (0, 255, 255),
        Color::White => (255, 255, 255),
        Color::Black | Color::Reset => (0, 0, 0),
        Color::Indexed(index) => return indexed_color(value, index),
    };
    composite_color(value, Rgba::new(rgb.0, rgb.1, rgb.2, 255))
}

const fn indexed_color(value: Rgba, index: u8) -> Color {
    const BASIC: [Color; 16] = [
        Color::Black,
        Color::Red,
        Color::Green,
        Color::Yellow,
        Color::Blue,
        Color::Magenta,
        Color::Cyan,
        Color::Gray,
        Color::DarkGray,
        Color::LightRed,
        Color::LightGreen,
        Color::LightYellow,
        Color::LightBlue,
        Color::LightMagenta,
        Color::LightCyan,
        Color::White,
    ];
    const LEVEL: [u8; 6] = [0, 95, 135, 175, 215, 255];
    if index < 16 {
        return native_color(value, BASIC[index as usize]);
    }
    if index >= 232 {
        let gray = 8 + (index - 232) * 10;
        return composite_color(value, Rgba::new(gray, gray, gray, 255));
    }
    let index = (index - 16) as usize;
    composite_color(
        value,
        Rgba::new(
            LEVEL[index / 36],
            LEVEL[(index / 6) % 6],
            LEVEL[index % 6],
            255,
        ),
    )
}