diff --git a/.vscode/launch.json b/.vscode/launch.json index 50032d9..8dc01cc 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -21,7 +21,8 @@ }, "args": [ "--filename", - "/home/gabm/Pictures/Screenshots/satty-20240109-22:19:08.png", + "/home/gabm/Pictures/Screenshots/satty-20240219-14:19:29.png", + //"/home/gabm/Pictures/Screenshots/satty-20240109-22:19:08.png", //"/home/gabm/Pictures/Wallpaper/torres_1.jpg" "--output-filename", "/tmp/out.png" diff --git a/src/femtovg_area/imp.rs b/src/femtovg_area/imp.rs index b8588c9..86c284c 100644 --- a/src/femtovg_area/imp.rs +++ b/src/femtovg_area/imp.rs @@ -38,6 +38,7 @@ pub struct FemtoVgAreaMut { active_tool: Rc>, crop_tool: Rc>, scale_factor: f32, + offset: Vec2D, drawables: Vec>, redo_stack: Vec>, } @@ -86,7 +87,7 @@ impl GLAreaImpl for FemtoVGArea { self.inner() .as_mut() .expect("Did you call init before using FemtoVgArea?") - .update_scale_factor(canvas); + .update_transformation(canvas); } fn render(&self, _context: >k::gdk::GLContext) -> bool { self.ensure_canvas(); @@ -147,6 +148,7 @@ impl FemtoVGArea { active_tool, crop_tool, scale_factor: 1.0, + offset: Vec2D::zero(), drawables: Vec::new(), redo_stack: Vec::new(), }); @@ -299,13 +301,8 @@ impl FemtoVgAreaMut { // setup transform to image coordinates let mut transform = Transform2D::identity(); - let offset_x = - canvas.width() as f32 - self.background_image.width() as f32 * self.scale_factor; - let offset_y = - canvas.height() as f32 - self.background_image.height() as f32 * self.scale_factor; - transform.scale(self.scale_factor, self.scale_factor); - transform.translate(offset_x / 2.0, offset_y / 2.0); + transform.translate(self.offset.x, self.offset.y); canvas.reset_transform(); canvas.set_transform(&transform); @@ -440,7 +437,11 @@ impl FemtoVgAreaMut { Ok(background_image_id) } - pub fn update_scale_factor(&mut self, canvas: &mut femtovg::Canvas) { + pub fn update_transformation( + &mut self, + canvas: &mut femtovg::Canvas, + ) { + // calculate scale let image_width = self.background_image.width() as f32; let image_height = self.background_image.height() as f32; let aspect_ratio = image_width / image_height; @@ -453,9 +454,26 @@ impl FemtoVgAreaMut { } else { canvas_height * aspect_ratio / image_width }; + + // calculate offset + self.offset = Vec2D::new( + (canvas.width() as f32 - self.background_image.width() as f32 * self.scale_factor) + / 2.0, + (canvas.height() as f32 - self.background_image.height() as f32 * self.scale_factor) + / 2.0, + ); } - pub fn get_scale_factor(&self) -> f32 { - self.scale_factor + pub fn abs_canvas_to_image_coordinates(&self, input: Vec2D, dpi_scale_factor: f32) -> Vec2D { + Vec2D::new( + (input.x * dpi_scale_factor - self.offset.x) / self.scale_factor, + (input.y * dpi_scale_factor - self.offset.y) / self.scale_factor, + ) + } + pub fn rel_canvas_to_image_coordinates(&self, input: Vec2D, dpi_scale_factor: f32) -> Vec2D { + Vec2D::new( + input.x * dpi_scale_factor / self.scale_factor, + input.y * dpi_scale_factor / self.scale_factor, + ) } } diff --git a/src/femtovg_area/mod.rs b/src/femtovg_area/mod.rs index 6fdb825..e9b543a 100644 --- a/src/femtovg_area/mod.rs +++ b/src/femtovg_area/mod.rs @@ -10,6 +10,7 @@ use relm4::{ }; use crate::{ + math::Vec2D, sketch_board::{Action, SketchBoardInput}, tools::{CropTool, Drawable, Tool}, }; @@ -59,16 +60,20 @@ impl FemtoVGArea { self.imp().request_render(action); } - pub fn get_scale_factor(&self) -> f32 { - let renderer_scale_factor = self - .imp() + pub fn abs_canvas_to_image_coordinates(&self, input: Vec2D) -> Vec2D { + self.imp() .inner() .as_mut() .expect("Did you call init before using FemtoVgArea?") - .get_scale_factor(); - let dpi_scale_factor = self.scale_factor() as f32; + .abs_canvas_to_image_coordinates(input, self.scale_factor() as f32) + } - renderer_scale_factor / dpi_scale_factor + pub fn rel_canvas_to_image_coordinates(&self, input: Vec2D) -> Vec2D { + self.imp() + .inner() + .as_mut() + .expect("Did you call init before using FemtoVgArea?") + .rel_canvas_to_image_coordinates(input, self.scale_factor() as f32) } pub fn init( &mut self, diff --git a/src/sketch_board.rs b/src/sketch_board.rs index d5b4bb6..8b4afe4 100644 --- a/src/sketch_board.rs +++ b/src/sketch_board.rs @@ -70,7 +70,7 @@ pub enum TextEventMsg { Commit(String), } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] pub enum MouseEventType { BeginDrag, EndDrag, @@ -122,14 +122,16 @@ impl From for MouseButton { } impl InputEvent { - fn screen2image(p: &mut Vec2D, scale: f32) { - p.x /= scale; - p.y /= scale; - } - - fn remap_event_coordinates(&mut self, scale: f32) { + fn remap_event_coordinates(&mut self, renderer: &FemtoVGArea) { if let InputEvent::Mouse(me) = self { - Self::screen2image(&mut me.pos, scale) + match me.type_ { + MouseEventType::BeginDrag | MouseEventType::Click => { + me.pos = renderer.abs_canvas_to_image_coordinates(me.pos) + } + MouseEventType::EndDrag | MouseEventType::UpdateDrag => { + me.pos = renderer.rel_canvas_to_image_coordinates(me.pos) + } + } }; } } @@ -440,7 +442,7 @@ impl Component for SketchBoard { .handle_event(ToolEvent::Input(ie)) } } else { - ie.remap_event_coordinates(self.renderer.get_scale_factor()); + ie.remap_event_coordinates(&self.renderer); self.active_tool .borrow_mut() .handle_event(ToolEvent::Input(ie))