mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-08 14:31:06 +00:00
feat(core/rust): introduce unlock-screen animated overlay
[no changelog]
This commit is contained in:
parent
321e4be819
commit
c0b3a2c26b
3
core/embed/rust/src/ui/model_mercury/cshape/mod.rs
Normal file
3
core/embed/rust/src/ui/model_mercury/cshape/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
mod unlock_overlay;
|
||||
|
||||
pub use unlock_overlay::UnlockOverlay;
|
115
core/embed/rust/src/ui/model_mercury/cshape/unlock_overlay.rs
Normal file
115
core/embed/rust/src/ui/model_mercury/cshape/unlock_overlay.rs
Normal file
@ -0,0 +1,115 @@
|
||||
use crate::ui::{
|
||||
display::Color,
|
||||
geometry::{Offset, Point, Rect},
|
||||
shape::{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 }))
|
||||
}
|
||||
}
|
@ -17,6 +17,10 @@ const ZLIB_CACHE_SLOTS: usize = 1;
|
||||
const ZLIB_CACHE_SLOTS: usize = 3;
|
||||
|
||||
const RENDER_BUFF_SIZE: usize = (240 * 2 * 16) + ALIGN_PAD;
|
||||
|
||||
#[cfg(feature = "model_mercury")]
|
||||
const IMAGE_BUFF_SIZE: usize = 32768 + ALIGN_PAD;
|
||||
#[cfg(not(feature = "model_mercury"))]
|
||||
const IMAGE_BUFF_SIZE: usize = 2048 + ALIGN_PAD;
|
||||
|
||||
pub type ImageBuff = [u8; IMAGE_BUFF_SIZE];
|
||||
|
@ -34,4 +34,5 @@ pub use rawimage::RawImage;
|
||||
pub use render::{DirectRenderer, ProgressiveRenderer, Renderer};
|
||||
pub use text::Text;
|
||||
pub use toif::ToifImage;
|
||||
#[cfg(feature = "model_mercury")]
|
||||
pub use utils::ImageBuffer;
|
||||
|
@ -4,6 +4,7 @@ use crate::ui::{
|
||||
};
|
||||
|
||||
/// Size of image buffer in bytes
|
||||
/// (up to 180x180 pixel, 16-bit RGB565 image)
|
||||
const IMAGE_BUFFER_SIZE: usize = 64 * 1024;
|
||||
|
||||
#[repr(align(16))]
|
||||
|
@ -6,6 +6,9 @@ mod trigo;
|
||||
|
||||
pub use blur::{BlurAlgorithm, BlurBuff};
|
||||
pub use circle::circle_points;
|
||||
|
||||
#[cfg(feature = "model_mercury")]
|
||||
pub use imagebuf::ImageBuffer;
|
||||
|
||||
pub use line::line_points;
|
||||
pub use trigo::sin_f32;
|
||||
|
Loading…
Reference in New Issue
Block a user