KisColorSmudgeStrategyLightness.cpp 6.59 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
 *  SPDX-FileCopyrightText: 2021 Dmitry Kazakov <dimula73@gmail.com>
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 */

#include <KoColorModelStandardIds.h>
#include <KoCompositeOpRegistry.h>
#include "KisColorSmudgeStrategyLightness.h"

#include "kis_painter.h"
#include "kis_paint_device.h"
#include "kis_fixed_paint_device.h"
#include "kis_selection.h"

#include "KisColorSmudgeInterstrokeData.h"

KisColorSmudgeStrategyLightness::KisColorSmudgeStrategyLightness(KisPainter *painter, bool smearAlpha,
                                                                 bool useDullingMode)
        : KisColorSmudgeStrategyBase(useDullingMode)
        , m_maskDab(new KisFixedPaintDevice(KoColorSpaceRegistry::instance()->alpha8()))
        , m_origDab(new KisFixedPaintDevice(KoColorSpaceRegistry::instance()->rgb8()))
        , m_smearAlpha(smearAlpha)
        , m_initializationPainter(painter)
{
}

void KisColorSmudgeStrategyLightness::initializePainting()
{
    KisColorSmudgeInterstrokeData *colorSmudgeData =
            dynamic_cast<KisColorSmudgeInterstrokeData*>(m_initializationPainter->device()->interstrokeData().data());

    if (colorSmudgeData) {
        m_projectionDevice = colorSmudgeData->projectionDevice;
        m_colorOnlyDevice = colorSmudgeData->colorBlendDevice;
        m_heightmapDevice = colorSmudgeData->heightmapDevice;
        m_layerOverlayDevice = &colorSmudgeData->overlayDeviceWrapper;
    }

    KIS_SAFE_ASSERT_RECOVER(colorSmudgeData) {
        m_projectionDevice = new KisPaintDevice(*m_initializationPainter->device());

        const KoColorSpace *cs = m_initializationPainter->device()->colorSpace();
        m_projectionDevice->convertTo(
                KoColorSpaceRegistry::instance()->colorSpace(
                        cs->colorModelId().id(),
                        Integer16BitsColorDepthID.id(),
                        cs->profile()));

        m_colorOnlyDevice = new KisPaintDevice(*m_projectionDevice);
        m_heightmapDevice = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb8());
    }

    initializePaintingImpl(m_colorOnlyDevice->colorSpace(),
                           m_smearAlpha,
                           m_initializationPainter->compositeOp()->id());

    m_heightmapPainter.begin(m_heightmapDevice);

    m_finalPainter.begin(m_colorOnlyDevice);
    m_finalPainter.setCompositeOp(COMPOSITE_COPY);
    m_finalPainter.setSelection(m_initializationPainter->selection());
    m_finalPainter.setChannelFlags(m_initializationPainter->channelFlags());
    m_finalPainter.copyMirrorInformationFrom(m_initializationPainter);

    m_heightmapPainter.setCompositeOp(COMPOSITE_ALPHA_DARKEN);
    m_heightmapPainter.setSelection(m_initializationPainter->selection());
    m_heightmapPainter.copyMirrorInformationFrom(m_initializationPainter);
69

70
71
    // we should read data from the color layer, not from the final projection layer
    m_sourceWrapperDevice = toQShared(new KisColorSmudgeSourcePaintDevice(*m_layerOverlayDevice, 1));
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
}

KisColorSmudgeStrategyBase::DabColoringStrategy &KisColorSmudgeStrategyLightness::coloringStrategy()
{
    return m_coloringStrategy;
}

void KisColorSmudgeStrategyLightness::updateMask(KisDabCache *dabCache, const KisPaintInformation &info,
                                                 const KisDabShape &shape, const QPointF &cursorPoint,
                                                 QRect *dstDabRect)
{

    m_origDab = dabCache->fetchNormalizedImageDab(m_origDab->colorSpace(),
                                                  cursorPoint,
                                                  shape,
                                                  info,
                                                  1.0,
                                                  dstDabRect);

    const int numPixels = m_origDab->bounds().width() * m_origDab->bounds().height();

    m_maskDab->setRect(m_origDab->bounds());
    m_maskDab->lazyGrowBufferWithoutInitialization();
    m_origDab->colorSpace()->copyOpacityU8(m_origDab->data(), m_maskDab->data(), numPixels);

    m_shouldPreserveOriginalDab = !dabCache->needSeparateOriginal();
}

QVector<QRect>
KisColorSmudgeStrategyLightness::paintDab(const QRect &srcRect, const QRect &dstRect, const KoColor &currentPaintColor,
                                          qreal opacity, qreal colorRateValue, qreal smudgeRateValue,
                                          qreal maxPossibleSmudgeRateValue, qreal lightnessStrengthValue,
                                          qreal smudgeRadiusValue)
{
    const int numPixels = dstRect.width() * dstRect.height();

    const QVector<QRect> mirroredRects = m_finalPainter.calculateAllMirroredRects(dstRect);

    QVector<QRect> readRects;
    readRects << mirroredRects;
    readRects << srcRect;
113
    m_sourceWrapperDevice->readRects(readRects);
114
115

    blendBrush({&m_finalPainter},
116
               m_sourceWrapperDevice,
117
118
119
120
121
122
123
124
125
               m_maskDab, m_shouldPreserveOriginalDab,
               srcRect, dstRect,
               currentPaintColor,
               opacity,
               smudgeRateValue,
               maxPossibleSmudgeRateValue,
               colorRateValue,
               smudgeRadiusValue);

126
    m_heightmapPainter.setOpacity(qRound(lightnessStrengthValue * 255.0));
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
    m_heightmapPainter.bltFixed(dstRect.topLeft(), m_origDab, m_origDab->bounds());
    m_heightmapPainter.renderMirrorMaskSafe(dstRect, m_origDab, m_shouldPreserveOriginalDab);

    KisFixedPaintDeviceSP tempColorDevice =
            new KisFixedPaintDevice(m_colorOnlyDevice->colorSpace(), m_memoryAllocator);

    KisFixedPaintDeviceSP tempHeightmapDevice =
            new KisFixedPaintDevice(m_heightmapDevice->colorSpace(), m_memoryAllocator);

    Q_FOREACH (const QRect &rc, mirroredRects) {
            tempColorDevice->setRect(rc);
            tempColorDevice->lazyGrowBufferWithoutInitialization();

            tempHeightmapDevice->setRect(rc);
            tempHeightmapDevice->lazyGrowBufferWithoutInitialization();

            m_colorOnlyDevice->readBytes(tempColorDevice->data(), rc);
            m_heightmapDevice->readBytes(tempHeightmapDevice->data(), rc);
            tempColorDevice->colorSpace()->
                    modulateLightnessByGrayBrush(tempColorDevice->data(),
                                                 reinterpret_cast<const QRgb*>(tempHeightmapDevice->data()),
                                                 0,
149
                                                 1.0,
150
151
152
153
154
155
156
                                                 numPixels);
            m_projectionDevice->writeBytes(tempColorDevice->data(), tempColorDevice->bounds());
        }
    m_layerOverlayDevice->writeRects(mirroredRects);

    return mirroredRects;
}