use super::SwRenderer;
use super::rect_fill::rounded_rect_coverage;
use crate::types::{Color, Fixed, Rect};
impl SwRenderer<'_> {
pub(super) fn stroke_rect_inner(
&mut self,
area: &Rect,
clip: &Rect,
width: Fixed,
color: &Color,
radius: Fixed,
opa: u8,
) {
let phys_area = self.viewport.rect_to_physical(*area);
let phys_clip = self.viewport.rect_to_physical(*clip);
let width = width * self.viewport.scale();
let radius = radius * self.viewport.scale();
let area = &phys_area;
let clip = &phys_clip;
let screen = Rect::new(0, 0, self.target.width, self.target.height);
let Some(draw_area) = area.intersect(clip) else {
return;
};
let Some(draw_area) = draw_area.intersect(&screen) else {
return;
};
let r = radius.min(area.w / 2).min(area.h / 2);
let bw = width;
let (px_x0, px_y0, px_x1, px_y1) = draw_area.pixel_bounds();
let opa_norm = Fixed::from_int(opa as i32).map_range((0, 255), (Fixed::ZERO, Fixed::ONE));
let inner_r = (r - bw).max(Fixed::ZERO);
let inner_w = (area.w - bw * 2).max(Fixed::ZERO);
let inner_h = (area.h - bw * 2).max(Fixed::ZERO);
for py in px_y0..px_y1 {
for px in px_x0..px_x1 {
let rel_x = Fixed::from_int(px) - area.x;
let rel_y = Fixed::from_int(py) - area.y;
let outer_cov = rounded_rect_coverage(rel_x, rel_y, area.w, area.h, r);
if outer_cov == Fixed::ZERO {
continue;
}
let inner_rel_x = rel_x - bw;
let inner_rel_y = rel_y - bw;
let inner_cov = if inner_rel_x >= Fixed::ZERO
&& inner_rel_y >= Fixed::ZERO
&& inner_rel_x < inner_w
&& inner_rel_y < inner_h
{
rounded_rect_coverage(inner_rel_x, inner_rel_y, inner_w, inner_h, inner_r)
} else {
Fixed::ZERO
};
let border_cov = (outer_cov - inner_cov).max(Fixed::ZERO);
let final_opa = (border_cov * opa_norm).map01(255).to_int() as u8;
if final_opa > 0 {
self.target.blend_pixel(
Fixed::from_int(px),
Fixed::from_int(py),
color,
final_opa,
);
}
}
}
}
}