feat: 更新曲线和多边形功能状态控制

This commit is contained in:
2026-03-03 00:52:19 +08:00
parent a261d975c1
commit 02c18c7387
2 changed files with 106 additions and 70 deletions

View File

@@ -731,14 +731,7 @@ impl MSCanvas {
/// - x, y: 左上角坐标 /// - x, y: 左上角坐标
/// - width, height: 尺寸(必须 > 0 /// - width, height: 尺寸(必须 > 0
/// - radius: 圆角半径(会被 clamp 到合理范围) /// - radius: 圆角半径(会被 clamp 到合理范围)
pub fn fill_round_rect( pub fn fill_round_rect(&mut self, x: f32, y: f32, width: f32, height: f32, radius: f32) {
&mut self,
x: f32,
y: f32,
width: f32,
height: f32,
radius: f32,
) {
if (width as i32) <= 2 * self.line_width if (width as i32) <= 2 * self.line_width
|| (height as i32) <= 2 * self.line_width || (height as i32) <= 2 * self.line_width
|| width <= 2.0 * radius || width <= 2.0 * radius
@@ -757,7 +750,10 @@ impl MSCanvas {
let corners = [ let corners = [
((x + radius) as i32, (y + radius) as i32), // 左上 ((x + radius) as i32, (y + radius) as i32), // 左上
((x + width - 1.0 - radius) as i32, (y + radius) as i32), // 右上 ((x + width - 1.0 - radius) as i32, (y + radius) as i32), // 右上
((x + width - 1.0 - radius) as i32, (y + height - 1.0 - radius) as i32), // 右下 (
(x + width - 1.0 - radius) as i32,
(y + height - 1.0 - radius) as i32,
), // 右下
((x + radius) as i32, (y + height - 1.0 - radius) as i32), // 左下 ((x + radius) as i32, (y + height - 1.0 - radius) as i32), // 左下
]; ];
@@ -906,13 +902,13 @@ impl MSCanvas {
pub fn rect(&mut self, x: i32, y: i32, width: i32, height: i32) { pub fn rect(&mut self, x: i32, y: i32, width: i32, height: i32) {
if width < 2 * self.line_width || height < 2 * self.line_width { if width < 2 * self.line_width || height < 2 * self.line_width {
self.fill_rect(x, y, width, height); self.fill_rect_foreground_color(x, y, width, height);
return; return;
} }
self.fill_rect(x, y, width, self.line_width); self.fill_rect_foreground_color(x, y, width, self.line_width);
self.fill_rect(x, y + height - self.line_width, width, self.line_width); self.fill_rect_foreground_color(x, y + height - self.line_width, width, self.line_width);
self.fill_rect(x, y, self.line_width, height); self.fill_rect_foreground_color(x, y, self.line_width, height);
self.fill_rect(x + width - self.line_width, y, self.line_width, height); self.fill_rect_foreground_color(x + width - self.line_width, y, self.line_width, height);
} }
pub fn rect1(&mut self, p1: Point, p2: Point) { pub fn rect1(&mut self, p1: Point, p2: Point) {
@@ -997,7 +993,7 @@ impl MSCanvas {
while t <= 1.0 { while t <= 1.0 {
let point = self.recursive_bezier(&control_points, t); let point = self.recursive_bezier(&control_points, t);
self.brush_circle(point); self.brush_circle(point);
t += 0.001; t += 0.0005;
} }
} }

View File

@@ -246,6 +246,14 @@ impl Config {
} }
} }
#[derive(Debug, Clone, Copy, PartialEq)]
enum ControlState {
Zero,
One,
Two,
Three,
}
struct PaintApp { struct PaintApp {
tool_states: [bool; Tool::Count as usize], tool_states: [bool; Tool::Count as usize],
tool_selected: Tool, tool_selected: Tool,
@@ -261,11 +269,9 @@ struct PaintApp {
end_point: Point, end_point: Point,
/// 贝塞尔曲线控制 /// 贝塞尔曲线控制
is_controlling: bool, control_state: ControlState,
control_points: Vec<Point>, control_points: Vec<Point>,
is_path_beginning: bool,
/// 用于显示的图像句柄缓存 /// 用于显示的图像句柄缓存
/// 每次像素变化后需要重新生成 /// 每次像素变化后需要重新生成
image_handle: image::Handle, image_handle: image::Handle,
@@ -290,7 +296,6 @@ impl PaintApp {
let pixels = canvas.get_pixels(); let pixels = canvas.get_pixels();
let config = Config::default(); let config = Config::default();
canvas.set_line_width(config.line_width); canvas.set_line_width(config.line_width);
canvas.set_background_color(MSColor::GREEN);
Self { Self {
tool_states: [false; Tool::Count as usize], tool_states: [false; Tool::Count as usize],
tool_selected: Tool::Count, tool_selected: Tool::Count,
@@ -298,9 +303,8 @@ impl PaintApp {
is_drawing: false, is_drawing: false,
begin_point: Point::ORIGIN, begin_point: Point::ORIGIN,
end_point: Point::ORIGIN, end_point: Point::ORIGIN,
is_controlling: false, control_state: ControlState::Zero,
control_points: Vec::with_capacity(2), control_points: Vec::with_capacity(2),
is_path_beginning: false,
image_handle: image::Handle::from_rgba(width as u32, height as u32, pixels), image_handle: image::Handle::from_rgba(width as u32, height as u32, pixels),
dirty: false, dirty: false,
config, config,
@@ -797,14 +801,23 @@ impl PaintApp {
pub fn update_with_curve(&mut self, message: Message) { pub fn update_with_curve(&mut self, message: Message) {
match message { match message {
Message::MousePressed(pos) => { Message::MousePressed(pos) => match self.control_state {
if self.is_controlling { ControlState::Zero => {
if self.control_points.len() == 0 { self.begin_point = pos;
self.is_drawing = true;
self.canvas.save_pixels();
self.control_state = ControlState::One;
}
ControlState::One => {
self.is_drawing = true;
self.canvas.restore_pixels(); self.canvas.restore_pixels();
self.canvas self.canvas
.quadratic_bezier(self.begin_point, self.end_point, pos); .quadratic_bezier(self.begin_point, self.end_point, pos);
self.control_points.push(pos); self.dirty = true;
} else { self.control_state = ControlState::Two;
}
ControlState::Two => {
self.is_drawing = true;
self.canvas.restore_pixels(); self.canvas.restore_pixels();
self.canvas.cubic_bezier( self.canvas.cubic_bezier(
self.begin_point, self.begin_point,
@@ -812,32 +825,56 @@ impl PaintApp {
self.control_points[0], self.control_points[0],
pos, pos,
); );
self.dirty = true;
self.control_state = ControlState::Three;
}
_ => {}
},
Message::MouseReleased(pos) => {
self.is_drawing = false;
match self.control_state {
ControlState::One => {
self.end_point = pos;
}
ControlState::Two => {
self.control_points.push(pos); self.control_points.push(pos);
} }
self.dirty = true; ControlState::Three => {
} else { self.control_state = ControlState::Zero;
self.is_drawing = true;
self.canvas.save_pixels();
self.begin_point = pos;
}
}
Message::MouseReleased(pos) => {
if self.control_points.len() == 0 {
self.is_drawing = false;
self.end_point = pos;
self.is_controlling = true;
} else if self.control_points.len() == 2 {
self.control_points.clear(); self.control_points.clear();
self.is_controlling = false; }
_ => {}
} }
} }
Message::MouseMoved(pos) => { Message::MouseMoved(pos) => {
if self.is_drawing { if self.is_drawing {
match self.control_state {
ControlState::One => {
self.canvas.restore_pixels(); self.canvas.restore_pixels();
self.canvas self.canvas
.draw_line_with_circle_brush(self.begin_point, pos); .draw_line_with_circle_brush(self.begin_point, pos);
self.dirty = true; self.dirty = true;
} }
ControlState::Two => {
self.canvas.restore_pixels();
self.canvas
.quadratic_bezier(self.begin_point, self.end_point, pos);
self.dirty = true;
}
ControlState::Three => {
self.canvas.restore_pixels();
self.canvas.restore_pixels();
self.canvas.cubic_bezier(
self.begin_point,
self.end_point,
self.control_points[0],
pos,
);
self.dirty = true;
}
_ => {}
}
}
} }
_ => {} _ => {}
} }
@@ -857,7 +894,7 @@ impl PaintApp {
Message::MouseMoved(pos) => { Message::MouseMoved(pos) => {
if self.is_drawing { if self.is_drawing {
self.canvas.restore_pixels(); self.canvas.restore_pixels();
self.canvas.stroke_rect1(self.begin_point, pos); self.canvas.rect1(self.begin_point, pos);
self.dirty = true; self.dirty = true;
} }
} }
@@ -867,24 +904,27 @@ impl PaintApp {
pub fn update_with_polygon(&mut self, message: Message) { pub fn update_with_polygon(&mut self, message: Message) {
match message { match message {
Message::MousePressed(pos) => { Message::MousePressed(pos) => match self.control_state {
if self.is_path_beginning { ControlState::Zero => {
self.is_drawing = true;
self.begin_point = pos;
self.canvas.save_pixels();
self.canvas.begin_path();
self.canvas.move_to(pos);
self.control_state = ControlState::One;
}
ControlState::One => {
self.is_drawing = true; self.is_drawing = true;
self.canvas.restore_pixels(); self.canvas.restore_pixels();
self.canvas.stroke(); self.canvas.stroke();
self.canvas self.canvas
.draw_line_with_circle_brush(self.begin_point, pos); .draw_line_with_circle_brush(self.begin_point, pos);
self.dirty = true; self.dirty = true;
} else {
self.is_path_beginning = true;
self.is_drawing = true;
self.canvas.save_pixels();
self.begin_point = pos;
self.canvas.begin_path();
self.canvas.move_to(pos);
}
} }
_ => {}
},
Message::MouseReleased(pos) => { Message::MouseReleased(pos) => {
self.is_drawing = false;
self.canvas.line_to(pos); self.canvas.line_to(pos);
self.begin_point = pos; self.begin_point = pos;
} }
@@ -901,7 +941,7 @@ impl PaintApp {
self.canvas.close_path(); self.canvas.close_path();
self.canvas.stroke(); self.canvas.stroke();
self.is_drawing = false; self.is_drawing = false;
self.is_path_beginning = false; self.control_state = ControlState::Zero;
self.dirty = true; self.dirty = true;
} }
_ => {} _ => {}
@@ -978,7 +1018,7 @@ impl PaintApp {
self.tool_selected = idx.into(); self.tool_selected = idx.into();
self.is_drawing = false; self.is_drawing = false;
self.is_path_beginning = false; self.control_state = ControlState::Zero;
} }
/// 将原始字节转换为 Iced 的图像句柄 /// 将原始字节转换为 Iced 的图像句柄