From 22585e2845c0b9a3ea7799f576239a5478a18050 Mon Sep 17 00:00:00 2001 From: Davipb Date: Sun, 20 Jun 2021 10:53:41 -0300 Subject: [PATCH] PixelPaint: Expose more complex selection operations Now that we use RectMask internally to store the selection, we can expose more powerful APIs to allow for better control over the image selection. --- .../PixelPaint/RectangleSelectTool.cpp | 2 +- .../Applications/PixelPaint/Selection.cpp | 20 +++++++++++++++++++ Userland/Applications/PixelPaint/Selection.h | 17 +++++++++++++++- Userland/Applications/PixelPaint/main.cpp | 2 +- 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/Userland/Applications/PixelPaint/RectangleSelectTool.cpp b/Userland/Applications/PixelPaint/RectangleSelectTool.cpp index 66b541405f5..70d0c366a76 100644 --- a/Userland/Applications/PixelPaint/RectangleSelectTool.cpp +++ b/Userland/Applications/PixelPaint/RectangleSelectTool.cpp @@ -60,7 +60,7 @@ void RectangleSelectTool::on_mouseup(Layer&, GUI::MouseEvent&, GUI::MouseEvent& m_editor->update(); auto rect_in_image = Gfx::IntRect::from_two_points(m_selection_start, m_selection_end); - m_editor->selection().set(rect_in_image); + m_editor->selection().merge(rect_in_image, Selection::MergeMode::Set); } void RectangleSelectTool::on_keydown(GUI::KeyEvent& key_event) diff --git a/Userland/Applications/PixelPaint/Selection.cpp b/Userland/Applications/PixelPaint/Selection.cpp index 776999069c2..dc1e9e08387 100644 --- a/Userland/Applications/PixelPaint/Selection.cpp +++ b/Userland/Applications/PixelPaint/Selection.cpp @@ -107,6 +107,26 @@ void Selection::clear() m_editor.update(); } +void Selection::merge(Mask const& mask, MergeMode mode) +{ + switch (mode) { + case MergeMode::Set: + m_mask = mask; + break; + case MergeMode::Add: + m_mask.add(mask); + break; + case MergeMode::Subtract: + m_mask.subtract(mask); + break; + case MergeMode::Intersect: + m_mask.intersect(mask); + break; + default: + VERIFY_NOT_REACHED(); + } +} + void Selection::draw_marching_ants_pixel(Gfx::Painter& painter, int x, int y) const { int pattern_index = x + y + m_marching_ants_offset; diff --git a/Userland/Applications/PixelPaint/Selection.h b/Userland/Applications/PixelPaint/Selection.h index f521421f7fe..4080b9c09ea 100644 --- a/Userland/Applications/PixelPaint/Selection.h +++ b/Userland/Applications/PixelPaint/Selection.h @@ -18,13 +18,28 @@ class ImageEditor; // Coordinates are image-relative. class Selection { public: + enum class MergeMode { + Set, + Add, + Subtract, + Intersect, + __Count, + }; + explicit Selection(ImageEditor&); bool is_empty() const { return m_mask.is_null(); } void clear(); - void set(Gfx::IntRect const& rect) { m_mask = Mask::full(rect); } + void merge(Mask const&, MergeMode); + void merge(Gfx::IntRect const& rect, MergeMode mode) { merge(Mask::full(rect), mode); } Gfx::IntRect bounding_rect() const { return m_mask.bounding_rect(); } + [[nodiscard]] bool is_selected(int x, int y) const { return m_mask.get(x, y) > 0; } + [[nodiscard]] bool is_selected(Gfx::IntPoint const& point) const { return is_selected(point.x(), point.y()); } + + [[nodiscard]] u8 get_selection_alpha(int x, int y) const { return m_mask.get(x, y); } + [[nodiscard]] u8 get_selection_alpha(Gfx::IntPoint const& point) const { return get_selection_alpha(point.x(), point.y()); } + void paint(Gfx::Painter&); void draw_marching_ants(Gfx::Painter&, Gfx::IntRect const&) const; diff --git a/Userland/Applications/PixelPaint/main.cpp b/Userland/Applications/PixelPaint/main.cpp index 76d413fa429..bbce9285220 100644 --- a/Userland/Applications/PixelPaint/main.cpp +++ b/Userland/Applications/PixelPaint/main.cpp @@ -237,7 +237,7 @@ int main(int argc, char** argv) auto* editor = current_image_editor(); if (!editor->active_layer()) return; - editor->selection().set(editor->active_layer()->relative_rect()); + editor->selection().merge(editor->active_layer()->relative_rect(), PixelPaint::Selection::MergeMode::Set); })); edit_menu.add_action(GUI::Action::create( "Clear &Selection", { Mod_Ctrl | Mod_Shift, Key_A }, [&](auto&) {