feat: allow brush strokes to extend beyond canvas edges in viewport and shader calculations
mandatory-regression-gate / deterministic-tests (push) Waiting to run
mandatory-regression-gate / protected-performance-path (push) Waiting to run

This commit is contained in:
Your Name
2026-07-25 16:34:51 +03:00
parent eb17bf4205
commit 45a231a456
3 changed files with 25 additions and 35 deletions
@@ -1024,8 +1024,9 @@ pub struct CanvasShaderProgram {
/// Convert a viewport-local point to canvas-space coordinates.
///
/// `local_pos` is relative to the shader widget's top-left corner.
/// `viewport_size` is the widget's size. Returns `(Some(x), Some(y))`
/// when inside the canvas image bounds, otherwise `(None, None)`.
/// `viewport_size` is the widget's size. Returns the full signed canvas
/// coordinates even when the cursor is outside the visible canvas image,
/// so brush strokes can continue mathematically beyond the canvas edges.
fn screen_to_canvas_local(
local_pos: Point,
viewport_w: f32,
@@ -1053,17 +1054,7 @@ fn screen_to_canvas_local(
let canvas_x = (local_pos.x - origin_x) / zoom;
let canvas_y = (local_pos.y - origin_y) / zoom;
let cx = if canvas_x >= 0.0 && canvas_x < engine_w {
Some(canvas_x)
} else {
None
};
let cy = if canvas_y >= 0.0 && canvas_y < engine_h {
Some(canvas_y)
} else {
None
};
(cx, cy)
(Some(canvas_x), Some(canvas_y))
}
impl shader::Program<Message> for CanvasShaderProgram {
@@ -1106,8 +1097,8 @@ impl shader::Program<Message> for CanvasShaderProgram {
// Left mouse drag (drawing)
if state.left_pressed {
let cx = canvas_x.unwrap_or(0.0).clamp(0.0, self.engine_w as f32);
let cy = canvas_y.unwrap_or(0.0).clamp(0.0, self.engine_h as f32);
let cx = canvas_x.unwrap_or(0.0);
let cy = canvas_y.unwrap_or(0.0);
return (
iced::event::Status::Captured,
Some(Message::CanvasPointerMoved {
@@ -200,6 +200,9 @@ impl Program<Message> for CanvasViewportProgram {
}
/// Convert viewport-space coordinates to canvas-space coordinates.
///
/// 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)> {
let display_w = config.engine_w as f32 * config.zoom;
let display_h = config.engine_h as f32 * config.zoom;
@@ -210,13 +213,7 @@ fn viewport_to_canvas(viewport_pos: Point, bounds: Rectangle, config: &CanvasVie
let canvas_x = (viewport_pos.x - origin_x) / config.zoom;
let canvas_y = (viewport_pos.y - origin_y) / config.zoom;
if canvas_x >= 0.0 && canvas_x < config.engine_w as f32
&& canvas_y >= 0.0 && canvas_y < config.engine_h as f32
{
Some((canvas_x, canvas_y))
} else {
None
}
Some((canvas_x, canvas_y))
}
/// Build the canvas viewport widget.