embedded_gui/
framebuffer.rs1use embedded_graphics_core::{
13 Pixel,
14 draw_target::DrawTarget,
15 geometry::{OriginDimensions, Point, Size},
16 pixelcolor::{Rgb565, RgbColor},
17};
18
19use crate::render::PixelRead;
20
21#[derive(Clone, Debug, PartialEq, Eq)]
24pub struct Framebuffer<const N: usize> {
25 pixels: [Rgb565; N],
26 width: u32,
27 height: u32,
28}
29
30impl<const N: usize> Framebuffer<N> {
31 pub fn new(width: u32, height: u32) -> Self {
35 assert!(
36 (width as usize) * (height as usize) <= N,
37 "Framebuffer backing array too small for width * height",
38 );
39 Self {
40 pixels: [Rgb565::BLACK; N],
41 width,
42 height,
43 }
44 }
45
46 pub fn clear_color(&mut self, color: Rgb565) {
48 let len = self.len();
49 for p in self.pixels[..len].iter_mut() {
50 *p = color;
51 }
52 }
53
54 pub fn pixels(&self) -> &[Rgb565] {
57 &self.pixels[..self.len()]
58 }
59
60 pub const fn width(&self) -> u32 {
61 self.width
62 }
63
64 pub const fn height(&self) -> u32 {
65 self.height
66 }
67
68 #[inline]
69 fn len(&self) -> usize {
70 (self.width as usize) * (self.height as usize)
71 }
72
73 #[inline]
74 fn index(&self, x: i32, y: i32) -> Option<usize> {
75 if x < 0 || y < 0 || x as u32 >= self.width || y as u32 >= self.height {
76 return None;
77 }
78 Some((y as usize) * (self.width as usize) + (x as usize))
79 }
80}
81
82impl<const N: usize> OriginDimensions for Framebuffer<N> {
83 fn size(&self) -> Size {
84 Size::new(self.width, self.height)
85 }
86}
87
88impl<const N: usize> DrawTarget for Framebuffer<N> {
89 type Color = Rgb565;
90 type Error = core::convert::Infallible;
91
92 fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
93 where
94 I: IntoIterator<Item = Pixel<Self::Color>>,
95 {
96 for Pixel(point, color) in pixels {
97 if let Some(idx) = self.index(point.x, point.y) {
98 self.pixels[idx] = color;
99 }
100 }
101 Ok(())
102 }
103}
104
105impl<const N: usize> PixelRead for Framebuffer<N> {
106 fn get_pixel(&self, point: Point) -> Rgb565 {
107 match self.index(point.x, point.y) {
108 Some(idx) => self.pixels[idx],
109 None => Rgb565::BLACK,
110 }
111 }
112}