pub fn fill_triangle(
buf: &mut Vec<u32>,
width: usize,
height: usize,
color: u32,
x0: f32, y0: f32,
x1: f32, y1: f32,
x2: f32, y2: f32,
) {
if width == 0 || height == 0 { return; }
if !x0.is_finite() || !y0.is_finite()
|| !x1.is_finite() || !y1.is_finite()
|| !x2.is_finite() || !y2.is_finite() { return; }
let min_x = x0.min(x1).min(x2).max(0.0) as i32;
let max_x = x0.max(x1).max(x2).min(width as f32 - 1.0) as i32;
let min_y = y0.min(y1).min(y2).max(0.0) as i32;
let max_y = y0.max(y1).max(y2).min(height as f32 - 1.0) as i32;
if min_x > max_x || min_y > max_y { return; }
let de0 = -(y1 - y0);
let de1 = -(y2 - y1);
let de2 = -(y0 - y2);
for py in min_y..=max_y {
let fy = py as f32 + 0.5;
let fx0 = min_x as f32 + 0.5;
let mut e0 = (x1 - x0) * (fy - y0) - (y1 - y0) * (fx0 - x0);
let mut e1 = (x2 - x1) * (fy - y1) - (y2 - y1) * (fx0 - x1);
let mut e2 = (x0 - x2) * (fy - y2) - (y0 - y2) * (fx0 - x2);
let mut in_span = false;
let row = py as usize * width;
for px in min_x..=max_x {
let inside = (e0 >= 0.0 && e1 >= 0.0 && e2 >= 0.0)
|| (e0 <= 0.0 && e1 <= 0.0 && e2 <= 0.0);
if inside {
buf[row + px as usize] = color;
in_span = true;
} else if in_span {
break; }
e0 += de0; e1 += de1; e2 += de2;
}
}
}
pub fn draw_line(
buf: &mut Vec<u32>,
width: usize,
height: usize,
color: u32,
x0: f32, y0: f32,
x1: f32, y1: f32,
) {
if width == 0 || height == 0 { return; }
if !x0.is_finite() || !y0.is_finite()
|| !x1.is_finite() || !y1.is_finite() { return; }
let xmax = (width - 1) as f32;
let ymax = (height - 1) as f32;
let (mut ax, mut ay, mut bx, mut by) = (x0, y0, x1, y1);
if !cs_clip(&mut ax, &mut ay, &mut bx, &mut by, xmax, ymax) { return; }
let mut x = ax as i32;
let mut y = ay as i32;
let x2 = bx as i32;
let y2 = by as i32;
let dx = (x2 - x).abs();
let dy = -((y2 - y).abs());
let sx: i32 = if x < x2 { 1 } else { -1 };
let sy: i32 = if y < y2 { 1 } else { -1 };
let mut err = dx + dy;
loop {
if x >= 0 && y >= 0 && (x as usize) < width && (y as usize) < height {
buf[y as usize * width + x as usize] = color;
}
if x == x2 && y == y2 { break; }
let e2 = 2 * err;
if e2 >= dy { err += dy; x += sx; }
if e2 <= dx { err += dx; y += sy; }
}
}
#[inline]
fn cs_code(x: f32, y: f32, xmax: f32, ymax: f32) -> u8 {
let mut c = 0u8;
if x < 0.0 { c |= 1; }
if x > xmax { c |= 2; }
if y < 0.0 { c |= 4; }
if y > ymax { c |= 8; }
c
}
fn cs_clip(
ax: &mut f32, ay: &mut f32,
bx: &mut f32, by: &mut f32,
xmax: f32, ymax: f32,
) -> bool {
loop {
let ca = cs_code(*ax, *ay, xmax, ymax);
let cb = cs_code(*bx, *by, xmax, ymax);
if ca | cb == 0 { return true; } if ca & cb != 0 { return false; } let co = if ca != 0 { ca } else { cb };
let dx = *bx - *ax;
let dy = *by - *ay;
let (nx, ny) = if co & 1 != 0 {
(0.0_f32, *ay + dy * (0.0 - *ax) / dx)
} else if co & 2 != 0 {
(xmax, *ay + dy * (xmax - *ax) / dx)
} else if co & 4 != 0 {
(*ax + dx * (0.0 - *ay) / dy, 0.0_f32)
} else {
(*ax + dx * (ymax - *ay) / dy, ymax)
};
if co == ca { *ax = nx; *ay = ny; } else { *bx = nx; *by = ny; }
}
}