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:

```rust
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.

[`embedded-graphics-core`]: https://docs.rs/embedded-graphics-core
[`DrawTarget`]: https://docs.rs/embedded-graphics-core/latest/embedded_graphics_core/draw_target/trait.DrawTarget.html