device_envoy_core/
pixel_target.rs1use core::convert::Infallible;
4
5use embedded_graphics::{
6 Pixel,
7 draw_target::DrawTarget,
8 geometry::{OriginDimensions, Size},
9 pixelcolor::{Rgb565, Rgb888},
10 prelude::RgbColor,
11};
12
13pub fn fill_ellipse_pixels(
18 center: (f32, f32),
19 axis_a: (f32, f32),
20 axis_b: (f32, f32),
21 mut put_pixel: impl FnMut(i32, i32),
22) {
23 let (axis_ax, axis_ay) = axis_a;
24 let (axis_bx, axis_by) = axis_b;
25 let determinant = axis_ax * axis_by - axis_ay * axis_bx;
26 if determinant.abs() < 0.5 {
27 return;
28 }
29 let inverse_determinant = 1.0 / determinant;
30 let bound_x = (axis_ax.abs() + axis_bx.abs()) as i32 + 1;
31 let bound_y = (axis_ay.abs() + axis_by.abs()) as i32 + 1;
32 let center_x = center.0 as i32;
33 let center_y = center.1 as i32;
34 for local_y in -bound_y..=bound_y {
35 for local_x in -bound_x..=bound_x {
36 let delta_x = local_x as f32;
37 let delta_y = local_y as f32;
38 let s = (axis_by * delta_x - axis_bx * delta_y) * inverse_determinant;
39 let t = (axis_ax * delta_y - axis_ay * delta_x) * inverse_determinant;
40 if s * s + t * t <= 1.0 {
41 put_pixel(center_x + local_x, center_y + local_y);
42 }
43 }
44 }
45}
46
47pub trait PixelTarget {
54 fn width(&self) -> usize;
55 fn height(&self) -> usize;
56 fn put_pixel(&mut self, x: usize, y: usize, color: Rgb888);
57
58 fn put_pixel_565(&mut self, x: usize, y: usize, rgb565: u16) {
60 self.put_pixel(x, y, rgb888_from_rgb565(rgb565));
61 }
62}
63
64pub const fn rgb888_from_rgb565(rgb565: u16) -> Rgb888 {
66 let red5 = ((rgb565 >> 11) & 0x1f) as u8;
67 let green6 = ((rgb565 >> 5) & 0x3f) as u8;
68 let blue5 = (rgb565 & 0x1f) as u8;
69
70 let red = (red5 << 3) | (red5 >> 2);
71 let green = (green6 << 2) | (green6 >> 4);
72 let blue = (blue5 << 3) | (blue5 >> 2);
73
74 Rgb888::new(red, green, blue)
75}
76
77pub const fn rgb565_from_rgb888_components(red: u8, green: u8, blue: u8) -> Rgb565 {
79 Rgb565::new(red >> 3, green >> 2, blue >> 3)
80}
81
82pub fn rgb565_from_rgb888(color: Rgb888) -> Rgb565 {
84 rgb565_from_rgb888_components(color.r(), color.g(), color.b())
85}
86
87pub fn pixel_put<T: PixelTarget>(target: &mut T, x: i32, y: i32, color: Rgb888) {
89 if x < 0 || y < 0 {
90 return;
91 }
92 let x = x as usize;
93 let y = y as usize;
94 if x >= target.width() || y >= target.height() {
95 return;
96 }
97 target.put_pixel(x, y, color);
98}
99
100pub fn pixel_put_565<T: PixelTarget>(target: &mut T, x: i32, y: i32, rgb565: u16) {
102 if x < 0 || y < 0 {
103 return;
104 }
105 let x = x as usize;
106 let y = y as usize;
107 if x >= target.width() || y >= target.height() {
108 return;
109 }
110 target.put_pixel_565(x, y, rgb565);
111}
112
113pub struct PixelTargetAdapter<'a, T: PixelTarget>(pub &'a mut T);
115
116impl<T: PixelTarget> DrawTarget for PixelTargetAdapter<'_, T> {
117 type Color = Rgb888;
118 type Error = Infallible;
119
120 fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
121 where
122 I: IntoIterator<Item = Pixel<Rgb888>>,
123 {
124 for Pixel(point, color) in pixels {
125 pixel_put(self.0, point.x, point.y, color);
126 }
127 Ok(())
128 }
129}
130
131impl<T: PixelTarget> OriginDimensions for PixelTargetAdapter<'_, T> {
132 fn size(&self) -> Size {
133 Size::new(self.0.width() as u32, self.0.height() as u32)
134 }
135}