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 {
50 fn width(&self) -> usize;
51 fn height(&self) -> usize;
52 fn put_pixel(&mut self, x: usize, y: usize, color: Rgb888);
53
54 fn put_pixel_565(&mut self, x: usize, y: usize, rgb565: u16) {
56 self.put_pixel(x, y, rgb888_from_rgb565(rgb565));
57 }
58}
59
60pub const fn rgb888_from_rgb565(rgb565: u16) -> Rgb888 {
62 let red5 = ((rgb565 >> 11) & 0x1f) as u8;
63 let green6 = ((rgb565 >> 5) & 0x3f) as u8;
64 let blue5 = (rgb565 & 0x1f) as u8;
65
66 let red = (red5 << 3) | (red5 >> 2);
67 let green = (green6 << 2) | (green6 >> 4);
68 let blue = (blue5 << 3) | (blue5 >> 2);
69
70 Rgb888::new(red, green, blue)
71}
72
73pub const fn rgb565_from_rgb888_components(red: u8, green: u8, blue: u8) -> Rgb565 {
75 Rgb565::new(red >> 3, green >> 2, blue >> 3)
76}
77
78pub fn rgb565_from_rgb888(color: Rgb888) -> Rgb565 {
80 rgb565_from_rgb888_components(color.r(), color.g(), color.b())
81}
82
83pub fn pixel_put<T: PixelTarget>(target: &mut T, x: i32, y: i32, color: Rgb888) {
85 if x < 0 || y < 0 {
86 return;
87 }
88 let x = x as usize;
89 let y = y as usize;
90 if x >= target.width() || y >= target.height() {
91 return;
92 }
93 target.put_pixel(x, y, color);
94}
95
96pub fn pixel_put_565<T: PixelTarget>(target: &mut T, x: i32, y: i32, rgb565: u16) {
98 if x < 0 || y < 0 {
99 return;
100 }
101 let x = x as usize;
102 let y = y as usize;
103 if x >= target.width() || y >= target.height() {
104 return;
105 }
106 target.put_pixel_565(x, y, rgb565);
107}
108
109pub struct PixelTargetAdapter<'a, T: PixelTarget>(pub &'a mut T);
111
112impl<T: PixelTarget> DrawTarget for PixelTargetAdapter<'_, T> {
113 type Color = Rgb888;
114 type Error = Infallible;
115
116 fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
117 where
118 I: IntoIterator<Item = Pixel<Rgb888>>,
119 {
120 for Pixel(point, color) in pixels {
121 pixel_put(self.0, point.x, point.y, color);
122 }
123 Ok(())
124 }
125}
126
127impl<T: PixelTarget> OriginDimensions for PixelTargetAdapter<'_, T> {
128 fn size(&self) -> Size {
129 Size::new(self.0.width() as u32, self.0.height() as u32)
130 }
131}