feat: 更新曲线和多边形功能状态控制
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
142
src/paint.rs
142
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<Point>,
|
||||
|
||||
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 的图像句柄
|
||||
|
||||
Reference in New Issue
Block a user