From 5ba0b551f44759db649abaef70cdb4a382f5f37a Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Wed, 14 Dec 2022 18:00:30 +0000 Subject: [PATCH] PixelPaint: Display a preview image when scaling with the move tool A preview of the scaled image and an outline of the updated layer boundary are now shown when scaling with the move tool. --- .../PixelPaint/Tools/MoveTool.cpp | 52 ++++++++++++++++--- .../Applications/PixelPaint/Tools/MoveTool.h | 4 ++ 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/Userland/Applications/PixelPaint/Tools/MoveTool.cpp b/Userland/Applications/PixelPaint/Tools/MoveTool.cpp index 756492330ad..9de45d8bf6a 100644 --- a/Userland/Applications/PixelPaint/Tools/MoveTool.cpp +++ b/Userland/Applications/PixelPaint/Tools/MoveTool.cpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace PixelPaint { @@ -57,6 +58,9 @@ void MoveTool::on_mousemove(Layer* layer, MouseEvent& event) m_editor->update_tool_cursor(); } + if (!m_layer_being_moved) + return; + if (m_scaling) { auto cursor_location = event.image_event().position(); auto width = abs(m_layer_being_moved->location().x() - cursor_location.x()); @@ -70,15 +74,13 @@ void MoveTool::on_mousemove(Layer* layer, MouseEvent& event) } m_new_layer_size = Gfx::IntSize(width, height); // TODO: Change this according to which direction the user is scaling - m_new_scaled_layer_location = Gfx::IntPoint(m_layer_being_moved->location().x(), m_layer_being_moved->location().y()); + m_new_scaled_layer_location = m_layer_being_moved->location(); + } else { + auto& image_event = event.image_event(); + auto delta = image_event.position() - m_event_origin; + m_layer_being_moved->set_location(m_layer_origin.translated(delta)); } - - auto& image_event = event.image_event(); - if (!m_layer_being_moved || m_scaling) - return; - auto delta = image_event.position() - m_event_origin; - m_layer_being_moved->set_location(m_layer_origin.translated(delta)); - m_editor->layers_did_change(); + m_editor->update(); } void MoveTool::on_mouseup(Layer* layer, MouseEvent& event) @@ -98,10 +100,12 @@ void MoveTool::on_mouseup(Layer* layer, MouseEvent& event) if (m_scaling) { m_editor->active_layer()->resize(m_new_layer_size, m_new_scaled_layer_location, Gfx::Painter::ScalingMode::BilinearBlend); + m_editor->layers_did_change(); } m_scaling = false; m_layer_being_moved = nullptr; + m_cached_preview_bitmap = nullptr; m_editor->update_tool_cursor(); m_editor->did_complete_action(tool_name()); } @@ -151,6 +155,38 @@ void MoveTool::on_keyup(GUI::KeyEvent& event) m_keep_ascept_ratio = false; } +void MoveTool::on_second_paint(Layer const* layer, GUI::PaintEvent& event) +{ + if (layer != m_layer_being_moved.ptr() || !m_scaling) + return; + + GUI::Painter painter(*m_editor); + painter.add_clip_rect(event.rect()); + painter.translate(editor_layer_location(*layer)); + + auto dst_rect = Gfx::IntRect(Gfx::IntPoint(0, 0), m_scaling ? m_new_layer_size : layer->size()); + auto rect_in_editor = m_editor->content_to_frame_rect(dst_rect).to_rounded(); + painter.draw_rect(rect_in_editor, Color::Black); + if (!m_cached_preview_bitmap.is_null() || !update_cached_preview_bitmap(layer).is_error()) { + painter.add_clip_rect(m_editor->content_rect()); + painter.draw_scaled_bitmap(rect_in_editor, *m_cached_preview_bitmap, m_cached_preview_bitmap->rect(), 1.0f, Gfx::Painter::ScalingMode::BilinearBlend); + } +} + +ErrorOr MoveTool::update_cached_preview_bitmap(Layer const* layer) +{ + auto editor_rect_size = m_editor->frame_inner_rect().size(); + auto const& source_bitmap = layer->content_bitmap(); + auto preview_bitmap_size = editor_rect_size.contains(source_bitmap.size()) ? source_bitmap.size() : editor_rect_size; + + m_cached_preview_bitmap = TRY(Gfx::Bitmap::try_create(source_bitmap.format(), preview_bitmap_size)); + GUI::Painter preview_painter(*m_cached_preview_bitmap); + preview_painter.draw_scaled_bitmap(m_cached_preview_bitmap->rect(), source_bitmap, source_bitmap.rect(), 0.8f, Gfx::Painter::ScalingMode::BilinearBlend); + Gfx::ContrastFilter preview_filter(0.5f); + preview_filter.apply(*m_cached_preview_bitmap, m_cached_preview_bitmap->rect(), *m_cached_preview_bitmap, m_cached_preview_bitmap->rect()); + return {}; +} + Variant> MoveTool::cursor() { if (m_mouse_in_resize_corner || m_scaling) diff --git a/Userland/Applications/PixelPaint/Tools/MoveTool.h b/Userland/Applications/PixelPaint/Tools/MoveTool.h index b96efe6eb79..516c2ac2fef 100644 --- a/Userland/Applications/PixelPaint/Tools/MoveTool.h +++ b/Userland/Applications/PixelPaint/Tools/MoveTool.h @@ -22,10 +22,12 @@ public: virtual void on_mouseup(Layer*, MouseEvent&) override; virtual bool on_keydown(GUI::KeyEvent&) override; virtual void on_keyup(GUI::KeyEvent&) override; + virtual void on_second_paint(Layer const*, GUI::PaintEvent&) override; virtual Variant> cursor() override; private: virtual StringView tool_name() const override { return "Move Tool"sv; } + ErrorOr update_cached_preview_bitmap(Layer const* layer); RefPtr m_layer_being_moved; Gfx::IntPoint m_event_origin; @@ -35,6 +37,8 @@ private: bool m_scaling { false }; bool m_mouse_in_resize_corner { false }; bool m_keep_ascept_ratio { false }; + + RefPtr m_cached_preview_bitmap { nullptr }; }; }