embedded-draw-target 0.1.1

Readback and windowed-present capability traits for embedded-graphics draw targets
Documentation

embedded-draw-target

Capability traits that sit one layer above embedded-graphics-core, for draw targets that can do more than accept a stream of pixels.

embedded-graphics-core deliberately models a display as a write-only sink. That is the right lowest common denominator, but it leaves three things unexpressed that in-RAM framebuffers can trivially provide:

Trait Capability Unlocks
PixelRead read a pixel back true alpha blending, analytical anti-aliasing, cross-fades
DirtyTracking report the region touched this frame partial present
WindowedDrawTarget restrict writes to a sub-rectangle pushing only the rows that changed

Every graphics library that wants readback has so far had to define its own trait for it, so a buffer that satisfies one library does not satisfy the next and callers end up writing adapters or maintaining parallel buffers. This crate exists so there is one trait identity to implement, and so an application can point embedded-graphics, a GUI library and a 3D rasterizer at a single buffer.

Transparent to embedded-graphics

These are extension traits with DrawTarget as a supertrait, not a replacement for it. A type that implements them is still an ordinary embedded-graphics target, and every existing Drawable keeps working unchanged:

use embedded_draw_target::PixelRead;
use embedded_graphics::{
    pixelcolor::Rgb565,
    prelude::*,
    primitives::{Circle, PrimitiveStyle},
};
use embedded_graphics_framebuf::FrameBuf;

let mut data = [Rgb565::BLACK; 64 * 64];
let mut fb = FrameBuf::new(&mut data, 64, 64);

// Plain embedded-graphics drawing, unaware of this crate.
Circle::new(Point::new(16, 16), 32)
    .into_styled(PrimitiveStyle::with_fill(Rgb565::RED))
    .draw(&mut fb)?;

// ...and readback on the same buffer, for code that needs it.
assert_eq!(fb.get_pixel(Point::new(32, 32)), Rgb565::RED);
# Ok::<(), core::convert::Infallible>(())

FrameBuf implements PixelRead out of the box via the default framebuf feature.

Contracts worth knowing

  • PixelRead::get_pixel is infallible and must not panic out of bounds; it returns a neutral color (Default::default()) instead. It is called from rasterizer inner loops, so an error path per pixel is not affordable.
  • DirtyTracking implementations may over-report (a bounding box is the normal choice) but must never under-report, or the present step will drop updates.

Feature flags

  • framebuf (default): PixelRead for embedded_graphics_framebuf::FrameBuf.

License

MIT OR Apache-2.0.