1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-03-12 14:16:06 +00:00

feat(eckhart): implement bootloader loader

This commit is contained in:
obrusvit 2025-03-10 18:04:11 +01:00
parent b6f27f3087
commit 942e3953e2
3 changed files with 86 additions and 30 deletions

View File

@ -1,40 +1,96 @@
use crate::ui::{display::Color, geometry::Point, shape, shape::Renderer};
use crate::ui::{
constant::SCREEN,
geometry::{Offset, Rect},
lerp::Lerp,
shape::{self, Renderer},
};
use super::super::constant;
pub enum LoaderRange {
Full,
FromTo(f32, f32),
}
use super::{super::theme::BG, ScreenBorder};
pub fn render_loader<'s>(
center: Point,
inactive_color: Color,
active_color: Color,
background_color: Color,
range: LoaderRange,
progress: u16,
border: &'static ScreenBorder,
target: &mut impl Renderer<'s>,
) {
shape::Circle::new(center, constant::LOADER_OUTER)
.with_bg(inactive_color)
.render(target);
match range {
LoaderRange::Full => {
shape::Circle::new(center, constant::LOADER_OUTER)
.with_bg(active_color)
.render(target);
// convert to ration from 0.0 to 1.0
let progress_ratio = (progress as f32 / 1000.0).clamp(0.0, 1.0);
let (clip, top_gap) = get_clips(progress_ratio);
render_clipped_border(border, clip, top_gap, u8::MAX, target);
}
LoaderRange::FromTo(start, end) => {
shape::Circle::new(center, constant::LOADER_OUTER)
.with_bg(active_color)
.with_start_angle(start)
.with_end_angle(end)
.render(target);
fn get_clips(progress_ratio: f32) -> (Rect, Rect) {
/// Ratio of total_duration for the bottom part of the border
const BOTTOM_DURATION_RATIO: f32 = 0.125;
/// Ratio of total_duration for the side parts of the border
const SIDES_DURATION_RATIO: f32 = 0.5;
/// Ratio of total_duration for the top part of the border
const TOP_DURATION_RATIO: f32 = 0.375;
const TOP_GAP_ZERO: Rect = Rect::from_center_and_size(
SCREEN.top_center().ofs(Offset::y(ScreenBorder::WIDTH / 2)),
Offset::zero(),
);
const TOP_GAP_FULL: Rect = Rect::from_center_and_size(
SCREEN.top_center().ofs(Offset::y(ScreenBorder::WIDTH / 2)),
Offset::new(SCREEN.width(), ScreenBorder::WIDTH),
);
match progress_ratio {
// Bottom phase growing linearly
p if p < BOTTOM_DURATION_RATIO => {
let bottom_progress = (p / BOTTOM_DURATION_RATIO).clamp(0.0, 1.0);
let width = i16::lerp(0, SCREEN.width(), bottom_progress);
let clip = Rect::from_center_and_size(
SCREEN
.bottom_center()
.ofs(Offset::y(-ScreenBorder::WIDTH / 2)),
Offset::new(width, ScreenBorder::WIDTH),
);
(clip, TOP_GAP_FULL)
}
// Sides phase growing up linearly
p if p < (BOTTOM_DURATION_RATIO + SIDES_DURATION_RATIO) => {
let sides_progress =
((p - BOTTOM_DURATION_RATIO) / SIDES_DURATION_RATIO).clamp(0.0, 1.0);
let height = i16::lerp(ScreenBorder::WIDTH, SCREEN.height(), sides_progress);
let clip = Rect::from_bottom_left_and_size(
SCREEN.bottom_left(),
Offset::new(SCREEN.width(), height),
);
(clip, TOP_GAP_FULL)
}
// Top gap shrinking linearly
p if p < 1.0 => {
let top_progress = ((p - BOTTOM_DURATION_RATIO - SIDES_DURATION_RATIO)
/ TOP_DURATION_RATIO)
.clamp(0.0, 1.0);
let width = i16::lerp(SCREEN.width(), 0, top_progress);
let top_gap = Rect::from_center_and_size(
SCREEN.top_center().ofs(Offset::y(ScreenBorder::WIDTH / 2)),
Offset::new(width, ScreenBorder::WIDTH),
);
(SCREEN, top_gap)
}
// Animation complete
_ => (SCREEN, TOP_GAP_ZERO),
}
}
shape::Circle::new(center, constant::LOADER_INNER + 2)
.with_bg(background_color)
fn render_clipped_border<'s>(
border: &'static ScreenBorder,
clip: Rect,
top_gap: Rect,
alpha: u8,
target: &mut impl Renderer<'s>,
) {
target.in_clip(clip, &|target| {
border.render(alpha, target);
});
shape::Bar::new(top_gap)
.with_bg(BG)
.with_fg(BG)
.render(target);
}

View File

@ -1,5 +1,5 @@
mod loader;
mod screen_border;
pub use loader::{render_loader, LoaderRange};
pub use loader::render_loader;
pub use screen_border::ScreenBorder;

View File

@ -17,7 +17,7 @@ pub struct ScreenBorder {
impl ScreenBorder {
pub const WIDTH: i16 = 4;
pub fn new(color: Color) -> Self {
pub const fn new(color: Color) -> Self {
let screen = constant::screen();
// Top bar: from the right edge of top-left icon to the left edge of top-right