use crate::common::BitMatrix;
use super::BitMatrixCursorTrait;
pub struct FastEdgeToEdgeCounter<'a> {
p: u32, stride: isize, stepsToBorder: i32, _arr: isize,
under_arry: &'a BitMatrix, }
impl<'a> FastEdgeToEdgeCounter<'a> {
pub fn new<T: BitMatrixCursorTrait>(cur: &T) -> FastEdgeToEdgeCounter {
let stride = cur.d().y as isize * cur.img().width() as isize + cur.d().x as isize;
let p = ((cur.p().y as isize * cur.img().width() as isize).abs() as i32 + cur.p().x as i32)
as u32;
let maxStepsX: i32 = if cur.d().x != 0.0 {
if cur.d().x > 0.0 {
cur.img().width() as i32 - 1 - cur.p().x as i32
} else {
cur.p().x as i32
}
} else {
i32::MAX
};
let maxStepsY: i32 = if cur.d().y != 0.0 {
if cur.d().y > 0.0 {
cur.img().height() as i32 - 1 - cur.p().y as i32
} else {
cur.p().y as i32
}
} else {
i32::MAX
};
let stepsToBorder = std::cmp::min(maxStepsX, maxStepsY);
FastEdgeToEdgeCounter {
p,
stride,
stepsToBorder,
_arr: cur.p().y as isize * stride, under_arry: cur.img(), }
}
pub fn stepToNextEdge(&mut self, range: u32) -> u32 {
let maxSteps = std::cmp::min(self.stepsToBorder, range as i32);
let mut steps = 0;
loop {
steps += 1;
if steps > maxSteps {
if maxSteps == self.stepsToBorder {
break;
} else {
return 0;
}
}
let idx_pt = self.get_array_check_index(steps);
if self.under_arry.get_index(idx_pt) != self.under_arry.get_index(self.p as usize) {
break;
}
}
self.p = (self.p as isize + (steps as isize * self.stride)).unsigned_abs() as u32;
self.stepsToBorder -= steps;
steps as u32
}
#[inline(always)]
fn get_array_check_index(&self, steps: i32) -> usize {
(self.p as isize + (steps as isize * self.stride)) as usize
}
}