mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-20 06:28:09 +00:00
feat(core): add alpha capabilities to toif, text, circle
[no changelog]
This commit is contained in:
parent
2a123b3c5e
commit
4f1d03fce8
@ -81,7 +81,7 @@ pub trait Canvas: BasicCanvas {
|
|||||||
/// Draws a single pixel and blends its color with the background.
|
/// Draws a single pixel and blends its color with the background.
|
||||||
///
|
///
|
||||||
/// - If alpha == 255, the (foreground) pixel color is used.
|
/// - If alpha == 255, the (foreground) pixel color is used.
|
||||||
/// - If 0 < alpha << 255, pixel and backround colors are blended.
|
/// - If 0 < alpha << 255, pixel and background colors are blended.
|
||||||
/// - If alpha == 0, the background color is used.
|
/// - If alpha == 0, the background color is used.
|
||||||
fn blend_pixel(&mut self, pt: Point, color: Color, alpha: u8);
|
fn blend_pixel(&mut self, pt: Point, color: Color, alpha: u8);
|
||||||
|
|
||||||
@ -364,7 +364,7 @@ pub trait Canvas: BasicCanvas {
|
|||||||
|
|
||||||
// Draws circle with the specified center and the radius.
|
// Draws circle with the specified center and the radius.
|
||||||
#[cfg(not(feature = "ui_antialiasing"))]
|
#[cfg(not(feature = "ui_antialiasing"))]
|
||||||
fn draw_circle(&mut self, center: Point, radius: i16, color: Color) {
|
fn draw_circle(&mut self, center: Point, radius: i16, color: Color, alpha: u8) {
|
||||||
let split = unwrap!(circle_points(radius).last()).v;
|
let split = unwrap!(circle_points(radius).last()).v;
|
||||||
|
|
||||||
let r = Rect::new(
|
let r = Rect::new(
|
||||||
@ -376,8 +376,8 @@ pub trait Canvas: BasicCanvas {
|
|||||||
for p in circle_points(radius) {
|
for p in circle_points(radius) {
|
||||||
let pt_l = Point::new(center.x - p.u, center.y - p.v);
|
let pt_l = Point::new(center.x - p.u, center.y - p.v);
|
||||||
let pt_r = Point::new(center.x + p.u, center.y - p.v);
|
let pt_r = Point::new(center.x + p.u, center.y - p.v);
|
||||||
self.draw_pixel(pt_l, color);
|
self.blend_pixel(pt_l, color, alpha);
|
||||||
self.draw_pixel(pt_r, color);
|
self.blend_pixel(pt_r, color, alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,8 +390,8 @@ pub trait Canvas: BasicCanvas {
|
|||||||
for p in circle_points(radius).take_while(|p| p.u < p.v) {
|
for p in circle_points(radius).take_while(|p| p.u < p.v) {
|
||||||
let pt_l = Point::new(center.x - p.v, center.y - p.u);
|
let pt_l = Point::new(center.x - p.v, center.y - p.u);
|
||||||
let pt_r = Point::new(center.x + p.v, center.y - p.u);
|
let pt_r = Point::new(center.x + p.v, center.y - p.u);
|
||||||
self.draw_pixel(pt_l, color);
|
self.blend_pixel(pt_l, color, alpha);
|
||||||
self.draw_pixel(pt_r, color);
|
self.blend_pixel(pt_r, color, alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,8 +404,8 @@ pub trait Canvas: BasicCanvas {
|
|||||||
for p in circle_points(radius).skip(1).take_while(|p| p.u < p.v) {
|
for p in circle_points(radius).skip(1).take_while(|p| p.u < p.v) {
|
||||||
let pt_l = Point::new(center.x - p.v, center.y + p.u);
|
let pt_l = Point::new(center.x - p.v, center.y + p.u);
|
||||||
let pt_r = Point::new(center.x + p.v, center.y + p.u);
|
let pt_r = Point::new(center.x + p.v, center.y + p.u);
|
||||||
self.draw_pixel(pt_l, color);
|
self.blend_pixel(pt_l, color, alpha);
|
||||||
self.draw_pixel(pt_r, color);
|
self.blend_pixel(pt_r, color, alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,17 +418,16 @@ pub trait Canvas: BasicCanvas {
|
|||||||
for p in circle_points(radius) {
|
for p in circle_points(radius) {
|
||||||
let pt_l = Point::new(center.x - p.u, center.y + p.v);
|
let pt_l = Point::new(center.x - p.u, center.y + p.v);
|
||||||
let pt_r = Point::new(center.x + p.u, center.y + p.v);
|
let pt_r = Point::new(center.x + p.u, center.y + p.v);
|
||||||
self.draw_pixel(pt_l, color);
|
self.blend_pixel(pt_l, color, alpha);
|
||||||
self.draw_pixel(pt_r, color);
|
self.blend_pixel(pt_r, color, alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draws filled circle with the specified center and the radius.
|
/// Draws filled circle with the specified center and the radius.
|
||||||
#[cfg(not(feature = "ui_antialiasing"))]
|
#[cfg(not(feature = "ui_antialiasing"))]
|
||||||
fn fill_circle(&mut self, center: Point, radius: i16, color: Color) {
|
fn fill_circle(&mut self, center: Point, radius: i16, color: Color, alpha: u8) {
|
||||||
let split = unwrap!(circle_points(radius).last()).v;
|
let split = unwrap!(circle_points(radius).last()).v;
|
||||||
let alpha = 255;
|
|
||||||
|
|
||||||
let r = Rect::new(
|
let r = Rect::new(
|
||||||
Point::new(center.x - radius, center.y - radius),
|
Point::new(center.x - radius, center.y - radius),
|
||||||
@ -490,10 +489,9 @@ pub trait Canvas: BasicCanvas {
|
|||||||
/// Draws antialiased filled circle with the specified center and the
|
/// Draws antialiased filled circle with the specified center and the
|
||||||
/// radius.
|
/// radius.
|
||||||
#[cfg(feature = "ui_antialiasing")]
|
#[cfg(feature = "ui_antialiasing")]
|
||||||
fn fill_circle(&mut self, center: Point, radius: i16, color: Color) {
|
fn fill_circle(&mut self, center: Point, radius: i16, color: Color, alpha: u8) {
|
||||||
let split = unwrap!(circle_points(radius).last()).v;
|
let split = unwrap!(circle_points(radius).last()).v;
|
||||||
|
|
||||||
let alpha = 255;
|
|
||||||
let alpha_mul = |a: u8| -> u8 { ((a as u16 * alpha as u16) / 255) as u8 };
|
let alpha_mul = |a: u8| -> u8 { ((a as u16 * alpha as u16) / 255) as u8 };
|
||||||
|
|
||||||
let r = Rect::new(
|
let r = Rect::new(
|
||||||
|
@ -14,6 +14,7 @@ pub struct Circle {
|
|||||||
fg_color: Option<Color>,
|
fg_color: Option<Color>,
|
||||||
bg_color: Option<Color>,
|
bg_color: Option<Color>,
|
||||||
thickness: i16,
|
thickness: i16,
|
||||||
|
alpha: u8,
|
||||||
start_angle: Option<i16>,
|
start_angle: Option<i16>,
|
||||||
end_angle: Option<i16>,
|
end_angle: Option<i16>,
|
||||||
}
|
}
|
||||||
@ -26,6 +27,7 @@ impl Circle {
|
|||||||
fg_color: None,
|
fg_color: None,
|
||||||
bg_color: None,
|
bg_color: None,
|
||||||
thickness: 1,
|
thickness: 1,
|
||||||
|
alpha: 255,
|
||||||
start_angle: None,
|
start_angle: None,
|
||||||
end_angle: None,
|
end_angle: None,
|
||||||
}
|
}
|
||||||
@ -49,6 +51,10 @@ impl Circle {
|
|||||||
Self { thickness, ..self }
|
Self { thickness, ..self }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_alpha(self, alpha: u8) -> Self {
|
||||||
|
Self { alpha, ..self }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_start_angle(self, from_angle: i16) -> Self {
|
pub fn with_start_angle(self, from_angle: i16) -> Self {
|
||||||
Self {
|
Self {
|
||||||
start_angle: Some(from_angle),
|
start_angle: Some(from_angle),
|
||||||
@ -94,22 +100,22 @@ impl Shape<'_> for Circle {
|
|||||||
if self.start_angle.is_none() && self.end_angle.is_none() {
|
if self.start_angle.is_none() && self.end_angle.is_none() {
|
||||||
if th == 1 {
|
if th == 1 {
|
||||||
if let Some(color) = self.bg_color {
|
if let Some(color) = self.bg_color {
|
||||||
canvas.fill_circle(self.center, self.radius, color);
|
canvas.fill_circle(self.center, self.radius, color, self.alpha);
|
||||||
}
|
}
|
||||||
if let Some(color) = self.fg_color {
|
if let Some(color) = self.fg_color {
|
||||||
#[cfg(not(feature = "ui_antialiasing"))]
|
#[cfg(not(feature = "ui_antialiasing"))]
|
||||||
canvas.draw_circle(self.center, self.radius, color);
|
canvas.draw_circle(self.center, self.radius, color, self.alpha);
|
||||||
#[cfg(feature = "ui_antialiasing")]
|
#[cfg(feature = "ui_antialiasing")]
|
||||||
canvas.fill_circle(self.center, self.radius, color);
|
canvas.fill_circle(self.center, self.radius, color, self.alpha);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let Some(color) = self.fg_color {
|
if let Some(color) = self.fg_color {
|
||||||
if th > 0 {
|
if th > 0 {
|
||||||
canvas.fill_circle(self.center, self.radius, color);
|
canvas.fill_circle(self.center, self.radius, color, self.alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(color) = self.bg_color {
|
if let Some(color) = self.bg_color {
|
||||||
canvas.fill_circle(self.center, self.radius - th, color);
|
canvas.fill_circle(self.center, self.radius - th, color, self.alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -15,6 +15,8 @@ pub struct Text<'a> {
|
|||||||
text: &'a str,
|
text: &'a str,
|
||||||
// Text color
|
// Text color
|
||||||
color: Color,
|
color: Color,
|
||||||
|
// Text alpha
|
||||||
|
alpha: u8,
|
||||||
// Text font
|
// Text font
|
||||||
font: Font,
|
font: Font,
|
||||||
// Horizontal alignment
|
// Horizontal alignment
|
||||||
@ -31,6 +33,7 @@ impl<'a> Text<'a> {
|
|||||||
pos,
|
pos,
|
||||||
text,
|
text,
|
||||||
color: Color::white(),
|
color: Color::white(),
|
||||||
|
alpha: 255,
|
||||||
font: Font::NORMAL,
|
font: Font::NORMAL,
|
||||||
align: Alignment::Start,
|
align: Alignment::Start,
|
||||||
bounds: Rect::zero(),
|
bounds: Rect::zero(),
|
||||||
@ -49,6 +52,10 @@ impl<'a> Text<'a> {
|
|||||||
Self { align, ..self }
|
Self { align, ..self }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_alpha(self, alpha: u8) -> Self {
|
||||||
|
Self { alpha, ..self }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn render<'r>(mut self, renderer: &mut impl Renderer<'r>) {
|
pub fn render<'r>(mut self, renderer: &mut impl Renderer<'r>) {
|
||||||
self.bounds = self.calc_bounds();
|
self.bounds = self.calc_bounds();
|
||||||
renderer.render_shape(self);
|
renderer.render_shape(self);
|
||||||
@ -98,6 +105,7 @@ impl<'a> Shape<'_> for Text<'a> {
|
|||||||
let glyph = self.font.get_glyph(ch);
|
let glyph = self.font.get_glyph(ch);
|
||||||
let glyph_bitmap = glyph.bitmap();
|
let glyph_bitmap = glyph.bitmap();
|
||||||
let glyph_view = BitmapView::new(&glyph_bitmap)
|
let glyph_view = BitmapView::new(&glyph_bitmap)
|
||||||
|
.with_alpha(self.alpha)
|
||||||
.with_fg(self.color)
|
.with_fg(self.color)
|
||||||
.with_offset(Offset::new(
|
.with_offset(Offset::new(
|
||||||
-glyph.bearing_x,
|
-glyph.bearing_x,
|
||||||
|
@ -22,6 +22,8 @@ pub struct ToifImage<'a> {
|
|||||||
fg_color: Color,
|
fg_color: Color,
|
||||||
// Optional background color
|
// Optional background color
|
||||||
bg_color: Option<Color>,
|
bg_color: Option<Color>,
|
||||||
|
// Alpha value
|
||||||
|
alpha: u8,
|
||||||
/// Final size calculated from TOIF data
|
/// Final size calculated from TOIF data
|
||||||
size: Offset,
|
size: Offset,
|
||||||
}
|
}
|
||||||
@ -34,6 +36,7 @@ impl<'a> ToifImage<'a> {
|
|||||||
toif,
|
toif,
|
||||||
fg_color: Color::white(),
|
fg_color: Color::white(),
|
||||||
bg_color: None,
|
bg_color: None,
|
||||||
|
alpha: 255,
|
||||||
size: Offset::zero(),
|
size: Offset::zero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,6 +48,7 @@ impl<'a> ToifImage<'a> {
|
|||||||
toif: toif.original_data().into(),
|
toif: toif.original_data().into(),
|
||||||
fg_color: Color::white(),
|
fg_color: Color::white(),
|
||||||
bg_color: None,
|
bg_color: None,
|
||||||
|
alpha: 255,
|
||||||
size: Offset::zero(),
|
size: Offset::zero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,6 +68,10 @@ impl<'a> ToifImage<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_alpha(self, alpha: u8) -> Self {
|
||||||
|
Self { alpha, ..self }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn render(mut self, renderer: &mut impl Renderer<'a>) {
|
pub fn render(mut self, renderer: &mut impl Renderer<'a>) {
|
||||||
self.size = self.calc_size();
|
self.size = self.calc_size();
|
||||||
renderer.render_shape(self);
|
renderer.render_shape(self);
|
||||||
@ -106,7 +114,8 @@ impl<'a> ToifImage<'a> {
|
|||||||
let slice_view = slice
|
let slice_view = slice
|
||||||
.view()
|
.view()
|
||||||
.with_fg(self.fg_color)
|
.with_fg(self.fg_color)
|
||||||
.with_offset(Offset::new(r.x0 - bounds.top_left().x, 0));
|
.with_offset(Offset::new(r.x0 - bounds.top_left().x, 0))
|
||||||
|
.with_alpha(self.alpha);
|
||||||
|
|
||||||
match self.bg_color {
|
match self.bg_color {
|
||||||
Some(bg_color) => canvas.draw_bitmap(r, slice_view.with_bg(bg_color)),
|
Some(bg_color) => canvas.draw_bitmap(r, slice_view.with_bg(bg_color)),
|
||||||
|
Loading…
Reference in New Issue
Block a user