From 0e1771d7e0341a80d77ef10bc61b1085be8414b5 Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Fri, 28 Jun 2024 20:25:55 -0400 Subject: [PATCH] Make Rgb use [0:1] as range --- cursive-core/src/style/color.rs | 16 +++++++++--- cursive-core/src/style/gradient/mod.rs | 34 ++++++++++++++++++++------ 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/cursive-core/src/style/color.rs b/cursive-core/src/style/color.rs index bcb60fe7..82d3efd9 100644 --- a/cursive-core/src/style/color.rs +++ b/cursive-core/src/style/color.rs @@ -97,7 +97,9 @@ impl From for BaseColor { /// RGB color. /// -/// If `T = u8` this is a 24-bit color. +/// If `T = u8` this is the usual 24-bit true color. +/// +/// If `T = f32` this uses floats between 0 and 1. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct Rgb { /// Red component. @@ -161,8 +163,12 @@ impl Rgb { impl Rgb { /// Casts each component to u8. + /// + /// Goes from `[0:1]` to `[0:255]` range. pub fn as_u8(self) -> Rgb { - self.map(|x| x as u8) + // Going from [0:1.0] to [0:255] + // We add 0.5 to make sure the float is above the integer we want. + self.map(|x| (0.5 + (x.clamp(0.0, 1.0) * 255.0).round()) as u8) } /// Convert to a Color. @@ -173,6 +179,8 @@ impl Rgb { impl Rgb<(f32, f32)> { /// Interpolate each component individually. + /// + /// This is a simple linear interpolation per channel. pub fn interpolate(self, x: f32) -> Rgb { self.map(|(a, b)| a * (1f32 - x) + b * x) } @@ -181,7 +189,7 @@ impl Rgb<(f32, f32)> { impl Rgb<(u8, u8)> { /// Cast each component to a tuple of f32. pub fn as_f32(self) -> Rgb<(f32, f32)> { - self.map(|(x, y)| (x as f32, y as f32)) + self.map(|(x, y)| (x as f32 / 255.0, y as f32 / 255.0)) } } @@ -203,7 +211,7 @@ impl Rgb { /// Cast each component to f32. pub fn as_f32(self) -> Rgb { - self.map(|x| x as f32) + self.map(|x| x as f32 / 255.0) } /// Returns a pure red RGB color. diff --git a/cursive-core/src/style/gradient/mod.rs b/cursive-core/src/style/gradient/mod.rs index cbea5e0e..b7901ce6 100644 --- a/cursive-core/src/style/gradient/mod.rs +++ b/cursive-core/src/style/gradient/mod.rs @@ -1,7 +1,31 @@ //! Gradients +//! +//! This module defines a few types to help work with gradients: +//! +//! * [`Linear`] is a 1-dimensional (linear) piecewise gradient: given a float value between 0 and +//! 1, it returns the interpolated [`crate::style::Rgb`] color at that point. +//! * A few 2D gradients assign float values between 0 and 1 to each cell of a grid, and internally +//! use a `Linear` gradient to convert that to a color. +//! * [`Angled`] applies its linear gradient on the 2D grid at an angle. +//! * [`Radial`] applies its linear gradient according to the distance from a center. +//! * [`Bilinear`] uses bilinear interpolation between the 4 corners to compute the color for +//! each cell. +//! +//! Note that this module works with `Rgb`, where each color has a f32 value between 0 and 1. +//! Various conversions to/from `Rgb` and [`crate::style::Color`] are available. use crate::{style::Rgb, Vec2, XY}; -/// A linear gradient interpolating between 0 and 1. +/// A 2D color distribution. +/// +/// Types implementing this trait can assign a color to each point of a grid. +pub trait Interpolator { + /// Get the color for the given position, given the total size of the area to cover. + /// + /// The resulting value uses floats between 0 and 1. + fn interpolate(&self, pos: Vec2, size: Vec2) -> Rgb; +} + +/// A linear gradient interpolating color for floats between 0 and 1. pub struct Linear { /// Color for the start of the gradient. pub start: Rgb, @@ -53,6 +77,8 @@ impl Linear { } /// Interpolate the color for the given position. + /// + /// The resulting value uses floats between 0 and 1. pub fn interpolate(&self, x: f32) -> Rgb { // Find the segment if x <= 0f32 { @@ -151,12 +177,6 @@ pub struct Angled { pub gradient: Linear, } -/// Something that can interpolate. -pub trait Interpolator { - /// Get the color for the given position, given the total size. - fn interpolate(&self, pos: Vec2, size: Vec2) -> Rgb; -} - impl Interpolator for Angled { fn interpolate(&self, mut pos: Vec2, mut size: Vec2) -> Rgb { use std::f32::consts::{FRAC_PI_2, PI, TAU};