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/line.rs

95 lines
2.1 KiB

/// Iterator providing points on a line (using bresenham's algorithm)
///
/// The iterator supplies coordinates of pixels relative to the
/// line's start point.
///
/// constraint: `du` >= `dv`, `start_u` < `du`
///
/// for p in line_points(du, dv, start_u) {
/// println!("{}, {}", p.u, p.v); // coordinates <0,radius>..<du-1, dv-1>
/// println!("{}", p.frac); // distance from the line <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.
pub fn line_points(du: i16, dv: i16, start_u: i16) -> LinePoints {
let mut d = 2 * du - 2 * dv;
let mut y = 0;
for _ in 0..start_u {
if d <= 0 {
d += 2 * du - 2 * dv;
y += 1;
} else {
d -= 2 * dv;
}
}
LinePoints {
du,
dv,
d,
u: start_u,
v: y,
first: true,
}
}
pub struct LinePoints {
du: i16,
dv: i16,
d: i16,
u: i16,
v: i16,
first: bool,
}
#[derive(Copy, Clone)]
pub struct LinePointsItem {
pub u: i16,
pub v: i16,
pub frac: u8,
pub first: bool,
pub last: bool,
}
impl Iterator for LinePoints {
type Item = LinePointsItem;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
if self.u < self.du {
let frac = if self.dv < self.du {
255 - ((self.d + 2 * self.dv - 1) as i32 * 255 / (2 * self.du - 1) as i32) as u8
} else {
0
};
let next = LinePointsItem {
u: self.u,
v: self.v,
frac,
first: self.first,
last: self.d <= 0,
};
if self.d <= 0 {
self.d += 2 * self.du - 2 * self.dv;
self.v += 1;
self.first = true;
} else {
self.d -= 2 * self.dv;
self.first = false;
}
self.u += 1;
Some(next)
} else {
None
}
}
}