1use crate::pixelcolor::{
2 raw::{RawData, RawU1},
3 PixelColor,
4};
5
6/// Binary color.
7///
8/// `BinaryColor` is used for displays and images with two possible color states.
9///
10/// The interpretation of active and inactive states can be different for
11/// different types of displays. A `BinaryColor::On` might represent a black
12/// pixel on an LCD and a white pixel on an OLED display.
13///
14/// To simplify the conversion from `BinaryColor` to RGB and grayscale color
15/// types the default conversions assume that `BinaryColor::Off` is black and
16/// `BinaryColor::On` is white.
17///
18/// # Conversion between BinaryColor and bool
19///
20/// ```
21/// use embedded_graphics::pixelcolor::BinaryColor;
22///
23/// // A BinaryColor can be converted to a bool by using the is_on and is_off methods.
24/// let color = BinaryColor::On;
25/// assert!(color.is_on());
26/// assert!(color.invert().is_off());
27///
28/// // BinaryColor implements From<bool>.
29/// let bool_value = true;
30/// let color: BinaryColor = bool_value.into();
31/// assert_eq!(color, BinaryColor::On);
32///
33/// // this is equivalent to:
34/// let bool_value = true;
35/// let color = if bool_value {
36/// BinaryColor::On
37/// } else {
38/// BinaryColor::Off
39/// };
40/// assert_eq!(color, BinaryColor::On);
41/// ```
42#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
43#[cfg_attr(feature = "defmt", derive(::defmt::Format))]
44pub enum BinaryColor {
45 /// Inactive pixel.
46 Off,
47
48 /// Active pixel.
49 On,
50}
51
52impl Default for BinaryColor {
53 fn default() -> Self {
54 Self::Off
55 }
56}
57
58impl BinaryColor {
59 /// Inverts the color.
60 ///
61 /// # Examples
62 ///
63 /// ```
64 /// use embedded_graphics::pixelcolor::BinaryColor;
65 ///
66 /// assert_eq!(BinaryColor::Off.invert(), BinaryColor::On);
67 /// assert_eq!(BinaryColor::On.invert(), BinaryColor::Off);
68 /// ```
69 #[inline]
70 pub const fn invert(self) -> Self {
71 match self {
72 BinaryColor::On => BinaryColor::Off,
73 BinaryColor::Off => BinaryColor::On,
74 }
75 }
76
77 /// Returns `true` if this color is `On`.
78 ///
79 /// # Examples
80 ///
81 /// ```
82 /// use embedded_graphics::pixelcolor::BinaryColor;
83 ///
84 /// assert!(BinaryColor::On.is_on());
85 /// ```
86 #[inline]
87 pub const fn is_on(self) -> bool {
88 matches!(self, BinaryColor::On)
89 }
90
91 /// Returns `true` if this color is `Off`.
92 ///
93 /// # Examples
94 ///
95 /// ```
96 /// use embedded_graphics::pixelcolor::BinaryColor;
97 ///
98 /// assert!(BinaryColor::Off.is_off());
99 /// ```
100 #[inline]
101 pub const fn is_off(self) -> bool {
102 matches!(self, BinaryColor::Off)
103 }
104
105 /// Maps active and inactive colors to a different type.
106 ///
107 /// # Examples
108 ///
109 /// ```ignore
110 /// use embedded_graphics::pixelcolor::{BinaryColor, Rgb565};
111 /// let color = BinaryColor::On;
112 /// assert_eq!(color.map_color(Rgb565::RED, Rgb565::GREEN), Rgb565::GREEN)
113 /// ```
114 pub(crate) fn map_color<T>(self, value_off: T, value_on: T) -> T {
115 match self {
116 BinaryColor::On => value_on,
117 BinaryColor::Off => value_off,
118 }
119 }
120}
121
122impl PixelColor for BinaryColor {
123 type Raw = RawU1;
124}
125
126impl From<RawU1> for BinaryColor {
127 fn from(data: RawU1) -> Self {
128 if data.into_inner() != 0 {
129 BinaryColor::On
130 } else {
131 BinaryColor::Off
132 }
133 }
134}
135
136impl From<BinaryColor> for RawU1 {
137 fn from(color: BinaryColor) -> Self {
138 RawU1::new(color.map_color(value_off:0, value_on:1))
139 }
140}
141
142impl From<bool> for BinaryColor {
143 fn from(value: bool) -> Self {
144 if value {
145 BinaryColor::On
146 } else {
147 BinaryColor::Off
148 }
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use super::*;
155 use crate::pixelcolor::{IntoStorage, Rgb565, RgbColor};
156
157 #[test]
158 fn default_color_is_off() {
159 assert_eq!(BinaryColor::default(), BinaryColor::Off);
160 }
161
162 #[test]
163 fn invert_binary_color() {
164 assert_eq!(BinaryColor::Off.invert(), BinaryColor::On);
165 assert_eq!(BinaryColor::On.invert(), BinaryColor::Off);
166 }
167
168 #[test]
169 fn map_binary_color() {
170 assert_eq!(
171 BinaryColor::Off.map_color(Rgb565::RED, Rgb565::GREEN),
172 Rgb565::RED
173 );
174 assert_eq!(
175 BinaryColor::On.map_color(Rgb565::RED, Rgb565::GREEN),
176 Rgb565::GREEN
177 );
178 }
179
180 #[test]
181 fn from_data() {
182 assert_eq!(BinaryColor::from(RawU1::new(0)), BinaryColor::Off);
183 assert_eq!(BinaryColor::from(RawU1::new(1)), BinaryColor::On);
184 }
185
186 #[test]
187 fn into_data() {
188 assert_eq!(RawU1::from(BinaryColor::Off).into_inner(), 0);
189 assert_eq!(RawU1::from(BinaryColor::On).into_inner(), 1);
190 }
191
192 #[test]
193 fn from_bool() {
194 assert_eq!(BinaryColor::from(false), BinaryColor::Off);
195 assert_eq!(BinaryColor::from(true), BinaryColor::On);
196 }
197
198 #[test]
199 fn is_on_off() {
200 assert!(BinaryColor::Off.is_off());
201 assert!(!BinaryColor::On.is_off());
202
203 assert!(!BinaryColor::Off.is_on());
204 assert!(BinaryColor::On.is_on());
205 }
206
207 #[test]
208 fn into_storage() {
209 assert_eq!(BinaryColor::Off.into_storage(), 0u8);
210 assert_eq!(BinaryColor::On.into_storage(), 1u8);
211 }
212}
213