You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-firmware/core/embed/rust/src/ui/shape/bar.rs

129 lines
3.7 KiB

use crate::ui::{display::Color, geometry::Rect};
use super::{Canvas, DrawingCache, Renderer, Shape, ShapeClone};
use without_alloc::alloc::LocalAllocLeakExt;
/// A shape for the rendering variuous type of rectangles.
pub struct Bar {
/// Rectangle position and dimenstion
area: Rect,
/// Foreground color (default None)
fg_color: Option<Color>,
/// Background color (default None)
bg_color: Option<Color>,
/// Thickness (default 0)
thickness: i16,
/// Corner radius (default 0)
radius: i16,
/// Alpha (default 255)
alpha: u8,
}
impl Bar {
pub fn new(area: Rect) -> Self {
Self {
area,
fg_color: None,
bg_color: None,
thickness: 1,
radius: 0,
alpha: 255,
}
}
pub fn with_fg(self, fg_color: Color) -> Self {
Self {
fg_color: Some(fg_color),
..self
}
}
pub fn with_bg(self, bg_color: Color) -> Self {
Self {
bg_color: Some(bg_color),
..self
}
}
pub fn with_radius(self, radius: i16) -> Self {
Self { radius, ..self }
}
pub fn with_thickness(self, thickness: i16) -> Self {
Self { thickness, ..self }
}
pub fn with_alpha(self, alpha: u8) -> Self {
Self { alpha, ..self }
}
pub fn render<'s>(self, renderer: &mut impl Renderer<'s>) {
renderer.render_shape(self);
}
}
impl Shape<'_> for Bar {
fn bounds(&self, _cache: &DrawingCache) -> Rect {
self.area
}
fn cleanup(&mut self, _cache: &DrawingCache) {}
fn draw(&mut self, canvas: &mut dyn Canvas, _cache: &DrawingCache) {
// NOTE: drawing of rounded bars without a background
// is not supported. If we needed it, we would have to
// introduce a new function in RgbCanvas.
// TODO: panic! in unsupported scenarious
let th = match self.fg_color {
Some(_) => self.thickness,
None => 0,
};
if self.radius == 0 {
if let Some(fg_color) = self.fg_color {
// outline
if th > 0 {
let r = self.area;
canvas.fill_rect(Rect { y1: r.y0 + th, ..r }, fg_color, self.alpha);
canvas.fill_rect(Rect { x1: r.x0 + th, ..r }, fg_color, self.alpha);
canvas.fill_rect(Rect { x0: r.x1 - th, ..r }, fg_color, self.alpha);
canvas.fill_rect(Rect { y0: r.y1 - th, ..r }, fg_color, self.alpha);
}
}
if let Some(bg_color) = self.bg_color {
// background
let bg_r = self.area.shrink(th);
canvas.fill_rect(bg_r, bg_color, self.alpha);
}
} else {
if let Some(fg_color) = self.fg_color {
if th > 0 {
if self.bg_color.is_some() {
canvas.fill_round_rect(self.area, self.radius, fg_color, self.alpha);
} else {
#[cfg(not(feature = "ui_antialiasing"))]
canvas.draw_round_rect(self.area, self.radius, fg_color);
}
}
}
if let Some(bg_color) = self.bg_color {
let bg_r = self.area.shrink(th);
canvas.fill_round_rect(bg_r, self.radius, bg_color, self.alpha);
}
}
}
}
impl<'s> ShapeClone<'s> for Bar {
fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape<'s>>
where
T: LocalAllocLeakExt<'alloc>,
{
let clone = bump.alloc_t::<Bar>()?;
Some(clone.uninit.init(Bar { ..self }))
}
}