/rust/registry/src/index.crates.io-6f17d22bba15001f/nu-ansi-term-0.46.0/src/rgb.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Code liberally borrowed from here |
2 | | // https://github.com/navierr/coloriz |
3 | | use std::ops; |
4 | | use std::u32; |
5 | | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
6 | | pub struct Rgb { |
7 | | /// Red |
8 | | pub r: u8, |
9 | | /// Green |
10 | | pub g: u8, |
11 | | /// Blue |
12 | | pub b: u8, |
13 | | } |
14 | | |
15 | | impl Rgb { |
16 | | /// Creates a new [Rgb] color |
17 | | #[inline] |
18 | 0 | pub const fn new(r: u8, g: u8, b: u8) -> Self { |
19 | 0 | Self { r, g, b } |
20 | 0 | } |
21 | | |
22 | | /// Creates a new [Rgb] color with a hex code |
23 | | #[inline] |
24 | 0 | pub const fn from_hex(hex: u32) -> Self { |
25 | 0 | Self::new((hex >> 16) as u8, (hex >> 8) as u8, hex as u8) |
26 | 0 | } |
27 | | |
28 | 0 | pub fn from_hex_string(hex: String) -> Self { |
29 | 0 | if hex.chars().count() == 8 && hex.starts_with("0x") { |
30 | | // eprintln!("hex:{:?}", hex); |
31 | 0 | let (_, value_string) = hex.split_at(2); |
32 | 0 | // eprintln!("value_string:{:?}", value_string); |
33 | 0 | let int_val = u64::from_str_radix(value_string, 16); |
34 | 0 | match int_val { |
35 | 0 | Ok(num) => Self::new( |
36 | 0 | ((num & 0xff0000) >> 16) as u8, |
37 | 0 | ((num & 0xff00) >> 8) as u8, |
38 | 0 | (num & 0xff) as u8, |
39 | 0 | ), |
40 | | // Don't fail, just make the color black |
41 | | // Should we fail? |
42 | 0 | _ => Self::new(0, 0, 0), |
43 | | } |
44 | | } else { |
45 | | // Don't fail, just make the color black. |
46 | | // Should we fail? |
47 | 0 | Self::new(0, 0, 0) |
48 | | } |
49 | 0 | } |
50 | | |
51 | | /// Creates a new [Rgb] color with three [f32] values |
52 | 0 | pub fn from_f32(r: f32, g: f32, b: f32) -> Self { |
53 | 0 | Self::new( |
54 | 0 | (r.clamp(0.0, 1.0) * 255.0) as u8, |
55 | 0 | (g.clamp(0.0, 1.0) * 255.0) as u8, |
56 | 0 | (b.clamp(0.0, 1.0) * 255.0) as u8, |
57 | 0 | ) |
58 | 0 | } |
59 | | |
60 | | /// Creates a grayscale [Rgb] color |
61 | | #[inline] |
62 | 0 | pub const fn gray(x: u8) -> Self { |
63 | 0 | Self::new(x, x, x) |
64 | 0 | } |
65 | | |
66 | | /// Creates a grayscale [Rgb] color with a [f32] value |
67 | 0 | pub fn gray_f32(x: f32) -> Self { |
68 | 0 | Self::from_f32(x, x, x) |
69 | 0 | } |
70 | | |
71 | | /// Creates a new [Rgb] color from a [HSL] color |
72 | | // pub fn from_hsl(hsl: HSL) -> Self { |
73 | | // if hsl.s == 0.0 { |
74 | | // return Self::gray_f32(hsl.l); |
75 | | // } |
76 | | |
77 | | // let q = if hsl.l < 0.5 { |
78 | | // hsl.l * (1.0 + hsl.s) |
79 | | // } else { |
80 | | // hsl.l + hsl.s - hsl.l * hsl.s |
81 | | // }; |
82 | | // let p = 2.0 * hsl.l - q; |
83 | | // let h2c = |t: f32| { |
84 | | // let t = t.clamp(0.0, 1.0); |
85 | | // if 6.0 * t < 1.0 { |
86 | | // p + 6.0 * (q - p) * t |
87 | | // } else if t < 0.5 { |
88 | | // q |
89 | | // } else if 1.0 < 1.5 * t { |
90 | | // p + 6.0 * (q - p) * (1.0 / 1.5 - t) |
91 | | // } else { |
92 | | // p |
93 | | // } |
94 | | // }; |
95 | | |
96 | | // Self::from_f32(h2c(hsl.h + 1.0 / 3.0), h2c(hsl.h), h2c(hsl.h - 1.0 / 3.0)) |
97 | | // } |
98 | | |
99 | | /// Computes the linear interpolation between `self` and `other` for `t` |
100 | 0 | pub fn lerp(&self, other: Self, t: f32) -> Self { |
101 | 0 | let t = t.clamp(0.0, 1.0); |
102 | 0 | self * (1.0 - t) + other * t |
103 | 0 | } |
104 | | } |
105 | | |
106 | | impl From<(u8, u8, u8)> for Rgb { |
107 | 0 | fn from((r, g, b): (u8, u8, u8)) -> Self { |
108 | 0 | Self::new(r, g, b) |
109 | 0 | } |
110 | | } |
111 | | |
112 | | impl From<(f32, f32, f32)> for Rgb { |
113 | 0 | fn from((r, g, b): (f32, f32, f32)) -> Self { |
114 | 0 | Self::from_f32(r, g, b) |
115 | 0 | } |
116 | | } |
117 | | |
118 | | use crate::ANSIColorCode; |
119 | | use crate::TargetGround; |
120 | | impl ANSIColorCode for Rgb { |
121 | 0 | fn ansi_color_code(&self, target: TargetGround) -> String { |
122 | 0 | format!("{};2;{};{};{}", target.code() + 8, self.r, self.g, self.b) |
123 | 0 | } |
124 | | } |
125 | | |
126 | | overload::overload!( |
127 | | (lhs: ?Rgb) + (rhs: ?Rgb) -> Rgb { |
128 | | Rgb::new( |
129 | | lhs.r.saturating_add(rhs.r), |
130 | | lhs.g.saturating_add(rhs.g), |
131 | | lhs.b.saturating_add(rhs.b) |
132 | | ) |
133 | | } |
134 | | ); |
135 | | |
136 | | overload::overload!( |
137 | | (lhs: ?Rgb) - (rhs: ?Rgb) -> Rgb { |
138 | | Rgb::new( |
139 | | lhs.r.saturating_sub(rhs.r), |
140 | | lhs.g.saturating_sub(rhs.g), |
141 | | lhs.b.saturating_sub(rhs.b) |
142 | | ) |
143 | | } |
144 | | ); |
145 | | |
146 | | overload::overload!( |
147 | | (lhs: ?Rgb) * (rhs: ?f32) -> Rgb { |
148 | | Rgb::new( |
149 | | (lhs.r as f32 * rhs.clamp(0.0, 1.0)) as u8, |
150 | | (lhs.g as f32 * rhs.clamp(0.0, 1.0)) as u8, |
151 | | (lhs.b as f32 * rhs.clamp(0.0, 1.0)) as u8 |
152 | | ) |
153 | | } |
154 | | ); |
155 | | |
156 | | overload::overload!( |
157 | | (lhs: ?f32) * (rhs: ?Rgb) -> Rgb { |
158 | | Rgb::new( |
159 | | (rhs.r as f32 * lhs.clamp(0.0, 1.0)) as u8, |
160 | | (rhs.g as f32 * lhs.clamp(0.0, 1.0)) as u8, |
161 | | (rhs.b as f32 * lhs.clamp(0.0, 1.0)) as u8 |
162 | | ) |
163 | | } |
164 | | ); |
165 | | |
166 | | overload::overload!( |
167 | | -(rgb: ?Rgb) -> Rgb { |
168 | | Rgb::new( |
169 | | 255 - rgb.r, |
170 | | 255 - rgb.g, |
171 | | 255 - rgb.b) |
172 | | } |
173 | | ); |