feat: 实现圆角矩形填充
This commit is contained in:
114
src/mscanvas.rs
114
src/mscanvas.rs
@@ -727,6 +727,98 @@ impl MSCanvas {
|
|||||||
self.fill_rect_color(x, y, width, height, self.background_color)
|
self.fill_rect_color(x, y, width, height, self.background_color)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 填充一个圆角矩形
|
||||||
|
/// - x, y: 左上角坐标
|
||||||
|
/// - width, height: 尺寸(必须 > 0)
|
||||||
|
/// - radius: 圆角半径(会被 clamp 到合理范围)
|
||||||
|
pub fn fill_round_rect(
|
||||||
|
&mut self,
|
||||||
|
x: f32,
|
||||||
|
y: f32,
|
||||||
|
width: f32,
|
||||||
|
height: f32,
|
||||||
|
radius: f32,
|
||||||
|
) {
|
||||||
|
if (width as i32) <= 2 * self.line_width
|
||||||
|
|| (height as i32) <= 2 * self.line_width
|
||||||
|
|| width <= 2.0 * radius
|
||||||
|
|| height <= 2.0 * radius
|
||||||
|
{
|
||||||
|
self.fill_rect(x as i32, y as i32, width as i32, height as i32);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let min_x = x;
|
||||||
|
let max_x = x + width - 1.0;
|
||||||
|
let min_y = y;
|
||||||
|
let max_y = y + height - 1.0;
|
||||||
|
|
||||||
|
// 预计算四个圆角的圆心
|
||||||
|
let corners = [
|
||||||
|
((x + radius) as i32, (y + radius) as i32), // 左上
|
||||||
|
((x + width - 1.0 - radius) as i32, (y + radius) as i32), // 右上
|
||||||
|
((x + width - 1.0 - radius) as i32, (y + height - 1.0 - radius) as i32), // 右下
|
||||||
|
((x + radius) as i32, (y + height - 1.0 - radius) as i32), // 左下
|
||||||
|
];
|
||||||
|
|
||||||
|
let min_x = min_x as i32;
|
||||||
|
let max_x = max_x as i32;
|
||||||
|
let min_y = min_y as i32;
|
||||||
|
let max_y = max_y as i32;
|
||||||
|
let radius_sq = (radius + 0.05) * (radius + 0.05);
|
||||||
|
let radius_int = radius as i32;
|
||||||
|
for py in min_y..=max_y {
|
||||||
|
for px in min_x..=max_x {
|
||||||
|
// 判断是否在“直边区域”(无需检查圆角)
|
||||||
|
if px >= min_x + radius_int && px <= max_x - radius_int {
|
||||||
|
// 在左右圆角之间的竖直带 → 一定在内部
|
||||||
|
self.draw_pixel_at1(px, py);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if py >= min_y + radius_int && py <= max_y - radius_int {
|
||||||
|
// 在上下圆角之间的水平带 → 一定在内部
|
||||||
|
self.draw_pixel_at1(px, py);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 否则,点位于四个角落之一,需检查是否在四分之一圆内
|
||||||
|
let in_corner =
|
||||||
|
// 左上角区域
|
||||||
|
(distance_sq1((px, py), corners[0]) <= radius_sq) ||
|
||||||
|
// 右上角区域
|
||||||
|
(distance_sq1((px, py), corners[1]) <= radius_sq) ||
|
||||||
|
// 右下角区域
|
||||||
|
(distance_sq1((px, py), corners[2]) <= radius_sq) ||
|
||||||
|
// 左下角区域
|
||||||
|
(distance_sq1((px, py), corners[3]) <= radius_sq);
|
||||||
|
|
||||||
|
if in_corner {
|
||||||
|
self.draw_pixel_at1(px, py);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fill_round_rect1(&mut self, p1: Point, p2: Point, radius: f32) {
|
||||||
|
let mut x = p1.x;
|
||||||
|
let mut y = p1.y;
|
||||||
|
let mut width = (p2.x - p1.x);
|
||||||
|
let mut height = (p2.y - p1.y);
|
||||||
|
if width < 0.0 && height < 0.0 {
|
||||||
|
x = p2.x;
|
||||||
|
y = p2.y;
|
||||||
|
width = (p1.x - p2.x);
|
||||||
|
height = (p1.y - p2.y);
|
||||||
|
} else if width < 0.0 {
|
||||||
|
x += width;
|
||||||
|
width = -width;
|
||||||
|
} else if height < 0.0 {
|
||||||
|
y += height;
|
||||||
|
height = -height;
|
||||||
|
}
|
||||||
|
self.fill_round_rect(x, y, width, height, radius);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn round_rect(&mut self, x: f32, y: f32, width: f32, height: f32, radius: f32) {
|
pub fn round_rect(&mut self, x: f32, y: f32, width: f32, height: f32, radius: f32) {
|
||||||
if (width as i32) < 2 * self.line_width
|
if (width as i32) < 2 * self.line_width
|
||||||
|| (height as i32) < 2 * self.line_width
|
|| (height as i32) < 2 * self.line_width
|
||||||
@@ -812,7 +904,7 @@ impl MSCanvas {
|
|||||||
self.round_rect(x, y, width, height, radius);
|
self.round_rect(x, y, width, height, radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stroke_rect(&mut self, x: i32, y: i32, width: i32, height: i32) {
|
pub fn rect(&mut self, x: i32, y: i32, width: i32, height: i32) {
|
||||||
if width < 2 * self.line_width || height < 2 * self.line_width {
|
if width < 2 * self.line_width || height < 2 * self.line_width {
|
||||||
self.fill_rect(x, y, width, height);
|
self.fill_rect(x, y, width, height);
|
||||||
return;
|
return;
|
||||||
@@ -823,7 +915,7 @@ impl MSCanvas {
|
|||||||
self.fill_rect(x + width - self.line_width, y, self.line_width, height);
|
self.fill_rect(x + width - self.line_width, y, self.line_width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stroke_rect1(&mut self, p1: Point, p2: Point) {
|
pub fn rect1(&mut self, p1: Point, p2: Point) {
|
||||||
let mut x = p1.x;
|
let mut x = p1.x;
|
||||||
let mut y = p1.y;
|
let mut y = p1.y;
|
||||||
let mut width = (p2.x - p1.x);
|
let mut width = (p2.x - p1.x);
|
||||||
@@ -840,7 +932,7 @@ impl MSCanvas {
|
|||||||
y += height;
|
y += height;
|
||||||
height = -height;
|
height = -height;
|
||||||
}
|
}
|
||||||
self.stroke_rect(x as i32, y as i32, width as i32, height as i32);
|
self.rect(x as i32, y as i32, width as i32, height as i32);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
@@ -1108,3 +1200,19 @@ fn normalize_radian(radian: f32) -> f32 {
|
|||||||
|
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// 辅助函数:计算两点间距离的平方(避免开方)
|
||||||
|
fn distance_sq(a: Point, b: Point) -> f32 {
|
||||||
|
let dx = a.x - b.x;
|
||||||
|
let dy = a.y - b.y;
|
||||||
|
dx * dx + dy * dy
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// 辅助函数:计算两点间距离的平方(避免开方)
|
||||||
|
fn distance_sq1(a: (i32, i32), b: (i32, i32)) -> f32 {
|
||||||
|
let dx = a.0 - b.0;
|
||||||
|
let dy = a.1 - b.1;
|
||||||
|
(dx * dx + dy * dy) as f32
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user