mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-26 17:38:39 +00:00
feat(core/rust): introduce ImageBuffer for advanced drawing
[no changelog]
This commit is contained in:
parent
001acc770c
commit
89ae44ebfa
@ -5,7 +5,7 @@ use crate::ui::{
|
||||
|
||||
use super::super::{
|
||||
utils::{circle_points, line_points, sin_f32},
|
||||
BitmapView, Viewport,
|
||||
Bitmap, BitmapFormat, BitmapView, Viewport,
|
||||
};
|
||||
|
||||
#[cfg(feature = "ui_blurring")]
|
||||
@ -71,6 +71,16 @@ pub trait BasicCanvas {
|
||||
fn draw_bitmap(&mut self, r: Rect, bitmap: BitmapView);
|
||||
}
|
||||
|
||||
pub trait CanvasBuilder<'a> {
|
||||
/// Returns a format of the underlying bitmap.
|
||||
fn format() -> BitmapFormat;
|
||||
|
||||
/// Creates a new canvas from the specified bitmap.
|
||||
///
|
||||
/// The bitmap must be mutable and have the same format as the canvas.
|
||||
fn from_bitmap(bitmap: Bitmap<'a>) -> Self;
|
||||
}
|
||||
|
||||
pub trait Canvas: BasicCanvas {
|
||||
/// Returns a non-mutable view of the underlying bitmap.
|
||||
fn view(&self) -> BitmapView;
|
||||
|
@ -4,7 +4,7 @@ mod rgb565;
|
||||
mod rgba8888;
|
||||
mod viewport;
|
||||
|
||||
pub use common::{BasicCanvas, Canvas};
|
||||
pub use common::{BasicCanvas, Canvas, CanvasBuilder};
|
||||
pub use mono8::Mono8Canvas;
|
||||
pub use rgb565::Rgb565Canvas;
|
||||
pub use rgba8888::Rgba8888Canvas;
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
|
||||
use super::{
|
||||
super::{Bitmap, BitmapFormat, BitmapView},
|
||||
BasicCanvas, Canvas, Viewport,
|
||||
BasicCanvas, Canvas, CanvasBuilder, Viewport,
|
||||
};
|
||||
|
||||
#[cfg(feature = "ui_blurring")]
|
||||
@ -74,6 +74,18 @@ impl<'a> BasicCanvas for Mono8Canvas<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> CanvasBuilder<'a> for Mono8Canvas<'a> {
|
||||
fn format() -> BitmapFormat {
|
||||
BitmapFormat::MONO8
|
||||
}
|
||||
|
||||
fn from_bitmap(bitmap: Bitmap<'a>) -> Self {
|
||||
assert!(bitmap.format() == Self::format());
|
||||
let viewport = Viewport::from_size(bitmap.size());
|
||||
Self { bitmap, viewport }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Canvas for Mono8Canvas<'a> {
|
||||
fn view(&self) -> BitmapView {
|
||||
BitmapView::new(&self.bitmap)
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
|
||||
use super::{
|
||||
super::{Bitmap, BitmapFormat, BitmapView},
|
||||
BasicCanvas, Canvas, Viewport,
|
||||
BasicCanvas, Canvas, CanvasBuilder, Viewport,
|
||||
};
|
||||
|
||||
#[cfg(feature = "ui_blurring")]
|
||||
@ -74,6 +74,18 @@ impl<'a> BasicCanvas for Rgb565Canvas<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> CanvasBuilder<'a> for Rgb565Canvas<'a> {
|
||||
fn format() -> BitmapFormat {
|
||||
BitmapFormat::RGB565
|
||||
}
|
||||
|
||||
fn from_bitmap(bitmap: Bitmap<'a>) -> Self {
|
||||
assert!(bitmap.format() == Self::format());
|
||||
let viewport = Viewport::from_size(bitmap.size());
|
||||
Self { bitmap, viewport }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Canvas for Rgb565Canvas<'a> {
|
||||
fn view(&self) -> BitmapView {
|
||||
BitmapView::new(&self.bitmap)
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
|
||||
use super::{
|
||||
super::{Bitmap, BitmapFormat, BitmapView},
|
||||
BasicCanvas, Canvas, Viewport,
|
||||
BasicCanvas, Canvas, CanvasBuilder, Viewport,
|
||||
};
|
||||
|
||||
#[cfg(feature = "ui_blurring")]
|
||||
@ -74,6 +74,18 @@ impl<'a> BasicCanvas for Rgba8888Canvas<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> CanvasBuilder<'a> for Rgba8888Canvas<'a> {
|
||||
fn format() -> BitmapFormat {
|
||||
BitmapFormat::RGBA8888
|
||||
}
|
||||
|
||||
fn from_bitmap(bitmap: Bitmap<'a>) -> Self {
|
||||
assert!(bitmap.format() == Self::format());
|
||||
let viewport = Viewport::from_size(bitmap.size());
|
||||
Self { bitmap, viewport }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Canvas for Rgba8888Canvas<'a> {
|
||||
fn view(&self) -> BitmapView {
|
||||
BitmapView::new(&self.bitmap)
|
||||
|
@ -21,7 +21,9 @@ pub use bitmap::{Bitmap, BitmapFormat, BitmapView};
|
||||
#[cfg(feature = "ui_blurring")]
|
||||
pub use blur::Blurring;
|
||||
pub use cache::drawing_cache::DrawingCache;
|
||||
pub use canvas::{BasicCanvas, Canvas, Mono8Canvas, Rgb565Canvas, Rgba8888Canvas, Viewport};
|
||||
pub use canvas::{
|
||||
BasicCanvas, Canvas, CanvasBuilder, Mono8Canvas, Rgb565Canvas, Rgba8888Canvas, Viewport,
|
||||
};
|
||||
pub use circle::Circle;
|
||||
pub use display::render_on_display;
|
||||
#[cfg(feature = "ui_jpeg_decoder")]
|
||||
@ -30,4 +32,4 @@ pub use qrcode::QrImage;
|
||||
pub use render::{DirectRenderer, ProgressiveRenderer, Renderer};
|
||||
pub use text::Text;
|
||||
pub use toif::ToifImage;
|
||||
pub use utils::PI4;
|
||||
pub use utils::ImageBuffer;
|
||||
|
83
core/embed/rust/src/ui/shape/utils/imagebuf.rs
Normal file
83
core/embed/rust/src/ui/shape/utils/imagebuf.rs
Normal file
@ -0,0 +1,83 @@
|
||||
use crate::ui::{
|
||||
geometry::Offset,
|
||||
shape::{Bitmap, BitmapView, Canvas, CanvasBuilder},
|
||||
};
|
||||
|
||||
/// Size of image buffer in bytes
|
||||
const IMAGE_BUFFER_SIZE: usize = 64 * 1024;
|
||||
|
||||
#[repr(align(16))]
|
||||
struct AlignedBuffer {
|
||||
bytes: [u8; IMAGE_BUFFER_SIZE],
|
||||
}
|
||||
|
||||
/// Raw image buffer used by `ImageBuffer` instances.
|
||||
|
||||
static mut IMAGE_BUFFER: AlignedBuffer = AlignedBuffer {
|
||||
bytes: [0; IMAGE_BUFFER_SIZE],
|
||||
};
|
||||
|
||||
/// Set to `true` if the `IMAGE_BUFFER` is locked
|
||||
/// (in use by some instance of `ImageBuffer`)
|
||||
static mut IMAGE_BUFFER_LOCKED: bool = false;
|
||||
|
||||
/// A struct representing an image buffer - generic buffer for mutable images.
|
||||
pub struct ImageBuffer<T: Canvas + CanvasBuilder<'static>> {
|
||||
canvas: T,
|
||||
}
|
||||
|
||||
impl<T> Drop for ImageBuffer<T>
|
||||
where
|
||||
T: Canvas + CanvasBuilder<'static>,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
// It's safe to modify static variable as whole app
|
||||
// is single-threaded.
|
||||
unsafe {
|
||||
IMAGE_BUFFER_LOCKED = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ImageBuffer<T>
|
||||
where
|
||||
T: Canvas + CanvasBuilder<'static>,
|
||||
{
|
||||
/// Creates a new image buffer with the specified format and size.
|
||||
///
|
||||
/// Returns `None` if the buffer is already in use or the
|
||||
/// buffer is not big enough to hold the image.
|
||||
pub fn new(size: Offset) -> Option<Self> {
|
||||
// SAFETY:
|
||||
// It's safe to read/modify mutable static variable as
|
||||
// whole app is single-threaded.
|
||||
//
|
||||
// We can be sure that `IMAGE_BUFFER` is not shared between
|
||||
// multiple instances of `ImageBuffer` as we have `IMAGE_BUFFER_LOCKED`
|
||||
// to prevent that.
|
||||
unsafe {
|
||||
if IMAGE_BUFFER_LOCKED {
|
||||
return None;
|
||||
}
|
||||
|
||||
let bitmap =
|
||||
Bitmap::new_mut(T::format(), None, size, None, &mut IMAGE_BUFFER.bytes[..])?;
|
||||
|
||||
IMAGE_BUFFER_LOCKED = true;
|
||||
|
||||
Some(Self {
|
||||
canvas: T::from_bitmap(bitmap),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the canvas for the bitmap in the image buffer.
|
||||
pub fn canvas(&mut self) -> &mut T {
|
||||
&mut self.canvas
|
||||
}
|
||||
|
||||
/// Returns the immutable view of the bitmap in the image buffer.
|
||||
pub fn view(&self) -> BitmapView {
|
||||
self.canvas.view()
|
||||
}
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
mod blur;
|
||||
mod circle;
|
||||
mod imagebuf;
|
||||
mod line;
|
||||
mod trigo;
|
||||
|
||||
pub use blur::{BlurAlgorithm, BlurBuff};
|
||||
pub use circle::circle_points;
|
||||
pub use imagebuf::ImageBuffer;
|
||||
pub use line::line_points;
|
||||
pub use trigo::sin_f32;
|
||||
|
Loading…
Reference in New Issue
Block a user