pub trait DrawTarget<C>where
C: PixelColor,{
type Error;
// Required methods
fn draw_pixel(&mut self, item: Pixel<C>) -> Result<(), Self::Error>;
fn size(&self) -> Size;
// Provided methods
fn draw_iter<T>(&mut self, item: T) -> Result<(), Self::Error>
where T: IntoIterator<Item = Pixel<C>> { ... }
fn clear(&mut self, color: C) -> Result<(), Self::Error>
where Self: Sized { ... }
fn draw_line(
&mut self,
item: &Styled<Line, PrimitiveStyle<C>>,
) -> Result<(), Self::Error> { ... }
fn draw_triangle(
&mut self,
item: &Styled<Triangle, PrimitiveStyle<C>>,
) -> Result<(), Self::Error> { ... }
fn draw_rectangle(
&mut self,
item: &Styled<Rectangle, PrimitiveStyle<C>>,
) -> Result<(), Self::Error> { ... }
fn draw_circle(
&mut self,
item: &Styled<Circle, PrimitiveStyle<C>>,
) -> Result<(), Self::Error> { ... }
fn draw_image<'a, 'b, I>(
&mut self,
item: &'a Image<'b, I, C>,
) -> Result<(), Self::Error>
where &'b I: IntoPixelIter<C>,
I: ImageDimensions,
C: PixelColor + From<<C as PixelColor>::Raw> { ... }
}
Expand description
Defines a display that can be used to render Drawable
objects.
To to add embedded-graphics support to a display driver, DrawTarget
must be implemented. Once
a DrawTarget
is defined, it can be used to render Drawable
s. Note that any iterator over
Pixel
s can be drawn as Drawable
is implemented for Iterator<Item = Pixel<C: PixelColor>>
. See the Drawable
trait documentation for more details.
DrawTarget
provides default implementations of methods to draw primitive
s and clear the
display which delegate to DrawTarget::draw_iter
. If the target display supports accelerated
drawing commands, these methods can be overridden with specialised implementations that take
advantage of the hardware to speed up drawing operations.
Note that some displays require a “flush” operation to write changes from a framebuffer to the display. See docs associated with the chosen display driver for details on how to update the display.
§Examples
§Implement DrawTarget
for an 8 bit grayscale display
This example uses an imaginary display that has a 64x64px framebuffer of 8 bit values that is sent to the display over a (simplified) SPI interface.
use core::convert::TryInto;
use embedded_graphics::{
drawable::Pixel,
egcircle,
geometry::Size,
pixelcolor::{Gray8, GrayColor},
prelude::*,
primitive_style, DrawTarget,
};
/// A fake 64px x 64px display where each pixel is stored as a single `u8`
struct ExampleDisplay {
framebuffer: [u8; 64 * 64],
iface: SPI1,
}
impl ExampleDisplay {
/// Send buffer to the display
pub fn flush(&self) -> Result<(), ()> {
self.iface.send_bytes(&self.framebuffer)
}
}
impl DrawTarget<Gray8> for ExampleDisplay {
type Error = core::convert::Infallible;
/// Draw a `Pixel` that has a color defined as `Gray8`.
fn draw_pixel(&mut self, pixel: Pixel<Gray8>) -> Result<(), Self::Error> {
let Pixel(coord, color) = pixel;
// Place an (x, y) pixel at the right index in the framebuffer. If the pixel coordinates
// are out of bounds (negative or greater than (63, 63)), this operation will be a
// noop.
if let Ok((x @ 0..=63, y @ 0..=63)) = coord.try_into() {
let index: u32 = x + y * 64;
self.framebuffer[index as usize] = color.luma();
}
Ok(())
}
fn size(&self) -> Size {
Size::new(64, 64)
}
}
let mut display = ExampleDisplay {
framebuffer: [0; 4096],
iface: SPI1,
};
// Draw a circle centered around `(32, 32)` with a radius of `10` and a white stroke
let circle = egcircle!(
center = (32, 32),
radius = 10,
style = primitive_style!(stroke_color = Gray8::WHITE, stroke_width = 1)
);
circle.draw(&mut display)?;
// Update the display
display.flush().expect("Failed to send data to display");
§Hardware Acceleration
In addition to defining draw_pixel
, an implementation of DrawTarget
can also provide
alternative implementations for hardware accelerated drawing operations. This example implements
DrawTarget
for a display without a framebuffer that supports hardware accelerated drawing of
styled Rectangle
s.
The default implementations of draw_rectangle
as well as other shape drawing methods
(draw_circle
, etc) defer to draw_iter
internally. In this example, the default
implementation of draw_rectangle
is overridden to allow usage of accelerated draw commands
specific to the targeted hardware.
As this example doesn’t use a framebuffer, a “flush” operation is not required. All draw
operations are performed in “immediate mode” directly on the display. As each drawing operation
requires communication with the display that may fail, a custom error type CommError
is
introduced.
/// SPI communication error
#[derive(Debug)]
struct CommError;
/// A fake display which uses hardware drawing commands instead of a framebuffer
struct FastExampleDisplay {
iface: SPI1,
}
impl FastExampleDisplay {
/// Draw a rectangle using hardware accelerated commands
pub fn fast_rectangle(
&self,
rect: &Styled<Rectangle, PrimitiveStyle<Gray8>>,
) -> Result<(), CommError> {
// Send rectangle drawing commands to the display
Ok(())
}
}
impl DrawTarget<Gray8> for FastExampleDisplay {
type Error = CommError;
/// Draw a `pixel` that has a color defined as `Gray8`
fn draw_pixel(&mut self, pixel: Pixel<Gray8>) -> Result<(), Self::Error> {
let Pixel(coord, color) = pixel;
// Send commands directly to the display to set an individual pixel to the given color
Ok(())
}
fn size(&self) -> Size {
Size::new(64, 64)
}
/// Use the accelerated method when drawing rectangles
///
/// This method overrides the default implementation. If `fast_rectangle()` fails, the error
/// will be propagated through this method.
fn draw_rectangle(
&mut self,
item: &Styled<Rectangle, PrimitiveStyle<Gray8>>,
) -> Result<(), Self::Error> {
self.fast_rectangle(item)
}
}
let mut display = FastExampleDisplay { iface: SPI1 };
// Draw a rectangle from (10, 20) to (30, 40) with a white stroke
let rect = egrectangle!(
top_left = (10, 20),
bottom_right = (30, 40),
style = primitive_style!(stroke_color = Gray8::WHITE, stroke_width = 1)
)
.draw(&mut display)?;
// Draw a rectangle on the display using accelerated `draw_rectangle()` function
Required Associated Types§
Sourcetype Error
type Error
Error type to return when a drawing operation fails.
This error is returned if an error occurred during a drawing operation. This mainly applies
to drivers that need to communicate with the display for each drawing operation, where a
communication error can occur. For drivers that use an internal framebuffer where drawing
operations can never fail, core::convert::Infallible
can instead be used as the Error
type.
Required Methods§
Provided Methods§
Sourcefn draw_iter<T>(&mut self, item: T) -> Result<(), Self::Error>where
T: IntoIterator<Item = Pixel<C>>,
fn draw_iter<T>(&mut self, item: T) -> Result<(), Self::Error>where
T: IntoIterator<Item = Pixel<C>>,
Draws an object from an iterator over its pixels.
Sourcefn clear(&mut self, color: C) -> Result<(), Self::Error>where
Self: Sized,
fn clear(&mut self, color: C) -> Result<(), Self::Error>where
Self: Sized,
Clears the display with the supplied color.
This default implementation can be replaced if the implementing driver provides an accelerated clearing method.
Sourcefn draw_line(
&mut self,
item: &Styled<Line, PrimitiveStyle<C>>,
) -> Result<(), Self::Error>
fn draw_line( &mut self, item: &Styled<Line, PrimitiveStyle<C>>, ) -> Result<(), Self::Error>
Draws a styled line primitive.
This default trait method can be overridden if a display provides hardware-accelerated methods for drawing lines.
§Caution
This method should not be called directly from application code. It is used to define the
internals of the draw
method used for the Styled
Line
primitive. To draw a line,
call draw
on a Styled<Line>
object.
Sourcefn draw_triangle(
&mut self,
item: &Styled<Triangle, PrimitiveStyle<C>>,
) -> Result<(), Self::Error>
fn draw_triangle( &mut self, item: &Styled<Triangle, PrimitiveStyle<C>>, ) -> Result<(), Self::Error>
Draws a styled triangle primitive.
This default trait method can be overridden if a display provides hardware-accelerated methods for drawing triangles.
§Caution
This method should not be called directly from application code. It is used to define the
internals of the draw
method used for the Styled
Triangle
primitive. To draw a
triangle, call draw
on a Styled<Triangle>
object.
Sourcefn draw_rectangle(
&mut self,
item: &Styled<Rectangle, PrimitiveStyle<C>>,
) -> Result<(), Self::Error>
fn draw_rectangle( &mut self, item: &Styled<Rectangle, PrimitiveStyle<C>>, ) -> Result<(), Self::Error>
Draws a styled rectangle primitive.
This default trait method can be overridden if a display provides hardware-accelerated methods for drawing rectangle.
§Caution
This method should not be called directly from application code. It is used to define the
internals of the draw
method used for the Styled
Rectangle
primitive. To draw a
rectangle, call draw
on a Styled<Rectangle>
object.
Sourcefn draw_circle(
&mut self,
item: &Styled<Circle, PrimitiveStyle<C>>,
) -> Result<(), Self::Error>
fn draw_circle( &mut self, item: &Styled<Circle, PrimitiveStyle<C>>, ) -> Result<(), Self::Error>
Draws a styled circle primitive.
This default trait method can be overridden if a display provides hardware-accelerated methods for drawing circles.
§Caution
This method should not be called directly from application code. It is used to define the
internals of the draw
method used for the Styled
Circle
primitive. To draw a
circle, call draw
on a Styled<Circle>
object.
Sourcefn draw_image<'a, 'b, I>(
&mut self,
item: &'a Image<'b, I, C>,
) -> Result<(), Self::Error>
fn draw_image<'a, 'b, I>( &mut self, item: &'a Image<'b, I, C>, ) -> Result<(), Self::Error>
Draws an image with known size
This default trait method can be overridden if a display provides hardware-accelerated methods for drawing an image with known size.
§Caution
This method should not be called directly from application code. It is used to define the
internals of the draw
method used for the Image
primitive. To draw an
image, call draw
on a Image
object.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.