feat: 优化 overlay_pixels
This commit is contained in:
@@ -290,23 +290,28 @@ impl MSCanvas {
|
|||||||
|
|
||||||
pub fn overlay_pixels(&mut self, canvas: &MSCanvas) -> Vec<u8> {
|
pub fn overlay_pixels(&mut self, canvas: &MSCanvas) -> Vec<u8> {
|
||||||
let mut pixels = canvas.get_pixels();
|
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 {
|
for y in 0..height {
|
||||||
|
let src_base = y * src_stride;
|
||||||
|
let dst_base = y * dst_stride;
|
||||||
|
|
||||||
|
// 使用显式循环,可能被编译器自动向量化
|
||||||
for x in 0..width {
|
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 {
|
if self.pixels[src_idx + 3] != 0 {
|
||||||
continue;
|
// 一次复制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) {
|
pub fn stroke_cross(&mut self, point: Point) {
|
||||||
let Point { x, y } = point;
|
let Point { x, y } = point;
|
||||||
let r = 10;
|
let r = 10;
|
||||||
@@ -1280,10 +1291,10 @@ impl MSCanvas {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 填充一个简单多边形(支持凹多边形)
|
fn rasterize_polygon(&mut self, points: &[Point]) -> Vec<Point<i32>> {
|
||||||
pub fn fill_polygon(&mut self, points: &[Point]) {
|
let mut result = Vec::new();
|
||||||
if points.len() < 3 {
|
if points.len() < 3 {
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算 y 范围
|
// 计算 y 范围
|
||||||
@@ -1330,7 +1341,7 @@ impl MSCanvas {
|
|||||||
let x_start = active_edges[i].x.ceil() as i32;
|
let x_start = active_edges[i].x.ceil() as i32;
|
||||||
let x_end = active_edges[i + 1].x.floor() as i32;
|
let x_end = active_edges[i + 1].x.floor() as i32;
|
||||||
for x in x_start..=x_end {
|
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;
|
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) {
|
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 w = (rect.w).min(self.width - x).min(rect.w + x);
|
||||||
let h = (rect.h as i32).min(self.height - y).min(rect.h + y);
|
let h = (rect.h).min(self.height - y).min(rect.h + y);
|
||||||
|
|
||||||
if w == 0 || h == 0 {
|
if w == 0 || h == 0 {
|
||||||
return;
|
return;
|
||||||
@@ -1407,14 +1426,17 @@ impl MSCanvas {
|
|||||||
let width = self.width as usize;
|
let width = self.width as usize;
|
||||||
|
|
||||||
for dy in 0..h {
|
for dy in 0..h {
|
||||||
let src_start = ((dy + src_offset_y) * rect.w as usize + src_offset_x) * 4;
|
for dx in 0..w {
|
||||||
let dst_start = ((y + dy) * width + x) * 4;
|
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 块进一步优化(如果确定索引安全)
|
self.pixels[dst_index] = rect.pixels[src_index];
|
||||||
unsafe {
|
self.pixels[dst_index + 1] = rect.pixels[src_index + 1];
|
||||||
let src_slice = &rect.pixels.get_unchecked(src_start..src_start + w * 4);
|
self.pixels[dst_index + 2] = rect.pixels[src_index + 2];
|
||||||
let dst_slice = self.pixels.get_unchecked_mut(dst_start..dst_start + w * 4);
|
self.pixels[dst_index + 3] = rect.pixels[src_index + 3];
|
||||||
dst_slice.copy_from_slice(src_slice);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user