refactor: improve code readability by formatting and restructuring function parameters and logic
This commit is contained in:
@@ -117,17 +117,25 @@ impl Engine {
|
||||
if mask.len() != full_size {
|
||||
let mut full_mask = vec![layer.mask_default_color; full_size];
|
||||
if let Some(mb) = layer.mask_bounds {
|
||||
let (m_top, m_left, m_bottom, m_right) =
|
||||
(mb[0].max(0) as u32, mb[1].max(0) as u32, mb[2].max(0) as u32, mb[3].max(0) as u32);
|
||||
let (m_top, m_left, m_bottom, m_right) = (
|
||||
mb[0].max(0) as u32,
|
||||
mb[1].max(0) as u32,
|
||||
mb[2].max(0) as u32,
|
||||
mb[3].max(0) as u32,
|
||||
);
|
||||
let mw = (m_right - m_left) as usize;
|
||||
let mh = (m_bottom - m_top) as usize;
|
||||
if mw > 0 && mh > 0 && mask.len() == mw * mh {
|
||||
for y in 0..mh {
|
||||
let gy = m_top as usize + y;
|
||||
if gy >= ch as usize { break; }
|
||||
if gy >= ch as usize {
|
||||
break;
|
||||
}
|
||||
for x in 0..mw {
|
||||
let gx = m_left as usize + x;
|
||||
if gx >= cw as usize { break; }
|
||||
if gx >= cw as usize {
|
||||
break;
|
||||
}
|
||||
full_mask[gy * cw as usize + gx] = mask[y * mw + x];
|
||||
}
|
||||
}
|
||||
@@ -181,7 +189,9 @@ impl Engine {
|
||||
let cw = self.document.canvas_width as usize;
|
||||
let ch = self.document.canvas_height as usize;
|
||||
let mask_len = cw * ch;
|
||||
if mask_len == 0 { return; }
|
||||
if mask_len == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(layer) = self.document.get_layer_by_id_mut(layer_id) {
|
||||
if layer.mask_pixels.is_none() {
|
||||
@@ -294,7 +304,13 @@ impl Engine {
|
||||
|
||||
self.draw_target_pixels_or_mask(
|
||||
layer_id,
|
||||
|pixels, lw, lh, mask_ref, active_stroke_mask, stroke_before_buf, sketch_history| {
|
||||
|pixels,
|
||||
lw,
|
||||
lh,
|
||||
mask_ref,
|
||||
active_stroke_mask,
|
||||
stroke_before_buf,
|
||||
sketch_history| {
|
||||
let sketch_hist = if tip.style == BrushStyle::Sketch {
|
||||
sketch_history
|
||||
} else {
|
||||
@@ -361,8 +377,15 @@ impl Engine {
|
||||
if self.editing_mask {
|
||||
self.draw_target_pixels_or_mask(
|
||||
layer_id,
|
||||
|pixels, lw, lh, mask_ref, active_stroke_mask, stroke_before_buf, _sketch_history| {
|
||||
let mut temp_layer = hcie_protocol::Layer::from_rgba("temp", lw, lh, pixels.to_vec());
|
||||
|pixels,
|
||||
lw,
|
||||
lh,
|
||||
mask_ref,
|
||||
active_stroke_mask,
|
||||
stroke_before_buf,
|
||||
_sketch_history| {
|
||||
let mut temp_layer =
|
||||
hcie_protocol::Layer::from_rgba("temp", lw, lh, pixels.to_vec());
|
||||
draw_brush_stroke(
|
||||
&mut temp_layer,
|
||||
&[(x, y, pressure)],
|
||||
|
||||
@@ -2901,11 +2901,14 @@ impl HcieIcedApp {
|
||||
let paint_tool =
|
||||
matches!(tool, Tool::Pen | Tool::Brush | Tool::Eraser | Tool::Spray);
|
||||
if paint_tool && (self.modifiers.control() || self.modifiers.logo()) {
|
||||
let cx = canvas_x as u32;
|
||||
let cy = canvas_y as u32;
|
||||
let width = self.documents[self.active_doc].engine.canvas_width();
|
||||
if cx < width && cy < self.documents[self.active_doc].engine.canvas_height() {
|
||||
let index = ((cy * width + cx) * 4) as usize;
|
||||
let height = self.documents[self.active_doc].engine.canvas_height();
|
||||
if canvas_x >= 0.0
|
||||
&& canvas_y >= 0.0
|
||||
&& (canvas_x as u32) < width
|
||||
&& (canvas_y as u32) < height
|
||||
{
|
||||
let index = ((canvas_y as u32 * width + canvas_x as u32) * 4) as usize;
|
||||
if index + 3 < self.documents[self.active_doc].composite_raw.len() {
|
||||
let pixels = &self.documents[self.active_doc].composite_raw;
|
||||
let color = [
|
||||
@@ -3247,13 +3250,11 @@ impl HcieIcedApp {
|
||||
let is_ctrl = self.modifiers.control() || self.modifiers.logo();
|
||||
if is_ctrl {
|
||||
// Pick color
|
||||
let cx = x as u32;
|
||||
let cy = y as u32;
|
||||
let w = self.documents[self.active_doc].engine.canvas_width();
|
||||
let h = self.documents[self.active_doc].engine.canvas_height();
|
||||
if cx < w && cy < h {
|
||||
if x >= 0.0 && y >= 0.0 && (x as u32) < w && (y as u32) < h {
|
||||
let pixels = &self.documents[self.active_doc].composite_raw;
|
||||
let idx = ((cy * w + cx) * 4) as usize;
|
||||
let idx = ((y as u32 * w + x as u32) * 4) as usize;
|
||||
if idx + 3 < pixels.len() {
|
||||
let color = [
|
||||
pixels[idx],
|
||||
@@ -3719,7 +3720,9 @@ impl HcieIcedApp {
|
||||
}
|
||||
|
||||
Message::LayerSetEditMask(editing) => {
|
||||
self.documents[self.active_doc].engine.set_editing_mask(editing);
|
||||
self.documents[self.active_doc]
|
||||
.engine
|
||||
.set_editing_mask(editing);
|
||||
self.documents[self.active_doc].cached_layers =
|
||||
self.documents[self.active_doc].engine.layer_infos();
|
||||
}
|
||||
@@ -6711,10 +6714,8 @@ impl HcieIcedApp {
|
||||
self.settings.tool_settings.vector_angle = angle.to_degrees();
|
||||
|
||||
// Track snap state for visual overlay feedback
|
||||
let is_rotate = matches!(
|
||||
session.handle,
|
||||
hcie_engine_api::VectorEditHandle::Rotate
|
||||
);
|
||||
let is_rotate =
|
||||
matches!(session.handle, hcie_engine_api::VectorEditHandle::Rotate);
|
||||
let is_resize = matches!(
|
||||
session.handle,
|
||||
hcie_engine_api::VectorEditHandle::TopLeft
|
||||
@@ -7784,7 +7785,8 @@ impl HcieIcedApp {
|
||||
}
|
||||
Message::PasteImage => {
|
||||
// Check internal clipboard first
|
||||
if let Some(transform) = self.documents[self.active_doc].internal_clipboard.clone() {
|
||||
if let Some(transform) = self.documents[self.active_doc].internal_clipboard.clone()
|
||||
{
|
||||
// Enter transform mode with the clipboard content
|
||||
let mut placed = transform;
|
||||
placed.pos.x += 10.0;
|
||||
@@ -8481,12 +8483,10 @@ impl HcieIcedApp {
|
||||
return self.update(Message::OpenFileRfd);
|
||||
}
|
||||
|
||||
Message::FileOpened(Ok(path)) => {
|
||||
match self.open_path_in_new_tab(path, true) {
|
||||
Ok(_) => return Task::perform(async {}, |_| Message::CompositeRefresh),
|
||||
Err(error) => log::error!("Failed to open file: {error}"),
|
||||
}
|
||||
}
|
||||
Message::FileOpened(Ok(path)) => match self.open_path_in_new_tab(path, true) {
|
||||
Ok(_) => return Task::perform(async {}, |_| Message::CompositeRefresh),
|
||||
Err(error) => log::error!("Failed to open file: {error}"),
|
||||
},
|
||||
|
||||
Message::FileOpened(Err(e)) => {
|
||||
log::error!("Failed to open file: {}", e);
|
||||
@@ -9153,9 +9153,7 @@ impl HcieIcedApp {
|
||||
| crate::theme::ThemePreset::ProDark
|
||||
| crate::theme::ThemePreset::Amoled => crate::theme::ThemePreset::ProLight,
|
||||
crate::theme::ThemePreset::PhotoshopLight
|
||||
| crate::theme::ThemePreset::ProLight => {
|
||||
crate::theme::ThemePreset::Photopea
|
||||
}
|
||||
| crate::theme::ThemePreset::ProLight => crate::theme::ThemePreset::Photopea,
|
||||
};
|
||||
self.theme_state.set_preset(new_preset);
|
||||
self.settings.theme_preset = new_preset;
|
||||
@@ -10308,10 +10306,8 @@ mod cycle_one_ux_tests {
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos();
|
||||
let path = std::env::temp_dir().join(format!(
|
||||
"hcie-open-tab-{}-{unique}.png",
|
||||
std::process::id()
|
||||
));
|
||||
let path =
|
||||
std::env::temp_dir().join(format!("hcie-open-tab-{}-{unique}.png", std::process::id()));
|
||||
image::save_buffer(
|
||||
&path,
|
||||
&[255, 0, 0, 255, 0, 255, 0, 255],
|
||||
@@ -10328,7 +10324,10 @@ mod cycle_one_ux_tests {
|
||||
assert_eq!(app.active_doc, 1);
|
||||
assert_eq!(app.documents[0].name, original_name);
|
||||
assert!(app.documents[0].source_path.is_none());
|
||||
assert_eq!(app.documents[1].source_path.as_deref(), Some(path.as_path()));
|
||||
assert_eq!(
|
||||
app.documents[1].source_path.as_deref(),
|
||||
Some(path.as_path())
|
||||
);
|
||||
assert_eq!(app.documents[1].engine.canvas_width(), 2);
|
||||
assert_eq!(app.documents[1].engine.canvas_height(), 1);
|
||||
|
||||
|
||||
@@ -985,8 +985,7 @@ fn should_publish_cursor_status(
|
||||
current: (u32, u32),
|
||||
elapsed: Option<std::time::Duration>,
|
||||
) -> bool {
|
||||
previous != Some(current)
|
||||
&& elapsed.map_or(true, |duration| duration >= CURSOR_STATUS_INTERVAL)
|
||||
previous != Some(current) && elapsed.map_or(true, |duration| duration >= CURSOR_STATUS_INTERVAL)
|
||||
}
|
||||
|
||||
/// Canvas shader program — implements `iced::widget::shader::Program`.
|
||||
|
||||
@@ -110,23 +110,44 @@ impl Program<Message> for CanvasViewportProgram {
|
||||
let mut frame = Frame::new(bounds.size());
|
||||
|
||||
// Draw checkerboard background (tiled to cover display area)
|
||||
let checker_pattern = canvas::Pattern::new(&cfg.checker_handle).mode(canvas::PatternMode::Repeat);
|
||||
let checker_path = Path::rectangle(Point::new(origin_x, origin_y), Size::new(display_w, display_h));
|
||||
let checker_pattern =
|
||||
canvas::Pattern::new(&cfg.checker_handle).mode(canvas::PatternMode::Repeat);
|
||||
let checker_path = Path::rectangle(
|
||||
Point::new(origin_x, origin_y),
|
||||
Size::new(display_w, display_h),
|
||||
);
|
||||
frame.fill(&checker_path, checker_pattern);
|
||||
|
||||
// Draw composite texture
|
||||
let composite_image = canvas::Image::new(&cfg.composite_handle)
|
||||
.destination_rectangle(Rectangle::new(Point::new(origin_x, origin_y), Size::new(display_w, display_h)));
|
||||
let composite_image =
|
||||
canvas::Image::new(&cfg.composite_handle).destination_rectangle(Rectangle::new(
|
||||
Point::new(origin_x, origin_y),
|
||||
Size::new(display_w, display_h),
|
||||
));
|
||||
frame.draw_image(composite_image);
|
||||
|
||||
// Draw canvas border
|
||||
let border_path = Path::rectangle(Point::new(origin_x, origin_y), Size::new(display_w, display_h));
|
||||
frame.stroke(&border_path, Stroke::default().with_color(Color::from_rgb(0.35, 0.35, 0.35)).with_width(1.0));
|
||||
let border_path = Path::rectangle(
|
||||
Point::new(origin_x, origin_y),
|
||||
Size::new(display_w, display_h),
|
||||
);
|
||||
frame.stroke(
|
||||
&border_path,
|
||||
Stroke::default()
|
||||
.with_color(Color::from_rgb(0.35, 0.35, 0.35))
|
||||
.with_width(1.0),
|
||||
);
|
||||
|
||||
vec![frame.into_geometry()]
|
||||
}
|
||||
|
||||
fn update(&self, state: &mut (), event: iced::Event, bounds: Rectangle, cursor: Cursor) -> (iced::widget::canvas::Status, Option<Message>) {
|
||||
fn update(
|
||||
&self,
|
||||
state: &mut (),
|
||||
event: iced::Event,
|
||||
bounds: Rectangle,
|
||||
cursor: Cursor,
|
||||
) -> (iced::widget::canvas::Status, Option<Message>) {
|
||||
let mut program_state = self.state.lock().unwrap();
|
||||
|
||||
match event {
|
||||
@@ -140,17 +161,22 @@ impl Program<Message> for CanvasViewportProgram {
|
||||
iced::mouse::Event::ButtonPressed(iced::mouse::Button::Left) => {
|
||||
if let Some(pos) = program_state.last_cursor {
|
||||
if bounds.contains(pos) {
|
||||
let (cx, cy) = viewport_to_canvas(pos, bounds, &program_state.config);
|
||||
let (cx, cy) =
|
||||
viewport_to_canvas(pos, bounds, &program_state.config);
|
||||
if let Some((cx, cy)) = (cx, cy) {
|
||||
return (iced::widget::canvas::Status::Captured, Some(Message::CanvasPointerPressed { x: cx, y: cy }));
|
||||
return (
|
||||
iced::widget::canvas::Status::Captured,
|
||||
Some(Message::CanvasPointerPressed { x: cx, y: cy }),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
(iced::widget::canvas::Status::Captured, None)
|
||||
}
|
||||
iced::mouse::Event::ButtonReleased(iced::mouse::Button::Left) => {
|
||||
(iced::widget::canvas::Status::Captured, Some(Message::CanvasPointerReleased))
|
||||
}
|
||||
iced::mouse::Event::ButtonReleased(iced::mouse::Button::Left) => (
|
||||
iced::widget::canvas::Status::Captured,
|
||||
Some(Message::CanvasPointerReleased),
|
||||
),
|
||||
iced::mouse::Event::Scrolled { delta } => {
|
||||
if program_state.is_hovered {
|
||||
let scroll_delta = match delta {
|
||||
@@ -164,7 +190,12 @@ impl Program<Message> for CanvasViewportProgram {
|
||||
let new_zoom = (old_zoom * factor).clamp(0.1, 10.0);
|
||||
|
||||
if let Some(cursor_pos) = program_state.last_cursor {
|
||||
let (canvas_x, canvas_y) = viewport_to_canvas(cursor_pos, bounds, &program_state.config).unwrap_or((0.0, 0.0));
|
||||
let (canvas_x, canvas_y) = viewport_to_canvas(
|
||||
cursor_pos,
|
||||
bounds,
|
||||
&program_state.config,
|
||||
)
|
||||
.unwrap_or((0.0, 0.0));
|
||||
|
||||
// Calculate new pan_offset to keep cursor over same canvas point
|
||||
let display_w = program_state.config.engine_w as f32 * new_zoom;
|
||||
@@ -174,11 +205,18 @@ impl Program<Message> for CanvasViewportProgram {
|
||||
let new_default_origin_x = (bounds.width - display_w) / 2.0;
|
||||
let new_default_origin_y = (bounds.height - display_h) / 2.0;
|
||||
|
||||
program_state.config.pan_offset.x = new_origin_x - new_default_origin_x;
|
||||
program_state.config.pan_offset.y = new_origin_y - new_default_origin_y;
|
||||
program_state.config.pan_offset.x =
|
||||
new_origin_x - new_default_origin_x;
|
||||
program_state.config.pan_offset.y =
|
||||
new_origin_y - new_default_origin_y;
|
||||
}
|
||||
program_state.config.zoom = new_zoom;
|
||||
return (iced::widget::canvas::Status::Captured, Some(Message::CanvasZoom { delta: scroll_delta }));
|
||||
return (
|
||||
iced::widget::canvas::Status::Captured,
|
||||
Some(Message::CanvasZoom {
|
||||
delta: scroll_delta,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
(iced::widget::canvas::Status::Ignored, None)
|
||||
@@ -190,7 +228,12 @@ impl Program<Message> for CanvasViewportProgram {
|
||||
}
|
||||
}
|
||||
|
||||
fn mouse_interaction(&self, _state: &(), bounds: Rectangle, cursor: Cursor) -> iced::mouse::Interaction {
|
||||
fn mouse_interaction(
|
||||
&self,
|
||||
_state: &(),
|
||||
bounds: Rectangle,
|
||||
cursor: Cursor,
|
||||
) -> iced::mouse::Interaction {
|
||||
if cursor.is_over(bounds) {
|
||||
iced::mouse::Interaction::Crosshair
|
||||
} else {
|
||||
@@ -203,7 +246,11 @@ impl Program<Message> for CanvasViewportProgram {
|
||||
///
|
||||
/// Returns signed canvas coordinates even when the cursor is outside the canvas
|
||||
/// image so brush strokes can start or continue beyond the visible edges.
|
||||
fn viewport_to_canvas(viewport_pos: Point, bounds: Rectangle, config: &CanvasViewportConfig) -> Option<(f32, f32)> {
|
||||
fn viewport_to_canvas(
|
||||
viewport_pos: Point,
|
||||
bounds: Rectangle,
|
||||
config: &CanvasViewportConfig,
|
||||
) -> Option<(f32, f32)> {
|
||||
let display_w = config.engine_w as f32 * config.zoom;
|
||||
let display_h = config.engine_h as f32 * config.zoom;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user