From 11808a6f14b52d7dcb88099cd4772be5795b96ce Mon Sep 17 00:00:00 2001 From: Martin Milata Date: Wed, 15 May 2024 21:42:01 +0200 Subject: [PATCH] fix(core): rebase on drawlib --- .../extmod/modtrezorui/modtrezorui-display.h | 4 + .../generated/translated_string.rs | 9 +- .../model_mercury/component/homescreen/mod.rs | 86 +++++++++++-------- .../embed/rust/src/ui/model_mercury/layout.rs | 18 ++-- .../rust/src/ui/shape/corner_highlight.rs | 10 +-- core/src/trezor/ui/layouts/mercury/reset.py | 2 +- core/translations/order.json | 7 +- core/translations/signatures.json | 6 +- 8 files changed, 76 insertions(+), 66 deletions(-) diff --git a/core/embed/extmod/modtrezorui/modtrezorui-display.h b/core/embed/extmod/modtrezorui/modtrezorui-display.h index 2b49e38249..ee7bc030e5 100644 --- a/core/embed/extmod/modtrezorui/modtrezorui-display.h +++ b/core/embed/extmod/modtrezorui/modtrezorui-display.h @@ -170,7 +170,11 @@ STATIC const mp_rom_map_elem_t mod_trezorui_Display_locals_dict_table[] = { {MP_ROM_QSTR(MP_QSTR_FONT_NORMAL), MP_ROM_INT(FONT_NORMAL)}, {MP_ROM_QSTR(MP_QSTR_FONT_DEMIBOLD), MP_ROM_INT(FONT_DEMIBOLD)}, {MP_ROM_QSTR(MP_QSTR_FONT_MONO), MP_ROM_INT(FONT_MONO)}, +#ifdef FONT_BOLD_UPPER {MP_ROM_QSTR(MP_QSTR_FONT_BOLD_UPPER), MP_ROM_INT(FONT_BOLD_UPPER)}, +#else + {MP_ROM_QSTR(MP_QSTR_FONT_BOLD_UPPER), MP_ROM_INT(FONT_BOLD)}, +#endif }; STATIC MP_DEFINE_CONST_DICT(mod_trezorui_Display_locals_dict, mod_trezorui_Display_locals_dict_table); diff --git a/core/embed/rust/src/translations/generated/translated_string.rs b/core/embed/rust/src/translations/generated/translated_string.rs index 0b9e9695c9..a79e554bda 100644 --- a/core/embed/rust/src/translations/generated/translated_string.rs +++ b/core/embed/rust/src/translations/generated/translated_string.rs @@ -1268,10 +1268,9 @@ pub enum TranslatedString { instructions__continue_in_app = 867, // "Continue in the app" words__cancel_and_exit = 868, // "Cancel and exit" address__confirmed = 869, // "Receive address confirmed" - reset__title_shamir_backup = 870, // "Multi-share backup" - pin__cancel_description = 871, // "Continue without PIN" - pin__cancel_info = 872, // "Without a PIN, anyone can access this device." - pin__cancel_setup = 873, // "Cancel PIN setup" + pin__cancel_description = 870, // "Continue without PIN" + pin__cancel_info = 871, // "Without a PIN, anyone can access this device." + pin__cancel_setup = 872, // "Cancel PIN setup" } impl TranslatedString { @@ -2535,7 +2534,6 @@ impl TranslatedString { Self::instructions__continue_in_app => "Continue in the app", Self::words__cancel_and_exit => "Cancel and exit", Self::address__confirmed => "Receive address confirmed", - Self::reset__title_shamir_backup => "Multi-share backup", Self::pin__cancel_description => "Continue without PIN", Self::pin__cancel_info => "Without a PIN, anyone can access this device.", Self::pin__cancel_setup => "Cancel PIN setup", @@ -3803,7 +3801,6 @@ impl TranslatedString { Qstr::MP_QSTR_instructions__continue_in_app => Some(Self::instructions__continue_in_app), Qstr::MP_QSTR_words__cancel_and_exit => Some(Self::words__cancel_and_exit), Qstr::MP_QSTR_address__confirmed => Some(Self::address__confirmed), - Qstr::MP_QSTR_reset__title_shamir_backup => Some(Self::reset__title_shamir_backup), Qstr::MP_QSTR_pin__cancel_description => Some(Self::pin__cancel_description), Qstr::MP_QSTR_pin__cancel_info => Some(Self::pin__cancel_info), Qstr::MP_QSTR_pin__cancel_setup => Some(Self::pin__cancel_setup), diff --git a/core/embed/rust/src/ui/model_mercury/component/homescreen/mod.rs b/core/embed/rust/src/ui/model_mercury/component/homescreen/mod.rs index 33d8e79cf3..69737881ea 100644 --- a/core/embed/rust/src/ui/model_mercury/component/homescreen/mod.rs +++ b/core/embed/rust/src/ui/model_mercury/component/homescreen/mod.rs @@ -1,12 +1,18 @@ use crate::{ - micropython::gc::Gc, + io::BinaryData, strutil::TString, time::{Duration, Instant}, translations::TR, trezorhal::usb::usb_configured, ui::{ component::{Component, Event, EventCtx, TimerToken}, - display::{tjpgd::jpeg_info, toif::Icon, Color, Font}, + display::{ + self, + image::{ImageInfo, ToifFormat}, + tjpgd::jpeg_info, + toif::{Icon, Toif}, + Color, Font, + }, event::{TouchEvent, USBEvent}, geometry::{Alignment, Alignment2D, Insets, Offset, Point, Rect}, layout::util::get_user_custom_image, @@ -37,6 +43,7 @@ const LOADER_DURATION: Duration = Duration::from_millis(2000); pub const HOMESCREEN_IMAGE_WIDTH: i16 = WIDTH; pub const HOMESCREEN_IMAGE_HEIGHT: i16 = HEIGHT; +pub const HOMESCREEN_TOIF_SIZE: i16 = 144; #[derive(Clone, Copy)] pub struct HomescreenNotification { @@ -48,7 +55,7 @@ pub struct HomescreenNotification { pub struct Homescreen { label: TString<'static>, notification: Option<(TString<'static>, u8)>, - custom_image: Option>, + image: BinaryData<'static>, hold_to_lock: bool, loader: Loader, delay: Option, @@ -67,7 +74,7 @@ impl Homescreen { Self { label, notification, - custom_image: get_user_custom_image().ok(), + image: get_homescreen_image(), hold_to_lock, loader: Loader::with_lock_icon().with_durations(LOADER_DURATION, LOADER_DURATION / 3), delay: None, @@ -185,15 +192,14 @@ impl Component for Homescreen { if self.loader.is_animating() || self.loader.is_completely_grown(Instant::now()) { self.render_loader(target); } else { - let img_data = match self.custom_image { - Some(ref img) => img.as_ref(), - None => IMAGE_HOMESCREEN, - }; - - if is_image_jpeg(img_data) { - shape::JpegImage::new(AREA.center(), img_data) + match ImageInfo::parse(self.image) { + ImageInfo::Jpeg(_) => shape::JpegImage::new_image(AREA.center(), self.image) .with_align(Alignment2D::CENTER) - .render(target); + .render(target), + ImageInfo::Toif(_) => shape::ToifImage::new_image(AREA.center(), self.image) + .with_align(Alignment2D::CENTER) + .render(target), + _ => {} } self.label.map(|t| { @@ -271,7 +277,7 @@ impl crate::trace::Trace for Homescreen { pub struct Lockscreen<'a> { label: TString<'a>, - custom_image: Option>, + image: BinaryData<'static>, bootscreen: bool, coinjoin_authorized: bool, } @@ -280,7 +286,7 @@ impl<'a> Lockscreen<'a> { pub fn new(label: TString<'a>, bootscreen: bool, coinjoin_authorized: bool) -> Self { Lockscreen { label, - custom_image: get_user_custom_image().ok(), + image: get_homescreen_image(), bootscreen, coinjoin_authorized, } @@ -306,19 +312,19 @@ impl Component for Lockscreen<'_> { } fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { - let img_data = match self.custom_image { - Some(ref img) => img.as_ref(), - None => IMAGE_HOMESCREEN, - }; + let center = AREA.center(); - let center = constant::screen().center(); - - if is_image_jpeg(img_data) { - shape::JpegImage::new(center, img_data) + match ImageInfo::parse(self.image) { + ImageInfo::Jpeg(_) => shape::JpegImage::new_image(center, self.image) .with_align(Alignment2D::CENTER) .with_blur(4) .with_dim(102) - .render(target); + .render(target), + ImageInfo::Toif(_) => shape::ToifImage::new_image(center, self.image) + .with_align(Alignment2D::CENTER) + //.with_blur(5) + .render(target), + _ => {} } shape::ToifImage::new(center, ICON_LOCKSCREEN_FILTER.toif) @@ -394,24 +400,30 @@ impl Component for Lockscreen<'_> { } } -pub fn check_homescreen_format(buffer: &[u8]) -> bool { - #[cfg(not(feature = "new_rendering"))] - let result = is_image_jpeg(buffer) && crate::ui::display::tjpgd::jpeg_test(buffer); - #[cfg(feature = "new_rendering")] - let result = is_image_jpeg(buffer); // !@# TODO: test like if `new_rendering` is off - - result +pub fn check_homescreen_format(image: BinaryData, accept_toif: bool) -> bool { + match ImageInfo::parse(image) { + ImageInfo::Jpeg(info) => { + info.width() == HOMESCREEN_IMAGE_WIDTH + && info.height() == HOMESCREEN_IMAGE_HEIGHT + && info.mcu_height() <= 16 + } + ImageInfo::Toif(info) => { + accept_toif + && info.width() == HOMESCREEN_TOIF_SIZE + && info.height() == HOMESCREEN_TOIF_SIZE + && info.format() == ToifFormat::FullColorBE + } + _ => false, + } } -fn is_image_jpeg(buffer: &[u8]) -> bool { - let jpeg = jpeg_info(buffer); - if let Some((size, mcu_height)) = jpeg { - if size.x == HOMESCREEN_IMAGE_WIDTH && size.y == HOMESCREEN_IMAGE_HEIGHT && mcu_height <= 16 - { - return true; +fn get_homescreen_image() -> BinaryData<'static> { + if let Ok(image) = get_user_custom_image() { + if check_homescreen_format(image, true) { + return image; } } - false + IMAGE_HOMESCREEN.into() } #[cfg(feature = "ui_debug")] diff --git a/core/embed/rust/src/ui/model_mercury/layout.rs b/core/embed/rust/src/ui/model_mercury/layout.rs index df100680ab..5e498151f0 100644 --- a/core/embed/rust/src/ui/model_mercury/layout.rs +++ b/core/embed/rust/src/ui/model_mercury/layout.rs @@ -2,9 +2,9 @@ use core::{cmp::Ordering, convert::TryInto}; use crate::{ error::Error, + io::BinaryData, micropython::{ - buffer::get_buffer, gc::Gc, iter::IterBuf, list::List, map::Map, module::Module, obj::Obj, - qstr::Qstr, util, + gc::Gc, iter::IterBuf, list::List, map::Map, module::Module, obj::Obj, qstr::Qstr, util, }, strutil::TString, translations::TR, @@ -14,7 +14,7 @@ use crate::{ base::ComponentExt, connect::Connect, image::BlendedImage, - jpeg::{ImageBuffer, Jpeg}, + jpeg::Jpeg, paginated::{PageMsg, Paginate}, text::{ op::OpTextLayout, @@ -26,7 +26,6 @@ use crate::{ }, Border, Component, Empty, FormattedText, Label, Never, Timeout, }, - display::tjpgd::jpeg_info, geometry, layout::{ obj::{ComponentMsgObj, LayoutObj}, @@ -561,15 +560,15 @@ extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *m let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let image: Obj = kwargs.get(Qstr::MP_QSTR_image)?; - let mut jpeg = unwrap!(ImageBuffer::from_object(image)); + let mut jpeg: BinaryData = image.try_into()?; if jpeg.is_empty() { // Incoming data may be empty, meaning we should // display default homescreen image. - jpeg = ImageBuffer::from_slice(theme::IMAGE_HOMESCREEN); + jpeg = theme::IMAGE_HOMESCREEN.into(); } - if jpeg_info(jpeg.data()).is_none() { + if !check_homescreen_format(jpeg, false) { return Err(value_error!("Invalid image.")); }; @@ -1417,9 +1416,8 @@ extern "C" fn new_show_lockscreen(n_args: usize, args: *const Obj, kwargs: *mut pub extern "C" fn upy_check_homescreen_format(data: Obj) -> Obj { let block = || { - let buffer = unsafe { get_buffer(data) }?; - - Ok(check_homescreen_format(buffer).into()) + let buffer = data.try_into()?; + Ok(check_homescreen_format(buffer, false).into()) }; unsafe { util::try_or_raise(block) } diff --git a/core/embed/rust/src/ui/shape/corner_highlight.rs b/core/embed/rust/src/ui/shape/corner_highlight.rs index f25f4ff872..f018f3ea9e 100644 --- a/core/embed/rust/src/ui/shape/corner_highlight.rs +++ b/core/embed/rust/src/ui/shape/corner_highlight.rs @@ -88,7 +88,7 @@ impl CornerHighlight { } impl Shape<'_> for CornerHighlight { - fn bounds(&self, _cache: &DrawingCache) -> Rect { + fn bounds(&self) -> Rect { Rect::snap( self.pos_rect, Offset::uniform(self.length), @@ -103,7 +103,7 @@ impl Shape<'_> for CornerHighlight { let circle_center = self.pos + Offset::uniform(self.r_outer).rotate(self.corner); let circle_visible_part = Rect::snap(self.pos_rect, Offset::uniform(self.r_outer), align); in_clip(canvas, circle_visible_part, &|can| { - can.fill_circle(circle_center, self.r_outer, self.color); + can.fill_circle(circle_center, self.r_outer, self.color, self.alpha); }); // rectangles (rounded) tailing from a corner @@ -146,7 +146,7 @@ impl Shape<'_> for CornerHighlight { self.pos + Offset::uniform(self.thickness + self.r_inner).rotate(self.corner); in_clip(canvas, rect_outer_fill, &|can| { can.fill_rect(rect_outer_fill, self.color, self.alpha); - can.fill_circle(circle_cover_center, self.r_inner, self.bg_color); + can.fill_circle(circle_cover_center, self.r_inner, self.bg_color, self.alpha); }); } @@ -154,9 +154,9 @@ impl Shape<'_> for CornerHighlight { } impl<'s> ShapeClone<'s> for CornerHighlight { - fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape<'s>> + fn clone_at_bump(self, bump: &'s T) -> Option<&'s mut dyn Shape<'s>> where - T: LocalAllocLeakExt<'alloc>, + T: LocalAllocLeakExt<'s>, { let clone = bump.alloc_t::()?; Some(clone.uninit.init(CornerHighlight { ..self })) diff --git a/core/src/trezor/ui/layouts/mercury/reset.py b/core/src/trezor/ui/layouts/mercury/reset.py index a614ddc8b4..eb7cc062e2 100644 --- a/core/src/trezor/ui/layouts/mercury/reset.py +++ b/core/src/trezor/ui/layouts/mercury/reset.py @@ -300,7 +300,7 @@ async def slip39_advanced_prompt_group_threshold(num_of_groups: int) -> int: ) -async def show_warning_backup(slip39: bool) -> None: +async def show_warning_backup() -> None: result = await interact( RustLayout( trezorui2.show_warning( diff --git a/core/translations/order.json b/core/translations/order.json index d0bceef212..6d15f658a3 100644 --- a/core/translations/order.json +++ b/core/translations/order.json @@ -869,8 +869,7 @@ "867": "instructions__continue_in_app", "868": "words__cancel_and_exit", "869": "address__confirmed", - "870": "reset__title_shamir_backup", - "871": "pin__cancel_description", - "872": "pin__cancel_info", - "873": "pin__cancel_setup" + "870": "pin__cancel_description", + "871": "pin__cancel_info", + "872": "pin__cancel_setup" } diff --git a/core/translations/signatures.json b/core/translations/signatures.json index eb1a5e8182..2e93c3afb8 100644 --- a/core/translations/signatures.json +++ b/core/translations/signatures.json @@ -1,8 +1,8 @@ { "current": { - "merkle_root": "9c620dab3212f47d952020e2badc61a9443778fbca180208db622f3d0ebcbe5c", - "datetime": "2024-05-17T10:46:08.576451", - "commit": "cce30d1364fb62e3ed51509fefe7d48c86b45a5c" + "merkle_root": "928438526b993d433d52359d86099848d570c13fbe6aac72a2f5a29a4e8e94c5", + "datetime": "2024-05-17T10:55:04.124405", + "commit": "1409ed27df07827a2a3e3756420db1b41fe108e5" }, "history": [ {