feat: 优化 overlay_pixels

This commit is contained in:
2026-03-06 16:37:20 +08:00
parent 6db8941b67
commit 2631fec53c

View File

@@ -290,23 +290,28 @@ impl MSCanvas {
pub fn overlay_pixels(&mut self, canvas: &MSCanvas) -> Vec<u8> {
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<Point<i32>>) {
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<Point<i32>> {
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];
}
}
}