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:
parent
e3a383526b
commit
f03e4c8d9c
@ -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`
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user