File indexing completed on 2025-02-02 04:16:07

0001 /*
0002  *  SPDX-License-Identifier: GPL-3.0-or-later
0003  */
0004 
0005 #include "KisSelectionBasedProcessingHelper.h"
0006 
0007 #include "kis_paint_device.h"
0008 #include "kis_painter.h"
0009 #include "kis_selection.h"
0010 #include "kis_transaction_based_command.h"
0011 #include "kis_transaction.h"
0012 #include "kis_undo_adapter.h"
0013 
0014 KisSelectionBasedProcessingHelper::KisSelectionBasedProcessingHelper(KisSelectionSP selection, Functor func)
0015     : m_selection(selection),
0016       m_func(func)
0017 {
0018 }
0019 
0020 void KisSelectionBasedProcessingHelper::setSelection(KisSelectionSP selection)
0021 {
0022     m_selection = selection;
0023 }
0024 
0025 KUndo2Command *KisSelectionBasedProcessingHelper::createInitCommand(Functor func)
0026 {
0027     if (!m_selection) return 0;
0028 
0029     struct ProcessSelectionCommand : KisTransactionBasedCommand {
0030         ProcessSelectionCommand(KisSelectionSP selection,
0031                                 KisSelectionSP cutSelection,
0032                                 std::function<void(KisPaintDeviceSP)> func)
0033             : m_selection(selection),
0034               m_cutSelection(cutSelection),
0035               m_func(func)
0036         {
0037         }
0038 
0039         KUndo2Command* paint() override {
0040             m_cutSelection->pixelSelection()->makeCloneFromRough(m_selection->pixelSelection(), m_selection->selectedRect());
0041 
0042             KisTransaction t(m_selection->pixelSelection());
0043             m_func(m_selection->pixelSelection());
0044 
0045             return t.endAndTake();
0046         }
0047 
0048         KisSelectionSP m_selection;
0049         KisSelectionSP m_cutSelection;
0050         Functor m_func;
0051     };
0052 
0053     m_cutSelection = new KisSelection();
0054     return new ProcessSelectionCommand(m_selection, m_cutSelection, func);
0055 }
0056 
0057 KUndo2Command *KisSelectionBasedProcessingHelper::createInitCommand()
0058 {
0059     return createInitCommand(m_func);
0060 }
0061 
0062 void KisSelectionBasedProcessingHelper::transformPaintDevice(KisPaintDeviceSP device, KisUndoAdapter *undoAdapter)
0063 {
0064     transformPaintDevice(device, undoAdapter, m_func);
0065 }
0066 
0067 void KisSelectionBasedProcessingHelper::transformPaintDevice(KisPaintDeviceSP device, KisUndoAdapter *undoAdapter, Functor func)
0068 {
0069     KIS_SAFE_ASSERT_RECOVER_RETURN(!!m_selection == !!m_cutSelection);
0070 
0071     if (m_selection && m_cutSelection) {
0072         // we have already processed the selection in the init command so try to skip it
0073         if (device != static_cast<KisPaintDevice*>(m_selection->pixelSelection().data())) {
0074             KisTransaction transaction(device);
0075 
0076             const QRect cutBounds = m_cutSelection->selectedExactRect();
0077             const QRect pasteBounds = m_selection->selectedExactRect();
0078 
0079 
0080             KisPaintDeviceSP tempDev = new KisPaintDevice(device->colorSpace());
0081             tempDev->makeCloneFromRough(device, cutBounds);
0082 
0083             func(tempDev);
0084 
0085             device->clearSelection(m_cutSelection);
0086             KisPainter::copyAreaOptimized(pasteBounds.topLeft(), tempDev, device, pasteBounds, m_selection);
0087             transaction.commit(undoAdapter);
0088         }
0089     } else {
0090         KisTransaction transaction(device);
0091         func(device);
0092         transaction.commit(undoAdapter);
0093     }
0094 }