Krita

Selection.cpp
1 /*
2  * SPDX-FileCopyrightText: 2016 Boudewijn Rempt <[email protected]>
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 
21 struct Selection::Private {
22  Private() {}
23  KisSelectionSP selection;
24 };
25 
26 Selection::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 
41 Selection::~Selection()
42 {
43  delete d;
44 }
45 
46 bool Selection::operator==(const Selection &other) const
47 {
48  return (d->selection == other.d->selection);
49 }
50 
51 bool 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 
62 int Selection::width() const
63 {
64  if (!d->selection) return 0;
65  return d->selection->selectedExactRect().width();
66 }
67 
68 int Selection::height() const
69 {
70  if (!d->selection) return 0;
71  return d->selection->selectedExactRect().height();
72 }
73 
74 int 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 
84 int 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 
94 void 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 
107 void 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 
154 void Selection::cut(Node* node)
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 
166 void 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 
199 void 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 
207 void 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 
215 void 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 
224 void 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 
249 void Selection::resize(int w, int h)
250 {
251  if (!d->selection) return;
252  d->selection->pixelSelection()->select(QRect(x(), y(), w, h));
253 }
254 
255 void 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 
261 void 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 
273 void 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 
298 QByteArray 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 
310 void 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 
318 KisSelectionSP Selection::selection() const
319 {
320  return d->selection;
321 }
322 
323 
Selection * duplicate() const
Definition: Selection.cpp:56
void contract(int value)
Make the selection's width and height smaller by the given value.
Definition: Selection.cpp:107
void selectAll(Node *node, int value)
Select all pixels in the given node.
Definition: Selection.cpp:261
QPoint topLeft() const const
void move(int x, int y)
Move the selection's top-left corner to the given coordinates.
Definition: Selection.cpp:94
Selection(KisSelectionSP selection, QObject *parent=0)
For internal use only.
Definition: Selection.cpp:26
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.
Definition: Selection.cpp:310
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.
Definition: Selection.cpp:298
void intersect(Selection *selection)
Intersect the given selection with this selection.
Definition: Selection.cpp:285
int width() const const
int x() const const
void symmetricdifference(Selection *selection)
Intersect with the inverse of the given selection with this selection.
Definition: Selection.cpp:291
int y() const const
Selection represents a selection on Krita.
Definition: Selection.h:30
void feather(int radius)
Feather the selection with the given radius.
Definition: Selection.cpp:207
void grow(int xradius, int yradius)
Grow the selection with the given radius.
Definition: Selection.cpp:215
void replace(Selection *selection)
Replace the current selection's selection with the one of the given selection.
Definition: Selection.cpp:267
void resize(int w, int h)
Resize the selection to the given width and height.
Definition: Selection.cpp:249
int x() const
Definition: Selection.cpp:74
void add(Selection *selection)
Add the given selection's selected pixels to the current selection.
Definition: Selection.cpp:273
void subtract(Selection *selection)
Subtract the given selection's selected pixels from the current selection.
Definition: Selection.cpp:279
void smooth()
Smooth the selection.
Definition: Selection.cpp:232
void copy(Node *node)
copy copies the area defined by the selection from the node to the clipboard.
Definition: Selection.cpp:113
int height() const
Definition: Selection.cpp:68
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...
Definition: Selection.cpp:166
void cut(Node *node)
cut erases the area defined by the selection from the node and puts a copy on the clipboard.
Definition: Selection.cpp:154
void clear()
Make the selection entirely unselected.
Definition: Selection.cpp:101
Node represents a layer or mask in a Krita image's Node hierarchy.
Definition: Node.h:21
int height() const const
void select(int x, int y, int w, int h, int value)
Select the given area.
Definition: Selection.cpp:255
const char * constData() const const
void invert()
Invert the selection.
Definition: Selection.cpp:241
void erode()
Erode the selection with a radius of 1 pixel.
Definition: Selection.cpp:183
int width() const
Definition: Selection.cpp:62
int y() const
Definition: Selection.cpp:84
void dilate()
Dilate the selection with a radius of 1 pixel.
Definition: Selection.cpp:191
void shrink(int xRadius, int yRadius, bool edgeLock)
Shrink the selection with the given radius.
Definition: Selection.cpp:224
void border(int xRadius, int yRadius)
Border the selection with the given radius.
Definition: Selection.cpp:199
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Wed Sep 27 2023 03:58:14 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.