diff --git a/src/mscanvas.rs b/src/mscanvas.rs index 0463d60..3e5ee09 100644 --- a/src/mscanvas.rs +++ b/src/mscanvas.rs @@ -261,7 +261,7 @@ impl MSCanvas { self.pixels[index + 3] = color.a; // A } - fn draw_pixel_at1(&mut self, x: i32, y: i32) { + fn draw_pixel_color_at1(&mut self, x: i32, y: i32, color: MSColor) { // 边界检查 if x < 0 || x >= self.width || y < 0 || y >= self.height { return; @@ -271,10 +271,14 @@ impl MSCanvas { // 写入 RGBA 数据 // 注意:Color 的 r, g, b, a 是 0.0 - 1.0,需要转为 0 - 255 - self.pixels[index] = self.foreground_color.r; // R - self.pixels[index + 1] = self.foreground_color.g; // G - self.pixels[index + 2] = self.foreground_color.b; // B - self.pixels[index + 3] = self.foreground_color.a; // A + self.pixels[index] = color.r; // R + self.pixels[index + 1] = color.g; // G + self.pixels[index + 2] = color.b; // B + self.pixels[index + 3] = color.a; // A + } + + fn draw_pixel_at1(&mut self, x: i32, y: i32) { + self.draw_pixel_color_at1(x, y, self.foreground_color); } pub fn draw_pixel_row(&mut self, xs: i32, xe: i32, y: i32) { @@ -525,7 +529,7 @@ impl MSCanvas { (iter_count, fill_count) } - pub fn fill_scanline(&mut self, begin: Point) -> (i32, i32) { + fn fill_scanline_with_color(&mut self, begin: Point, color: MSColor) { let start_x = begin.x as i32; let start_y = begin.y as i32; let width = self.width; @@ -533,22 +537,18 @@ impl MSCanvas { // 边界检查 if start_x < 0 || start_x >= width || start_y < 0 || start_y >= height { - return (0, 0); + return; } let target_color = self.pixel_at(start_x, start_y); - if target_color == (self.foreground_color) { - return (0, 0); + if target_color == color { + return; } // 栈中存储 (y, x1, x2):表示第 y 行从 x1 到 x2(含)需要向上/下扫描 let mut stack = vec![(start_y, start_x, start_x)]; - let mut iter_count = 0; - let mut fill_count = 0; while let Some((y, mut lx, mut rx)) = stack.pop() { - iter_count += 1; - // 向左扩展 lx while lx - 1 >= 0 && self.pixel_at(lx - 1, y) == target_color { lx -= 1; @@ -560,8 +560,7 @@ impl MSCanvas { // 填充当前行 [lx, rx] for x in lx..=rx { - self.draw_pixel_at1(x, y); - fill_count += 1; + self.draw_pixel_color_at1(x, y, color); } // 检查上一行 (y - 1) @@ -598,8 +597,10 @@ impl MSCanvas { } } } + } - (iter_count, fill_count) + pub fn fill_scanline(&mut self, begin: Point) { + self.fill_scanline_with_color(begin, self.foreground_color); } pub fn arc_1px( @@ -1074,6 +1075,65 @@ impl MSCanvas { } } + /// 填充一个椭圆 + /// - center: 椭圆中心 + /// - rx: 水平半径(必须 >= 0) + /// - ry: 垂直半径(必须 >= 0) + pub fn fill_ellipse(&mut self, center: Point, rx: f32, ry: f32) { + if rx <= 0.0 || ry <= 0.0 { + return; + } + + let rx = rx as f32; + let ry = ry as f32; + + // 计算包围矩形(整数边界) + let min_x = (center.x as f32 - rx).ceil() as i32; + let max_x = (center.x as f32 + rx).floor() as i32; + let min_y = (center.y as f32 - ry).ceil() as i32; + let max_y = (center.y as f32 + ry).floor() as i32; + + // 预计算常量:rx², ry², rx² * ry² + let rx2 = rx * rx; + let ry2 = ry * ry; + let rxy2 = rx2 * ry2; // 右边阈值 + + for y in min_y..=max_y { + for x in min_x..=max_x { + let dx = x as f32 - center.x as f32; + let dy = y as f32 - center.y as f32; + + // 判断是否在椭圆内:dx²/ rx² + dy²/ ry² <= 1 + // 等价于:dx² * ry² + dy² * rx² <= rx² * ry² + if dx * dx * ry2 + dy * dy * rx2 <= rxy2 { + self.draw_pixel_color_at1(x, y, self.background_color); + } + } + } + } + + pub fn fill_ellipse1(&mut self, p1: Point, p2: Point) { + let mut rx = (p2.x - p1.x) / 2.0; + let mut ry = (p2.y - p1.y) / 2.0; + if rx > 0.0 && ry > 0.0 { + let center = Point::new(p1.x + rx, p1.y + ry); + self.fill_ellipse(center, rx, ry); + } else if rx < 0.0 && ry < 0.0 { + rx = -rx; + ry = -ry; + let center = Point::new(p1.x - rx, p1.y - ry); + self.fill_ellipse(center, rx, ry); + } else if ry < 0.0 { + ry = -ry; + let center = Point::new(p1.x + rx, p1.y - ry); + self.fill_ellipse(center, rx, ry); + } else { + rx = -rx; + let center = Point::new(p1.x - rx, p1.y + ry); + self.fill_ellipse(center, rx, ry); + } + } + /// 填充一个简单多边形(支持凹多边形) pub fn fill_polygon(&mut self, points: &[Point]) { if points.len() < 3 {