1use std::ops::{Add, Mul, Sub};
4
5#[repr(C)]
10#[derive(Copy, Clone, Default)]
11pub struct Color {
12 pub r: u8,
14 pub g: u8,
16 pub b: u8,
18}
19
20impl Color {
21 pub const BLACK: Color = Color { r: 0, g: 0, b: 0 };
23 pub const WHITE: Color = Color {
25 r: 255,
26 g: 255,
27 b: 255,
28 };
29
30 pub fn rgb(r: u8, g: u8, b: u8) -> Color {
32 Color { r, g, b }
33 }
34}
35
36pub trait Blend<T> {
38 fn blend(self, other: Self, factor: T) -> Self;
51}
52
53impl Blend<u8> for u8 {
54 fn blend(self, other: u8, factor: u8) -> u8 {
55 (self as i16 + (((other as i16 - self as i16) * (factor as i16) + 127) / 255)) as u8
56 }
57}
58
59impl Blend<u8> for Color {
60 fn blend(self, other: Color, factor: u8) -> Color {
61 Color {
62 r: self.r.blend(other.r, factor),
63 g: self.g.blend(other.g, factor),
64 b: self.b.blend(other.b, factor),
65 }
66 }
67}
68
69impl Blend<f32> for u8 {
70 fn blend(self, other: u8, factor: f32) -> u8 {
71 (self as f32 * (1.0 - factor) + other as f32 * factor) as u8
72 }
73}
74
75impl Blend<f32> for Color {
76 fn blend(self, other: Color, factor: f32) -> Color {
77 Color {
78 r: self.r.blend(other.r, factor),
79 g: self.g.blend(other.g, factor),
80 b: self.b.blend(other.b, factor),
81 }
82 }
83}
84
85impl Add<Color> for Color {
86 type Output = Color;
87 fn add(self, rhs: Color) -> Color {
88 Color {
89 r: self.r.saturating_add(rhs.r),
90 g: self.g.saturating_add(rhs.g),
91 b: self.b.saturating_add(rhs.b),
92 }
93 }
94}
95
96impl Sub<Color> for Color {
97 type Output = Color;
98 fn sub(self, rhs: Color) -> Color {
99 Color {
100 r: self.r.saturating_sub(rhs.r),
101 g: self.g.saturating_sub(rhs.g),
102 b: self.b.saturating_sub(rhs.b),
103 }
104 }
105}
106
107impl Mul<Color> for Color {
108 type Output = Color;
109 fn mul(self, rhs: Color) -> Color {
110 Color {
111 r: ((self.r as u16 * rhs.r as u16) >> 8) as u8,
112 g: ((self.g as u16 * rhs.g as u16) >> 8) as u8,
113 b: ((self.b as u16 * rhs.b as u16) >> 8) as u8,
114 }
115 }
116}
117
118impl Mul<u8> for Color {
119 type Output = Color;
120 fn mul(self, rhs: u8) -> Color {
121 Color::BLACK.blend(self, rhs)
122 }
123}
124
125impl Mul<f32> for Color {
126 type Output = Color;
127 fn mul(self, rhs: f32) -> Color {
128 Color::BLACK.blend(self, rhs)
129 }
130}