Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_fill_painter.cc
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2004 Adrian Page <adrian@pagenet.plus.com>
3 * SPDX-FileCopyrightText: 2004 Bart Coppens <kde@bartcoppens.be>
4 * SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev@gmail.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include "kis_fill_painter.h"
10
11#include <stdlib.h>
12#include <string.h>
13#include <cfloat>
14#include <stack>
15
16#include <QFontInfo>
17#include <QFontMetrics>
18#include <QPen>
19#include <QImage>
20#include <QMap>
21#include <QPainter>
22#include <QRect>
23
24#include <klocalizedstring.h>
25
26#include <KoUpdater.h>
27
32#include "kis_debug.h"
33#include "kis_image.h"
34#include "kis_layer.h"
35#include "kis_paint_device.h"
36#include <resources/KoPattern.h>
37#include "KoColorSpace.h"
38#include "kis_transaction.h"
39#include "kis_pixel_selection.h"
46#include <krita_utils.h>
47#include <kis_default_bounds.h>
49
50
56
62
64 : KisPainter(device, selection)
65{
67}
68
84
85void KisFillPainter::fillSelection(const QRect &rc, const KoColor &color)
86{
87 KisPaintDeviceSP fillDevice = new KisPaintDevice(device()->colorSpace());
88 fillDevice->setDefaultPixel(color);
89
90 bitBlt(rc.topLeft(), fillDevice, rc);
91}
92
93// 'regular' filling
94// XXX: This also needs renaming, since filling ought to keep the opacity and the composite op in mind,
95// this is more eraseToColor.
96void KisFillPainter::fillRect(qint32 x1, qint32 y1, qint32 w, qint32 h, const KoColor& kc, quint8 opacity)
97{
98 if (w > 0 && h > 0) {
99 // Make sure we're in the right colorspace
100
101 KoColor kc2(kc); // get rid of const
102 kc2.convertTo(device()->colorSpace());
103 quint8 * data = kc2.data();
104 device()->colorSpace()->setOpacity(data, opacity, 1);
105
106 device()->fill(x1, y1, w, h, data);
107
108 addDirtyRect(QRect(x1, y1, w, h));
109 }
110}
111
112void KisFillPainter::fillRect(const QRect &rc, const KoPatternSP pattern, const QPoint &offset)
113{
114 fillRect(rc.x(), rc.y(), rc.width(), rc.height(), pattern, offset);
115}
116
117void KisFillPainter::fillRect(qint32 x1, qint32 y1, qint32 w, qint32 h, const KoPatternSP pattern, const QPoint &offset)
118{
119 if (!pattern) return;
120 if (!pattern->valid()) return;
121 if (!device()) return;
122 if (w < 1) return;
123 if (h < 1) return;
124
125 KisPaintDeviceSP patternLayer = new KisPaintDevice(device()->compositionSourceColorSpace(), pattern->name());
126 patternLayer->convertFromQImage(pattern->pattern(), 0);
127
128 if (!offset.isNull()) {
129 patternLayer->moveTo(offset);
130 }
131
132 fillRect(x1, y1, w, h, patternLayer, QRect(offset.x(), offset.y(), pattern->width(), pattern->height()));
133}
134
135void KisFillPainter::fillRectNoCompose(const QRect &rc, const KoPatternSP pattern, const QTransform transform)
136{
137 if (!pattern) return;
138 if (!pattern->valid()) return;
139 if (!device()) return;
140 if (rc.width() < 1) return;
141 if (rc.height() < 1) return;
142
143 KisPaintDeviceSP patternLayer = new KisPaintDevice(device()->colorSpace(), pattern->name());
144 patternLayer->convertFromQImage(pattern->pattern(), 0);
145
146 fillRectNoCompose(rc.x(), rc.y(), rc.width(), rc.height(), patternLayer, QRect(0, 0, pattern->width(), pattern->height()), transform);
147}
148
149void KisFillPainter::fillRectNoCompose(qint32 x1, qint32 y1, qint32 w, qint32 h, const KisPaintDeviceSP device, const QRect& deviceRect, const QTransform transform)
150{
156 KIS_SAFE_ASSERT_RECOVER_RETURN(device->pixelSize() == this->device()->pixelSize());
157 KIS_SAFE_ASSERT_RECOVER_NOOP(*device->colorSpace() == *this->device()->colorSpace());
158
159 KisPaintDeviceSP wrapped = device;
160 KisDefaultBoundsBaseSP oldBounds = wrapped->defaultBounds();
161 wrapped->setDefaultBounds(new KisWrapAroundBoundsWrapper(oldBounds, deviceRect));
162 const bool oldSupportsWrapAroundMode = wrapped->supportsWraproundMode();
163 wrapped->setSupportsWraparoundMode(true);
164
165
166 KisPerspectiveTransformWorker worker(this->device(), transform, false, this->progressUpdater());
167 worker.runPartialDst(device, this->device(), QRect(x1, y1, w, h));
168
169 addDirtyRect(QRect(x1, y1, w, h));
170 wrapped->setDefaultBounds(oldBounds);
171 wrapped->setSupportsWraparoundMode(oldSupportsWrapAroundMode);
172}
173
174void KisFillPainter::fillRect(const QRect &rc, const KisPaintDeviceSP device, const QRect& deviceRect)
175{
176 fillRect(rc.x(), rc.y(), rc.width(), rc.height(), device, deviceRect);
177}
178
179void KisFillPainter::fillRect(qint32 x1, qint32 y1, qint32 w, qint32 h, const KisPaintDeviceSP device, const QRect& deviceRect)
180{
181 const QRect &patternRect = deviceRect;
182 const QRect fillRect(x1, y1, w, h);
183
184 auto toPatternLocal = [](int value, int offset, int width) {
185 const int normalizedValue = value - offset;
186 return offset + (normalizedValue >= 0 ?
187 normalizedValue % width :
188 width - (-normalizedValue - 1) % width - 1);
189 };
190
191 int dstY = fillRect.y();
192 while (dstY <= fillRect.bottom()) {
193 const int dstRowsRemaining = fillRect.bottom() - dstY + 1;
194
195 const int srcY = toPatternLocal(dstY, patternRect.y(), patternRect.height());
196 const int height = qMin(patternRect.height() - srcY + patternRect.y(), dstRowsRemaining);
197
198 int dstX = fillRect.x();
199 while (dstX <= fillRect.right()) {
200 const int dstColumnsRemaining = fillRect.right() - dstX + 1;
201
202 const int srcX = toPatternLocal(dstX, patternRect.x(), patternRect.width());
203 const int width = qMin(patternRect.width() - srcX + patternRect.x(), dstColumnsRemaining);
204
205 bitBlt(dstX, dstY, device, srcX, srcY, width, height);
206
207 dstX += width;
208 }
209 dstY += height;
210 }
211
212 addDirtyRect(QRect(x1, y1, w, h));
213}
214
215void KisFillPainter::fillRect(qint32 x1, qint32 y1, qint32 w, qint32 h, const KisFilterConfigurationSP generator)
216{
217 if (!generator) return;
219 if (!device()) return;
220 if (w < 1) return;
221 if (h < 1) return;
222
223 QRect tmpRc(x1, y1, w, h);
224
225 KisProcessingInformation dstCfg(device(), tmpRc.topLeft(), 0);
226
227 g->generate(dstCfg, tmpRc.size(), generator);
228
229 addDirtyRect(tmpRc);
230}
231
232// flood filling
233
234void KisFillPainter::fillColor(int startX, int startY, KisPaintDeviceSP sourceDevice)
235{
236 if (!m_useCompositing) {
237 if (m_sizemod || m_feather ||
239 !isOpacityUnit() ||
240 sourceDevice != device()) {
241
242 warnKrita << "WARNING: Fast Flood Fill (no compositing mode)"
243 << "does not support compositeOps, opacity, "
244 << "selection enhancements and separate source "
245 << "devices";
246 }
247
248 QRect fillBoundsRect(0, 0, m_width, m_height);
249 QPoint startPoint(startX, startY);
250
251 if (!fillBoundsRect.contains(startPoint)) return;
252
253 KisScanlineFill gc(device(), startPoint, fillBoundsRect);
256 gc.fill(paintColor());
257 } else {
259 }
260
262
263 } else {
264 genericFillStart(startX, startY, sourceDevice);
265
266 // Now create a layer and fill it
268 Q_CHECK_PTR(filled);
269 KisFillPainter painter(filled);
270 painter.fillRect(0, 0, m_width, m_height, paintColor());
271 painter.end();
272
273 genericFillEnd(filled);
274 }
275}
276
277void KisFillPainter::fillPattern(int startX, int startY, KisPaintDeviceSP sourceDevice, QTransform patternTransform)
278{
279 genericFillStart(startX, startY, sourceDevice);
280
281 // Now create a layer and fill it
283 Q_CHECK_PTR(filled);
284 KisFillPainter painter(filled);
285 painter.fillRectNoCompose(QRect(0, 0, m_width, m_height), pattern(), patternTransform);
286 painter.end();
287
288 genericFillEnd(filled);
289}
290
291void KisFillPainter::genericFillStart(int startX, int startY, KisPaintDeviceSP sourceDevice)
292{
293 Q_ASSERT(m_width > 0);
294 Q_ASSERT(m_height > 0);
295
296 // Create a selection from the surrounding area
297
298 KisPixelSelectionSP pixelSelection = createFloodSelection(startX, startY, sourceDevice,
299 (selection().isNull() ? 0 : selection()->pixelSelection()));
300 KisSelectionSP newSelection = new KisSelection(pixelSelection->defaultBounds(),
301 selection() ? selection()->resolutionProxy() : KisImageResolutionProxy::identity());
302 newSelection->pixelSelection()->applySelection(pixelSelection, SELECTION_REPLACE);
303 m_fillSelection = newSelection;
304}
305
307{
308 if (progressUpdater() && progressUpdater()->interrupted()) {
309 m_width = m_height = -1;
310 return;
311 }
312
313// TODO: filling using the correct bound of the selection would be better, *but*
314// the selection is limited to the exact bound of a layer, while in reality, we don't
315// want that, since we want a transparent layer to be completely filled
316// QRect rc = m_fillSelection->selectedExactRect();
317
318
322 KisSelectionSP realSelection = selection();
323 QRect rc;
324
325 if (realSelection) {
326 rc = m_fillSelection->selectedExactRect().intersected(realSelection->projection()->selectedExactRect());
328 realSelection->projection(), SELECTION_INTERSECT);
329 } else {
331 }
332
334 bitBlt(rc.topLeft(), filled, rc);
335 setSelection(realSelection);
336
338
339 m_width = m_height = -1;
340}
341
343 KisPaintDeviceSP existingSelection)
344{
346 return createFloodSelection(newSelection, startX, startY, sourceDevice, existingSelection);
347}
348
350 KisPaintDeviceSP sourceDevice, KisPaintDeviceSP existingSelection)
351{
352
353 if (m_width < 0 || m_height < 0) {
354 if (selection() && m_careForSelection) {
355 QRect rc = selection()->selectedExactRect();
356 m_width = rc.width() - (startX - rc.x());
357 m_height = rc.height() - (startY - rc.y());
358 }
359 }
360 dbgImage << "Width: " << m_width << " Height: " << m_height;
361 // Otherwise the width and height should have been set
362 Q_ASSERT(m_width > 0 && m_height > 0);
363
364 QRect fillBoundsRect(0, 0, m_width, m_height);
365 QPoint startPoint(startX, startY);
366
367 if (!fillBoundsRect.contains(startPoint)) {
368 return pixelSelection;
369 }
370
371 KisScanlineFill gc(sourceDevice, startPoint, fillBoundsRect);
375
377 if (m_useSelectionAsBoundary && !pixelSelection.isNull()) {
378 gc.fillSelection(pixelSelection, existingSelection);
379 } else {
380 gc.fillSelection(pixelSelection);
381 }
382 } else {
383 if (m_useSelectionAsBoundary && !pixelSelection.isNull()) {
384 gc.fillSelectionUntilColor(pixelSelection, m_regionFillingBoundaryColor, existingSelection);
385 } else {
387 }
388 }
389
390 if (m_useCompositing) {
391 if (m_sizemod > 0) {
394 biggy.process(pixelSelection, pixelSelection->selectedRect().adjusted(-m_sizemod, -m_sizemod, m_sizemod, m_sizemod));
395 } else {
397 biggy.process(pixelSelection, pixelSelection->selectedRect().adjusted(-m_sizemod, -m_sizemod, m_sizemod, m_sizemod));
398 }
399 }
400 else if (m_sizemod < 0) {
402 tiny.process(pixelSelection, pixelSelection->selectedRect());
403 }
404 // Since the feathering already smooths the selection, the antiAlias
405 // is not applied if we must feather
406 if (m_feather > 0) {
408 feathery.process(pixelSelection, pixelSelection->selectedRect().adjusted(-m_feather, -m_feather, m_feather, m_feather));
409 } else if (m_antiAlias) {
410 KisAntiAliasSelectionFilter antiAliasFilter;
411 antiAliasFilter.process(pixelSelection, pixelSelection->selectedRect());
412 }
413 }
414
415 return pixelSelection;
416}
417
418template <typename DifferencePolicy, typename SelectionPolicy>
420 KisPaintDeviceSP referenceDevice,
421 const QRect &rect,
423 DifferencePolicy differencePolicy,
424 SelectionPolicy selectionPolicy,
425 KoUpdater *updater = nullptr)
426{
427 KisSequentialConstIterator referenceDeviceIterator(referenceDevice, rect);
428 KisSequentialIterator outSelectionIterator(outSelection, rect);
429
430 const int totalNumberOfPixels = rect.width() * rect.height();
431 const int numberOfUpdates = 4;
432 const int numberOfPixelsPerUpdate = totalNumberOfPixels / numberOfUpdates;
433 const int progressIncrement = 100 / numberOfUpdates;
434 int numberOfPixelsProcessed = 0;
435
436 if (mask) {
437 KisSequentialConstIterator maskIterator(mask, rect);
438 while (referenceDeviceIterator.nextPixel() &&
439 outSelectionIterator.nextPixel() &&
440 maskIterator.nextPixel()) {
441 if (*maskIterator.rawDataConst() != MIN_SELECTED) {
442 *outSelectionIterator.rawData() =
443 selectionPolicy.opacityFromDifference(
444 differencePolicy.difference(referenceDeviceIterator.rawDataConst())
445 );
446 }
447 if (updater) {
448 ++numberOfPixelsProcessed;
449 if (numberOfPixelsProcessed > numberOfPixelsPerUpdate) {
450 numberOfPixelsProcessed = 0;
451 updater->setProgress(updater->progress() + progressIncrement);
452 }
453 }
454 }
455 } else {
456 while (referenceDeviceIterator.nextPixel() &&
457 outSelectionIterator.nextPixel()) {
458 *outSelectionIterator.rawData() =
459 selectionPolicy.opacityFromDifference(
460 differencePolicy.difference(referenceDeviceIterator.rawDataConst())
461 );
462 if (updater) {
463 ++numberOfPixelsProcessed;
464 if (numberOfPixelsProcessed > numberOfPixelsPerUpdate) {
465 numberOfPixelsProcessed = 0;
466 updater->setProgress(updater->progress() + progressIncrement);
467 }
468 }
469 }
470 }
471 if (updater) {
472 updater->setProgress(100);
473 }
474}
475
477 const KoColor &referenceColor,
478 KisPaintDeviceSP referenceDevice,
479 const QRect &rect,
481{
482 if (rect.isEmpty()) {
483 return;
484 }
485
486 KoColor srcColor(referenceColor);
487 srcColor.convertTo(referenceDevice->colorSpace());
488
489 const int pixelSize = referenceDevice->pixelSize();
490 const int softness = 100 - opacitySpread();
491
492 using namespace KisColorSelectionPolicies;
493
494 if (softness == 0) {
496 if (pixelSize == 1) {
498 createSimilarColorsSelectionImpl(outSelection, referenceDevice, rect, mask, dp, sp);
499 } else if (pixelSize == 2) {
501 createSimilarColorsSelectionImpl(outSelection, referenceDevice, rect, mask, dp, sp);
502 } else if (pixelSize == 4) {
504 createSimilarColorsSelectionImpl(outSelection, referenceDevice, rect, mask, dp, sp);
505 } else if (pixelSize == 8) {
507 createSimilarColorsSelectionImpl(outSelection, referenceDevice, rect, mask, dp, sp);
508 } else {
509 SlowDifferencePolicy dp(srcColor, fillThreshold());
510 createSimilarColorsSelectionImpl(outSelection, referenceDevice, rect, mask, dp, sp);
511 }
512 } else {
513 SoftSelectionPolicy sp(fillThreshold(), softness);
514 if (pixelSize == 1) {
516 createSimilarColorsSelectionImpl(outSelection, referenceDevice, rect, mask, dp, sp);
517 } else if (pixelSize == 2) {
519 createSimilarColorsSelectionImpl(outSelection, referenceDevice, rect, mask, dp, sp);
520 } else if (pixelSize == 4) {
522 createSimilarColorsSelectionImpl(outSelection, referenceDevice, rect, mask, dp, sp);
523 } else if (pixelSize == 8) {
525 createSimilarColorsSelectionImpl(outSelection, referenceDevice, rect, mask, dp, sp);
526 } else {
527 SlowDifferencePolicy dp(srcColor, fillThreshold());
528 createSimilarColorsSelectionImpl(outSelection, referenceDevice, rect, mask, dp, sp);
529 }
530 }
531}
532
534 KisPixelSelectionSP outSelection,
535 const QSharedPointer<KoColor> referenceColor,
536 KisPaintDeviceSP referenceDevice,
537 const QRect &rect,
540)
541{
542 if (rect.isEmpty()) {
543 return {};
544 }
545
547 QVector<QRect> fillPatches =
549 const int threshold = fillThreshold();
550 const int softness = 100 - opacitySpread();
551 const int sizemod = this->sizemod();
553 const int feather = this->feather();
554 const bool antiAlias = this->antiAlias();
555
556 KritaUtils::addJobBarrier(jobsData, nullptr);
557
558 for (const QRect &patch : fillPatches) {
560 jobsData,
561 [referenceDevice, outSelection, mask, referenceColor,
562 threshold, softness, patch, progressHelper]() mutable
563 {
564 if (patch.isEmpty()) {
565 return;
566 }
567
568 KoUpdater *updater = progressHelper ? progressHelper->updater() : nullptr;
569
570 using namespace KisColorSelectionPolicies;
571
572 const int pixelSize = referenceDevice->pixelSize();
573 KoColor srcColor(*referenceColor);
574 srcColor.convertTo(referenceDevice->colorSpace());
575
576 if (softness == 0) {
577 HardSelectionPolicy sp(threshold);
578 if (pixelSize == 1) {
579 OptimizedDifferencePolicy<quint8> dp(srcColor, threshold);
580 createSimilarColorsSelectionImpl(outSelection, referenceDevice, patch, mask, dp, sp, updater);
581 } else if (pixelSize == 2) {
582 OptimizedDifferencePolicy<quint16> dp(srcColor, threshold);
583 createSimilarColorsSelectionImpl(outSelection, referenceDevice, patch, mask, dp, sp, updater);
584 } else if (pixelSize == 4) {
585 OptimizedDifferencePolicy<quint32> dp(srcColor, threshold);
586 createSimilarColorsSelectionImpl(outSelection, referenceDevice, patch, mask, dp, sp, updater);
587 } else if (pixelSize == 8) {
588 OptimizedDifferencePolicy<quint64> dp(srcColor, threshold);
589 createSimilarColorsSelectionImpl(outSelection, referenceDevice, patch, mask, dp, sp, updater);
590 } else {
591 SlowDifferencePolicy dp(srcColor, threshold);
592 createSimilarColorsSelectionImpl(outSelection, referenceDevice, patch, mask, dp, sp, updater);
593 }
594 } else {
595 SoftSelectionPolicy sp(threshold, softness);
596 if (pixelSize == 1) {
597 OptimizedDifferencePolicy<quint8> dp(srcColor, threshold);
598 createSimilarColorsSelectionImpl(outSelection, referenceDevice, patch, mask, dp, sp, updater);
599 } else if (pixelSize == 2) {
600 OptimizedDifferencePolicy<quint16> dp(srcColor, threshold);
601 createSimilarColorsSelectionImpl(outSelection, referenceDevice, patch, mask, dp, sp, updater);
602 } else if (pixelSize == 4) {
603 OptimizedDifferencePolicy<quint32> dp(srcColor, threshold);
604 createSimilarColorsSelectionImpl(outSelection, referenceDevice, patch, mask, dp, sp, updater);
605 } else if (pixelSize == 8) {
606 OptimizedDifferencePolicy<quint64> dp(srcColor, threshold);
607 createSimilarColorsSelectionImpl(outSelection, referenceDevice, patch, mask, dp, sp, updater);
608 } else {
609 SlowDifferencePolicy dp(srcColor, threshold);
610 createSimilarColorsSelectionImpl(outSelection, referenceDevice, patch, mask, dp, sp, updater);
611 }
612 }
613 }
614 );
615 }
616
618 jobsData,
619 [outSelection, referenceDevice, mask,
620 sizemod, stopGrowingAtDarkestPixel, feather, antiAlias, progressHelper]() mutable
621 {
622 KoUpdater *updater = progressHelper ? progressHelper->updater() : nullptr;
623
624 if (sizemod > 0) {
626 KisGrowUntilDarkestPixelSelectionFilter biggy(sizemod, referenceDevice);
627 biggy.process(outSelection, outSelection->selectedRect().adjusted(-sizemod, -sizemod, sizemod, sizemod));
628 } else {
630 biggy.process(outSelection, outSelection->selectedRect().adjusted(-sizemod, -sizemod, sizemod, sizemod));
631 }
632 } else if (sizemod < 0) {
634 tiny.process(outSelection, outSelection->selectedRect());
635 }
636 if (updater) {
637 updater->setProgress(33);
638 }
639
640 // Since the feathering already smooths the selection, the antiAlias
641 // is not applied if we must feather
642 if (feather > 0) {
644 feathery.process(outSelection, outSelection->selectedRect().adjusted(-feather, -feather, feather, feather));
645 } else if (antiAlias) {
646 KisAntiAliasSelectionFilter antiAliasFilter;
647 antiAliasFilter.process(outSelection, outSelection->selectedRect());
648 }
649 if (updater) {
650 updater->setProgress(66);
651 }
652
653 if (mask) {
654 outSelection->applySelection(mask, SELECTION_INTERSECT);
655 }
656 if (updater) {
657 updater->setProgress(100);
658 }
659 }
660 );
661
662 return jobsData;
663}
float value(const T *src, size_t ch)
@ SELECTION_REPLACE
@ SELECTION_INTERSECT
const QString COMPOSITE_OVER
AntiAlias filter for selections inspired by FXAA.
void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override
void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override
void fillSelection(const QRect &rc, const KoColor &color)
KisPixelSelectionSP createFloodSelection(int startX, int startY, KisPaintDeviceSP sourceDevice, KisPaintDeviceSP existingSelection)
KoColor m_regionFillingBoundaryColor
QVector< KisStrokeJobData * > createSimilarColorsSelectionJobs(KisPixelSelectionSP outSelection, const QSharedPointer< KoColor > referenceColor, KisPaintDeviceSP referenceDevice, const QRect &rect, KisPixelSelectionSP mask, QSharedPointer< KisProcessingVisitor::ProgressHelper > progressHelper=nullptr)
void fillRect(qint32 x, qint32 y, qint32 w, qint32 h, const KoColor &c, quint8 opacity)
int sizemod() const
int fillThreshold() const
int opacitySpread() const
bool antiAlias() const
void fillColor(int startX, int startY, KisPaintDeviceSP sourceDevice)
void fillPattern(int startX, int startY, KisPaintDeviceSP sourceDevice, QTransform patternTransform=QTransform())
uint feather() const
void genericFillEnd(KisPaintDeviceSP filled)
void createSimilarColorsSelection(KisPixelSelectionSP outSelection, const KoColor &referenceColor, KisPaintDeviceSP referenceDevice, const QRect &rect, KisPixelSelectionSP mask)
void genericFillStart(int startX, int startY, KisPaintDeviceSP sourceDevice)
bool stopGrowingAtDarkestPixel() const
RegionFillingMode m_regionFillingMode
void fillRectNoCompose(const QRect &rc, const KoPatternSP pattern, const QTransform transform)
fillRect Fill a rectangle with a certain pattern. The pattern is repeated if it does not fit the enti...
KisSelectionSP m_fillSelection
static KisGeneratorRegistry * instance()
virtual void generate(KisProcessingInformation dst, const QSize &size, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const =0
void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override
Filter that dilates a selection and that can stop dilating adaptively at areas of higher darkness or ...
void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override
static KisImageResolutionProxySP identity()
quint32 pixelSize() const
bool supportsWraproundMode() const
void setDefaultPixel(const KoColor &defPixel)
void setDefaultBounds(KisDefaultBoundsBaseSP bounds)
KisPaintDeviceSP createCompositionSourceDevice() const
void fill(const QRect &rc, const KoColor &color)
const KoColorSpace * colorSpace() const
void setSupportsWraparoundMode(bool value)
KisDefaultBoundsBaseSP defaultBounds() const
void convertFromQImage(const QImage &image, const KoColorProfile *profile, qint32 offsetX=0, qint32 offsetY=0)
void moveTo(qint32 x, qint32 y)
const KoColorSpace * colorSpace
QString compositeOpId
bool isOpacityUnit
quint32 pixelSize
KoColor paintColor
KisFilterConfigurationSP generator
void setSelection(KisSelectionSP selection)
KoUpdater * progressUpdater
KisSelectionSP selection
QTransform patternTransform
void bitBlt(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight)
void addDirtyRect(const QRect &r)
KisPaintDeviceSP device
KoPatternSP pattern
void runPartialDst(KisPaintDeviceSP srcDev, KisPaintDeviceSP dstDev, const QRect &dstRect)
ALWAYS_INLINE quint8 * rawData()
ALWAYS_INLINE const quint8 * rawDataConst() const
bool isNull() const
void process(KisPixelSelectionSP pixelSelection, const QRect &rect) override
virtual void setOpacity(quint8 *pixels, quint8 alpha, qint32 nPixels) const =0
void convertTo(const KoColorSpace *cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
Definition KoColor.cpp:136
quint8 * data()
Definition KoColor.h:144
const T value(const QString &id) const
void setProgress(int percent)
Definition KoUpdater.cpp:38
#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 warnKrita
Definition kis_debug.h:87
#define dbgImage
Definition kis_debug.h:46
void createSimilarColorsSelectionImpl(KisPixelSelectionSP outSelection, KisPaintDeviceSP referenceDevice, const QRect &rect, KisPixelSelectionSP mask, DifferencePolicy differencePolicy, SelectionPolicy selectionPolicy, KoUpdater *updater=nullptr)
const quint8 MIN_SELECTED
Definition kis_global.h:33
QVector< QRect > splitRectIntoPatches(const QRect &rc, const QSize &patchSize)
void addJobConcurrent(QVector< Job * > &jobs, Func func)
void addJobSequential(QVector< Job * > &jobs, Func func)
void addJobBarrier(QVector< Job * > &jobs, Func func)
QSize optimalPatchSize()
QRect selectedExactRect() const
void applySelection(KisPixelSelectionSP selection, SelectionAction action)
void fillSelectionUntilColor(KisPixelSelectionSP pixelSelection, const KoColor &boundaryColor, KisPaintDeviceSP boundarySelection)
void fillUntilColor(const KoColor &fillColor, const KoColor &boundaryColor)
void setCloseGap(int closeGap)
void fill(const KoColor &fillColor)
void fillSelection(KisPixelSelectionSP pixelSelection, KisPaintDeviceSP boundarySelection)
void setThreshold(int threshold)
void setOpacitySpread(int opacitySpread)
KisPixelSelectionSP projection() const
KisPixelSelectionSP pixelSelection
QRect selectedExactRect() const
Slow, but exact way of determining the rectangle that encloses the selection.
The KisWrapAroundBoundsWrapper class wrapper around a KisDefaultBoundsBaseSP to enable wraparound....