leptos_chartistry/colours/
mod.rs1mod colourmaps;
2mod scheme;
3
4pub use colourmaps::*;
5pub use scheme::{ColourScheme, DivergingGradient, LinearGradientSvg, SequentialGradient};
6
7use std::str::FromStr;
8
9#[derive(Copy, Clone, Debug, PartialEq)]
11pub struct Colour {
12 red: u8,
13 green: u8,
14 blue: u8,
15}
16
17impl Colour {
18 #[deprecated(since = "0.1.1", note = "renamed to `from_rgb`")]
20 pub const fn new(red: u8, green: u8, blue: u8) -> Self {
21 Self::from_rgb(red, green, blue)
22 }
23
24 pub const fn from_rgb(red: u8, green: u8, blue: u8) -> Self {
26 Self { red, green, blue }
27 }
28
29 fn interpolate(self, rhs: Self, ratio: f64) -> Self {
30 let ratio = ratio.clamp(0.0, 1.0);
31 let interpolate = |pre: u8, post: u8| {
32 let pre = pre as f64;
33 let post = post as f64;
34 let diff = post - pre;
35 (pre + (diff * ratio)).round() as u8
36 };
37 Colour {
38 red: interpolate(self.red, rhs.red),
39 green: interpolate(self.green, rhs.green),
40 blue: interpolate(self.blue, rhs.blue),
41 }
42 }
43}
44
45impl std::fmt::Display for Colour {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 write!(f, "#{:02X}{:02X}{:02X}", self.red, self.green, self.blue)
48 }
49}
50
51impl FromStr for Colour {
52 type Err = String;
53
54 fn from_str(s: &str) -> Result<Self, Self::Err> {
55 let s = s.trim_start_matches('#');
56 let len = s.len();
57 if len != 6 {
58 return Err(format!("expected 6 characters, got {}", len));
59 }
60 let red = u8::from_str_radix(&s[0..2], 16).map_err(|e| e.to_string())?;
61 let green = u8::from_str_radix(&s[2..4], 16).map_err(|e| e.to_string())?;
62 let blue = u8::from_str_radix(&s[4..6], 16).map_err(|e| e.to_string())?;
63 Ok(Colour { red, green, blue })
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn test_colour_interpolation() {
73 let black = Colour::from_rgb(0, 0, 0);
74 let white = Colour::from_rgb(255, 255, 255);
75 assert_eq!(black.interpolate(white, 1.0), white);
76 assert_eq!(black.interpolate(white, 0.0), black);
77 assert_eq!(white.interpolate(black, 1.0), black);
78 assert_eq!(white.interpolate(black, 0.0), white);
79 assert_eq!(black.interpolate(white, 0.2), Colour::from_rgb(51, 51, 51));
80 assert_eq!(
81 white.interpolate(black, 0.2),
82 Colour::from_rgb(204, 204, 204)
83 );
84 let other = Colour::from_rgb(34, 202, 117);
85 assert_eq!(black.interpolate(other, 0.4), Colour::from_rgb(14, 81, 47));
86 assert_eq!(
87 white.interpolate(other, 0.2),
88 Colour::from_rgb(211, 244, 227)
89 );
90 assert_eq!(
91 white.interpolate(other, 0.8),
92 Colour::from_rgb(78, 213, 145)
93 );
94 }
95}