diff --git a/src/app/tools/tool_loop.h b/src/app/tools/tool_loop.h index c08360fe6..b71327cef 100644 --- a/src/app/tools/tool_loop.h +++ b/src/app/tools/tool_loop.h @@ -222,6 +222,8 @@ namespace app { // Returns true if the loop was canceled by the user virtual bool isCanceled() = 0; + virtual void limitDirtyAreaToViewport(gfx::Region& rgn) = 0; + // Redraws the dirty area. virtual void updateDirtyArea(const gfx::Region& dirtyArea) = 0; diff --git a/src/app/tools/tool_loop_manager.cpp b/src/app/tools/tool_loop_manager.cpp index ed1fe1822..8a0db5948 100644 --- a/src/app/tools/tool_loop_manager.cpp +++ b/src/app/tools/tool_loop_manager.cpp @@ -111,7 +111,8 @@ bool ToolLoopManager::releaseButton(const Pointer& pointer) bool res = m_toolLoop->getController()->releaseButton(m_stroke, spritePoint); - if (!res && (m_toolLoop->getInk()->isSelection() || + if (!res && (m_toolLoop->getTracePolicy() == TracePolicy::Last || + m_toolLoop->getInk()->isSelection() || m_toolLoop->getInk()->isSlice() || m_toolLoop->getFilled())) { m_toolLoop->getInk()->setFinalStep(m_toolLoop, true); @@ -165,6 +166,13 @@ void ToolLoopManager::doLoopStep(bool lastStep) calculateDirtyArea(strokes); + // If we are not in the last step (when the mouse button is + // released) we are only showing a preview of the tool, so we can + // limit the dirty area to the visible viewport bounds. In this way + // the area using in validateoDstImage() can be a lot smaller. + if (m_toolLoop->getTracePolicy() == TracePolicy::Last && !lastStep) + m_toolLoop->limitDirtyAreaToViewport(m_dirtyArea); + // Validate source image area. if (m_toolLoop->getInk()->needsSpecialSourceArea()) { gfx::Region srcArea; @@ -177,10 +185,10 @@ void ToolLoopManager::doLoopStep(bool lastStep) m_toolLoop->getInk()->prepareForStrokes(m_toolLoop, strokes); - // Invalidate destionation image areas. + // Invalidate destination image area. if (m_toolLoop->getTracePolicy() == TracePolicy::Last) { // Copy source to destination (reset the previous trace). Useful - // for tools like Line and Ellipse (we kept the last trace only). + // for tools like Line and Ellipse (we keep the last trace only). m_toolLoop->invalidateDstImage(); } else if (m_toolLoop->getTracePolicy() == TracePolicy::AccumulateUpdateLast) { diff --git a/src/app/ui/editor/tool_loop_impl.cpp b/src/app/ui/editor/tool_loop_impl.cpp index 75156f8cf..45bacae93 100644 --- a/src/app/ui/editor/tool_loop_impl.cpp +++ b/src/app/ui/editor/tool_loop_impl.cpp @@ -260,6 +260,10 @@ public: tools::Symmetry* getSymmetry() override { return m_symmetry.get(); } doc::Remap* getShadingRemap() override { return m_shadingRemap.get(); } + void limitDirtyAreaToViewport(gfx::Region& rgn) override { + rgn &= gfx::Region(m_editor->getVisibleSpriteBounds().inflate(1, 1)); + } + void updateDirtyArea(const gfx::Region& dirtyArea) override { // This is necessary here so the "on sprite crosshair" is hidden, // we update screen pixels with the new sprite, and then we show