Krita Source Code Documentation
Loading...
Searching...
No Matches
KisAsyncColorSamplerHelper.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2022 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <QPainter>
10
13#include "KoViewConverter.h"
14#include "KoIcon.h"
15#include "kis_cursor.h"
18#include "kis_config.h"
19#include "kis_canvas2.h"
20#include "KisViewManager.h"
21#include "KisDocument.h"
26
27
28namespace {
29std::pair<QRectF,QRectF> colorPreviewDocRectImpl(const QPointF &outlineDocPoint, bool colorPreviewShowComparePlate, const KoViewConverter *converter)
30{
31 KisConfig cfg(true);
32 const QRectF colorPreviewViewRect = cfg.colorPreviewRect();
33
34 const QRectF colorPreviewBaseColorViewRect =
35 colorPreviewShowComparePlate ?
36 colorPreviewViewRect.translated(colorPreviewViewRect.width(), 0) :
37 QRectF();
38
39 const QRectF colorPreviewDocumentRect = converter->viewToDocument(colorPreviewViewRect);
40 const QRectF colorPreviewBaseColorDocumentRect =
41 converter->viewToDocument(colorPreviewBaseColorViewRect);
42
43 return std::make_pair(colorPreviewDocumentRect.translated(outlineDocPoint),
44 colorPreviewBaseColorDocumentRect.translated(outlineDocPoint));
45}
46}
47
49{
51 : canvas(_canvas)
52 {}
53
55
57 bool sampleCurrentLayer {true};
58 bool updateGlobalColor {true};
59
60 bool isActive {false};
61 bool showPreview {false};
62 bool showComparePlate {false};
63
66 QScopedPointer<SamplingCompressor> samplingCompressor;
67
69
72
74 QColor baseColor;
75
77 return canvas->image().data();
78 }
79
80 const KoViewConverter &converter() const {
81 return *canvas->imageView()->viewConverter();
82 }
83
84};
85
87 : m_d(new Private(canvas))
88{
89 using namespace std::placeholders; // For _1 placeholder
90 std::function<void(QPointF)> callback =
92 m_d->samplingCompressor.reset(
94
95 m_d->activationDelayTimer.setInterval(100);
96 m_d->activationDelayTimer.setSingleShot(true);
97 connect(&m_d->activationDelayTimer, SIGNAL(timeout()), this, SLOT(activateDelayedPreview()));
98}
99
104
106{
107 return m_d->isActive;
108}
109
110void KisAsyncColorSamplerHelper::activate(bool sampleCurrentLayer, bool pickFgColor)
111{
113 m_d->isActive = true;
114
115 m_d->sampleResourceId =
116 pickFgColor ?
119
120 m_d->sampleCurrentLayer = sampleCurrentLayer;
121 m_d->showComparePlate = false;
122
123 m_d->activationDelayTimer.start();
124}
125
127{
128 // the event may come after we have finished color
129 // picking if the user is quick
130 if (!m_d->isActive) return;
131
132 m_d->showPreview = true;
133
134 const KoColor currentColor =
135 m_d->canvas->resourceManager()->koColorResource(m_d->sampleResourceId);
136 const QColor previewColor = m_d->canvas->displayColorConverter()->toQColor(currentColor);
137
138 m_d->currentColor = previewColor;
139 m_d->baseColor = previewColor;
140
141 updateCursor(m_d->sampleCurrentLayer, m_d->sampleResourceId == KoCanvasResource::ForegroundColor);
142
144}
145
146void KisAsyncColorSamplerHelper::updateCursor(bool sampleCurrentLayer, bool pickFgColor)
147{
148 const int sampleResourceId =
149 pickFgColor ?
152
153 QCursor cursor;
154
155 if (sampleCurrentLayer) {
156 if (sampleResourceId == KoCanvasResource::ForegroundColor) {
158 } else {
160 }
161 } else {
162 if (sampleResourceId == KoCanvasResource::ForegroundColor) {
164 } else {
166 }
167 }
168
169 Q_EMIT sigRequestCursor(cursor);
170}
171
173{
174 m_d->updateGlobalColor = value;
175}
176
178{
179 return m_d->updateGlobalColor;
180}
181
183{
184 KIS_SAFE_ASSERT_RECOVER(!m_d->strokeId) {
185 endAction();
186 }
187
188 m_d->activationDelayTimer.stop();
189
190 m_d->showPreview = false;
191 m_d->showComparePlate = false;
192
193 m_d->currentColorDocRect = QRectF();
194 m_d->currentColor = QColor();
195 m_d->baseColor = QColor();
196 m_d->baseColorDocRect = QRectF();
197
198 m_d->isActive = false;
199
200 Q_EMIT sigRequestCursorReset();
202}
203
204void KisAsyncColorSamplerHelper::startAction(const QPointF &docPoint, int radius, int blend)
205{
211
212 m_d->strokeId = m_d->strokesFacade()->startStroke(strategy);
213 m_d->samplingCompressor->start(docPoint);
214}
215
217{
219 m_d->samplingCompressor->start(docPoint);
220}
221
223{
225
226 m_d->strokesFacade()->addJob(m_d->strokeId,
228
229 m_d->strokesFacade()->endStroke(m_d->strokeId);
230 m_d->strokeId.clear();
231}
232
234{
235 if (!m_d->showPreview) return QRectF();
236
237 std::tie(m_d->currentColorDocRect, m_d->baseColorDocRect) =
238 colorPreviewDocRectImpl(docPoint, m_d->showComparePlate, &m_d->converter());
239
240 return m_d->currentColorDocRect | m_d->baseColorDocRect;
241}
242
243void KisAsyncColorSamplerHelper::paint(QPainter &gc, const KoViewConverter &converter)
244{
245 if (!m_d->showPreview) return;
246
247 const QRectF viewRect = converter.documentToView(m_d->currentColorDocRect);
248 gc.fillRect(viewRect, m_d->currentColor);
249
250 if (m_d->showComparePlate) {
251 const QRectF baseColorRect = converter.documentToView(m_d->baseColorDocRect);
252 gc.fillRect(baseColorRect, m_d->baseColor);
253 }
254}
255
257{
262 if (!m_d->strokeId) return;
263
264 KisImageSP image = m_d->canvas->image();
265
266 const QPoint imagePoint = image->documentToImagePixelFloored(docPoint);
267
268 if (!m_d->sampleCurrentLayer) {
269 KisSharedPtr<KisReferenceImagesLayer> referencesLayer = m_d->canvas->imageView()->document()->referenceImagesLayer();
270 if (referencesLayer && m_d->canvas->referenceImagesDecoration()->visible()) {
271 QColor color = referencesLayer->getPixel(imagePoint);
272 if (color.isValid() && color.alpha() != 0) {
274 return;
275 }
276 }
277 }
278
279 KisPaintDeviceSP device = m_d->sampleCurrentLayer ?
280 m_d->canvas->imageView()->currentNode()->colorSampleSourceDevice() :
281 image->projection();
282
283 if (device) {
284 // Used for color sampler blending.
285 const KoColor currentColor =
286 m_d->canvas->resourceManager()->koColorResource(m_d->sampleResourceId);
287
288 m_d->strokesFacade()->addJob(m_d->strokeId,
289 new KisColorSamplerStrokeStrategy::Data(device, imagePoint, currentColor));
290 } else {
291 QString message = i18n("Color sampler does not work on this layer.");
292 m_d->canvas->viewManager()->showFloatingMessage(message, koIcon("object-locked"));
293 }
294}
295
297{
298 KoColor color(rawColor);
299
301
302 if (m_d->updateGlobalColor) {
303 m_d->canvas->resourceManager()->setResource(m_d->sampleResourceId, color);
304 }
305
306 Q_EMIT sigRawColorSelected(rawColor);
307 Q_EMIT sigColorSelected(color);
308
309 if (!m_d->showPreview) return;
310
311 const QColor previewColor = m_d->canvas->displayColorConverter()->toQColor(color);
312
313 m_d->showComparePlate = true;
314 m_d->currentColor = previewColor;
315
317}
float value(const T *src, size_t ch)
const quint8 OPACITY_OPAQUE_U8
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
void slotColorSamplingFinished(const KoColor &rawColor)
void activate(bool sampleCurrentLayer, bool pickFgColor)
void sigFinalColorSelected(const KoColor &color)
void slotAddSamplingJob(const QPointF &docPoint)
void sigRequestCursor(const QCursor &cursor)
void paint(QPainter &gc, const KoViewConverter &converter)
void updateCursor(bool sampleCurrentLayer, bool pickFgColor)
void continueAction(const QPointF &docPoint)
void startAction(const QPointF &docPoint, int radius, int blend)
void sigColorSelected(const KoColor &color)
void sigRawColorSelected(const KoColor &color)
QRectF colorPreviewDocRect(const QPointF &docPoint)
KisImageWSP image() const
QPointer< KisView > imageView() const
void sigFinalColorSelected(const KoColor &color)
void sigColorUpdated(const KoColor &color)
static QCursor samplerImageBackgroundCursor()
static QCursor samplerLayerBackgroundCursor()
static QCursor samplerLayerForegroundCursor()
static QCursor samplerImageForegroundCursor()
const KoColorSpace * colorSpace() const
KisPaintDeviceSP projection() const
QPoint documentToImagePixelFloored(const QPointF &documentCoord) const
void setOpacity(quint8 alpha)
Definition KoColor.cpp:333
void toQColor(QColor *c) const
a convenience method for the above.
Definition KoColor.cpp:198
virtual QPointF viewToDocument(const QPointF &viewPoint) const
virtual QPointF documentToView(const QPointF &documentPoint) const
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
#define koIcon(name)
Use these macros for icons without any issues.
Definition kis_icon.h:25
typedef void(QOPENGLF_APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC)(GLuint buffer)
@ BackgroundColor
The active background color selected for this canvas.
@ ForegroundColor
The active foreground color selected for this canvas.
QScopedPointer< SamplingCompressor > samplingCompressor
KisSignalCompressorWithParam< QPointF > SamplingCompressor
KisCanvas2 * canvas