File indexing completed on 2024-05-26 04:33:50

0001 /*
0002  *  SPDX-FileCopyrightText: 2021 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "KisColorSmudgeStrategyWithOverlay.h"
0008 
0009 #include <KoCompositeOpRegistry.h>
0010 
0011 #include "kis_image.h"
0012 #include "kis_paint_device.h"
0013 #include "kis_fixed_paint_device.h"
0014 #include "kis_selection.h"
0015 
0016 #include "KisOverlayPaintDeviceWrapper.h"
0017 
0018 KisColorSmudgeStrategyWithOverlay::KisColorSmudgeStrategyWithOverlay(KisPainter *painter, KisImageSP image,
0019                                                                      bool smearAlpha, bool useDullingMode,
0020                                                                      bool useOverlayMode)
0021         : KisColorSmudgeStrategyBase(useDullingMode)
0022         , m_maskDab(new KisFixedPaintDevice(KoColorSpaceRegistry::instance()->alpha8()))
0023         , m_smearAlpha(smearAlpha)
0024         , m_initializationPainter(painter)
0025 {
0026     if (useOverlayMode && image) {
0027         m_imageOverlayDevice.reset(new KisOverlayPaintDeviceWrapper(image->projection(), 1, KisOverlayPaintDeviceWrapper::PreciseMode));
0028         m_layerOverlayDevice.reset(new KisOverlayPaintDeviceWrapper(painter->device(), 1, KisOverlayPaintDeviceWrapper::LazyPreciseMode, m_imageOverlayDevice->overlayColorSpace()));
0029         m_sourceWrapperDevice.reset(new KisColorSmudgeSourceImage(image, *m_imageOverlayDevice));
0030     } else {
0031         m_layerOverlayDevice.reset(new KisOverlayPaintDeviceWrapper(painter->device(), 1, KisOverlayPaintDeviceWrapper::LazyPreciseMode));
0032         m_sourceWrapperDevice.reset(new KisColorSmudgeSourcePaintDevice(*m_layerOverlayDevice));
0033     }
0034 }
0035 
0036 KisColorSmudgeStrategyWithOverlay::~KisColorSmudgeStrategyWithOverlay() {
0037 
0038 }
0039 
0040 void KisColorSmudgeStrategyWithOverlay::initializePainting()
0041 {
0042     initializePaintingImpl(m_layerOverlayDevice->overlayColorSpace(),
0043                            m_smearAlpha,
0044                            m_initializationPainter->compositeOpId());
0045 
0046     m_finalPainter.begin(m_layerOverlayDevice->overlay());
0047     m_finalPainter.setCompositeOpId(finalCompositeOp(m_smearAlpha));
0048     m_finalPainter.setSelection(m_initializationPainter->selection());
0049     m_finalPainter.setChannelFlags(m_initializationPainter->channelFlags());
0050     m_finalPainter.copyMirrorInformationFrom(m_initializationPainter);
0051 
0052     if (m_imageOverlayDevice) {
0053         m_overlayPainter.reset(new KisPainter());
0054         m_overlayPainter->begin(m_imageOverlayDevice->overlay());
0055         m_overlayPainter->setCompositeOpId(finalCompositeOp(m_smearAlpha));
0056         m_overlayPainter->setSelection(m_initializationPainter->selection());
0057         m_overlayPainter->setChannelFlags(m_initializationPainter->channelFlags());
0058         m_overlayPainter->copyMirrorInformationFrom(m_initializationPainter);
0059     }
0060 }
0061 
0062 QVector<KisPainter *> KisColorSmudgeStrategyWithOverlay::finalPainters()
0063 {
0064     QVector<KisPainter*> result;
0065     result << &m_finalPainter;
0066     if (m_overlayPainter) {
0067         result << m_overlayPainter.data();
0068     }
0069     return result;
0070 }
0071 
0072 QVector<QRect> KisColorSmudgeStrategyWithOverlay::paintDab(const QRect &srcRect, const QRect &dstRect,
0073                                                            const KoColor &currentPaintColor, qreal opacity,
0074                                                            qreal colorRateValue, qreal smudgeRateValue,
0075                                                            qreal maxPossibleSmudgeRateValue,
0076                                                            qreal lightnessStrengthValue, qreal smudgeRadiusValue)
0077 {
0078     Q_UNUSED(lightnessStrengthValue);
0079 
0080     const QVector<QRect> mirroredRects = m_finalPainter.calculateAllMirroredRects(dstRect);
0081 
0082     QVector<QRect> readRects;
0083     readRects << mirroredRects;
0084     readRects << srcRect;
0085 
0086     m_sourceWrapperDevice->readRects(readRects);
0087 
0088     if (m_imageOverlayDevice) {
0089         /**
0090          * If we have m_imageOverlayDevice set, then m_sourceWrapperOverlay points to it, not
0091          * to the layer's overlay. Therefore, we should read from it as well.
0092          */
0093         m_layerOverlayDevice->readRects(readRects);
0094     }
0095 
0096     blendBrush(finalPainters(),
0097                m_sourceWrapperDevice,
0098                m_maskDab, m_shouldPreserveMaskDab,
0099                srcRect, dstRect,
0100                currentPaintColor,
0101                opacity,
0102                smudgeRateValue,
0103                maxPossibleSmudgeRateValue,
0104                colorRateValue, smudgeRadiusValue);
0105 
0106     m_layerOverlayDevice->writeRects(mirroredRects);
0107 
0108     return mirroredRects;
0109 }