mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-08-01 19:38:33 +00:00
feat(core/rust): introduce unlock-screen animated overlay
[no changelog]
This commit is contained in:
parent
257495aff7
commit
20392ea22c
@ -14,6 +14,7 @@ mod rawimage;
|
||||
mod render;
|
||||
mod text;
|
||||
mod toif;
|
||||
mod unlock_overlay;
|
||||
mod utils;
|
||||
|
||||
pub use bar::Bar;
|
||||
@ -34,4 +35,5 @@ pub use rawimage::RawImage;
|
||||
pub use render::{DirectRenderer, ProgressiveRenderer, Renderer};
|
||||
pub use text::Text;
|
||||
pub use toif::ToifImage;
|
||||
pub use unlock_overlay::UnlockOverlay;
|
||||
pub use utils::ImageBuffer;
|
||||
|
116
core/embed/rust/src/ui/shape/unlock_overlay.rs
Normal file
116
core/embed/rust/src/ui/shape/unlock_overlay.rs
Normal file
@ -0,0 +1,116 @@
|
||||
use crate::ui::{
|
||||
display::Color,
|
||||
geometry::{Offset, Point, Rect},
|
||||
};
|
||||
|
||||
use super::{Canvas, DrawingCache, Mono8Canvas, Renderer, Shape, ShapeClone};
|
||||
|
||||
use without_alloc::alloc::LocalAllocLeakExt;
|
||||
|
||||
/// A special shape for rendering 7 differently rotated circular
|
||||
/// sectors on 5 concentric circles, used as an overlay on the background
|
||||
/// image on the lock screen.
|
||||
///
|
||||
/// The overlay covers area of 170x170 pixels (centered at `pos`).
|
||||
pub struct UnlockOverlay {
|
||||
/// Center of the overlay
|
||||
pos: Point,
|
||||
// Angle of the rotation (in degrees)
|
||||
angle: f32,
|
||||
}
|
||||
|
||||
impl UnlockOverlay {
|
||||
/// Outer radius
|
||||
pub const RADIUS: i16 = 85;
|
||||
/// Distance between the circles
|
||||
pub const SPAN: i16 = 10;
|
||||
/// Thickness of the circles
|
||||
pub const THICKNESS: i16 = 4;
|
||||
|
||||
/// Create a new overlay with the given center and rotation angle.
|
||||
pub fn new(pos: Point, angle: f32) -> Self {
|
||||
Self { pos, angle }
|
||||
}
|
||||
|
||||
pub fn render<'a>(self, renderer: &mut impl Renderer<'a>) {
|
||||
renderer.render_shape(self);
|
||||
}
|
||||
|
||||
fn prepare_overlay(&self, canvas: &mut dyn Canvas) {
|
||||
let center = canvas.bounds().center();
|
||||
|
||||
let transp = Color::black();
|
||||
let opaque = Color::white();
|
||||
|
||||
canvas.fill_background(opaque);
|
||||
|
||||
// The most outer circle (with two sectors)
|
||||
let angle = self.angle;
|
||||
let r = Self::RADIUS;
|
||||
canvas.fill_sector(center, r, 0.0 + angle, 140.0 + angle, transp);
|
||||
canvas.fill_sector(center, r, 235.0 + angle, 270.0 + angle, transp);
|
||||
canvas.fill_circle(center, r - Self::THICKNESS, opaque, 255);
|
||||
|
||||
// The second circle (with one sector)
|
||||
let angle = -self.angle - 20.0;
|
||||
let r = Self::RADIUS - Self::SPAN;
|
||||
canvas.fill_sector(center, r, 0.0 + angle, 135.0 + angle, transp);
|
||||
canvas.fill_circle(center, r - Self::THICKNESS, opaque, 255);
|
||||
|
||||
// The third circle (with one sector)
|
||||
let angle = self.angle / 2.0 + 90.0;
|
||||
let r = Self::RADIUS - 2 * Self::SPAN;
|
||||
canvas.fill_sector(center, r, 0.0 + angle, 270.0 + angle, transp);
|
||||
canvas.fill_circle(center, r - Self::THICKNESS, opaque, 255);
|
||||
|
||||
// The fourth circle (with two sectors)
|
||||
let angle = -self.angle / 2.0 + 60.0;
|
||||
let r = Self::RADIUS - 3 * Self::SPAN;
|
||||
canvas.fill_sector(center, r, 0.0 + angle, 110.0 + angle, transp);
|
||||
canvas.fill_sector(center, r, 180.0 + angle, 280.0 + angle, transp);
|
||||
canvas.fill_circle(center, r - Self::THICKNESS, opaque, 255);
|
||||
|
||||
// Innner fixed circle
|
||||
let r = Self::RADIUS - (9 * Self::SPAN) / 2;
|
||||
canvas.fill_circle(center, r, transp, 255);
|
||||
canvas.fill_circle(center, r - Self::THICKNESS, opaque, 255);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Shape<'a> for UnlockOverlay {
|
||||
fn bounds(&self) -> Rect {
|
||||
Rect::new(
|
||||
self.pos - Offset::uniform(Self::RADIUS),
|
||||
self.pos + Offset::uniform(Self::RADIUS + 1),
|
||||
)
|
||||
}
|
||||
|
||||
fn cleanup(&mut self, _cache: &DrawingCache<'a>) {
|
||||
// TODO: inform the cache that we won't use the zlib slot anymore
|
||||
}
|
||||
|
||||
fn draw(&mut self, canvas: &mut dyn Canvas, cache: &DrawingCache<'a>) {
|
||||
let bounds = self.bounds();
|
||||
|
||||
let overlay_buff = &mut unwrap!(cache.image_buff(), "No image buffer");
|
||||
|
||||
let mut overlay_canvas = unwrap!(
|
||||
Mono8Canvas::new(bounds.size(), None, None, &mut overlay_buff[..]),
|
||||
"Too small buffer"
|
||||
);
|
||||
|
||||
self.prepare_overlay(&mut overlay_canvas);
|
||||
|
||||
canvas.blend_bitmap(bounds, overlay_canvas.view().with_fg(Color::black()));
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ShapeClone<'a> for UnlockOverlay {
|
||||
fn clone_at_bump<T>(self, bump: &'a T) -> Option<&'a mut dyn Shape<'a>>
|
||||
where
|
||||
T: LocalAllocLeakExt<'a>,
|
||||
{
|
||||
let clone = bump.alloc_t()?;
|
||||
Some(clone.uninit.init(UnlockOverlay { ..self }))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user