@@ -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 {