mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-24 14:20:57 +00:00
refactor(core): make imagebuffer allocation fallible
This commit is contained in:
parent
83a96f7a5a
commit
e424fd8d3b
@ -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,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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),
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user