From f03e4c8d9cdd37ab2f51cb6cbc38ab1940e5434f Mon Sep 17 00:00:00 2001 From: cepetr Date: Thu, 16 May 2024 16:12:03 +0200 Subject: [PATCH] feat(core/rust): introduce f32 angles for sector drawing [no changelog] --- core/embed/rust/src/ui/shape/canvas/common.rs | 20 ++++++------ core/embed/rust/src/ui/shape/circle.rs | 12 +++---- core/embed/rust/src/ui/shape/utils/mod.rs | 2 +- core/embed/rust/src/ui/shape/utils/trigo.rs | 31 +++++-------------- 4 files changed, 25 insertions(+), 40 deletions(-) diff --git a/core/embed/rust/src/ui/shape/canvas/common.rs b/core/embed/rust/src/ui/shape/canvas/common.rs index 796b74d2f8..ea24983902 100644 --- a/core/embed/rust/src/ui/shape/canvas/common.rs +++ b/core/embed/rust/src/ui/shape/canvas/common.rs @@ -4,7 +4,7 @@ use crate::ui::{ }; use super::super::{ - utils::{circle_points, line_points, sin_i16, PI4}, + utils::{circle_points, line_points, sin_f32}, BitmapView, Viewport, }; @@ -576,12 +576,12 @@ pub trait Canvas: BasicCanvas { &mut self, center: Point, radius: i16, - mut start: i16, - mut end: i16, + mut start: f32, + mut end: f32, color: Color, ) { - start = (PI4 * 8 + start % (PI4 * 8)) % (PI4 * 8); - end = (PI4 * 8 + end % (PI4 * 8)) % (PI4 * 8); + start = (360.0 + start % 360.0) % 360.0; + end = (360.0 + end % 360.0) % 360.0; let alpha = 255; let alpha_mul = |a: u8| -> u8 { ((a as u16 * alpha as u16) / 255) as u8 }; @@ -591,12 +591,14 @@ pub trait Canvas: BasicCanvas { self.draw_pixel(center, color); } + const PI4: f32 = 45.0; + for octant in 0..8 { - let angle = octant * PI4; + let angle = PI4 * octant as f32; // Function for calculation of 'u' coordinate inside the circle octant // radius * sin(angle) - let sin = |angle: i16| -> i16 { sin_i16(angle, radius) }; + let sin = |angle: f32| -> i16 { (sin_f32(angle) * radius as f32 + 0.5) as i16 }; // Calculate the octant's bounding rectangle let p = Point::new(sin(PI4) + 1, -radius - 1).rot(octant); @@ -660,7 +662,7 @@ pub trait Canvas: BasicCanvas { } else { // Partial fill let u1 = if start <= angle { - sin(corr(0)) + sin(corr(0.0)) } else { sin(corr(start - angle)) }; @@ -682,7 +684,7 @@ pub trait Canvas: BasicCanvas { // Partial fill if (end > angle) && (end < angle + PI4) { // Fill up to `end` - fill_octant(radius, sin(corr(0)), sin(corr(end - angle)), filler); + fill_octant(radius, sin(corr(0.0)), sin(corr(end - angle)), filler); } if start < angle + PI4 { // Fill all from `start` diff --git a/core/embed/rust/src/ui/shape/circle.rs b/core/embed/rust/src/ui/shape/circle.rs index 40778838c6..af2558466f 100644 --- a/core/embed/rust/src/ui/shape/circle.rs +++ b/core/embed/rust/src/ui/shape/circle.rs @@ -15,8 +15,8 @@ pub struct Circle { bg_color: Option, thickness: i16, alpha: u8, - start_angle: Option, - end_angle: Option, + start_angle: Option, + end_angle: Option, } impl Circle { @@ -55,14 +55,14 @@ impl Circle { Self { alpha, ..self } } - pub fn with_start_angle(self, from_angle: i16) -> Self { + pub fn with_start_angle(self, from_angle: f32) -> Self { Self { start_angle: Some(from_angle), ..self } } - pub fn with_end_angle(self, to_angle: i16) -> Self { + pub fn with_end_angle(self, to_angle: f32) -> Self { Self { end_angle: Some(to_angle), ..self @@ -119,8 +119,8 @@ impl Shape<'_> for Circle { } } } else { - let start = self.start_angle.unwrap_or(0); - let end = self.end_angle.unwrap_or(360); + let start = self.start_angle.unwrap_or(0.0); + let end = self.end_angle.unwrap_or(360.0); if let Some(color) = self.fg_color { if th > 0 { diff --git a/core/embed/rust/src/ui/shape/utils/mod.rs b/core/embed/rust/src/ui/shape/utils/mod.rs index d9e23288c1..0b9c296cdc 100644 --- a/core/embed/rust/src/ui/shape/utils/mod.rs +++ b/core/embed/rust/src/ui/shape/utils/mod.rs @@ -6,4 +6,4 @@ mod trigo; pub use blur::{BlurAlgorithm, BlurBuff}; pub use circle::circle_points; pub use line::line_points; -pub use trigo::{sin_i16, PI4}; +pub use trigo::sin_f32; diff --git a/core/embed/rust/src/ui/shape/utils/trigo.rs b/core/embed/rust/src/ui/shape/utils/trigo.rs index a18a7bf791..c9db25a17f 100644 --- a/core/embed/rust/src/ui/shape/utils/trigo.rs +++ b/core/embed/rust/src/ui/shape/utils/trigo.rs @@ -1,29 +1,12 @@ -/// Integer representing an angle of 45 degress (PI/4). -// -// Changing this constant requires revisiting isin() algorithm -// (for higher values consider changing T type to i64 or f32) -pub const PI4: i16 = 45; - /// Fast sine approximation. /// -/// Returns mult * sin(angle). +/// Returns sin(angle). /// -/// Angle must be in range <0..PI4>. -/// This function provides an error within +-1 for multiplier up to 500 -pub fn sin_i16(angle: i16, mult: i16) -> i16 { - assert!((0..=PI4).contains(&angle)); - assert!(mult <= 2500); +/// Angle must be in range <0..45>. +pub fn sin_f32(angle: f32) -> f32 { + assert!((0.0..=45.0).contains(&angle)); - type T = i32; - - // Based on polynomial x - x^3 / 6 - let x = angle as T; - - // Constants for the approximation - const K: f32 = (PI4 as f32) * 4.0 / core::f32::consts::PI; - const M: T = (6.0 * K * K + 0.5) as T; - const N: T = (6.0 * K * K * K + 0.5) as T; - - // Applying the approximation - (((M * x - x * x * x) * mult as T + N / 2) / N) as i16 + // Applying the approximation x - x^3 / 6 + let x = (angle / 180.0) * core::f32::consts::PI; + x - x * x * x / 6.0 }