speedy2d/
color.rs

1/*
2 *  Copyright 2021 QuantumBadger
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 *  you may not use this file except in compliance with the License.
6 *  You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *  Unless required by applicable law or agreed to in writing, software
11 *  distributed under the License is distributed on an "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 *  See the License for the specific language governing permissions and
14 *  limitations under the License.
15 */
16
17/// A struct representing a color with red, green, blue, and alpha components.
18/// Each component is stored as a float.
19#[derive(Debug, PartialEq, Clone, Copy)]
20pub struct Color
21{
22    r: f32,
23    g: f32,
24    b: f32,
25    a: f32
26}
27
28impl Color
29{
30    /// Color constant for transparency, with the alpha value set to zero.
31    pub const TRANSPARENT: Color = Color::from_rgba(0.0, 0.0, 0.0, 0.0);
32
33    /// Constant for the color black.
34    pub const BLACK: Color = Color::from_rgb(0.0, 0.0, 0.0);
35
36    /// Constant for the color white.
37    pub const WHITE: Color = Color::from_rgb(1.0, 1.0, 1.0);
38
39    /// Constant for the color red.
40    pub const RED: Color = Color::from_rgb(1.0, 0.0, 0.0);
41
42    /// Constant for the color green.
43    pub const GREEN: Color = Color::from_rgb(0.0, 1.0, 0.0);
44
45    /// Constant for the color blue.
46    pub const BLUE: Color = Color::from_rgb(0.0, 0.0, 1.0);
47
48    /// Constant for the color yellow.
49    pub const YELLOW: Color = Color::from_rgb(1.0, 1.0, 0.0);
50
51    /// Constant for the color cyan.
52    pub const CYAN: Color = Color::from_rgb(0.0, 1.0, 1.0);
53
54    /// Constant for the color magenta.
55    pub const MAGENTA: Color = Color::from_rgb(1.0, 0.0, 1.0);
56
57    /// Constant for the color gray.
58    pub const GRAY: Color = Color::from_rgb(0.5, 0.5, 0.5);
59
60    /// Constant for the color light gray.
61    pub const LIGHT_GRAY: Color = Color::from_rgb(0.75, 0.75, 0.75);
62
63    /// Constant for the color dark gray.
64    pub const DARK_GRAY: Color = Color::from_rgb(0.25, 0.25, 0.25);
65
66    /// Creates a color with the specified components, including an alpha
67    /// component. Each component should be in the range `0.0` to `1.0`.
68    #[inline]
69    pub const fn from_rgba(r: f32, g: f32, b: f32, a: f32) -> Self
70    {
71        Color { r, g, b, a }
72    }
73
74    /// Creates a color with the specified components. The alpha component will
75    /// be set to 1.0 (full opacity). Each component should be in the range
76    /// `0.0` to `1.0`.
77    #[inline]
78    pub const fn from_rgb(r: f32, g: f32, b: f32) -> Self
79    {
80        Color { r, g, b, a: 1.0 }
81    }
82
83    /// Creates a color with the specified components, including an alpha
84    /// component. Each component should be in the range `0` to `255`.
85    #[inline]
86    pub fn from_int_rgba(r: u8, g: u8, b: u8, a: u8) -> Self
87    {
88        Color {
89            r: r as f32 / 255.0,
90            g: g as f32 / 255.0,
91            b: b as f32 / 255.0,
92            a: a as f32 / 255.0
93        }
94    }
95
96    /// Creates a color with the specified components. The alpha component will
97    /// be set to 255 (full opacity). Each component should be in the range
98    /// `0` to `255`.
99    #[inline]
100    pub fn from_int_rgb(r: u8, g: u8, b: u8) -> Self
101    {
102        Color {
103            r: r as f32 / 255.0,
104            g: g as f32 / 255.0,
105            b: b as f32 / 255.0,
106            a: 1.0
107        }
108    }
109
110    /// Creates a color from the specified integer value, including an alpha
111    /// component.
112    ///
113    /// For example, the input value `0xAABBCCDD` will result in a color with:
114    ///
115    /// * Alpha = `0xAA`
116    /// * Red   = `0xBB`
117    /// * Green = `0xCC`
118    /// * Blue  = `0xDD`
119    ///
120    /// Note: If you don't specify the alpha component, the color will be
121    /// transparent.
122    #[inline]
123    pub fn from_hex_argb(argb: u32) -> Self
124    {
125        Color::from_int_rgba(
126            (argb >> 16) as u8,
127            (argb >> 8) as u8,
128            argb as u8,
129            (argb >> 24) as u8
130        )
131    }
132
133    /// Creates a color from the specified integer value, with the alpha
134    /// component set to `255` (full opacity).
135    ///
136    /// For example, the input value `0xAABBCC` will result in a color with:
137    ///
138    /// * Alpha = `0xFF`
139    /// * Red   = `0xAA`
140    /// * Green = `0xBB`
141    /// * Blue  = `0xCC`
142    ///
143    /// Note: if an alpha component is specified in the high bits of the
144    /// integer, it will be ignored. See [Color::from_hex_argb] if you wish to
145    /// specify the alpha component.
146    #[inline]
147    pub fn from_hex_rgb(rgb: u32) -> Self
148    {
149        Color::from_int_rgb((rgb >> 16) as u8, (rgb >> 8) as u8, rgb as u8)
150    }
151
152    /// Creates a shade of gray from the specified float value, between `0.0`
153    /// and `1.0`. All three RGB components will be set to this value.
154    #[inline]
155    pub const fn from_gray(brightness: f32) -> Self
156    {
157        Self::from_rgb(brightness, brightness, brightness)
158    }
159
160    /// Returns the red component of the color, as a value in the range `0.0` to
161    /// `1.0`.
162    #[inline]
163    pub const fn r(&self) -> f32
164    {
165        self.r
166    }
167
168    /// Returns the green component of the color, as a value in the range `0.0`
169    /// to `1.0`.
170    #[inline]
171    pub const fn g(&self) -> f32
172    {
173        self.g
174    }
175
176    /// Returns the blue component of the color, as a value in the range `0.0`
177    /// to `1.0`.
178    #[inline]
179    pub const fn b(&self) -> f32
180    {
181        self.b
182    }
183
184    /// Returns the alpha component of the color, as a value in the range `0.0`
185    /// to `1.0`. The value `0.0` is fully transparent, and the value `1.0`
186    /// is fully opaque.
187    #[inline]
188    pub const fn a(&self) -> f32
189    {
190        self.a
191    }
192
193    /// Returns the brightness of the color as perceived by a human, as a value
194    /// in the range `0.0` to `1.0`.
195    ///
196    /// This is calculated using the following formula:
197    ///
198    /// ```
199    /// # let red = 0.0;
200    /// # let green = 0.0;
201    /// # let blue = 0.0;
202    /// # let result =
203    /// red * 0.299 + green * 0.587 + blue * 0.114
204    /// # ;
205    /// ```
206    pub fn subjective_brightness(&self) -> f32
207    {
208        self.r * 0.299 + self.g * 0.587 + self.b * 0.114
209    }
210}
211
212#[cfg(test)]
213mod tests
214{
215    use super::*;
216
217    #[test]
218    fn test_from_hex()
219    {
220        // We're comparing floats for equality here, which is normally a bad idea, but
221        // here the result should be deterministic as it's computed the same way both
222        // times.
223
224        assert_eq!(
225            Color::from_hex_rgb(0xFF5511),
226            Color::from_int_rgb(0xFF, 0x55, 0x11)
227        );
228
229        assert_eq!(
230            Color::from_hex_argb(0xAAFF5511),
231            Color::from_int_rgba(0xFF, 0x55, 0x11, 0xAA)
232        );
233    }
234}