Krita

Selection.cpp
1/*
2 * SPDX-FileCopyrightText: 2016 Boudewijn Rempt <boud@valdyas.org>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6#include "Selection.h"
7
8#include <KoColorSpace.h>
9#include "kis_iterator_ng.h"
10#include <kis_selection.h>
11#include <kis_pixel_selection.h>
12#include <kis_paint_device.h>
13#include <kis_selection_filters.h>
14#include <kis_painter.h>
15#include <kis_node.h>
16#include <kis_clipboard.h>
17#include <QByteArray>
18
19#include <Node.h>
20
21struct Selection::Private {
22 Private() {}
23 KisSelectionSP selection;
24};
25
26Selection::Selection(KisSelectionSP selection, QObject *parent)
27 : QObject(parent)
28 , d(new Private)
29{
30 d->selection = selection;
31}
32
33
35 : QObject(parent)
36 , d(new Private)
37{
38 d->selection = new KisSelection();
39}
40
41Selection::~Selection()
42{
43 delete d;
44}
45
46bool Selection::operator==(const Selection &other) const
47{
48 return (d->selection == other.d->selection);
49}
50
51bool Selection::operator!=(const Selection &other) const
52{
53 return !(operator==(other));
54}
55
57{
58 return new Selection(d->selection ? new KisSelection(*d->selection)
59 : new KisSelection());
60}
61
63{
64 if (!d->selection) return 0;
65 return d->selection->selectedExactRect().width();
66}
67
69{
70 if (!d->selection) return 0;
71 return d->selection->selectedExactRect().height();
72}
73
74int Selection::x() const
75{
76 if (!d->selection) return 0;
77 int xPos = d->selection->x();
78 if (d->selection->hasNonEmptyPixelSelection()) {
79 xPos = d->selection->selectedExactRect().x();
80 }
81 return xPos;
82}
83
84int Selection::y() const
85{
86 if (!d->selection) return 0;
87 int yPos = d->selection->y();
88 if (d->selection->hasNonEmptyPixelSelection()) {
89 yPos = d->selection->selectedExactRect().y();
90 }
91 return yPos;
92}
93
94void Selection::move(int x, int y)
95{
96 if (!d->selection) return;
97 d->selection->pixelSelection()->moveTo(QPoint(x, y));
98}
99
100
102{
103 if (!d->selection) return;
104 d->selection->clear();
105}
106
107void Selection::contract(int value)
108{
109 if (!d->selection) return;
110 d->selection->pixelSelection()->select(QRect(x(), y(), width() - value, height() - value));
111}
112
114{
115 if (!node) return;
116 if (!d->selection) return;
117 if (node->node()->exactBounds().isEmpty()) return;
118 if (!node->node()->hasEditablePaintDevice()) return;
119
120 KisPaintDeviceSP dev = node->node()->paintDevice();
121 KisPaintDeviceSP clip = new KisPaintDevice(dev->colorSpace());
122 KisPaintDeviceSP selectionProjection = d->selection->projection();
123
124 const KoColorSpace *cs = clip->colorSpace();
125 const KoColorSpace *selCs = d->selection->projection()->colorSpace();
126
127 QRect rc = d->selection->selectedExactRect();
128
129 KisPainter::copyAreaOptimized(QPoint(), dev, clip, rc);
130
131 KisHLineIteratorSP layerIt = clip->createHLineIteratorNG(0, 0, rc.width());
132 KisHLineConstIteratorSP selectionIt = selectionProjection->createHLineIteratorNG(rc.x(), rc.y(), rc.width());
133
134 for (qint32 y = 0; y < rc.height(); y++) {
135 for (qint32 x = 0; x < rc.width(); x++) {
136
137 qreal dstAlpha = cs->opacityF(layerIt->rawData());
138 qreal sel = selCs->opacityF(selectionIt->oldRawData());
139 qreal newAlpha = sel * dstAlpha / (1.0 - dstAlpha + sel * dstAlpha);
140 float mask = newAlpha / dstAlpha;
141
142 cs->applyAlphaNormedFloatMask(layerIt->rawData(), &mask, 1);
143
144 layerIt->nextPixel();
145 selectionIt->nextPixel();
146 }
147 layerIt->nextRow();
148 selectionIt->nextRow();
149 }
150
151 KisClipboard::instance()->setClip(clip, rc.topLeft());
152}
153
155{
156 if (!node) return;
157 if (!d->selection) return;
158 if (node->node()->exactBounds().isEmpty()) return;
159 if (!node->node()->hasEditablePaintDevice()) return;
160 KisPaintDeviceSP dev = node->node()->paintDevice();
161 copy(node);
162 dev->clearSelection(d->selection);
163 node->node()->setDirty(d->selection->selectedExactRect());
164}
165
166void Selection::paste(Node *destination, int x, int y)
167{
168 if (!destination) return;
169 if (!d->selection) return;
170 if (!KisClipboard::instance()->hasClip()) return;
171
172 KisPaintDeviceSP src = KisClipboard::instance()->clip(QRect(), false);
173 KisPaintDeviceSP dst = destination->node()->paintDevice();
174 if (!dst || !src) return;
175 KisPainter::copyAreaOptimized(QPoint(x, y),
176 src,
177 dst,
178 src->exactBounds(),
179 d->selection);
180 destination->node()->setDirty();
181}
182
184{
185 if (!d->selection) return;
186 KisErodeSelectionFilter esf;
187 QRect rc = esf.changeRect(d->selection->selectedExactRect(), d->selection->pixelSelection()->defaultBounds());
188 esf.process(d->selection->pixelSelection(), rc);
189}
190
192{
193 if (!d->selection) return;
194 KisDilateSelectionFilter dsf;
195 QRect rc = dsf.changeRect(d->selection->selectedExactRect(), d->selection->pixelSelection()->defaultBounds());
196 dsf.process(d->selection->pixelSelection(), rc);
197}
198
199void Selection::border(int xRadius, int yRadius)
200{
201 if (!d->selection) return;
202 KisBorderSelectionFilter sf(xRadius, yRadius, true);
203 QRect rc = sf.changeRect(d->selection->selectedExactRect(), d->selection->pixelSelection()->defaultBounds());
204 sf.process(d->selection->pixelSelection(), rc);
205}
206
207void Selection::feather(int radius)
208{
209 if (!d->selection) return;
210 KisFeatherSelectionFilter fsf(radius);
211 QRect rc = fsf.changeRect(d->selection->selectedExactRect(), d->selection->pixelSelection()->defaultBounds());
212 fsf.process(d->selection->pixelSelection(), rc);
213}
214
215void Selection::grow(int xradius, int yradius)
216{
217 if (!d->selection) return;
218 KisGrowSelectionFilter gsf(xradius, yradius);
219 QRect rc = gsf.changeRect(d->selection->selectedExactRect(), d->selection->pixelSelection()->defaultBounds());
220 gsf.process(d->selection->pixelSelection(), rc);
221}
222
223
224void Selection::shrink(int xRadius, int yRadius, bool edgeLock)
225{
226 if (!d->selection) return;
227 KisShrinkSelectionFilter sf(xRadius, yRadius, edgeLock);
228 QRect rc = sf.changeRect(d->selection->selectedExactRect(), d->selection->pixelSelection()->defaultBounds());
229 sf.process(d->selection->pixelSelection(), rc);
230}
231
233{
234 if (!d->selection) return;
235 KisSmoothSelectionFilter sf;
236 QRect rc = sf.changeRect(d->selection->selectedExactRect(), d->selection->pixelSelection()->defaultBounds());
237 sf.process(d->selection->pixelSelection(), rc);
238}
239
240
242{
243 if (!d->selection) return;
244 KisInvertSelectionFilter sf;
245 QRect rc = sf.changeRect(d->selection->selectedExactRect(), d->selection->pixelSelection()->defaultBounds());
246 sf.process(d->selection->pixelSelection(), rc);
247}
248
249void Selection::resize(int w, int h)
250{
251 if (!d->selection) return;
252 d->selection->pixelSelection()->select(QRect(x(), y(), w, h));
253}
254
255void Selection::select(int x, int y, int w, int h, int value)
256{
257 if (!d->selection) return;
258 d->selection->pixelSelection()->select(QRect(x, y, w, h), value);
259}
260
261void Selection::selectAll(Node *node, int value)
262{
263 if (!d->selection) return;
264 d->selection->pixelSelection()->select(node->node()->exactBounds(), value);
265}
266
268{
269 if (!d->selection) return;
270 d->selection->pixelSelection()->applySelection(selection->selection()->pixelSelection(), SELECTION_REPLACE);
271}
272
273void Selection::add(Selection *selection)
274{
275 if (!d->selection) return;
276 d->selection->pixelSelection()->applySelection(selection->selection()->pixelSelection(), SELECTION_ADD);
277}
278
280{
281 if (!d->selection) return;
282 d->selection->pixelSelection()->applySelection(selection->selection()->pixelSelection(), SELECTION_SUBTRACT);
283}
284
286{
287 if (!d->selection) return;
288 d->selection->pixelSelection()->applySelection(selection->selection()->pixelSelection(), SELECTION_INTERSECT);
289}
290
292{
293 if (!d->selection) return;
294 d->selection->pixelSelection()->applySelection(selection->selection()->pixelSelection(), SELECTION_SYMMETRICDIFFERENCE);
295}
296
297
298QByteArray Selection::pixelData(int x, int y, int w, int h) const
299{
300 QByteArray ba;
301 if (!d->selection) return ba;
302 KisPaintDeviceSP dev = d->selection->projection();
303 quint8 *data = new quint8[w * h];
304 dev->readBytes(data, x, y, w, h);
305 ba = QByteArray((const char*)data, (int)(w * h));
306 delete[] data;
307 return ba;
308}
309
310void Selection::setPixelData(QByteArray value, int x, int y, int w, int h)
311{
312 if (!d->selection) return;
313 KisPixelSelectionSP dev = d->selection->pixelSelection();
314 if (!dev) return;
315 dev->writeBytes((const quint8*)value.constData(), x, y, w, h);
316}
317
318KisSelectionSP Selection::selection() const
319{
320 return d->selection;
321}
322
323
Node represents a layer or mask in a Krita image's Node hierarchy.
Definition Node.h:24
Selection represents a selection on Krita.
Definition Selection.h:31
void move(int x, int y)
Move the selection's top-left corner to the given coordinates.
Definition Selection.cpp:94
void resize(int w, int h)
Resize the selection to the given width and height.
void cut(Node *node)
cut erases the area defined by the selection from the node and puts a copy on the clipboard.
int y() const
Definition Selection.cpp:84
void intersect(Selection *selection)
Intersect the given selection with this selection.
void copy(Node *node)
copy copies the area defined by the selection from the node to the clipboard.
Selection(KisSelectionSP selection, QObject *parent=0)
For internal use only.
Definition Selection.cpp:26
void paste(Node *destination, int x, int y)
paste pastes the content of the clipboard to the given node, limited by the area of the current selec...
int width() const
Definition Selection.cpp:62
void selectAll(Node *node, int value)
Select all pixels in the given node.
void clear()
Make the selection entirely unselected.
void contract(int value)
Make the selection's width and height smaller by the given value.
void shrink(int xRadius, int yRadius, bool edgeLock)
Shrink the selection with the given radius.
Selection * duplicate() const
Definition Selection.cpp:56
void smooth()
Smooth the selection.
void subtract(Selection *selection)
Subtract the given selection's selected pixels from the current selection.
int x() const
Definition Selection.cpp:74
void dilate()
Dilate the selection with a radius of 1 pixel.
void erode()
Erode the selection with a radius of 1 pixel.
void feather(int radius)
Feather the selection with the given radius.
void setPixelData(QByteArray value, int x, int y, int w, int h)
setPixelData writes the given bytes, of which there must be enough, into the Selection.
void invert()
Invert the selection.
void border(int xRadius, int yRadius)
Border the selection with the given radius.
QByteArray pixelData(int x, int y, int w, int h) const
pixelData reads the given rectangle from the Selection's mask and returns it as a byte array.
void grow(int xradius, int yradius)
Grow the selection with the given radius.
void add(Selection *selection)
Add the given selection's selected pixels to the current selection.
void select(int x, int y, int w, int h, int value)
Select the given area.
int height() const
Definition Selection.cpp:68
void replace(Selection *selection)
Replace the current selection's selection with the one of the given selection.
void symmetricdifference(Selection *selection)
Intersect with the inverse of the given selection with this selection.
const char * constData() const const
int height() const const
QPoint topLeft() const const
int width() const const
int x() const const
int y() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 22 2024 12:06:52 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.