From 2631fec53c8e6f56690c40d7c2b383fd4840cdee Mon Sep 17 00:00:00 2001 From: yeqing Date: Fri, 6 Mar 2026 16:37:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20overlay=5Fpixels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mscanvas.rs | 70 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/src/mscanvas.rs b/src/mscanvas.rs index 551658f..aa6a77a 100644 --- a/src/mscanvas.rs +++ b/src/mscanvas.rs @@ -290,23 +290,28 @@ impl MSCanvas { pub fn overlay_pixels(&mut self, canvas: &MSCanvas) -> Vec { let mut pixels = canvas.get_pixels(); + let width = canvas.width.min(self.width) as usize; + let height = canvas.height.min(self.height) as usize; - let width = canvas.width.min(self.width); - let height = canvas.height.min(self.height); + // 预计算步长,避免重复计算 + let src_stride = self.width as usize * 4; + let dst_stride = width * 4; for y in 0..height { + let src_base = y * src_stride; + let dst_base = y * dst_stride; + + // 使用显式循环,可能被编译器自动向量化 for x in 0..width { - let index = ((y * width + x) * 4) as usize; + let src_idx = src_base + x * 4; + let dst_idx = dst_base + x * 4; - // 跳过透明像素 - if self.pixels[index + 3] == 0 { - continue; + // 只在非透明时复制 + if self.pixels[src_idx + 3] != 0 { + // 一次复制4个字节(可能被优化为单个u32操作) + pixels[dst_idx..dst_idx + 4] + .copy_from_slice(&self.pixels[src_idx..src_idx + 4]); } - - pixels[index] = self.pixels[index]; - pixels[index + 1] = self.pixels[index + 1]; - pixels[index + 2] = self.pixels[index + 2]; - pixels[index + 3] = self.pixels[index + 3]; } } @@ -418,6 +423,12 @@ impl MSCanvas { } } + pub fn fill_pixels_i32(&mut self, points: Vec>) { + for point in points { + self.fill_pixel_at1(point.x, point.y); + } + } + pub fn stroke_cross(&mut self, point: Point) { let Point { x, y } = point; let r = 10; @@ -1280,10 +1291,10 @@ impl MSCanvas { } } - /// 填充一个简单多边形(支持凹多边形) - pub fn fill_polygon(&mut self, points: &[Point]) { + fn rasterize_polygon(&mut self, points: &[Point]) -> Vec> { + let mut result = Vec::new(); if points.len() < 3 { - return; + return result; } // 计算 y 范围 @@ -1330,7 +1341,7 @@ impl MSCanvas { let x_start = active_edges[i].x.ceil() as i32; let x_end = active_edges[i + 1].x.floor() as i32; for x in x_start..=x_end { - self.fill_pixel_at1(x, y); + result.push(Point::new(x, y)); } } } @@ -1340,6 +1351,14 @@ impl MSCanvas { edge.x += edge.dx_dy; } } + + result + } + + /// 填充一个简单多边形(支持凹多边形) + pub fn fill_polygon(&mut self, points: &[Point]) { + let filled_points = self.rasterize_polygon(points); + self.fill_pixels_i32(filled_points); } pub fn begin_path(&mut self) { @@ -1385,8 +1404,8 @@ impl MSCanvas { } // 考虑矩形四边出界的情况 - let w = (rect.w as i32).min(self.width - x).min(rect.w + x); - let h = (rect.h as i32).min(self.height - y).min(rect.h + y); + let w = (rect.w).min(self.width - x).min(rect.w + x); + let h = (rect.h).min(self.height - y).min(rect.h + y); if w == 0 || h == 0 { return; @@ -1407,14 +1426,17 @@ impl MSCanvas { let width = self.width as usize; for dy in 0..h { - let src_start = ((dy + src_offset_y) * rect.w as usize + src_offset_x) * 4; - let dst_start = ((y + dy) * width + x) * 4; + for dx in 0..w { + let src_index = ((dy + src_offset_y) * rect.w as usize + dx + src_offset_x) * 4; + if rect.pixels[src_index + 3] == 0 { + continue; + } + let dst_index = ((y + dy) * width + x + dx) * 4; - // 使用 unsafe 块进一步优化(如果确定索引安全) - unsafe { - let src_slice = &rect.pixels.get_unchecked(src_start..src_start + w * 4); - let dst_slice = self.pixels.get_unchecked_mut(dst_start..dst_start + w * 4); - dst_slice.copy_from_slice(src_slice); + self.pixels[dst_index] = rect.pixels[src_index]; + self.pixels[dst_index + 1] = rect.pixels[src_index + 1]; + self.pixels[dst_index + 2] = rect.pixels[src_index + 2]; + self.pixels[dst_index + 3] = rect.pixels[src_index + 3]; } } }