1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-31 18:40:56 +00:00

feat(core/rust): introduce f32 angles for sector drawing

[no changelog]
This commit is contained in:
cepetr 2024-05-16 16:12:03 +02:00 committed by cepetr
parent e3a383526b
commit f03e4c8d9c
4 changed files with 25 additions and 40 deletions

View File

@ -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`

View File

@ -15,8 +15,8 @@ pub struct Circle {
bg_color: Option<Color>,
thickness: i16,
alpha: u8,
start_angle: Option<i16>,
end_angle: Option<i16>,
start_angle: Option<f32>,
end_angle: Option<f32>,
}
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 {

View File

@ -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;

View File

@ -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
}