feat: 优化 overlay_pixels
This commit is contained in:
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user