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 ¤tPaintColor, 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 }