Use embedded-graphics crate to draw shapes and text

This commit is contained in:
Philipp Oppermann
2023-12-29 19:27:56 +01:00
parent 00fa82937a
commit 79f47fda12
4 changed files with 141 additions and 15 deletions

View File

@@ -10,3 +10,4 @@ bench = false
[dependencies]
bootloader_api = "0.11.0"
embedded-graphics = "0.8.1"

View File

@@ -1,4 +1,66 @@
use bootloader_api::info::{FrameBuffer, PixelFormat};
use embedded_graphics::{
draw_target::DrawTarget,
geometry::{self, Point},
pixelcolor::{Rgb888, RgbColor},
Pixel,
};
pub struct Display {
framebuffer: &'static mut FrameBuffer,
}
impl Display {
pub fn new(framebuffer: &'static mut FrameBuffer) -> Display {
Self { framebuffer }
}
fn draw_pixel(&mut self, coordinates: Point, color: Rgb888) {
// ignore any pixels that are out of bounds.
let (width, height) = {
let info = self.framebuffer.info();
(info.width, info.height)
};
let position = match (coordinates.x.try_into(), coordinates.y.try_into()) {
(Ok(x), Ok(y)) if x < width && y < height => Position { x, y },
_ => return, // ignore out-of-bounds pixel
};
let color = Color {
red: color.r(),
green: color.g(),
blue: color.b(),
};
set_pixel_in(self.framebuffer, position, color);
}
}
impl DrawTarget for Display {
type Color = Rgb888;
/// Drawing operations can never fail.
type Error = core::convert::Infallible;
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Pixel<Self::Color>>,
{
for Pixel(coordinates, color) in pixels.into_iter() {
self.draw_pixel(coordinates, color);
}
Ok(())
}
}
impl geometry::OriginDimensions for Display {
fn size(&self) -> geometry::Size {
let info = self.framebuffer.info();
geometry::Size::new(
info.width.try_into().unwrap(),
info.height.try_into().unwrap(),
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Position {

View File

@@ -1,9 +1,18 @@
#![no_std]
#![no_main]
use core::panic::PanicInfo;
use core::{convert::Infallible, panic::PanicInfo};
use bootloader_api::BootInfo;
use embedded_graphics::{
draw_target::DrawTarget,
geometry::Point,
mono_font::{self, MonoTextStyle},
pixelcolor::{Rgb888, RgbColor, WebColors},
primitives::{Circle, PrimitiveStyle, StyledDrawable},
text::Text,
Drawable,
};
mod framebuffer;
@@ -11,20 +20,16 @@ bootloader_api::entry_point!(kernel_main);
fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
if let Some(framebuffer) = boot_info.framebuffer.as_mut() {
let color = framebuffer::Color {
red: 0,
green: 0,
blue: 255,
};
for x in 0..100 {
for y in 0..100 {
let position = framebuffer::Position {
x: 20 + x,
y: 100 + y,
};
framebuffer::set_pixel_in(framebuffer, position, color);
}
}
let mut display = framebuffer::Display::new(framebuffer);
display.clear(Rgb888::RED).unwrap_or_else(infallible);
let style = PrimitiveStyle::with_fill(Rgb888::YELLOW);
Circle::new(Point::new(50, 50), 400)
.draw_styled(&style, &mut display)
.unwrap_or_else(infallible);
let character_style = MonoTextStyle::new(&mono_font::ascii::FONT_10X20, Rgb888::BLUE);
let text = Text::new("Hello, world!", Point::new(190, 250), character_style);
text.draw(&mut display).unwrap_or_else(infallible);
}
loop {}
}
@@ -34,3 +39,7 @@ fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
fn infallible<T>(v: Infallible) -> T {
match v {}
}