Skip to content

Commit 79cb629

Browse files
arlosieldruin
authored andcommitted
Perf: implement fill_contiguous
1 parent c74d321 commit 79cb629

File tree

2 files changed

+53
-2
lines changed

2 files changed

+53
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ SSD1306 monochrome OLED display.
99
### Fixed
1010
- Fix TerminalMode::write_str() to write all chars ([#228](https://github.com/rust-embedded-community/ssd1306/issues/228))
1111

12+
### Added
13+
- Implement `embedded_graphics::draw_target::DrawTarget::fill_contiguous` to more improve performance when filling
14+
contiguous regions.
15+
1216
## [0.10.0] - 2025-03-22
1317
### Changed
1418
- Added `DisplaySize64x32` to the prelude

src/mode/buffered_graphics.rs

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,9 @@ where
234234
#[cfg(feature = "graphics")]
235235
use embedded_graphics_core::{
236236
draw_target::DrawTarget,
237-
geometry::Size,
238-
geometry::{Dimensions, OriginDimensions},
237+
geometry::{AnchorX, AnchorY, Dimensions, OriginDimensions, Size},
239238
pixelcolor::BinaryColor,
239+
primitives::Rectangle,
240240
Pixel,
241241
};
242242

@@ -276,6 +276,53 @@ where
276276
.for_each(|Pixel(pos, color)| {
277277
self.set_pixel(pos.x as u32, pos.y as u32, color.is_on());
278278
});
279+
Ok(())
280+
}
281+
282+
fn fill_contiguous<I>(&mut self, area: &Rectangle, pixels: I) -> Result<(), Self::Error>
283+
where
284+
I: IntoIterator<Item = Self::Color>,
285+
{
286+
let area = area.intersection(&self.bounding_box());
287+
let mut pixels = pixels.into_iter();
288+
289+
// Keep track of max and min values
290+
self.mode.min_x = self.mode.min_x.min(area.anchor_x(AnchorX::Left) as u8);
291+
self.mode.max_x = self.mode.max_x.max(area.anchor_x(AnchorX::Right) as u8);
292+
self.mode.min_y = self.mode.min_y.min(area.anchor_y(AnchorY::Top) as u8);
293+
self.mode.max_y = self.mode.max_y.max(area.anchor_y(AnchorY::Bottom) as u8);
294+
295+
let buffer = self.mode.buffer.as_mut();
296+
match self.rotation {
297+
DisplayRotation::Rotate0 | DisplayRotation::Rotate180 => {
298+
for y in area.rows() {
299+
for x in area.columns() {
300+
let Some(color) = pixels.next() else {
301+
return Ok(());
302+
};
303+
let value = color.is_on() as u8;
304+
let idx = ((y as usize) / 8 * SIZE::WIDTH as usize) + (x as usize);
305+
let bit = y % 8;
306+
let byte = &mut buffer[idx];
307+
*byte = *byte & !(1 << bit) | (value << bit);
308+
}
309+
}
310+
}
311+
DisplayRotation::Rotate90 | DisplayRotation::Rotate270 => {
312+
for y in area.rows() {
313+
for x in area.columns() {
314+
let Some(color) = pixels.next() else {
315+
return Ok(());
316+
};
317+
let value = color.is_on() as u8;
318+
let idx = ((x as usize) / 8 * SIZE::WIDTH as usize) + (y as usize);
319+
let bit = x % 8;
320+
let byte = &mut buffer[idx];
321+
*byte = *byte & !(1 << bit) | (value << bit);
322+
}
323+
}
324+
}
325+
};
279326

280327
Ok(())
281328
}

0 commit comments

Comments
 (0)