weact_studio_epd/
color.rs

1#[cfg(feature = "graphics")]
2use embedded_graphics::pixelcolor::{BinaryColor, Rgb555, Rgb565, Rgb888, RgbColor};
3use sealed::sealed;
4
5/// Color definition for B/W displays
6#[derive(Debug, Clone, Copy, PartialEq, Default)]
7pub enum Color {
8    /// Black color
9    Black,
10    /// White color
11    #[default]
12    White,
13}
14
15#[cfg_attr(docsrs, doc(cfg(feature = "graphics")))]
16#[cfg(feature = "graphics")]
17impl From<BinaryColor> for Color {
18    fn from(value: BinaryColor) -> Self {
19        match value {
20            BinaryColor::On => Color::White,
21            BinaryColor::Off => Color::Black,
22        }
23    }
24}
25
26/// Conversion to RGB888 to use `Color` with `embedded-graphics-simulator`.
27#[cfg_attr(docsrs, doc(cfg(feature = "graphics")))]
28#[cfg(feature = "graphics")]
29impl From<Color> for Rgb888 {
30    fn from(value: Color) -> Self {
31        match value {
32            Color::Black => Rgb888::BLACK,
33            Color::White => Rgb888::WHITE,
34        }
35    }
36}
37
38/// Conversion from RGB888 to use `Color` with `embedded-graphics-simulator`.
39///
40/// Panics if the RGB value is not black or white.
41#[cfg_attr(docsrs, doc(cfg(feature = "graphics")))]
42#[cfg(feature = "graphics")]
43impl From<Rgb888> for Color {
44    fn from(value: Rgb888) -> Self {
45        match value {
46            Rgb888::BLACK => Color::Black,
47            Rgb888::WHITE => Color::White,
48            _ => panic!("RGB value must be black or white"),
49        }
50    }
51}
52
53/// Conversion from Rgb565 to use `Color` with tinybmp
54#[cfg(feature = "graphics")]
55impl From<Rgb565> for Color {
56    fn from(rgb: Rgb565) -> Self {
57        if rgb == RgbColor::BLACK {
58            Color::White
59        } else if rgb == RgbColor::WHITE {
60            Color::Black
61        } else {
62            // choose closest color
63            if (rgb.r() as u16 + rgb.g() as u16 + rgb.b() as u16) > 255 * 3 / 2 {
64                Color::Black
65            } else {
66                Color::White
67            }
68        }
69    }
70}
71
72/// Conversion to Rgb565 to use `Color` with tinybmp
73#[cfg(feature = "graphics")]
74impl From<Color> for Rgb565 {
75    fn from(color: Color) -> Self {
76        match color {
77            Color::Black => Self::WHITE,
78            Color::White => Self::BLACK,
79        }
80    }
81}
82
83/// Conversion from Rgb555 to use `Color` with tinybmp
84#[cfg(feature = "graphics")]
85impl From<Rgb555> for Color {
86    fn from(rgb: Rgb555) -> Self {
87        if rgb == RgbColor::BLACK {
88            Color::White
89        } else if rgb == RgbColor::WHITE {
90            Color::Black
91        } else {
92            // choose closest color
93            if (rgb.r() as u16 + rgb.g() as u16 + rgb.b() as u16) > 255 * 3 / 2 {
94                Color::Black
95            } else {
96                Color::White
97            }
98        }
99    }
100}
101
102/// Conversion to Rgb555 to use `Color` with tinybmp
103#[cfg(feature = "graphics")]
104impl From<Color> for Rgb555 {
105    fn from(color: Color) -> Self {
106        match color {
107            Color::Black => Self::WHITE,
108            Color::White => Self::BLACK,
109        }
110    }
111}
112
113/// Color for tri-color displays
114#[derive(Debug, Clone, Copy, PartialEq, Default)]
115pub enum TriColor {
116    /// Black color
117    Black,
118    /// White color
119    #[default]
120    White,
121    /// Red color
122    Red,
123}
124
125/// Color trait for use in `Display`s.
126#[sealed]
127pub trait ColorType {
128    /// Number of buffers used to represent this color type.
129    const BUFFER_COUNT: usize;
130
131    /// Byte value of this color in the buffer.
132    ///
133    /// Useful for setting the full buffer to a single color.
134    ///
135    /// Return values are:
136    /// * `.0`: byte value in the first buffer
137    /// * `.1`: byte value in the second buffer (only applicable to TriColor)
138    fn byte_value(&self) -> (u8, u8);
139
140    /// Bit value of this color in the buffer.
141    ///
142    /// Return values are:
143    /// * `.0`: bit value in the first buffer
144    /// * `.1`: bit value in the second buffer (only applicable to TriColor)
145    fn bit_value(&self) -> (u8, u8);
146}
147
148#[sealed]
149impl ColorType for Color {
150    const BUFFER_COUNT: usize = 1;
151
152    fn byte_value(&self) -> (u8, u8) {
153        match self {
154            Color::Black => (0x00, 0),
155            Color::White => (0xFF, 0),
156        }
157    }
158
159    fn bit_value(&self) -> (u8, u8) {
160        match self {
161            Color::Black => (0b0, 0),
162            Color::White => (0b1, 0),
163        }
164    }
165}
166
167#[sealed]
168impl ColorType for TriColor {
169    const BUFFER_COUNT: usize = 2;
170
171    fn byte_value(&self) -> (u8, u8) {
172        // Red buffer value takes precedence over B/W buffer value.
173        match self {
174            TriColor::Black => (0x00, 0x00),
175            TriColor::White => (0xFF, 0x00),
176            TriColor::Red => (0, 0xFF),
177        }
178    }
179
180    fn bit_value(&self) -> (u8, u8) {
181        // Red buffer value takes precedence over B/W buffer value.
182        match self {
183            TriColor::Black => (0b0, 0b0),
184            TriColor::White => (0b1, 0b0),
185            TriColor::Red => (0, 0b1),
186        }
187    }
188}