diff --git a/CHANGELOG.md b/CHANGELOG.md index 8da9ada2..6dd276b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ SSD1306 monochrome OLED display. ### Fixed - Fix TerminalMode::write_str() to write all chars ([#228](https://github.com/rust-embedded-community/ssd1306/issues/228)) +### Added +- Implement `embedded_graphics::draw_target::DrawTarget::fill_contiguous` to more improve performance when filling + contiguous regions. + ## [0.10.0] - 2025-03-22 ### Changed - Added `DisplaySize64x32` to the prelude diff --git a/src/mode/buffered_graphics.rs b/src/mode/buffered_graphics.rs index 3e6695c5..95af77fa 100644 --- a/src/mode/buffered_graphics.rs +++ b/src/mode/buffered_graphics.rs @@ -234,9 +234,9 @@ where #[cfg(feature = "graphics")] use embedded_graphics_core::{ draw_target::DrawTarget, - geometry::Size, - geometry::{Dimensions, OriginDimensions}, + geometry::{AnchorX, AnchorY, Dimensions, OriginDimensions, Size}, pixelcolor::BinaryColor, + primitives::Rectangle, Pixel, }; @@ -276,6 +276,53 @@ where .for_each(|Pixel(pos, color)| { self.set_pixel(pos.x as u32, pos.y as u32, color.is_on()); }); + Ok(()) + } + + fn fill_contiguous(&mut self, area: &Rectangle, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator, + { + let area = area.intersection(&self.bounding_box()); + let mut pixels = pixels.into_iter(); + + // Keep track of max and min values + self.mode.min_x = self.mode.min_x.min(area.anchor_x(AnchorX::Left) as u8); + self.mode.max_x = self.mode.max_x.max(area.anchor_x(AnchorX::Right) as u8); + self.mode.min_y = self.mode.min_y.min(area.anchor_y(AnchorY::Top) as u8); + self.mode.max_y = self.mode.max_y.max(area.anchor_y(AnchorY::Bottom) as u8); + + let buffer = self.mode.buffer.as_mut(); + match self.rotation { + DisplayRotation::Rotate0 | DisplayRotation::Rotate180 => { + for y in area.rows() { + for x in area.columns() { + let Some(color) = pixels.next() else { + return Ok(()); + }; + let value = color.is_on() as u8; + let idx = ((y as usize) / 8 * SIZE::WIDTH as usize) + (x as usize); + let bit = y % 8; + let byte = &mut buffer[idx]; + *byte = *byte & !(1 << bit) | (value << bit); + } + } + } + DisplayRotation::Rotate90 | DisplayRotation::Rotate270 => { + for y in area.rows() { + for x in area.columns() { + let Some(color) = pixels.next() else { + return Ok(()); + }; + let value = color.is_on() as u8; + let idx = ((x as usize) / 8 * SIZE::WIDTH as usize) + (y as usize); + let bit = x % 8; + let byte = &mut buffer[idx]; + *byte = *byte & !(1 << bit) | (value << bit); + } + } + } + }; Ok(()) }