1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-24 06:11:06 +00:00

refactor(core): make imagebuffer allocation fallible

This commit is contained in:
matejcik 2025-01-02 12:38:49 +01:00 committed by matejcik
parent 83a96f7a5a
commit e424fd8d3b
8 changed files with 48 additions and 39 deletions

View File

@ -1,11 +1,11 @@
use crate::{
error::Error,
io::BinaryData,
ui::{
component::{Component, Event, EventCtx, Never},
display::image::ImageInfo,
geometry::{Offset, Point, Rect},
shape,
shape::{render_on_canvas, ImageBuffer, Renderer, Rgb565Canvas},
shape::{self, render_on_canvas, ImageBuffer, Renderer, Rgb565Canvas},
},
};
@ -17,7 +17,7 @@ pub struct CachedJpeg {
}
impl CachedJpeg {
pub fn new(image: BinaryData<'static>, scale: u8) -> Self {
pub fn new(image: BinaryData<'static>, scale: u8) -> Result<Self, Error> {
let size = match ImageInfo::parse(image) {
ImageInfo::Jpeg(info) => {
if info.mcu_height() > 16 {
@ -29,7 +29,7 @@ impl CachedJpeg {
_ => Offset::zero(),
};
let mut buf = unwrap!(ImageBuffer::new(size), "no image buf");
let mut buf = ImageBuffer::new(size)?;
render_on_canvas(buf.canvas(), None, |target| {
shape::JpegImage::new_image(Point::zero(), image)
@ -37,12 +37,12 @@ impl CachedJpeg {
.render(target);
});
Self {
Ok(Self {
area: Rect::zero(),
image_size: size,
jpeg: buf,
scale,
}
})
}
}

View File

@ -1,4 +1,5 @@
use crate::{
error::Error,
io::BinaryData,
strutil::TString,
time::{Duration, Instant, Stopwatch},
@ -432,12 +433,12 @@ impl Homescreen {
label: TString<'static>,
notification: Option<(TString<'static>, u8)>,
hold_to_lock: bool,
) -> Self {
) -> Result<Self, Error> {
let label_width = label.map(|t| theme::TEXT_DEMIBOLD.text_font.text_width(t));
let label_height = label.map(|t| theme::TEXT_DEMIBOLD.text_font.visible_text_height(t));
let image = get_homescreen_image();
let mut buf = unwrap!(ImageBuffer::new(AREA.size()), "no image buf");
let mut buf = ImageBuffer::new(AREA.size())?;
render_on_canvas(buf.canvas(), None, |target| {
if let Some(image) = image {
@ -447,7 +448,7 @@ impl Homescreen {
}
});
Self {
Ok(Self {
label: Label::new(label, Alignment::Center, theme::TEXT_DEMIBOLD).vertically_centered(),
label_width,
label_height,
@ -459,7 +460,7 @@ impl Homescreen {
delay: Timer::new(),
attach_animation: AttachAnimation::default(),
label_anim: HideLabelAnimation::new(label_width),
}
})
}
fn level_to_style(level: u8) -> (Color, Color) {
@ -724,9 +725,13 @@ pub struct Lockscreen {
}
impl Lockscreen {
pub fn new(label: TString<'static>, bootscreen: bool, coinjoin_authorized: bool) -> Self {
pub fn new(
label: TString<'static>,
bootscreen: bool,
coinjoin_authorized: bool,
) -> Result<Self, Error> {
let image = get_homescreen_image();
let mut buf = unwrap!(ImageBuffer::new(AREA.size()), "no image buf");
let mut buf = ImageBuffer::new(AREA.size())?;
render_on_canvas(buf.canvas(), None, |target| {
if let Some(image) = image {
@ -748,7 +753,7 @@ impl Lockscreen {
let label_height = label.map(|t| theme::TEXT_DEMIBOLD.text_font.visible_text_height(t));
Lockscreen {
Ok(Self {
anim: LockscreenAnim::default(),
attach_animation: AttachAnimation::default(),
label: Label::new(label, Alignment::Center, theme::TEXT_DEMIBOLD),
@ -760,7 +765,7 @@ impl Lockscreen {
coinjoin_authorized,
bg_image: buf,
label_anim: HideLabelAnimation::new(label_width),
}
})
}
}

View File

@ -182,7 +182,7 @@ impl FirmwareUI for UIMercury {
return Err(value_error!(c"Invalid image."));
};
flow::confirm_homescreen::new_confirm_homescreen(title, CachedJpeg::new(image, 1))?
flow::confirm_homescreen::new_confirm_homescreen(title, CachedJpeg::new(image, 1)?)?
};
Ok(layout)
}
@ -904,7 +904,7 @@ impl FirmwareUI for UIMercury {
notification_level: u8,
) -> Result<impl LayoutMaybeTrace, Error> {
let notification = notification.map(|w| (w, notification_level));
let layout = RootComponent::new(Homescreen::new(label, notification, hold));
let layout = RootComponent::new(Homescreen::new(label, notification, hold)?);
Ok(layout)
}
@ -958,7 +958,7 @@ impl FirmwareUI for UIMercury {
bootscreen: bool,
coinjoin_authorized: bool,
) -> Result<impl LayoutMaybeTrace, Error> {
let layout = RootComponent::new(Lockscreen::new(label, bootscreen, coinjoin_authorized));
let layout = RootComponent::new(Lockscreen::new(label, bootscreen, coinjoin_authorized)?);
Ok(layout)
}

View File

@ -1,4 +1,4 @@
use crate::trezorhal::bitblt;
use crate::{error::Error, trezorhal::bitblt};
use crate::ui::{display::Color, geometry::Offset};
@ -61,10 +61,8 @@ impl<'a> Bitmap<'a> {
mut size: Offset,
min_height: Option<i16>,
buff: &'a [u8],
) -> Option<Self> {
if size.x < 0 && size.y < 0 {
return None;
}
) -> Result<Self, Error> {
assert!(size.x >= 0 && size.y >= 0);
let min_stride = match format {
BitmapFormat::MONO1 => (size.x + 7) / 8,
@ -101,14 +99,14 @@ impl<'a> Bitmap<'a> {
if max_height >= min_height as usize {
size.y = max_height as i16;
} else {
return None;
return Err(Error::ValueError(c"Buffer too small."));
}
} else {
return None;
return Err(Error::ValueError(c"Buffer too small."));
}
}
Some(Self {
Ok(Self {
ptr: buff.as_ptr() as *mut u8,
stride,
size,
@ -134,10 +132,10 @@ impl<'a> Bitmap<'a> {
size: Offset,
min_height: Option<i16>,
buff: &'a mut [u8],
) -> Option<Self> {
) -> Result<Self, Error> {
let mut bitmap = Self::new(format, stride, size, min_height, buff)?;
bitmap.mutable = true;
Some(bitmap)
Ok(bitmap)
}
/// Returns bitmap width in pixels.

View File

@ -1,4 +1,5 @@
use crate::{
error::Error,
trezorhal::bitblt::{BitBltCopy, BitBltFill},
ui::{
display::Color,
@ -32,10 +33,10 @@ impl<'a> Mono8Canvas<'a> {
stride: Option<usize>,
min_height: Option<i16>,
buff: &'a mut [u8],
) -> Option<Self> {
) -> Result<Self, Error> {
let bitmap = Bitmap::new_mut(BitmapFormat::MONO8, stride, size, min_height, buff)?;
let viewport = Viewport::from_size(bitmap.size());
Some(Self { bitmap, viewport })
Ok(Self { bitmap, viewport })
}
/// Returns the specified row as a mutable slice.

View File

@ -1,4 +1,5 @@
use crate::{
error::Error,
trezorhal::bitblt::{BitBltCopy, BitBltFill},
ui::{
display::Color,
@ -32,10 +33,10 @@ impl<'a> Rgb565Canvas<'a> {
stride: Option<usize>,
min_height: Option<i16>,
buff: &'a mut [u8],
) -> Option<Self> {
) -> Result<Self, Error> {
let bitmap = Bitmap::new_mut(BitmapFormat::RGB565, stride, size, min_height, buff)?;
let viewport = Viewport::from_size(bitmap.size());
Some(Self { bitmap, viewport })
Ok(Self { bitmap, viewport })
}
/// Returns the specified row as a mutable slice.

View File

@ -1,4 +1,5 @@
use crate::{
error::Error,
trezorhal::bitblt::{BitBltCopy, BitBltFill},
ui::{
display::Color,
@ -32,10 +33,10 @@ impl<'a> Rgba8888Canvas<'a> {
stride: Option<usize>,
min_height: Option<i16>,
buff: &'a mut [u8],
) -> Option<Self> {
) -> Result<Self, Error> {
let bitmap = Bitmap::new_mut(BitmapFormat::RGBA8888, stride, size, min_height, buff)?;
let viewport = Viewport::from_size(bitmap.size());
Some(Self { bitmap, viewport })
Ok(Self { bitmap, viewport })
}
/// Returns the specified row as a mutable slice.

View File

@ -1,6 +1,9 @@
use crate::ui::{
geometry::Offset,
shape::{Bitmap, BitmapView, Canvas, CanvasBuilder},
use crate::{
error::Error,
ui::{
geometry::Offset,
shape::{Bitmap, BitmapView, Canvas, CanvasBuilder},
},
};
/// Size of image buffer in bytes
@ -48,7 +51,7 @@ where
///
/// 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> {
pub fn new(size: Offset) -> Result<Self, Error> {
// SAFETY:
// It's safe to read/modify mutable static variable as
// whole app is single-threaded.
@ -58,7 +61,7 @@ where
// to prevent that.
unsafe {
if IMAGE_BUFFER_LOCKED {
return None;
return Err(Error::AllocationFailed);
}
let bitmap =
@ -66,7 +69,7 @@ where
IMAGE_BUFFER_LOCKED = true;
Some(Self {
Ok(Self {
canvas: T::from_bitmap(bitmap),
})
}