From e424fd8d3b841b564e9e7724506b2a59e6b6acc6 Mon Sep 17 00:00:00 2001 From: matejcik Date: Thu, 2 Jan 2025 12:38:49 +0100 Subject: [PATCH] refactor(core): make imagebuffer allocation fallible --- .../rust/src/ui/component/cached_jpeg.rs | 12 +++++------ .../ui/model_mercury/component/homescreen.rs | 21 ++++++++++++------- .../rust/src/ui/model_mercury/ui_firmware.rs | 6 +++--- core/embed/rust/src/ui/shape/bitmap.rs | 18 +++++++--------- core/embed/rust/src/ui/shape/canvas/mono8.rs | 5 +++-- core/embed/rust/src/ui/shape/canvas/rgb565.rs | 5 +++-- .../rust/src/ui/shape/canvas/rgba8888.rs | 5 +++-- .../embed/rust/src/ui/shape/utils/imagebuf.rs | 15 +++++++------ 8 files changed, 48 insertions(+), 39 deletions(-) diff --git a/core/embed/rust/src/ui/component/cached_jpeg.rs b/core/embed/rust/src/ui/component/cached_jpeg.rs index 53f38357b9..a9d3317a56 100644 --- a/core/embed/rust/src/ui/component/cached_jpeg.rs +++ b/core/embed/rust/src/ui/component/cached_jpeg.rs @@ -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 { 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, - } + }) } } diff --git a/core/embed/rust/src/ui/model_mercury/component/homescreen.rs b/core/embed/rust/src/ui/model_mercury/component/homescreen.rs index db19990a41..10ec949ed0 100644 --- a/core/embed/rust/src/ui/model_mercury/component/homescreen.rs +++ b/core/embed/rust/src/ui/model_mercury/component/homescreen.rs @@ -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 { 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 { 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), - } + }) } } diff --git a/core/embed/rust/src/ui/model_mercury/ui_firmware.rs b/core/embed/rust/src/ui/model_mercury/ui_firmware.rs index 716eabdf20..16cda97b65 100644 --- a/core/embed/rust/src/ui/model_mercury/ui_firmware.rs +++ b/core/embed/rust/src/ui/model_mercury/ui_firmware.rs @@ -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 { 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 { - let layout = RootComponent::new(Lockscreen::new(label, bootscreen, coinjoin_authorized)); + let layout = RootComponent::new(Lockscreen::new(label, bootscreen, coinjoin_authorized)?); Ok(layout) } diff --git a/core/embed/rust/src/ui/shape/bitmap.rs b/core/embed/rust/src/ui/shape/bitmap.rs index 067d704c59..e828412dd2 100644 --- a/core/embed/rust/src/ui/shape/bitmap.rs +++ b/core/embed/rust/src/ui/shape/bitmap.rs @@ -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, buff: &'a [u8], - ) -> Option { - if size.x < 0 && size.y < 0 { - return None; - } + ) -> Result { + 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, buff: &'a mut [u8], - ) -> Option { + ) -> Result { let mut bitmap = Self::new(format, stride, size, min_height, buff)?; bitmap.mutable = true; - Some(bitmap) + Ok(bitmap) } /// Returns bitmap width in pixels. diff --git a/core/embed/rust/src/ui/shape/canvas/mono8.rs b/core/embed/rust/src/ui/shape/canvas/mono8.rs index 01e4085e21..d6f60c5092 100644 --- a/core/embed/rust/src/ui/shape/canvas/mono8.rs +++ b/core/embed/rust/src/ui/shape/canvas/mono8.rs @@ -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, min_height: Option, buff: &'a mut [u8], - ) -> Option { + ) -> Result { 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. diff --git a/core/embed/rust/src/ui/shape/canvas/rgb565.rs b/core/embed/rust/src/ui/shape/canvas/rgb565.rs index e5f1892496..a74b5aa139 100644 --- a/core/embed/rust/src/ui/shape/canvas/rgb565.rs +++ b/core/embed/rust/src/ui/shape/canvas/rgb565.rs @@ -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, min_height: Option, buff: &'a mut [u8], - ) -> Option { + ) -> Result { 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. diff --git a/core/embed/rust/src/ui/shape/canvas/rgba8888.rs b/core/embed/rust/src/ui/shape/canvas/rgba8888.rs index 46189c7be1..88eade7667 100644 --- a/core/embed/rust/src/ui/shape/canvas/rgba8888.rs +++ b/core/embed/rust/src/ui/shape/canvas/rgba8888.rs @@ -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, min_height: Option, buff: &'a mut [u8], - ) -> Option { + ) -> Result { 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. diff --git a/core/embed/rust/src/ui/shape/utils/imagebuf.rs b/core/embed/rust/src/ui/shape/utils/imagebuf.rs index cfbc824c87..7565d7937a 100644 --- a/core/embed/rust/src/ui/shape/utils/imagebuf.rs +++ b/core/embed/rust/src/ui/shape/utils/imagebuf.rs @@ -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 { + pub fn new(size: Offset) -> Result { // 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), }) }