/rust/registry/src/index.crates.io-6f17d22bba15001f/nu-ansi-term-0.49.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::u32; |
4 | | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
5 | | pub struct Rgb { |
6 | | /// Red |
7 | | pub r: u8, |
8 | | /// Green |
9 | | pub g: u8, |
10 | | /// Blue |
11 | | pub b: u8, |
12 | | } |
13 | | |
14 | | impl Rgb { |
15 | | /// Creates a new [Rgb] color |
16 | | #[inline] |
17 | 0 | pub const fn new(r: u8, g: u8, b: u8) -> Self { |
18 | 0 | Self { r, g, b } |
19 | 0 | } |
20 | | |
21 | | /// Creates a new [Rgb] color with a hex code |
22 | | #[inline] |
23 | 0 | pub const fn from_hex(hex: u32) -> Self { |
24 | 0 | Self::new((hex >> 16) as u8, (hex >> 8) as u8, hex as u8) |
25 | 0 | } |
26 | | |
27 | 0 | pub fn from_hex_string(hex: String) -> Self { |
28 | 0 | if hex.chars().count() == 8 && hex.starts_with("0x") { |
29 | | // eprintln!("hex:{:?}", hex); |
30 | 0 | let (_, value_string) = hex.split_at(2); |
31 | 0 | // eprintln!("value_string:{:?}", value_string); |
32 | 0 | let int_val = u64::from_str_radix(value_string, 16); |
33 | 0 | match int_val { |
34 | 0 | Ok(num) => Self::new( |
35 | 0 | ((num & 0xff0000) >> 16) as u8, |
36 | 0 | ((num & 0xff00) >> 8) as u8, |
37 | 0 | (num & 0xff) as u8, |
38 | 0 | ), |
39 | | // Don't fail, just make the color black |
40 | | // Should we fail? |
41 | 0 | _ => Self::new(0, 0, 0), |
42 | | } |
43 | | } else { |
44 | | // Don't fail, just make the color black. |
45 | | // Should we fail? |
46 | 0 | Self::new(0, 0, 0) |
47 | | } |
48 | 0 | } |
49 | | |
50 | | /// Creates a new [Rgb] color with three [f32] values |
51 | 0 | pub fn from_f32(r: f32, g: f32, b: f32) -> Self { |
52 | 0 | Self::new( |
53 | 0 | (r.clamp(0.0, 1.0) * 255.0) as u8, |
54 | 0 | (g.clamp(0.0, 1.0) * 255.0) as u8, |
55 | 0 | (b.clamp(0.0, 1.0) * 255.0) as u8, |
56 | 0 | ) |
57 | 0 | } |
58 | | |
59 | | /// Creates a grayscale [Rgb] color |
60 | | #[inline] |
61 | 0 | pub const fn gray(x: u8) -> Self { |
62 | 0 | Self::new(x, x, x) |
63 | 0 | } |
64 | | |
65 | | /// Creates a grayscale [Rgb] color with a [f32] value |
66 | 0 | pub fn gray_f32(x: f32) -> Self { |
67 | 0 | Self::from_f32(x, x, x) |
68 | 0 | } |
69 | | |
70 | | /// Creates a new [Rgb] color from a [HSL] color |
71 | | // pub fn from_hsl(hsl: HSL) -> Self { |
72 | | // if hsl.s == 0.0 { |
73 | | // return Self::gray_f32(hsl.l); |
74 | | // } |
75 | | |
76 | | // let q = if hsl.l < 0.5 { |
77 | | // hsl.l * (1.0 + hsl.s) |
78 | | // } else { |
79 | | // hsl.l + hsl.s - hsl.l * hsl.s |
80 | | // }; |
81 | | // let p = 2.0 * hsl.l - q; |
82 | | // let h2c = |t: f32| { |
83 | | // let t = t.clamp(0.0, 1.0); |
84 | | // if 6.0 * t < 1.0 { |
85 | | // p + 6.0 * (q - p) * t |
86 | | // } else if t < 0.5 { |
87 | | // q |
88 | | // } else if 1.0 < 1.5 * t { |
89 | | // p + 6.0 * (q - p) * (1.0 / 1.5 - t) |
90 | | // } else { |
91 | | // p |
92 | | // } |
93 | | // }; |
94 | | |
95 | | // Self::from_f32(h2c(hsl.h + 1.0 / 3.0), h2c(hsl.h), h2c(hsl.h - 1.0 / 3.0)) |
96 | | // } |
97 | | |
98 | | /// Computes the linear interpolation between `self` and `other` for `t` |
99 | 0 | pub fn lerp(&self, other: Self, t: f32) -> Self { |
100 | 0 | let t = t.clamp(0.0, 1.0); |
101 | 0 | self * (1.0 - t) + other * t |
102 | 0 | } |
103 | | } |
104 | | |
105 | | impl From<(u8, u8, u8)> for Rgb { |
106 | 0 | fn from((r, g, b): (u8, u8, u8)) -> Self { |
107 | 0 | Self::new(r, g, b) |
108 | 0 | } |
109 | | } |
110 | | |
111 | | impl From<(f32, f32, f32)> for Rgb { |
112 | 0 | fn from((r, g, b): (f32, f32, f32)) -> Self { |
113 | 0 | Self::from_f32(r, g, b) |
114 | 0 | } |
115 | | } |
116 | | |
117 | | use crate::ANSIColorCode; |
118 | | use crate::TargetGround; |
119 | | impl ANSIColorCode for Rgb { |
120 | 0 | fn ansi_color_code(&self, target: TargetGround) -> String { |
121 | 0 | format!("{};2;{};{};{}", target.code() + 8, self.r, self.g, self.b) |
122 | 0 | } |
123 | | } |
124 | | |
125 | 0 | const fn rgb_add(lhs: &Rgb, rhs: &Rgb) -> Rgb { |
126 | 0 | Rgb::new( |
127 | 0 | lhs.r.saturating_add(rhs.r), |
128 | 0 | lhs.g.saturating_add(rhs.g), |
129 | 0 | lhs.b.saturating_add(rhs.b), |
130 | 0 | ) |
131 | 0 | } |
132 | | |
133 | 0 | const fn rgb_sub(lhs: &Rgb, rhs: &Rgb) -> Rgb { |
134 | 0 | Rgb::new( |
135 | 0 | lhs.r.saturating_sub(rhs.r), |
136 | 0 | lhs.g.saturating_sub(rhs.g), |
137 | 0 | lhs.b.saturating_sub(rhs.b), |
138 | 0 | ) |
139 | 0 | } |
140 | | |
141 | 0 | fn rgb_mul_f32(lhs: &Rgb, rhs: &f32) -> Rgb { |
142 | 0 | Rgb::new( |
143 | 0 | (lhs.r as f32 * rhs.clamp(0.0, 1.0)) as u8, |
144 | 0 | (lhs.g as f32 * rhs.clamp(0.0, 1.0)) as u8, |
145 | 0 | (lhs.b as f32 * rhs.clamp(0.0, 1.0)) as u8, |
146 | 0 | ) |
147 | 0 | } |
148 | | |
149 | 0 | const fn rgb_negate(rgb: &Rgb) -> Rgb { |
150 | 0 | Rgb::new(255 - rgb.r, 255 - rgb.g, 255 - rgb.b) |
151 | 0 | } |
152 | | |
153 | | impl std::ops::Add<Rgb> for Rgb { |
154 | | type Output = Rgb; |
155 | | |
156 | 0 | fn add(self, rhs: Rgb) -> Self::Output { |
157 | 0 | rgb_add(&self, &rhs) |
158 | 0 | } |
159 | | } |
160 | | |
161 | | impl std::ops::Add<&Rgb> for Rgb { |
162 | | type Output = Rgb; |
163 | | |
164 | 0 | fn add(self, rhs: &Rgb) -> Self::Output { |
165 | 0 | rgb_add(&self, rhs) |
166 | 0 | } |
167 | | } |
168 | | |
169 | | impl std::ops::Add<Rgb> for &Rgb { |
170 | | type Output = Rgb; |
171 | | |
172 | 0 | fn add(self, rhs: Rgb) -> Self::Output { |
173 | 0 | rgb_add(self, &rhs) |
174 | 0 | } |
175 | | } |
176 | | |
177 | | impl std::ops::Add<&Rgb> for &Rgb { |
178 | | type Output = Rgb; |
179 | | |
180 | 0 | fn add(self, rhs: &Rgb) -> Self::Output { |
181 | 0 | rgb_add(self, rhs) |
182 | 0 | } |
183 | | } |
184 | | |
185 | | impl std::ops::Sub<Rgb> for Rgb { |
186 | | type Output = Rgb; |
187 | | |
188 | 0 | fn sub(self, rhs: Rgb) -> Self::Output { |
189 | 0 | rgb_sub(&self, &rhs) |
190 | 0 | } |
191 | | } |
192 | | |
193 | | impl std::ops::Sub<&Rgb> for Rgb { |
194 | | type Output = Rgb; |
195 | | |
196 | 0 | fn sub(self, rhs: &Rgb) -> Self::Output { |
197 | 0 | rgb_sub(&self, rhs) |
198 | 0 | } |
199 | | } |
200 | | |
201 | | impl std::ops::Sub<Rgb> for &Rgb { |
202 | | type Output = Rgb; |
203 | | |
204 | 0 | fn sub(self, rhs: Rgb) -> Self::Output { |
205 | 0 | rgb_sub(self, &rhs) |
206 | 0 | } |
207 | | } |
208 | | |
209 | | impl std::ops::Sub<&Rgb> for &Rgb { |
210 | | type Output = Rgb; |
211 | | |
212 | 0 | fn sub(self, rhs: &Rgb) -> Self::Output { |
213 | 0 | rgb_sub(self, rhs) |
214 | 0 | } |
215 | | } |
216 | | |
217 | | impl std::ops::Mul<f32> for Rgb { |
218 | | type Output = Rgb; |
219 | | |
220 | 0 | fn mul(self, rhs: f32) -> Self::Output { |
221 | 0 | rgb_mul_f32(&self, &rhs) |
222 | 0 | } |
223 | | } |
224 | | |
225 | | impl std::ops::Mul<&f32> for Rgb { |
226 | | type Output = Rgb; |
227 | | |
228 | 0 | fn mul(self, rhs: &f32) -> Self::Output { |
229 | 0 | rgb_mul_f32(&self, rhs) |
230 | 0 | } |
231 | | } |
232 | | |
233 | | impl std::ops::Mul<f32> for &Rgb { |
234 | | type Output = Rgb; |
235 | | |
236 | 0 | fn mul(self, rhs: f32) -> Self::Output { |
237 | 0 | rgb_mul_f32(self, &rhs) |
238 | 0 | } |
239 | | } |
240 | | |
241 | | impl std::ops::Mul<&f32> for &Rgb { |
242 | | type Output = Rgb; |
243 | | |
244 | 0 | fn mul(self, rhs: &f32) -> Self::Output { |
245 | 0 | rgb_mul_f32(self, rhs) |
246 | 0 | } |
247 | | } |
248 | | |
249 | | impl std::ops::Mul<Rgb> for f32 { |
250 | | type Output = Rgb; |
251 | | |
252 | 0 | fn mul(self, rhs: Rgb) -> Self::Output { |
253 | 0 | rgb_mul_f32(&rhs, &self) |
254 | 0 | } |
255 | | } |
256 | | |
257 | | impl std::ops::Mul<&Rgb> for f32 { |
258 | | type Output = Rgb; |
259 | | |
260 | 0 | fn mul(self, rhs: &Rgb) -> Self::Output { |
261 | 0 | rgb_mul_f32(rhs, &self) |
262 | 0 | } |
263 | | } |
264 | | |
265 | | impl std::ops::Mul<Rgb> for &f32 { |
266 | | type Output = Rgb; |
267 | | |
268 | 0 | fn mul(self, rhs: Rgb) -> Self::Output { |
269 | 0 | rgb_mul_f32(&rhs, self) |
270 | 0 | } |
271 | | } |
272 | | |
273 | | impl std::ops::Mul<&Rgb> for &f32 { |
274 | | type Output = Rgb; |
275 | | |
276 | 0 | fn mul(self, rhs: &Rgb) -> Self::Output { |
277 | 0 | rgb_mul_f32(rhs, self) |
278 | 0 | } |
279 | | } |
280 | | |
281 | | impl std::ops::Neg for Rgb { |
282 | | type Output = Rgb; |
283 | | |
284 | 0 | fn neg(self) -> Self::Output { |
285 | 0 | rgb_negate(&self) |
286 | 0 | } |
287 | | } |
288 | | |
289 | | impl std::ops::Neg for &Rgb { |
290 | | type Output = Rgb; |
291 | | |
292 | 0 | fn neg(self) -> Self::Output { |
293 | 0 | rgb_negate(self) |
294 | 0 | } |
295 | | } |