mirror of
https://github.com/wez/wezterm.git
synced 2024-11-23 06:54:45 +03:00
termwiz: fix 10bpc color bug. Allow hsl color specs
This commit teaches `RgbColor::from_rgb_str` to support colors in the form `hsl:235 100 50`, an HSL colorspace color specification. While banging my head on why my test wasn't passing, I realized that this was producing 10 bpc color and the code to convert those to RGB was incorrectly multiplying conversion terms! refs: https://github.com/wez/wezterm/issues/1436
This commit is contained in:
parent
acbb99f07d
commit
1203dff277
@ -28,6 +28,7 @@ As features stabilize some brief notes about them will accumulate here.
|
||||
* Bundled harfbuzz to 3.2.0
|
||||
* Bundled freetype to 2.11.1
|
||||
* macos: removing the titlebar from `window_decorations` now preserves rounded window corners [#1034](https://github.com/wez/wezterm/issues/1034)
|
||||
* Colors can now be specified in the HSL colorspace using syntax like `"hsl:235 100 50"` [#1436](https://github.com/wez/wezterm/issues/1436)
|
||||
|
||||
#### Fixed
|
||||
|
||||
|
@ -64,6 +64,24 @@ return {
|
||||
}
|
||||
```
|
||||
|
||||
*Since: nightly builds only*
|
||||
|
||||
You may specify colors in the HSL color space, if you prefer that over RGB, by using:
|
||||
|
||||
```lua
|
||||
return {
|
||||
colors = {
|
||||
-- the first number is the hue measured in degrees with a range
|
||||
-- of 0-360.
|
||||
-- The second number is the saturation measured in percentage with
|
||||
-- a range of 0-100.
|
||||
-- The third number is the lightness measured in percentage with
|
||||
-- a range of 0-100.
|
||||
foreground = "hsl:235 100 50",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Defining a Color Scheme in your `.wezterm.lua`
|
||||
|
||||
If you'd like to keep a couple of color schemes handy in your configuration
|
||||
|
@ -96,7 +96,7 @@ const TEN_BITS: u16 = 0b11_1111_1111;
|
||||
const MAX_TEN: f32 = 1023.;
|
||||
|
||||
fn ten_to_eight(bits: u32) -> u8 {
|
||||
((bits as u16 & TEN_BITS) as f32 * MAX_TEN / 255.0) as u8
|
||||
((bits as u16 & TEN_BITS) as f32 / MAX_TEN * 255.0) as u8
|
||||
}
|
||||
|
||||
impl RgbColor {
|
||||
@ -212,6 +212,10 @@ impl RgbColor {
|
||||
|
||||
/// Construct a color from a string of the form `#RRGGBB` where
|
||||
/// R, G and B are all hex digits.
|
||||
/// `hsl:hue sat light` is also accepted, and allows specifying a color
|
||||
/// in the HSL color space, where `hue` is measure in degrees and has
|
||||
/// a range of 0-360, and both `sat` and `light` are specified in percentage
|
||||
/// in the range 0-100.
|
||||
pub fn from_rgb_str(s: &str) -> Option<RgbColor> {
|
||||
if s.len() > 0 && s.as_bytes()[0] == b'#' {
|
||||
// Probably `#RGB`
|
||||
@ -311,6 +315,34 @@ impl RgbColor {
|
||||
let blue = digit!();
|
||||
|
||||
Some(Self::new_8bpc(red, green, blue))
|
||||
} else if s.starts_with("hsl:") {
|
||||
let fields: Vec<_> = s[4..].split(' ').collect();
|
||||
if fields.len() == 3 {
|
||||
// Expected to be degrees in range 0-360, but we allow for negative and wrapping
|
||||
let h: i32 = fields[0].parse().ok()?;
|
||||
// Expected to be percentage in range 0-100
|
||||
let s: i32 = fields[1].parse().ok()?;
|
||||
// Expected to be percentage in range 0-100
|
||||
let l: i32 = fields[2].parse().ok()?;
|
||||
|
||||
fn hsl_to_rgb(hue: i32, sat: i32, light: i32) -> (f32, f32, f32) {
|
||||
let hue = hue % 360;
|
||||
let hue = if hue < 0 { hue + 360 } else { hue } as f32;
|
||||
let sat = sat as f32 / 100.;
|
||||
let light = light as f32 / 100.;
|
||||
let a = sat * light.min(1. - light);
|
||||
let f = |n: f32| -> f32 {
|
||||
let k = (n + hue / 30.) % 12.;
|
||||
light - a * (k - 3.).min(9. - k).min(1.).max(-1.)
|
||||
};
|
||||
(f(0.), f(8.), f(4.))
|
||||
}
|
||||
|
||||
let (r, g, b) = hsl_to_rgb(h, s, l);
|
||||
Some(Self::new_f32(r, g, b))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -319,6 +351,10 @@ impl RgbColor {
|
||||
/// Construct a color from an SVG/CSS3 color name.
|
||||
/// or from a string of the form `#RRGGBB` where
|
||||
/// R, G and B are all hex digits.
|
||||
/// `hsl:hue sat light` is also accepted, and allows specifying a color
|
||||
/// in the HSL color space, where `hue` is measure in degrees and has
|
||||
/// a range of 0-360, and both `sat` and `light` are specified in percentage
|
||||
/// in the range 0-100.
|
||||
/// Returns None if the supplied name is not recognized.
|
||||
/// The list of names can be found here:
|
||||
/// <https://ogeon.github.io/docs/palette/master/palette/named/index.html>
|
||||
@ -439,6 +475,12 @@ mod tests {
|
||||
assert_eq!(dark_green.bits, 0x006400);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_hsl() {
|
||||
let foo = RgbColor::from_rgb_str("hsl:235 100 50").unwrap();
|
||||
assert_eq!(foo.to_rgb_string(), "#0015ff");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_rgb() {
|
||||
assert!(RgbColor::from_rgb_str("").is_none());
|
||||
|
Loading…
Reference in New Issue
Block a user