1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-22 06:18:07 +00:00

feat(core): implement loaders for T2B1

[no changelog]
This commit is contained in:
tychovrahe 2023-01-12 17:55:33 +01:00 committed by TychoVrahe
parent 52cd43bf29
commit 9aa8662ba9
6 changed files with 190 additions and 61 deletions

View File

@ -3,7 +3,6 @@ use crate::ui::{
display::Color,
geometry::{Offset, Point, Rect},
};
use core::slice::from_raw_parts;
#[cfg(feature = "dma2d")]
use crate::trezorhal::{
@ -16,9 +15,6 @@ use crate::ui::{
display::toif::Icon,
};
pub const LOADER_MIN: u16 = 0;
pub const LOADER_MAX: u16 = 1000;
const LOADER_SIZE: i32 = (LOADER_OUTER * 2.0) as i32;
const OUTER: f32 = constant::LOADER_OUTER;
@ -32,7 +28,7 @@ const INNER_OUTER_ANTI: i32 = ((INNER + 2.5) * (INNER + 2.5)) as i32;
const OUTER_OUT_ANTI: i32 = ((OUTER - 1.5) * (OUTER - 1.5)) as i32;
const OUTER_MAX: i32 = ((OUTER - 0.5) * (OUTER - 0.5)) as i32;
pub fn loader_uncompress(
pub fn loader_circular_uncompress(
y_offset: i16,
fg_color: Color,
bg_color: Color,
@ -47,7 +43,7 @@ pub fn loader_uncompress(
if toif_size.x <= ICON_MAX_SIZE && toif_size.y <= ICON_MAX_SIZE {
let mut icon_data = [0_u8; ((ICON_MAX_SIZE * ICON_MAX_SIZE) / 2) as usize];
icon.toif.uncompress(&mut icon_data);
let i = Some((icon, color, toif_size));
let i = Some((icon_data.as_ref(), color, toif_size));
loader_rust(y_offset, fg_color, bg_color, progress, indeterminate, i);
} else {
loader_rust(y_offset, fg_color, bg_color, progress, indeterminate, None);
@ -57,29 +53,24 @@ pub fn loader_uncompress(
}
}
#[no_mangle]
pub extern "C" fn loader_uncompress_r(
y_offset: cty::int32_t,
fg_color: cty::uint16_t,
bg_color: cty::uint16_t,
icon_color: cty::uint16_t,
progress: cty::int32_t,
indeterminate: cty::int32_t,
icon_data: cty::uintptr_t,
icon_data_size: cty::uint32_t,
pub fn loader_circular(
progress: u16,
y_offset: i16,
fg_color: Color,
bg_color: Color,
icon: Option<(Icon, Color)>,
) {
let fg = Color::from_u16(fg_color);
let bg = Color::from_u16(bg_color);
let ic_color = Color::from_u16(icon_color);
loader_circular_uncompress(y_offset, fg_color, bg_color, progress, false, icon);
}
let i = if icon_data != 0 {
let data_slice = unsafe { from_raw_parts(icon_data as _, icon_data_size as _) };
Some((Icon::new(data_slice), ic_color))
} else {
None
};
loader_uncompress(y_offset as _, fg, bg, progress as _, indeterminate != 0, i);
pub fn loader_circular_indeterminate(
progress: u16,
y_offset: i16,
fg_color: Color,
bg_color: Color,
icon: Option<(Icon, Color)>,
) {
loader_circular_uncompress(y_offset, fg_color, bg_color, progress, true, icon);
}
#[inline(always)]
@ -189,7 +180,7 @@ pub fn loader_rust(
bg_color: Color,
progress: u16,
indeterminate: bool,
icon: Option<(Icon, Color, Offset)>,
icon: Option<(&[u8], Color, Offset)>,
) {
let center = screen().center() + Offset::new(0, y_offset);
let r = Rect::from_center_and_size(center, Offset::uniform(LOADER_OUTER as i16 * 2));
@ -205,14 +196,14 @@ pub fn loader_rust(
let mut icon_area = Rect::zero();
let mut icon_area_clamped = Rect::zero();
let mut icon_width = 0;
let mut icon_data = None;
let mut icon_data = [].as_ref();
if let Some((data, color, size)) = icon {
if size.x <= ICON_MAX_SIZE && size.y <= ICON_MAX_SIZE {
icon_width = size.x;
icon_area = Rect::from_center_and_size(center, size);
icon_area_clamped = icon_area.clamp(constant::screen());
icon_data = Some(data);
icon_data = data;
use_icon = true;
icon_colortable = display::get_color_table(color, bg_color);
}
@ -238,8 +229,7 @@ pub fn loader_rust(
let x_i = x_c - icon_area.x0;
let y_i = y_c - icon_area.y0;
let data = unwrap!(icon_data).zdata()
[(((x_i & 0xFE) + (y_i * icon_width)) / 2) as usize];
let data = icon_data[(((x_i & 0xFE) + (y_i * icon_width)) / 2) as usize];
if (x_i & 0x01) == 0 {
underlying_color = icon_colortable[(data & 0xF) as usize];
} else {
@ -270,7 +260,7 @@ pub fn loader_rust(
bg_color: Color,
progress: u16,
indeterminate: bool,
icon: Option<(Icon, Color, Offset)>,
icon: Option<(&[u8], Color, Offset)>,
) {
let center = screen().center() + Offset::new(0, y_offset);
let r = Rect::from_center_and_size(center, Offset::uniform(LOADER_OUTER as i16 * 2));
@ -285,16 +275,16 @@ pub fn loader_rust(
let mut icon_width = 0;
let mut icon_offset = 0;
let mut icon_color = Color::from_u16(0);
let mut icon_data = None;
let mut icon_data = [].as_ref();
if let Some((icon, color, size)) = icon {
if let Some((data, color, size)) = icon {
if size.x <= ICON_MAX_SIZE && size.y <= ICON_MAX_SIZE {
icon_width = size.x;
icon_area = Rect::from_center_and_size(center, size);
icon_area_clamped = icon_area.clamp(constant::screen());
icon_offset = (icon_area_clamped.x0 - r.x0) / 2;
icon_color = color;
icon_data = Some(icon);
icon_data = data;
use_icon = true;
}
}
@ -338,7 +328,7 @@ pub fn loader_rust(
icon_buffer_used.buffer[icon_offset as usize..(icon_offset + icon_width / 2) as usize]
.copy_from_slice(
&unwrap!(icon_data).toif.zdata()[(y_i * (icon_width / 2)) as usize
&icon_data[(y_i * (icon_width / 2)) as usize
..((y_i + 1) * (icon_width / 2)) as usize],
);
icon_buffer = icon_buffer_used;
@ -371,23 +361,3 @@ pub fn loader_rust(
dma2d_wait_for_transfer();
}
pub fn loader(
progress: u16,
y_offset: i16,
fg_color: Color,
bg_color: Color,
icon: Option<(Icon, Color)>,
) {
loader_uncompress(y_offset, fg_color, bg_color, progress, false, icon);
}
pub fn loader_indeterminate(
progress: u16,
y_offset: i16,
fg_color: Color,
bg_color: Color,
icon: Option<(Icon, Color)>,
) {
loader_uncompress(y_offset, fg_color, bg_color, progress, true, icon);
}

View File

@ -0,0 +1,68 @@
mod circular;
mod rectangular;
mod starry;
use crate::ui::display::{Color, Icon};
use core::slice::from_raw_parts;
#[cfg(feature = "model_tt")]
use crate::ui::display::loader::circular::{
loader_circular as determinate, loader_circular_indeterminate as indeterminate,
};
#[cfg(not(feature = "model_tt"))]
use crate::ui::display::loader::rectangular::loader_rectangular as determinate;
#[cfg(not(feature = "model_tt"))]
use crate::ui::display::loader::starry::loader_starry_indeterminate as indeterminate;
pub const LOADER_MIN: u16 = 0;
pub const LOADER_MAX: u16 = 1000;
pub fn loader(
progress: u16,
y_offset: i16,
fg_color: Color,
bg_color: Color,
icon: Option<(Icon, Color)>,
) {
determinate(progress, y_offset, fg_color, bg_color, icon);
}
pub fn loader_indeterminate(
progress: u16,
y_offset: i16,
fg_color: Color,
bg_color: Color,
icon: Option<(Icon, Color)>,
) {
indeterminate(progress, y_offset, fg_color, bg_color, icon);
}
//TODO: remove when loader is no longer called from C
#[no_mangle]
pub extern "C" fn loader_uncompress_r(
y_offset: cty::int32_t,
fg_color: cty::uint16_t,
bg_color: cty::uint16_t,
icon_color: cty::uint16_t,
progress: cty::int32_t,
indeterminate: cty::int32_t,
icon_data: cty::uintptr_t,
icon_data_size: cty::uint32_t,
) {
let fg = Color::from_u16(fg_color);
let bg = Color::from_u16(bg_color);
let ic_color = Color::from_u16(icon_color);
let i = if icon_data != 0 {
let data_slice = unsafe { from_raw_parts(icon_data as _, icon_data_size as _) };
Some((Icon::new(data_slice), ic_color))
} else {
None
};
if indeterminate == 0 {
loader(progress as _, y_offset as _, fg, bg, i);
} else {
loader_indeterminate(progress as _, y_offset as _, fg, bg, i);
}
}

View File

@ -0,0 +1,25 @@
use crate::ui::{
constant::{screen, LOADER_INNER},
display,
display::{Color, Icon},
geometry::{Offset, Rect},
};
pub fn loader_rectangular(
progress: u16,
y_offset: i16,
fg_color: Color,
bg_color: Color,
icon: Option<(Icon, Color)>,
) {
let area = Rect::from_center_and_size(screen().center(), Offset::uniform(LOADER_INNER as _))
.translate(Offset::y(y_offset));
display::rect_rounded2_partial(
area,
fg_color,
bg_color,
(100 * progress as u32 / 1000) as i16,
icon,
);
}

View File

@ -0,0 +1,67 @@
use crate::ui::{
constant::{screen, LOADER_OUTER},
display::{rect_fill, rect_fill_rounded, rect_fill_rounded1, Color, Icon},
geometry::{Offset, Point, Rect, CENTER},
};
use core::f32::consts::SQRT_2;
const SIZE_SMALL: i16 = 2;
const SIZE_MEDIUM: i16 = 4;
const SIZE_LARGE: i16 = 6;
const RADIUS: i16 = 13;
const DIAGONAL: i16 = ((RADIUS as f32 * SQRT_2) / 2_f32) as i16;
fn star_small(center: Point, fg: Color, _bg: Color) {
let r = Rect::from_center_and_size(center, Offset::uniform(SIZE_SMALL));
rect_fill(r, fg);
}
fn star_medium(center: Point, fg: Color, bg: Color) {
let r = Rect::from_center_and_size(center, Offset::uniform(SIZE_MEDIUM));
rect_fill_rounded1(r, fg, bg);
}
fn star_large(center: Point, fg: Color, bg: Color) {
let r = Rect::from_center_and_size(center, Offset::uniform(SIZE_LARGE));
rect_fill_rounded(r, fg, bg, 2);
}
pub fn loader_starry_indeterminate(
progress: u16,
y_offset: i16,
fg_color: Color,
bg_color: Color,
icon: Option<(Icon, Color)>,
) {
let area = Rect::from_center_and_size(screen().center(), Offset::uniform(LOADER_OUTER as _))
.translate(Offset::y(y_offset));
rect_fill(area, bg_color);
let coords = [
Point::new(area.center().x, area.center().y - RADIUS),
Point::new(area.center().x + DIAGONAL, area.center().y - DIAGONAL),
Point::new(area.center().x + RADIUS, area.center().y),
Point::new(area.center().x + DIAGONAL, area.center().y + DIAGONAL),
Point::new(area.center().x, area.center().y + RADIUS),
Point::new(area.center().x - DIAGONAL, area.center().y + DIAGONAL),
Point::new(area.center().x - RADIUS, area.center().y),
Point::new(area.center().x - DIAGONAL, area.center().y - DIAGONAL),
];
let big_idx = (progress / 125) as usize % 8;
for (i, c) in coords.iter().enumerate() {
if i == big_idx {
star_large(*c, fg_color, bg_color);
} else if (big_idx + 1) % 8 == i || (big_idx - 1) % 8 == i {
star_medium(*c, fg_color, bg_color);
} else {
star_small(*c, fg_color, bg_color);
}
}
if let Some((icon, color)) = icon {
icon.draw(area.center(), CENTER, color, bg_color);
}
}

View File

@ -1,4 +1,3 @@
#[cfg(any(feature = "model_tt", feature = "model_tr"))]
pub mod loader;
#[cfg(feature = "jpeg")]
pub mod tjpgd;

View File

@ -5,9 +5,9 @@ pub const HEIGHT: i16 = 128;
pub const LINE_SPACE: i16 = 1;
pub const FONT_BPP: i16 = 1;
pub const LOADER_OUTER: f32 = 20_f32;
pub const LOADER_INNER: f32 = 14_f32;
pub const LOADER_ICON_MAX_SIZE: i16 = 24;
pub const LOADER_OUTER: f32 = 32_f32;
pub const LOADER_INNER: f32 = 18_f32;
pub const LOADER_ICON_MAX_SIZE: i16 = 8;
pub const fn size() -> Offset {
Offset::new(WIDTH, HEIGHT)