diff --git a/src/mscanvas.rs b/src/mscanvas.rs index 6d12267..6d335cd 100644 --- a/src/mscanvas.rs +++ b/src/mscanvas.rs @@ -727,6 +727,98 @@ impl MSCanvas { 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) { if (width 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); } - 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 { self.fill_rect(x, y, width, height); return; @@ -823,7 +915,7 @@ impl MSCanvas { 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 y = p1.y; let mut width = (p2.x - p1.x); @@ -840,7 +932,7 @@ impl MSCanvas { y += 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) { @@ -1108,3 +1200,19 @@ fn normalize_radian(radian: f32) -> f32 { 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 +} \ No newline at end of file