1use peek_poke::PeekPoke;
6use std::cmp;
7use std::hash::{Hash, Hasher};
8
9#[repr(C)]
17#[derive(Clone, Copy, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
18pub struct PremultipliedColorF {
19 pub r: f32,
20 pub g: f32,
21 pub b: f32,
22 pub a: f32,
23}
24
25#[allow(missing_docs)]
26impl PremultipliedColorF {
27 pub const BLACK: PremultipliedColorF = PremultipliedColorF { r: 0.0, g: 0.0, b: 0.0, a: 1.0 };
28 pub const TRANSPARENT: PremultipliedColorF = PremultipliedColorF { r: 0.0, g: 0.0, b: 0.0, a: 0.0 };
29 pub const WHITE: PremultipliedColorF = PremultipliedColorF { r: 1.0, g: 1.0, b: 1.0, a: 1.0 };
30
31 pub fn to_array(&self) -> [f32; 4] {
32 [self.r, self.g, self.b, self.a]
33 }
34}
35
36#[repr(C)]
41#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
42pub struct ColorF {
43 pub r: f32,
44 pub g: f32,
45 pub b: f32,
46 pub a: f32,
47}
48
49#[allow(missing_docs)]
50impl ColorF {
51 pub const BLACK: ColorF = ColorF { r: 0.0, g: 0.0, b: 0.0, a: 1.0 };
52 pub const TRANSPARENT: ColorF = ColorF { r: 0.0, g: 0.0, b: 0.0, a: 0.0 };
53 pub const WHITE: ColorF = ColorF { r: 1.0, g: 1.0, b: 1.0, a: 1.0 };
54
55 pub fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
57 ColorF { r, g, b, a }
58 }
59
60 pub fn scale_rgb(&self, scale: f32) -> Self {
62 ColorF {
63 r: self.r * scale,
64 g: self.g * scale,
65 b: self.b * scale,
66 a: self.a,
67 }
68 }
69
70 pub fn scale_alpha(&self, scale: f32) -> Self {
72 ColorF {
73 r: self.r,
74 g: self.g,
75 b: self.b,
76 a: self.a * scale,
77 }
78 }
79
80 pub fn to_array(&self) -> [f32; 4] {
81 [self.r, self.g, self.b, self.a]
82 }
83
84 pub fn premultiplied(&self) -> PremultipliedColorF {
86 let c = self.scale_rgb(self.a);
87 PremultipliedColorF { r: c.r, g: c.g, b: c.b, a: c.a }
88 }
89}
90
91impl Eq for PremultipliedColorF {}
93impl Ord for PremultipliedColorF {
94 fn cmp(&self, other: &Self) -> cmp::Ordering {
95 self.partial_cmp(other).unwrap_or(cmp::Ordering::Equal)
96 }
97}
98
99#[cfg_attr(feature = "cargo-clippy", allow(clippy::derive_hash_xor_eq))]
100impl Hash for PremultipliedColorF {
101 fn hash<H: Hasher>(&self, state: &mut H) {
102 self.r.to_bits().hash(state);
104 self.g.to_bits().hash(state);
105 self.b.to_bits().hash(state);
106 self.a.to_bits().hash(state);
107 }
108}
109
110#[repr(C)]
114#[derive(Clone, Copy, Hash, Eq, Debug, Deserialize, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
115pub struct ColorU {
116 pub r: u8,
117 pub g: u8,
118 pub b: u8,
119 pub a: u8,
120}
121
122impl ColorU {
123 pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
125 ColorU { r, g, b, a }
126 }
127}
128
129fn round_to_int(x: f32) -> u8 {
130 debug_assert!((0.0 <= x) && (x <= 1.0), "{} should be between 0 and 1", x);
131 let f = (255.0 * x) + 0.5;
132 let val = f.floor();
133 debug_assert!(val <= 255.0);
134 val as u8
135}
136
137impl From<ColorF> for ColorU {
141 fn from(color: ColorF) -> Self {
142 ColorU {
143 r: round_to_int(color.r),
144 g: round_to_int(color.g),
145 b: round_to_int(color.b),
146 a: round_to_int(color.a),
147 }
148 }
149}
150
151impl From<ColorU> for ColorF {
152 fn from(color: ColorU) -> Self {
153 ColorF {
154 r: color.r as f32 / 255.0,
155 g: color.g as f32 / 255.0,
156 b: color.b as f32 / 255.0,
157 a: color.a as f32 / 255.0,
158 }
159 }
160}