Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_selection_mask.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006 Boudewijn Rempt <boud@valdyas.org>
3 *
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
9
10#include "kis_image.h"
11#include "kis_layer.h"
12#include "kis_selection.h"
14#include <KoColorSpace.h>
15#include <KoProperties.h>
16#include "kis_fill_painter.h"
17#include <KoCompositeOp.h>
18#include "kis_node_visitor.h"
20#include "kis_pixel_selection.h"
21#include "kis_undo_adapter.h"
22#include <KoIcon.h>
23#include <kis_icon.h>
27
28#include "kis_image_config.h"
30
31
50
52 : KisEffectMask(image, name)
53 , m_d(new Private(this))
54{
55 setActive(false);
57
58 m_d->updatesCompressor =
60
61 connect(m_d->updatesCompressor, SIGNAL(timeout()), SLOT(slotSelectionChangedCompressed()));
62
63 connect(KisImageConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged()));
64 m_d->slotConfigChangedImpl(false);
65}
66
68 : KisEffectMask(rhs)
69 , m_d(new Private(this))
70{
71 m_d->updatesCompressor =
73
74 connect(m_d->updatesCompressor, SIGNAL(timeout()), SLOT(slotSelectionChangedCompressed()));
75
76 connect(KisImageConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged()));
77 m_d->slotConfigChangedImpl(false);
78}
79
81{
82 m_d->updatesCompressor->deleteLater();
83 delete m_d;
84}
85
87 return KisIconUtils::loadIcon("selectionMask");
88}
89
91 KisSelectionSP effectiveSelection,
92 const QRect &applyRect,
93 const QRect &preparedNeedRect,
95 KisRenderPassFlags flags) const
96{
97 Q_UNUSED(maskPos);
98 Q_UNUSED(preparedNeedRect);
99 Q_UNUSED(flags);
100
101 if (!effectiveSelection) return;
102
103 {
104 KisSelectionSP mainMaskSelection = this->selection();
105 if (mainMaskSelection &&
106 (!mainMaskSelection->isVisible() ||
107 mainMaskSelection->pixelSelection()->defaultBounds()->externalFrameActive())) {
108
109 return;
110 }
111 }
112
113 KisCachedPaintDevice::Guard d1(projection, m_d->paintDeviceCache);
114 KisPaintDeviceSP fillDevice = d1.device();
115 fillDevice->setDefaultPixel(m_d->maskColor);
116
117 const QRect selectionExtent = effectiveSelection->selectedRect();
118
119 if (selectionExtent.contains(applyRect) || selectionExtent.intersects(applyRect)) {
120 KisCachedSelection::Guard s1(m_d->cachedSelection);
121 KisSelectionSP invertedSelection = s1.selection();
122
123 invertedSelection->pixelSelection()->makeCloneFromRough(effectiveSelection->pixelSelection(), applyRect);
124 invertedSelection->pixelSelection()->invert();
125
127 gc.setSelection(invertedSelection);
128 gc.bitBlt(applyRect.topLeft(), fillDevice, applyRect);
129
130 } else {
132 gc.bitBlt(applyRect.topLeft(), fillDevice, applyRect);
133 }
134}
135
137{
138 return true;
139}
140
142{
143 if (selection) {
145 } else {
147
149 KisFillPainter gc(KisPaintDeviceSP(this->selection()->pixelSelection().data()));
150 gc.fillRect(image()->bounds(), KoColor(Qt::white, cs), MAX_SELECTED);
151 gc.end();
152 }
153 setDirty();
154}
155
157{
158 return v.visit(this);
159}
160
162{
163 return visitor.visit(this, undoAdapter);
164}
165
172
178
179void KisSelectionMask::setVisible(bool visible, bool isLoading)
180{
181 const bool oldVisible = this->visible(false);
182 setNodeProperty("visible", visible);
183
184 if (!isLoading && visible != oldVisible) {
185 if (selection())
187 }
188}
189
191{
192 return nodeProperties().boolProperty("active", true);
193}
194
196{
197 KisImageSP image = this->image();
198 KisLayerSP parentLayer = qobject_cast<KisLayer*>(parent().data());
199
200 if (active && parentLayer) {
201 KisSelectionMaskSP activeMask = parentLayer->selectionMask();
202 if (activeMask && activeMask != this) {
203 activeMask->setActive(false);
204 }
205 }
206
207 const bool oldActive = this->active();
208 setNodeProperty("active", active);
209
210
217 if (graphListener() &&
218 image && oldActive != active) {
219
222 }
223}
224
226{
227 Q_UNUSED(pos);
228
229 // selection masks just add an overlay, so the needed rect is simply passed through
230 return rect;
231}
232
234{
235 Q_UNUSED(pos);
236
237 // selection masks just add an overlay, so the changed rect is simply passed through
238 return rect;
239}
240
242{
243 // since mask overlay is inverted, the mask paints over
244 // the entire image bounds
245 QRect resultRect;
247
248 if (selection) {
249 resultRect = selection->pixelSelection()->defaultBounds()->bounds();
250
251 if (KisNodeSP parent = this->parent()) {
252 resultRect |= parent->extent();
253 }
254
255 } else if (KisNodeSP parent = this->parent()) {
257 if (dev) {
258 resultRect = dev->defaultBounds()->bounds();
259 }
260 }
261
262 return resultRect;
263}
264
266{
267 return extent();
268}
269
271{
272 m_d->updatesCompressor->start();
273}
274
276{
277 return selection()->isVisible();
278}
279
281{
282 if (value == decorationsVisible()) return;
283
284 const QRect oldExtent = extent();
285
287
288 if (update) {
289 setDirty(oldExtent | extent());
290 }
291}
292
294{
295 KisImageSP image = this->image();
296
297 if (image && image->overlaySelectionMask() == this) {
299 }
300}
301
302void KisSelectionMask::flattenSelectionProjection(KisSelectionSP selection, const QRect &dirtyRect) const
303{
304 Q_UNUSED(selection);
305 Q_UNUSED(dirtyRect);
306}
307
308void KisSelectionMask::Private::slotSelectionChangedCompressed()
309{
310 KisSelectionSP currentSelection = q->selection();
311 if (!currentSelection) return;
312
313 currentSelection->notifySelectionChanged();
314}
315
316void KisSelectionMask::Private::slotConfigChangedImpl(bool doUpdates)
317{
318 KisImageSP image = q->image();
319
320 const KoColorSpace *cs = image ?
321 image->colorSpace() :
323
324 KisImageConfig cfg(true);
325
326 maskColor = KoColor(cfg.selectionOverlayMaskColor(), cs);
327
328 if (doUpdates && image && image->overlaySelectionMask() == q) {
329 q->setDirty();
330 }
331}
332
333void KisSelectionMask::Private::slotConfigChanged()
334{
335 slotConfigChangedImpl(true);
336}
337
338#include "moc_kis_selection_mask.cpp"
float value(const T *src, size_t ch)
QPointF s1
qreal v
PythonPluginManager * instance
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
virtual bool externalFrameActive() const =0
virtual QRect bounds() const =0
void fillRect(qint32 x, qint32 y, qint32 w, qint32 h, const KoColor &c, quint8 opacity)
static KisImageConfigNotifier * instance()
KisUndoAdapter * undoAdapter() const
const KoColorSpace * colorSpace() const
KisSelectionMaskSP overlaySelectionMask() const
Definition kis_image.cc:685
static KisBaseNode::Property getProperty(const KoID &id, bool state)
void setDefaultPixel(const KoColor &defPixel)
void makeCloneFromRough(KisPaintDeviceSP src, const QRect &minimalRect)
KisDefaultBoundsBaseSP defaultBounds() const
void setSelection(KisSelectionSP selection)
void bitBlt(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight)
virtual void visit(KisNode *node, KisUndoAdapter *undoAdapter)=0
bool boolProperty(const QString &name, bool defaultValue=false) const
#define bounds(x, a, b)
const quint8 MAX_SELECTED
Definition kis_global.h:32
KisSharedPtr< KisPaintDevice > KisPaintDeviceSP
Definition kis_types.h:73
QIcon loadIcon(const QString &name)
void setNodeProperty(const QString &name, const QVariant &value)
void setSupportsLodMoves(bool value)
virtual KisPaintDeviceSP projection() const =0
const KoProperties & nodeProperties() const
KoProperties properties
KisImageWSP image
virtual QRect extent() const
virtual PropertyList sectionModelProperties() const
virtual bool visible(bool recursive=false) const
virtual void setSectionModelProperties(const PropertyList &properties)
KisPaintDeviceSP device() const
virtual KisSelectionMaskSP selectionMask() const
Definition kis_layer.cc:498
KisPaintDeviceSP projection() const override
Definition kis_mask.cc:234
void baseNodeChangedCallback() override
Definition kis_mask.cc:532
void setSelection(KisSelectionSP selection)
Definition kis_mask.cc:252
KisSelectionSP selection
Definition kis_mask.cc:44
PositionToFilthy
Definition kis_node.h:58
KisNodeWSP parent
Definition kis_node.cpp:86
KisNodeGraphListener * graphListener
Definition kis_node.cpp:87
virtual void setDirty()
Definition kis_node.cpp:577
void setVisible(bool visible, bool isLoading=false) override
bool accept(KisNodeVisitor &v) override
QRect changeRect(const QRect &rect, PositionToFilthy pos=N_FILTHY) const override
Private(KisSelectionMask *_q)
KisCachedSelection cachedSelection
void mergeInMaskInternal(KisPaintDeviceSP projection, KisSelectionSP effectiveSelection, const QRect &applyRect, const QRect &preparedNeedRect, KisNode::PositionToFilthy maskPos, KisRenderPassFlags flags) const override
QIcon icon() const override
KisBaseNode::PropertyList sectionModelProperties() const override
void slotConfigChangedImpl(bool blockUpdates)
KisSelectionMask(KisImageWSP image, const QString &name=QString())
bool paintsOutsideSelection() const override
void flattenSelectionProjection(KisSelectionSP selection, const QRect &dirtyRect) const override
KisCachedPaintDevice paintDeviceCache
KisThreadSafeSignalCompressor * updatesCompressor
bool decorationsVisible() const override
QRect extent() const override
KisSelectionMask * q
void slotConfigChanged()
void setSelection(KisSelectionSP selection)
Set the selection of this adjustment layer to a copy of selection.
void setActive(bool active)
void setSectionModelProperties(const KisBaseNode::PropertyList &properties) override
QRect needRect(const QRect &rect, PositionToFilthy pos=N_FILTHY) const override
QRect exactBounds() const override
void setDecorationsVisible(bool value, bool update) override
void slotSelectionChangedCompressed()
void notifySelectionChanged()
KisPixelSelectionSP pixelSelection
QRect selectedRect() const
void setVisible(bool visible)
static KoColorSpaceRegistry * instance()
const KoColorSpace * rgb8(const QString &profileName=QString())
const KoColorSpace * alpha8()