diff --git a/Cargo.toml b/Cargo.toml index beaac628d..66ec76622 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ document-features = { version = "0.2.7", optional = true } itertools = "0.13" lru = "0.12.0" paste = "1.0.2" +palette = { version = "0.7.6", optional = true } serde = { version = "1", optional = true, features = ["derive"] } stability = "0.2.0" strum = { version = "0.26", features = ["derive"] } @@ -122,6 +123,9 @@ serde = ["dep:serde", "bitflags/serde", "compact_str/serde"] ## enables the [`border!`] macro. macros = [] +## enables conversions from colors in the [`palette`] crate to [`Color`](crate::style::Color). +palette = ["dep:palette"] + ## enables all widgets. all-widgets = ["widget-calendar"] diff --git a/src/layout/layout.rs b/src/layout/layout.rs index e6799fd76..bb739a607 100644 --- a/src/layout/layout.rs +++ b/src/layout/layout.rs @@ -1881,14 +1881,11 @@ mod tests { let chunks = Layout::default() .direction(Direction::Vertical) - .constraints( - [ - Constraint::Percentage(10), - Constraint::Max(5), - Constraint::Min(1), - ] - .as_ref(), - ) + .constraints([ + Constraint::Percentage(10), + Constraint::Max(5), + Constraint::Min(1), + ]) .split(target); assert_eq!(target.height, chunks.iter().map(|r| r.height).sum::()); diff --git a/src/style.rs b/src/style.rs index 6a29b0344..6b033adf7 100644 --- a/src/style.rs +++ b/src/style.rs @@ -71,13 +71,14 @@ use std::fmt; use bitflags::bitflags; - -mod color; -mod stylize; - pub use color::{Color, ParseColorError}; pub use stylize::{Styled, Stylize}; + +mod color; pub mod palette; +#[cfg(feature = "palette")] +mod palette_conversion; +mod stylize; bitflags! { /// Modifier changes the way a piece of text is displayed. diff --git a/src/style/palette_conversion.rs b/src/style/palette_conversion.rs new file mode 100644 index 000000000..c1a0b3828 --- /dev/null +++ b/src/style/palette_conversion.rs @@ -0,0 +1,83 @@ +//! Conversions from colors in the `palette` crate to [`Color`]. + +use ::palette::{ + bool_mask::LazySelect, + num::{Arithmetics, MulSub, PartialCmp, Powf, Real}, + LinSrgb, +}; +use palette::{stimulus::IntoStimulus, Srgb}; + +use super::Color; + +/// Convert an [`palette::Srgb`] color to a [`Color`]. +/// +/// # Examples +/// +/// ``` +/// use palette::Srgb; +/// use ratatui::style::Color; +/// +/// let color = Color::from(Srgb::new(1.0f32, 0.0, 0.0)); +/// assert_eq!(color, Color::Rgb(255, 0, 0)); +/// ``` +impl> From> for Color { + fn from(color: Srgb) -> Self { + let (red, green, blue) = color.into_format().into_components(); + Color::Rgb(red, green, blue) + } +} + +/// Convert a [`palette::LinSrgb`] color to a [`Color`]. +/// +/// Note: this conversion only works for floating point linear sRGB colors. If you have a linear +/// sRGB color in another format, you need to convert it to floating point first. +/// +/// # Examples +/// +/// ``` +/// use palette::LinSrgb; +/// use ratatui::style::Color; +/// +/// let color = Color::from(LinSrgb::new(1.0f32, 0.0, 0.0)); +/// assert_eq!(color, Color::Rgb(255, 0, 0)); +/// ``` +impl> From> for Color +where + T: Real + Powf + MulSub + Arithmetics + PartialCmp + Clone, + T::Mask: LazySelect, +{ + fn from(color: LinSrgb) -> Self { + let srgb_color = Srgb::::from_linear(color); + Color::from(srgb_color) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn from_srgb() { + const RED: Color = Color::Rgb(255, 0, 0); + assert_eq!(Color::from(Srgb::new(255u8, 0, 0)), RED); + assert_eq!(Color::from(Srgb::new(65535u16, 0, 0)), RED); + assert_eq!(Color::from(Srgb::new(1.0f32, 0.0, 0.0)), RED); + + assert_eq!( + Color::from(Srgb::new(0.5f32, 0.5, 0.5)), + Color::Rgb(128, 128, 128) + ); + } + + #[test] + fn from_lin_srgb() { + const RED: Color = Color::Rgb(255, 0, 0); + assert_eq!(Color::from(LinSrgb::new(1.0f32, 0.0, 0.0)), RED); + assert_eq!(Color::from(LinSrgb::new(1.0f64, 0.0, 0.0)), RED); + + assert_eq!( + Color::from(LinSrgb::new(0.5f32, 0.5, 0.5)), + Color::Rgb(188, 188, 188) + ); + } +} diff --git a/src/widgets/barchart/bar_group.rs b/src/widgets/barchart/bar_group.rs index 2a85e9be9..6e934871b 100644 --- a/src/widgets/barchart/bar_group.rs +++ b/src/widgets/barchart/bar_group.rs @@ -78,7 +78,8 @@ impl<'a> From<&[(&'a str, u64)]> for BarGroup<'a> { impl<'a, const N: usize> From<&[(&'a str, u64); N]> for BarGroup<'a> { fn from(value: &[(&'a str, u64); N]) -> Self { - Self::from(value.as_ref()) + let value: &[(&'a str, u64)] = value.as_ref(); + Self::from(value) } }