From 15ccc852aa64c98ac8a484da8b4b795eab3b49ff Mon Sep 17 00:00:00 2001 From: DerpDays <34582078+DerpDays@users.noreply.github.com> Date: Fri, 29 Mar 2024 00:22:02 +0000 Subject: [PATCH 1/5] feat: add highlighting tool --- icons.toml | 3 +- src/command_line.rs | 2 + src/tools/highlight.rs | 237 +++++++++++++++++++++++++++++++++++++++++ src/tools/mod.rs | 13 ++- src/ui/toolbars.rs | 9 ++ 5 files changed, 261 insertions(+), 3 deletions(-) create mode 100644 src/tools/highlight.rs diff --git a/icons.toml b/icons.toml index cd41309..b705806 100644 --- a/icons.toml +++ b/icons.toml @@ -5,6 +5,7 @@ icons = [ "cursor-regular", "number-circle-1-regular", "drop-regular", + "highlight-regular", "arrow-redo-filled", "arrow-undo-filled", "save-regular", @@ -16,4 +17,4 @@ icons = [ "crop-filled", "arrow-up-right-filled", "rectangle-landscape-regular", -] \ No newline at end of file +] diff --git a/src/command_line.rs b/src/command_line.rs index cb24751..0aa9008 100644 --- a/src/command_line.rs +++ b/src/command_line.rs @@ -64,6 +64,7 @@ pub enum Tools { Text, Marker, Blur, + Highlight, Brush, } @@ -79,6 +80,7 @@ impl std::fmt::Display for Tools { Text => "text", Marker => "marker", Blur => "blur", + Highlight => "highlight", Brush => "brush", }; f.write_str(s) diff --git a/src/tools/highlight.rs b/src/tools/highlight.rs new file mode 100644 index 0000000..b25d064 --- /dev/null +++ b/src/tools/highlight.rs @@ -0,0 +1,237 @@ +use std::cell::RefCell; + +use anyhow::Result; +use femtovg::{imgref::Img, rgb::RGBA, ImageFlags, ImageId, Paint, Path}; + +use relm4::gtk::gdk::Key; + +use crate::{ + math::{self, Vec2D}, + sketch_board::{MouseEventMsg, MouseEventType}, + style::{Size, Style}, +}; + +use super::{Drawable, DrawableClone, Tool, ToolUpdateResult}; + +#[derive(Clone, Debug)] +pub struct Highlight { + top_left: Vec2D, + size: Option, + style: Style, + editing: bool, + cached_image: RefCell>, +} + +impl Highlight { + fn highlight( + &self, + canvas: &mut femtovg::Canvas, + pos: Vec2D, + size: Vec2D, + ) -> Result { + let strength = match self.style.size { + Size::Large => 0.5, + Size::Medium => 0.4, + Size::Small => 0.2, + }; + let img = canvas.screenshot()?; + let scale = canvas.transform().average_scale(); + let scaled_width = canvas.width() as f32 / scale; + let dpi = img.width() as f32 / scaled_width; + + let scaled_x = (pos.x * dpi).round(); + let scaled_y = (pos.y * dpi).round(); + let scaled_width = (size.x * dpi).round(); + let scaled_height = (size.y * dpi).round(); + + // error when any size dim is 0 since img.sub_image panics + if scaled_width == 0. || scaled_height == 0. { + return Err(anyhow::anyhow!("width or height is 0")); + } + let sub = img.sub_image( + scaled_x as usize, + scaled_y as usize, + scaled_width as usize, + scaled_height as usize, + ); + let new_buf = sub + .pixels() + .map(|pixel| { + // Alternate style + // RGBA::new( + // pixel.r.min(self.style.color.r), + // pixel.g.min(self.style.color.g), + // pixel.b.min(self.style.color.b), + // pixel.a, + // ) + RGBA::new( + (((1. - strength) * pixel.r as f64) + (strength * self.style.color.r as f64)) + as u8, + (((1. - strength) * pixel.g as f64) + (strength * self.style.color.g as f64)) + as u8, + (((1. - strength) * pixel.b as f64) + (strength * self.style.color.b as f64)) + as u8, + pixel.a, + ) + }) + .collect::>>(); + + let new_img = Img::new(new_buf, sub.width(), sub.height()); + let final_img_id = canvas.create_image(new_img.as_ref(), ImageFlags::empty())?; + Ok(final_img_id) + } +} + +impl Drawable for Highlight { + fn draw( + &self, + canvas: &mut femtovg::Canvas, + _font: femtovg::FontId, + ) -> Result<()> { + let size = match self.size { + Some(s) => s, + None => return Ok(()), // early exit if none + }; + + let (pos, size) = math::rect_ensure_positive_size(self.top_left, size); + let scale = canvas.transform().average_scale(); + let dimensions = Vec2D::new( + canvas.width() as f32 / scale, + canvas.height() as f32 / scale, + ); + // we clamp the area to the image dimensions so were not stretching the + // highlight when the selection exceeds the image size. + let clamped_pos = Vec2D::new(pos.x.max(0.), pos.y.max(0.)); + let clamped_size = Vec2D::new( + match pos.x.is_sign_negative() { + true => size.x - pos.x.abs(), + false => size.x, + } + .min(dimensions.x - clamped_pos.x), + match pos.y.is_sign_negative() { + true => size.y - pos.y.abs(), + false => size.y, + } + .min(dimensions.y - clamped_pos.y), + ); + if self.editing { + // set style + let paint = + Paint::color(self.style.color.into()).with_line_width(Size::Medium.to_line_width()); + + // make rect + let mut path = Path::new(); + path.rect(clamped_pos.x, clamped_pos.y, clamped_size.x, clamped_size.y); + + // draw + canvas.stroke_path(&path, &paint); + } else { + // create new cached image + if self.cached_image.borrow().is_none() { + match self.highlight(canvas, clamped_pos, clamped_size) { + Ok(hls_image) => self.cached_image.borrow_mut().replace(hls_image), + Err(error) => { + if error.to_string() == "width or height is 0" { + return Ok(()); + } + return Err(error); + } + }; + } + + let mut path = Path::new(); + path.rect(clamped_pos.x, clamped_pos.y, clamped_size.x, clamped_size.y); + canvas.fill_path( + &path, + &Paint::image( + self.cached_image.borrow().unwrap(), // this unwrap is safe because we placed it above + clamped_pos.x, + clamped_pos.y, + clamped_size.x, + clamped_size.y, + 0f32, + 1f32, + ), + ); + } + Ok(()) + } +} + +#[derive(Default)] +pub struct HighlightTool { + highlight: Option, + style: Style, +} + +impl Tool for HighlightTool { + fn handle_mouse_event(&mut self, event: MouseEventMsg) -> ToolUpdateResult { + match event.type_ { + MouseEventType::BeginDrag => { + // start new + self.highlight = Some(Highlight { + top_left: event.pos, + size: None, + style: self.style, + editing: true, + cached_image: RefCell::new(None), + }); + + ToolUpdateResult::Redraw + } + MouseEventType::EndDrag => { + if let Some(a) = &mut self.highlight { + if event.pos == Vec2D::zero() { + self.highlight = None; + + ToolUpdateResult::Redraw + } else { + a.size = Some(event.pos); + a.editing = false; + + let result = a.clone_box(); + self.highlight = None; + + ToolUpdateResult::Commit(result) + } + } else { + ToolUpdateResult::Unmodified + } + } + MouseEventType::UpdateDrag => { + if let Some(a) = &mut self.highlight { + if event.pos == Vec2D::zero() { + return ToolUpdateResult::Unmodified; + } + a.size = Some(event.pos); + + ToolUpdateResult::Redraw + } else { + ToolUpdateResult::Unmodified + } + } + _ => ToolUpdateResult::Unmodified, + } + } + + fn handle_key_event(&mut self, event: crate::sketch_board::KeyEventMsg) -> ToolUpdateResult { + if event.key == Key::Escape && self.highlight.is_some() { + self.highlight = None; + ToolUpdateResult::Redraw + } else { + ToolUpdateResult::Unmodified + } + } + + fn handle_style_event(&mut self, style: Style) -> ToolUpdateResult { + self.style = style; + ToolUpdateResult::Unmodified + } + + fn get_drawable(&self) -> Option<&dyn Drawable> { + match &self.highlight { + Some(d) => Some(d), + None => None, + } + } +} diff --git a/src/tools/mod.rs b/src/tools/mod.rs index 8c444ba..75ecfd6 100644 --- a/src/tools/mod.rs +++ b/src/tools/mod.rs @@ -20,6 +20,7 @@ mod arrow; mod blur; mod brush; mod crop; +mod highlight; mod line; mod marker; mod pointer; @@ -125,6 +126,7 @@ pub enum ToolUpdateResult { pub use arrow::ArrowTool; pub use blur::BlurTool; pub use crop::CropTool; +pub use highlight::HighlightTool; pub use line::LineTool; pub use rectangle::RectangleTool; pub use text::TextTool; @@ -142,7 +144,8 @@ pub enum Tools { Text = 5, Marker = 6, Blur = 7, - Brush = 8, + Highlight = 8, + Brush = 9, } pub struct ToolsManager { @@ -166,6 +169,10 @@ impl ToolsManager { ); tools.insert(Tools::Text, Rc::new(RefCell::new(TextTool::default()))); tools.insert(Tools::Blur, Rc::new(RefCell::new(BlurTool::default()))); + tools.insert( + Tools::Highlight, + Rc::new(RefCell::new(HighlightTool::default())), + ); tools.insert(Tools::Marker, Rc::new(RefCell::new(MarkerTool::default()))); tools.insert(Tools::Brush, Rc::new(RefCell::new(BrushTool::default()))); @@ -214,7 +221,8 @@ impl FromVariant for Tools { 5 => Some(Tools::Text), 6 => Some(Tools::Marker), 7 => Some(Tools::Blur), - 8 => Some(Tools::Brush), + 8 => Some(Tools::Highlight), + 9 => Some(Tools::Brush), _ => None, }) } @@ -231,6 +239,7 @@ impl From for Tools { command_line::Tools::Text => Self::Text, command_line::Tools::Marker => Self::Marker, command_line::Tools::Blur => Self::Blur, + command_line::Tools::Highlight => Self::Highlight, command_line::Tools::Brush => Self::Brush, } } diff --git a/src/ui/toolbars.rs b/src/ui/toolbars.rs index 333b88f..32df401 100644 --- a/src/ui/toolbars.rs +++ b/src/ui/toolbars.rs @@ -171,6 +171,15 @@ impl SimpleComponent for ToolsToolbar { set_tooltip: "Blur", ActionablePlus::set_action::: Tools::Blur, + }, + gtk::ToggleButton { + set_focusable: false, + set_hexpand: false, + + set_icon_name: "highlight-regular", + set_tooltip: "Highlight", + ActionablePlus::set_action::: Tools::Highlight, + }, gtk::Separator {}, gtk::Button { From 7921bd05d6f9fbd05f8e74e258f534b8adbbf1ee Mon Sep 17 00:00:00 2001 From: DerpDays <34582078+DerpDays@users.noreply.github.com> Date: Fri, 29 Mar 2024 00:22:02 +0000 Subject: [PATCH 2/5] chore: remove old highlighting algorithm --- src/tools/highlight.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/tools/highlight.rs b/src/tools/highlight.rs index b25d064..d62ff48 100644 --- a/src/tools/highlight.rs +++ b/src/tools/highlight.rs @@ -57,13 +57,6 @@ impl Highlight { let new_buf = sub .pixels() .map(|pixel| { - // Alternate style - // RGBA::new( - // pixel.r.min(self.style.color.r), - // pixel.g.min(self.style.color.g), - // pixel.b.min(self.style.color.b), - // pixel.a, - // ) RGBA::new( (((1. - strength) * pixel.r as f64) + (strength * self.style.color.r as f64)) as u8, From 20fe467c33f95e5f459a05aa30e0a899f7fcbd65 Mon Sep 17 00:00:00 2001 From: DerpDays <34582078+DerpDays@users.noreply.github.com> Date: Fri, 29 Mar 2024 03:12:32 +0000 Subject: [PATCH 3/5] chore: cleanup and add shadow to drag selection area --- src/tools/highlight.rs | 83 ++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/src/tools/highlight.rs b/src/tools/highlight.rs index d62ff48..ca8f515 100644 --- a/src/tools/highlight.rs +++ b/src/tools/highlight.rs @@ -32,17 +32,26 @@ impl Highlight { let strength = match self.style.size { Size::Large => 0.5, Size::Medium => 0.4, - Size::Small => 0.2, + Size::Small => 0.3, }; let img = canvas.screenshot()?; let scale = canvas.transform().average_scale(); - let scaled_width = canvas.width() as f32 / scale; - let dpi = img.width() as f32 / scaled_width; - let scaled_x = (pos.x * dpi).round(); - let scaled_y = (pos.y * dpi).round(); - let scaled_width = (size.x * dpi).round(); - let scaled_height = (size.y * dpi).round(); + // Ideally i'd want to be able to access the underlying area renderer + // so i'd be able to do a full resolution screenshot and also convert + // the coords which are relative to the main screenshot into abs coords + // for the resulting image e.g. + // + // let img = area.render_native_resolution()?; + // let pos = Vec2D::new( + // pos.x + area.offset.x, + // pos.y + area.offset.y, + // ); + // + let scaled_x = (pos.x * scale).round(); + let scaled_y = (pos.y * scale).round(); + let scaled_width = (size.x * scale).round(); + let scaled_height = (size.y * scale).round(); // error when any size dim is 0 since img.sub_image panics if scaled_width == 0. || scaled_height == 0. { @@ -87,41 +96,29 @@ impl Drawable for Highlight { }; let (pos, size) = math::rect_ensure_positive_size(self.top_left, size); - let scale = canvas.transform().average_scale(); - let dimensions = Vec2D::new( - canvas.width() as f32 / scale, - canvas.height() as f32 / scale, - ); - // we clamp the area to the image dimensions so were not stretching the - // highlight when the selection exceeds the image size. - let clamped_pos = Vec2D::new(pos.x.max(0.), pos.y.max(0.)); - let clamped_size = Vec2D::new( - match pos.x.is_sign_negative() { - true => size.x - pos.x.abs(), - false => size.x, - } - .min(dimensions.x - clamped_pos.x), - match pos.y.is_sign_negative() { - true => size.y - pos.y.abs(), - false => size.y, - } - .min(dimensions.y - clamped_pos.y), - ); - if self.editing { - // set style - let paint = - Paint::color(self.style.color.into()).with_line_width(Size::Medium.to_line_width()); - - // make rect - let mut path = Path::new(); - path.rect(clamped_pos.x, clamped_pos.y, clamped_size.x, clamped_size.y); - // draw - canvas.stroke_path(&path, &paint); + if self.editing { + // box + border to indicate selection + let shadow_paint = Paint::color(femtovg::Color { + r: 0., + g: 0., + b: 0., + a: 0.5, + }); + let mut shadow_path = Path::new(); + shadow_path.rect(pos.x, pos.y, size.x, size.y); + let border_paint = + Paint::color(self.style.color.into()).with_line_width(Size::Small.to_line_width()); + let mut border_path = Path::new(); + border_path.rect(pos.x, pos.y, size.x, size.y); + + canvas.save(); + canvas.fill_path(&shadow_path, &shadow_paint); + canvas.stroke_path(&border_path, &border_paint); } else { // create new cached image if self.cached_image.borrow().is_none() { - match self.highlight(canvas, clamped_pos, clamped_size) { + match self.highlight(canvas, pos, size) { Ok(hls_image) => self.cached_image.borrow_mut().replace(hls_image), Err(error) => { if error.to_string() == "width or height is 0" { @@ -133,15 +130,15 @@ impl Drawable for Highlight { } let mut path = Path::new(); - path.rect(clamped_pos.x, clamped_pos.y, clamped_size.x, clamped_size.y); + path.rect(pos.x, pos.y, size.x, size.y); canvas.fill_path( &path, &Paint::image( self.cached_image.borrow().unwrap(), // this unwrap is safe because we placed it above - clamped_pos.x, - clamped_pos.y, - clamped_size.x, - clamped_size.y, + pos.x, + pos.y, + size.x, + size.y, 0f32, 1f32, ), From c548aae870193b9bbf12bf81de4d684014c6bb35 Mon Sep 17 00:00:00 2001 From: DerpDays <34582078+DerpDays@users.noreply.github.com> Date: Fri, 29 Mar 2024 21:01:49 +0000 Subject: [PATCH 4/5] stop manually mixing rgb and instead use an colored alpha layer --- src/tools/highlight.rs | 133 ++++++++--------------------------------- src/ui/toolbars.rs | 4 -- 2 files changed, 26 insertions(+), 111 deletions(-) diff --git a/src/tools/highlight.rs b/src/tools/highlight.rs index ca8f515..4e73ddc 100644 --- a/src/tools/highlight.rs +++ b/src/tools/highlight.rs @@ -1,7 +1,5 @@ -use std::cell::RefCell; - use anyhow::Result; -use femtovg::{imgref::Img, rgb::RGBA, ImageFlags, ImageId, Paint, Path}; +use femtovg::{Paint, Path}; use relm4::gtk::gdk::Key; @@ -19,69 +17,6 @@ pub struct Highlight { size: Option, style: Style, editing: bool, - cached_image: RefCell>, -} - -impl Highlight { - fn highlight( - &self, - canvas: &mut femtovg::Canvas, - pos: Vec2D, - size: Vec2D, - ) -> Result { - let strength = match self.style.size { - Size::Large => 0.5, - Size::Medium => 0.4, - Size::Small => 0.3, - }; - let img = canvas.screenshot()?; - let scale = canvas.transform().average_scale(); - - // Ideally i'd want to be able to access the underlying area renderer - // so i'd be able to do a full resolution screenshot and also convert - // the coords which are relative to the main screenshot into abs coords - // for the resulting image e.g. - // - // let img = area.render_native_resolution()?; - // let pos = Vec2D::new( - // pos.x + area.offset.x, - // pos.y + area.offset.y, - // ); - // - let scaled_x = (pos.x * scale).round(); - let scaled_y = (pos.y * scale).round(); - let scaled_width = (size.x * scale).round(); - let scaled_height = (size.y * scale).round(); - - // error when any size dim is 0 since img.sub_image panics - if scaled_width == 0. || scaled_height == 0. { - return Err(anyhow::anyhow!("width or height is 0")); - } - let sub = img.sub_image( - scaled_x as usize, - scaled_y as usize, - scaled_width as usize, - scaled_height as usize, - ); - let new_buf = sub - .pixels() - .map(|pixel| { - RGBA::new( - (((1. - strength) * pixel.r as f64) + (strength * self.style.color.r as f64)) - as u8, - (((1. - strength) * pixel.g as f64) + (strength * self.style.color.g as f64)) - as u8, - (((1. - strength) * pixel.b as f64) + (strength * self.style.color.b as f64)) - as u8, - pixel.a, - ) - }) - .collect::>>(); - - let new_img = Img::new(new_buf, sub.width(), sub.height()); - let final_img_id = canvas.create_image(new_img.as_ref(), ImageFlags::empty())?; - Ok(final_img_id) - } } impl Drawable for Highlight { @@ -96,54 +31,39 @@ impl Drawable for Highlight { }; let (pos, size) = math::rect_ensure_positive_size(self.top_left, size); + let strength = match self.style.size { + Size::Large => 0.5, + Size::Medium => 0.4, + Size::Small => 0.3, + }; + let shadow_paint = Paint::color(femtovg::Color::rgba( + self.style.color.r, + self.style.color.g, + self.style.color.b, + (strength * 255.) as u8, + )); if self.editing { - // box + border to indicate selection - let shadow_paint = Paint::color(femtovg::Color { - r: 0., - g: 0., - b: 0., - a: 0.5, - }); - let mut shadow_path = Path::new(); - shadow_path.rect(pos.x, pos.y, size.x, size.y); + canvas.save(); let border_paint = Paint::color(self.style.color.into()).with_line_width(Size::Small.to_line_width()); let mut border_path = Path::new(); border_path.rect(pos.x, pos.y, size.x, size.y); - - canvas.save(); - canvas.fill_path(&shadow_path, &shadow_paint); canvas.stroke_path(&border_path, &border_paint); - } else { - // create new cached image - if self.cached_image.borrow().is_none() { - match self.highlight(canvas, pos, size) { - Ok(hls_image) => self.cached_image.borrow_mut().replace(hls_image), - Err(error) => { - if error.to_string() == "width or height is 0" { - return Ok(()); - } - return Err(error); - } - }; - } - - let mut path = Path::new(); - path.rect(pos.x, pos.y, size.x, size.y); - canvas.fill_path( - &path, - &Paint::image( - self.cached_image.borrow().unwrap(), // this unwrap is safe because we placed it above - pos.x, - pos.y, - size.x, - size.y, - 0f32, - 1f32, - ), - ); } + + let mut shadow_path = Path::new(); + shadow_path.rect(pos.x, pos.y, size.x, size.y); + + canvas.fill_path(&shadow_path, &shadow_paint); + let shadow_paint = Paint::color(femtovg::Color::rgba( + self.style.color.r, + self.style.color.g, + self.style.color.b, + ((strength * 255.) as u8).clamp(0, 255), + )); + + canvas.fill_path(&shadow_path, &shadow_paint); Ok(()) } } @@ -164,7 +84,6 @@ impl Tool for HighlightTool { size: None, style: self.style, editing: true, - cached_image: RefCell::new(None), }); ToolUpdateResult::Redraw diff --git a/src/ui/toolbars.rs b/src/ui/toolbars.rs index 32df401..2d22e72 100644 --- a/src/ui/toolbars.rs +++ b/src/ui/toolbars.rs @@ -152,7 +152,6 @@ impl SimpleComponent for ToolsToolbar { set_icon_name: "text-case-title-regular", set_tooltip: "Text tool", ActionablePlus::set_action::: Tools::Text, - }, gtk::ToggleButton { set_focusable: false, @@ -161,7 +160,6 @@ impl SimpleComponent for ToolsToolbar { set_icon_name: "number-circle-1-regular", set_tooltip: "Numbered Marker", ActionablePlus::set_action::: Tools::Marker, - }, gtk::ToggleButton { set_focusable: false, @@ -170,7 +168,6 @@ impl SimpleComponent for ToolsToolbar { set_icon_name: "drop-regular", set_tooltip: "Blur", ActionablePlus::set_action::: Tools::Blur, - }, gtk::ToggleButton { set_focusable: false, @@ -179,7 +176,6 @@ impl SimpleComponent for ToolsToolbar { set_icon_name: "highlight-regular", set_tooltip: "Highlight", ActionablePlus::set_action::: Tools::Highlight, - }, gtk::Separator {}, gtk::Button { From 8755f86f7f04d8c09d566b74fac4665c5bc931fc Mon Sep 17 00:00:00 2001 From: DerpDays <34582078+DerpDays@users.noreply.github.com> Date: Fri, 29 Mar 2024 21:25:50 +0000 Subject: [PATCH 5/5] chore: cleanup and move strength logic into the style struct --- src/style.rs | 8 ++++++++ src/tools/highlight.rs | 19 +++---------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/style.rs b/src/style.rs index c2f1a25..ccbcc15 100644 --- a/src/style.rs +++ b/src/style.rs @@ -204,4 +204,12 @@ impl Size { Size::Large => 30.0 * size_factor, } } + + pub fn to_highlight_opacity(self) -> u8 { + match self { + Size::Small => 50, + Size::Medium => 100, + Size::Large => 150, + } + } } diff --git a/src/tools/highlight.rs b/src/tools/highlight.rs index 4e73ddc..e67d375 100644 --- a/src/tools/highlight.rs +++ b/src/tools/highlight.rs @@ -27,24 +27,13 @@ impl Drawable for Highlight { ) -> Result<()> { let size = match self.size { Some(s) => s, - None => return Ok(()), // early exit if none + None => return Ok(()), // early exit if size is none }; let (pos, size) = math::rect_ensure_positive_size(self.top_left, size); - let strength = match self.style.size { - Size::Large => 0.5, - Size::Medium => 0.4, - Size::Small => 0.3, - }; - let shadow_paint = Paint::color(femtovg::Color::rgba( - self.style.color.r, - self.style.color.g, - self.style.color.b, - (strength * 255.) as u8, - )); if self.editing { - canvas.save(); + // include a border when selecting an area. let border_paint = Paint::color(self.style.color.into()).with_line_width(Size::Small.to_line_width()); let mut border_path = Path::new(); @@ -55,12 +44,11 @@ impl Drawable for Highlight { let mut shadow_path = Path::new(); shadow_path.rect(pos.x, pos.y, size.x, size.y); - canvas.fill_path(&shadow_path, &shadow_paint); let shadow_paint = Paint::color(femtovg::Color::rgba( self.style.color.r, self.style.color.g, self.style.color.b, - ((strength * 255.) as u8).clamp(0, 255), + self.style.size.to_highlight_opacity(), )); canvas.fill_path(&shadow_path, &shadow_paint); @@ -78,7 +66,6 @@ impl Tool for HighlightTool { fn handle_mouse_event(&mut self, event: MouseEventMsg) -> ToolUpdateResult { match event.type_ { MouseEventType::BeginDrag => { - // start new self.highlight = Some(Highlight { top_left: event.pos, size: None,