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/algo/circle.rs

77 lines
1.9 KiB

/// Iterator providing points for 1/8th of a circle (single octant)
///
/// The iterator supplies coordinates of pixels relative to the
/// circle's center point, along with an alpha value in
/// the range (0..255), indicating the proportion of the pixel
/// that lies inside the circle.
///
/// for p in circle_points(radius) {
/// println!("{}, {}", p.u, p.v); // coordinates <0,radius>..<see_below>
/// println!("{}", p.frac); // distance from the circle <0..255>
/// println!("{}", p.first); // `v` has changed
/// println!("{}", p.last); // next `v` will change
/// }
///
/// `u` axis is the main and increments at each iteration.
///
/// endpoint [t, t] or [t - 1, t] where t = radius * (1 / sqrt(2))
pub fn circle_points(radius: i16) -> CirclePoints {
CirclePoints {
radius,
u: 0,
v: radius,
t1: radius / 16,
first: true,
}
}
pub struct CirclePoints {
radius: i16,
u: i16,
v: i16,
t1: i16,
first: bool,
}
#[derive(Copy, Clone)]
pub struct CirclePointsItem {
pub u: i16,
pub v: i16,
pub frac: u8,
pub first: bool,
pub last: bool,
}
impl Iterator for CirclePoints {
type Item = CirclePointsItem;
fn next(&mut self) -> Option<Self::Item> {
if self.v >= self.u {
let mut item = CirclePointsItem {
u: self.u,
v: self.v,
frac: 255 - ((self.t1 as i32 * 255) / self.radius as i32) as u8,
first: self.first,
last: false,
};
self.first = false;
self.u += 1;
self.t1 += self.u;
let t2 = self.t1 - self.v;
if t2 >= 0 {
self.t1 = t2;
self.v -= 1;
self.first = true;
}
item.last = item.v != self.v;
Some(item)
} else {
None
}
}
}