diff --git a/src/mscanvas.rs b/src/mscanvas.rs index 6d335cd..0463d60 100644 --- a/src/mscanvas.rs +++ b/src/mscanvas.rs @@ -731,14 +731,7 @@ impl MSCanvas { /// - x, y: 左上角坐标 /// - width, height: 尺寸(必须 > 0) /// - radius: 圆角半径(会被 clamp 到合理范围) - pub fn fill_round_rect( - &mut self, - x: f32, - y: f32, - width: f32, - height: f32, - radius: f32, - ) { + pub fn fill_round_rect(&mut self, x: f32, y: f32, width: f32, height: f32, radius: f32) { if (width as i32) <= 2 * self.line_width || (height as i32) <= 2 * self.line_width || width <= 2.0 * radius @@ -755,10 +748,13 @@ impl MSCanvas { // 预计算四个圆角的圆心 let corners = [ - ((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 + height - 1.0 - radius) as i32), // 右下 - ((x + radius) as i32, (y + height - 1.0 - 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 + height - 1.0 - radius) as i32, + ), // 右下 + ((x + radius) as i32, (y + height - 1.0 - radius) as i32), // 左下 ]; let min_x = min_x as i32; @@ -906,13 +902,13 @@ impl MSCanvas { pub fn rect(&mut self, x: i32, y: i32, width: i32, height: i32) { 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; } - self.fill_rect(x, y, width, self.line_width); - self.fill_rect(x, y + height - self.line_width, width, self.line_width); - self.fill_rect(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, y, width, self.line_width); + self.fill_rect_foreground_color(x, y + height - self.line_width, width, self.line_width); + self.fill_rect_foreground_color(x, 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) { @@ -997,7 +993,7 @@ impl MSCanvas { while t <= 1.0 { let point = self.recursive_bezier(&control_points, t); self.brush_circle(point); - t += 0.001; + t += 0.0005; } } @@ -1215,4 +1211,4 @@ fn distance_sq1(a: (i32, i32), b: (i32, i32)) -> f32 { let dx = a.0 - b.0; let dy = a.1 - b.1; (dx * dx + dy * dy) as f32 -} \ No newline at end of file +} diff --git a/src/paint.rs b/src/paint.rs index 12f6b6f..7eadafb 100644 --- a/src/paint.rs +++ b/src/paint.rs @@ -246,6 +246,14 @@ impl Config { } } +#[derive(Debug, Clone, Copy, PartialEq)] +enum ControlState { + Zero, + One, + Two, + Three, +} + struct PaintApp { tool_states: [bool; Tool::Count as usize], tool_selected: Tool, @@ -261,11 +269,9 @@ struct PaintApp { end_point: Point, /// 贝塞尔曲线控制 - is_controlling: bool, + control_state: ControlState, control_points: Vec, - is_path_beginning: bool, - /// 用于显示的图像句柄缓存 /// 每次像素变化后需要重新生成 image_handle: image::Handle, @@ -290,7 +296,6 @@ impl PaintApp { let pixels = canvas.get_pixels(); let config = Config::default(); canvas.set_line_width(config.line_width); - canvas.set_background_color(MSColor::GREEN); Self { tool_states: [false; Tool::Count as usize], tool_selected: Tool::Count, @@ -298,9 +303,8 @@ impl PaintApp { is_drawing: false, begin_point: Point::ORIGIN, end_point: Point::ORIGIN, - is_controlling: false, + control_state: ControlState::Zero, control_points: Vec::with_capacity(2), - is_path_beginning: false, image_handle: image::Handle::from_rgba(width as u32, height as u32, pixels), dirty: false, config, @@ -797,46 +801,79 @@ impl PaintApp { pub fn update_with_curve(&mut self, message: Message) { match message { - Message::MousePressed(pos) => { - if self.is_controlling { - if self.control_points.len() == 0 { - self.canvas.restore_pixels(); - self.canvas - .quadratic_bezier(self.begin_point, self.end_point, pos); - self.control_points.push(pos); - } else { - self.canvas.restore_pixels(); - self.canvas.cubic_bezier( - self.begin_point, - self.end_point, - self.control_points[0], - pos, - ); - self.control_points.push(pos); - } - self.dirty = true; - } else { + Message::MousePressed(pos) => match self.control_state { + ControlState::Zero => { + self.begin_point = pos; self.is_drawing = true; self.canvas.save_pixels(); - self.begin_point = pos; + self.control_state = ControlState::One; } - } + ControlState::One => { + self.is_drawing = true; + self.canvas.restore_pixels(); + self.canvas + .quadratic_bezier(self.begin_point, self.end_point, pos); + self.dirty = true; + self.control_state = ControlState::Two; + } + ControlState::Two => { + self.is_drawing = true; + self.canvas.restore_pixels(); + self.canvas.cubic_bezier( + self.begin_point, + self.end_point, + self.control_points[0], + pos, + ); + self.dirty = true; + self.control_state = ControlState::Three; + } + _ => {} + }, 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.is_controlling = false; + self.is_drawing = false; + match self.control_state { + ControlState::One => { + self.end_point = pos; + } + ControlState::Two => { + self.control_points.push(pos); + } + ControlState::Three => { + self.control_state = ControlState::Zero; + self.control_points.clear(); + } + _ => {} } } Message::MouseMoved(pos) => { if self.is_drawing { - self.canvas.restore_pixels(); - self.canvas - .draw_line_with_circle_brush(self.begin_point, pos); - self.dirty = true; + match self.control_state { + ControlState::One => { + self.canvas.restore_pixels(); + self.canvas + .draw_line_with_circle_brush(self.begin_point, pos); + 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) => { if self.is_drawing { self.canvas.restore_pixels(); - self.canvas.stroke_rect1(self.begin_point, pos); + self.canvas.rect1(self.begin_point, pos); self.dirty = true; } } @@ -867,24 +904,27 @@ impl PaintApp { pub fn update_with_polygon(&mut self, message: Message) { match message { - Message::MousePressed(pos) => { - if self.is_path_beginning { + Message::MousePressed(pos) => match self.control_state { + 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.canvas.restore_pixels(); self.canvas.stroke(); self.canvas .draw_line_with_circle_brush(self.begin_point, pos); 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) => { + self.is_drawing = false; self.canvas.line_to(pos); self.begin_point = pos; } @@ -901,7 +941,7 @@ impl PaintApp { self.canvas.close_path(); self.canvas.stroke(); self.is_drawing = false; - self.is_path_beginning = false; + self.control_state = ControlState::Zero; self.dirty = true; } _ => {} @@ -978,7 +1018,7 @@ impl PaintApp { self.tool_selected = idx.into(); self.is_drawing = false; - self.is_path_beginning = false; + self.control_state = ControlState::Zero; } /// 将原始字节转换为 Iced 的图像句柄