From c18dd1fa5afc128c8bc06845553da22ed8ae3a19 Mon Sep 17 00:00:00 2001 From: Iris Webb Date: Thu, 27 Aug 2026 13:59:16 -0500 Subject: [PATCH] Add memory optimizations for filling rectangles --- src/backends.rs | 19 +++++++++++++++++++ src/lib.rs | 43 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/backends.rs b/src/backends.rs index 776bc9e..d1dde46 100644 --- a/src/backends.rs +++ b/src/backends.rs @@ -41,6 +41,13 @@ pub trait FrameBufferBackend { /// Returns a pixels color fn get(&self, index: usize) -> Self::Color; + /// Fills a line with a color, may be used with the slice copy methods for memory optimization + fn set_hline(&mut self, start: usize, width: usize, color: Self::Color) { + for pixel in start..width { + self.set(pixel, color); + } + } + /// Nr of elements in the backend fn nr_elements(&self) -> usize; } @@ -55,6 +62,10 @@ impl FrameBufferBackend for &mut [C; N] { self[index] } + fn set_hline(&mut self, start: usize, width: usize, color: Self::Color) { + self[start..start + width].fill(color) + } + fn nr_elements(&self) -> usize { self.len() } @@ -70,6 +81,10 @@ impl FrameBufferBackend for [C; N] { self[index] } + fn set_hline(&mut self, start: usize, width: usize, color: Self::Color) { + self[start..start + width].fill(color) + } + fn nr_elements(&self) -> usize { self.len() } @@ -86,6 +101,10 @@ impl FrameBufferBackend for &mut [C] { self[index] } + fn set_hline(&mut self, start: usize, width: usize, color: Self::Color) { + self[start..start + width].fill(color) + } + fn nr_elements(&self) -> usize { self.len() } diff --git a/src/lib.rs b/src/lib.rs index 812ee77..a54d73d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,8 +43,9 @@ use embedded_dma::{ReadBuffer, WriteBuffer}; use embedded_graphics::{ draw_target::DrawTarget, - geometry::OriginDimensions, + geometry::{Dimensions, OriginDimensions}, prelude::{PixelColor, Point, Size}, + primitives::Rectangle, Pixel, }; @@ -236,14 +237,33 @@ impl> DrawTarget for FrameBuf Result<(), Self::Error> { - for y in 0..self.height { - for x in 0..self.width { - self.set_color_at(Point::new(x as i32, y as i32), color); - } + fn fill_solid(&mut self, area: &Rectangle, color: Self::Color) -> Result<(), Self::Error> { + // Clip Rectangle + let area = if self.bounding_box().intersection(area) != *area { + self.bounding_box().intersection(area) + } else { + *area + }; + + let Rectangle { + top_left: Point { x, y }, + size: Size { width, height }, + } = area; + + for row in (y as u32)..(y as u32) + height { + self.data.set_hline( + self.point_to_index(Point::new(x, row as i32)), + width as usize, + color, + ); } + Ok(()) } + + fn clear(&mut self, color: Self::Color) -> Result<(), Self::Error> { + self.fill_solid(&self.bounding_box(), color) + } } /// An iterator for all [Pixels](Pixel) in the framebuffer. @@ -372,6 +392,11 @@ mod tests { .draw(&mut fbuf) .unwrap(); + Rectangle::new(Point::new(5, 5), Size::new(3, 3)) + .into_styled(PrimitiveStyle::with_fill(BinaryColor::On)) + .draw(&mut fbuf) + .unwrap(); + display.draw_iter(fbuf.into_iter()).unwrap(); display.assert_pattern(&[ "............", @@ -379,9 +404,9 @@ mod tests { "..#########.", "............", "............", - ".###........", - ".###........", - ".###........", + ".###.###....", + ".###.###....", + ".###.###....", ".###........", ".###........", ".###........",