mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
Ncurses: fix bad grayscale projection for very dark or very bright colors
This commit is contained in:
parent
8ed3085772
commit
45a9d54801
@ -16,6 +16,7 @@ pub mod pan;
|
|||||||
// Use AHash instead of the slower SipHash
|
// Use AHash instead of the slower SipHash
|
||||||
type HashMap<K, V> = std::collections::HashMap<K, V, ahash::ABuildHasher>;
|
type HashMap<K, V> = std::collections::HashMap<K, V, ahash::ABuildHasher>;
|
||||||
|
|
||||||
|
/// Split a i32 into individual bytes, little endian (least significant byte first).
|
||||||
fn split_i32(code: i32) -> Vec<u8> {
|
fn split_i32(code: i32) -> Vec<u8> {
|
||||||
(0..4).map(|i| ((code >> (8 * i)) & 0xFF) as u8).collect()
|
(0..4).map(|i| ((code >> (8 * i)) & 0xFF) as u8).collect()
|
||||||
}
|
}
|
||||||
@ -71,6 +72,10 @@ fn find_closest_pair(pair: ColorPair, max_colors: i16) -> (i16, i16) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Finds the closest index in the 256-color palette.
|
||||||
|
///
|
||||||
|
/// If `max_colors` is less than 256 (like 8 or 16), the color will be
|
||||||
|
/// downgraded to the closest one available.
|
||||||
fn find_closest(color: Color, max_colors: i16) -> i16 {
|
fn find_closest(color: Color, max_colors: i16) -> i16 {
|
||||||
match color {
|
match color {
|
||||||
Color::TerminalDefault => -1,
|
Color::TerminalDefault => -1,
|
||||||
@ -92,11 +97,18 @@ fn find_closest(color: Color, max_colors: i16) -> i16 {
|
|||||||
Color::Light(BaseColor::White) => 15 % max_colors,
|
Color::Light(BaseColor::White) => 15 % max_colors,
|
||||||
Color::Rgb(r, g, b) if max_colors >= 256 => {
|
Color::Rgb(r, g, b) if max_colors >= 256 => {
|
||||||
// If r = g = b, it may be a grayscale value!
|
// If r = g = b, it may be a grayscale value!
|
||||||
if r == g && g == b && r != 0 && r < 250 {
|
// Grayscale colors have a bit higher resolution than the rest of
|
||||||
// Grayscale
|
// the palette, so if we can use it we should!
|
||||||
// (r = g = b) = 8 + 10 * n
|
|
||||||
// (r - 8) / 10 = n
|
|
||||||
//
|
//
|
||||||
|
// r=g=b < 8 should go to pure black instead.
|
||||||
|
// r=g=b >= 247 should go to pure white.
|
||||||
|
|
||||||
|
// TODO: project almost-gray colors as well?
|
||||||
|
if r == g && g == b && r >= 8 && r < 247 {
|
||||||
|
// The grayscale palette says the colors 232+n are:
|
||||||
|
// (r = g = b) = 8 + 10 * n
|
||||||
|
// With 0 <= n <= 23. This gives:
|
||||||
|
// (r - 8) / 10 = n
|
||||||
let n = (r - 8) / 10;
|
let n = (r - 8) / 10;
|
||||||
i16::from(232 + n)
|
i16::from(232 + n)
|
||||||
} else {
|
} else {
|
||||||
@ -108,6 +120,7 @@ fn find_closest(color: Color, max_colors: i16) -> i16 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Color::Rgb(r, g, b) => {
|
Color::Rgb(r, g, b) => {
|
||||||
|
// Have to hack it down to 8 colors.
|
||||||
let r = if r > 127 { 1 } else { 0 };
|
let r = if r > 127 { 1 } else { 0 };
|
||||||
let g = if g > 127 { 1 } else { 0 };
|
let g = if g > 127 { 1 } else { 0 };
|
||||||
let b = if b > 127 { 1 } else { 0 };
|
let b = if b > 127 { 1 } else { 0 };
|
||||||
|
@ -71,22 +71,30 @@ pub enum Color {
|
|||||||
|
|
||||||
/// One of the 8 base colors.
|
/// One of the 8 base colors.
|
||||||
///
|
///
|
||||||
|
/// These colors should work on any terminal.
|
||||||
|
///
|
||||||
/// Note: the actual color used depends on the terminal configuration.
|
/// Note: the actual color used depends on the terminal configuration.
|
||||||
Dark(BaseColor),
|
Dark(BaseColor),
|
||||||
|
|
||||||
/// Lighter version of a base color.
|
/// Lighter version of a base color.
|
||||||
///
|
///
|
||||||
|
/// The native linux TTY usually doesn't support these colors, but almost
|
||||||
|
/// all terminal emulators should.
|
||||||
|
///
|
||||||
/// Note: the actual color used depends on the terminal configuration.
|
/// Note: the actual color used depends on the terminal configuration.
|
||||||
Light(BaseColor),
|
Light(BaseColor),
|
||||||
|
|
||||||
/// True-color, 24-bit.
|
/// True-color, 24-bit.
|
||||||
|
///
|
||||||
|
/// On terminals that don't support this, the color will be "downgraded"
|
||||||
|
/// to the closest one available.
|
||||||
Rgb(u8, u8, u8),
|
Rgb(u8, u8, u8),
|
||||||
|
|
||||||
/// Low-resolution
|
/// Low-resolution color.
|
||||||
///
|
///
|
||||||
/// Each value should be `<= 5` (you'll get panics otherwise).
|
/// Each value should be `<= 5` (you'll get panics otherwise).
|
||||||
///
|
///
|
||||||
/// These 216 possible colors are part of the default color palette.
|
/// These 216 possible colors are part of the default color palette (256 colors).
|
||||||
RgbLowRes(u8, u8, u8),
|
RgbLowRes(u8, u8, u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,6 +134,18 @@ impl Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a `Color::RgbLowRes` from the given values for red, green and
|
||||||
|
/// blue.
|
||||||
|
///
|
||||||
|
/// Returns `None` if any of the values exceeds 5.
|
||||||
|
pub fn low_res(r: u8, g: u8, b: u8) -> Option<Self> {
|
||||||
|
if r <= 5 && g <= 5 && b <= 5 {
|
||||||
|
Some(Color::RgbLowRes(r, g, b))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse a string into a color.
|
/// Parse a string into a color.
|
||||||
///
|
///
|
||||||
/// Examples:
|
/// Examples:
|
||||||
|
Loading…
Reference in New Issue
Block a user