24#define MEASURE_FILL_TIME 0
26#include <QElapsedTimer>
37struct CloseGapFillPoint
48 friend bool operator>(
const CloseGapFillPoint& a,
const CloseGapFillPoint& b) {
49 return std::make_tuple(!a.allowExpand, a.distance, a.y, a.x) >
50 std::make_tuple(!b.allowExpand, b.distance, b.y, b.x);
54class BasePixelAccessPolicy
59 SourceAccessorType m_srcIt;
66class ConstBasePixelAccessPolicy
71 SourceAccessorType m_srcIt;
78class CopyToSelectionPixelAccessPolicy :
public ConstBasePixelAccessPolicy
82 : ConstBasePixelAccessPolicy(sourceDevice)
83 , m_pixelSelection(pixelSelection)
84 , m_selectionIterator(m_pixelSelection->createRandomAccessorNG())
87 ALWAYS_INLINE void fillPixel(quint8 *dstPtr, quint8 opacity,
int x,
int y)
90 m_selectionIterator->moveTo(x, y);
91 *m_selectionIterator->rawData() = opacity;
99class FillWithColorPixelAccessPolicy :
public BasePixelAccessPolicy
103 : BasePixelAccessPolicy(sourceDevice)
104 , m_fillColor(fillColor)
105 , m_fillColorPtr(m_fillColor.data())
106 , m_pixelSize(m_fillColor.colorSpace()->pixelSize())
109 ALWAYS_INLINE void fillPixel(quint8 *dstPtr, quint8 opacity,
int x,
int y)
115 memcpy(dstPtr, m_fillColorPtr, m_pixelSize);
121 const quint8 *m_fillColorPtr;
125class FillWithColorExternalPixelAccessPolicy :
public ConstBasePixelAccessPolicy
131 : ConstBasePixelAccessPolicy(sourceDevice)
132 , m_externalDevice(externalDevice)
133 , m_externalDeviceIterator(m_externalDevice->createRandomAccessorNG())
134 , m_fillColor(fillColor)
135 , m_fillColorPtr(m_fillColor.data())
136 , m_pixelSize(m_fillColor.colorSpace()->pixelSize())
139 ALWAYS_INLINE void fillPixel(quint8 *dstPtr, quint8 opacity,
int x,
int y)
143 m_externalDeviceIterator->moveTo(x, y);
145 memcpy(m_externalDeviceIterator->rawData(), m_fillColorPtr, m_pixelSize);
153 const quint8 *m_fillColorPtr;
157template <
typename BaseSelectionPolicy>
161 SelectionPolicy(BaseSelectionPolicy baseSelectionPolicy)
162 : m_baseSelectionPolicy(baseSelectionPolicy)
165 ALWAYS_INLINE quint8 opacityFromDifference(quint8 difference,
int x,
int y)
170 return m_baseSelectionPolicy.opacityFromDifference(difference);
174 BaseSelectionPolicy m_baseSelectionPolicy;
177template <
typename BaseSelectionPolicy>
178class MaskedSelectionPolicy
181 MaskedSelectionPolicy(BaseSelectionPolicy baseSelectionPolicy,
183 : m_baseSelectionPolicy(baseSelectionPolicy)
187 ALWAYS_INLINE quint8 opacityFromDifference(quint8 difference,
int x,
int y)
189 m_maskIterator->moveTo(x, y);
190 const quint8* maskPtr = m_maskIterator->rawDataConst();
196 return m_baseSelectionPolicy.opacityFromDifference(difference);
200 BaseSelectionPolicy m_baseSelectionPolicy;
204class GroupSplitDifferencePolicy
207 GroupSplitDifferencePolicy(
int referenceValue)
208 : m_referenceValue(referenceValue)
211 ALWAYS_INLINE quint8 difference(
const quint8 *colorPtr)
const
213 return qAbs(*colorPtr - m_referenceValue);
217 int m_referenceValue;
223 GroupSplitSelectionPolicy(
int threshold)
227 ALWAYS_INLINE quint8 opacityFromDifference(quint8 difference,
int x,
int y) {
237class GroupSplitPixelAccessPolicy :
public BasePixelAccessPolicy
243 : BasePixelAccessPolicy(scribbleDevice)
244 , m_groupIndex(groupIndex)
250 ALWAYS_INLINE void fillPixel(quint8 *dstPtr, quint8 opacity,
int x,
int y)
258 m_groupMapIt->moveTo(x, y);
259 qint32 *groupMapPtr =
reinterpret_cast<qint32*
>(m_groupMapIt->rawData());
261 if (*groupMapPtr != 0) {
267 *groupMapPtr = m_groupIndex;
308 "FATAL: the forward stack must be empty "
309 "on a direction swap");
324 m_d->rowIncrement = 1;
327 m_d->opacitySpread = 0;
352 return m_d->fillExtent;
372 if (
m_d->gapMapSp &&
m_d->gapMapSp->gapSize() > 0) {
373 const quint32
distance =
m_d->gapMapSp->distance(x, y);
378 CloseGapFillPoint seed;
382 seed.allowExpand = allowExpand;
384 m_d->closeGapQueue.push(seed);
391template <
typename DifferencePolicy,
typename SelectionPolicy,
typename PixelAccessPolicy>
393 DifferencePolicy &differencePolicy,
394 SelectionPolicy &selectionPolicy,
395 PixelAccessPolicy &pixelAccessPolicy)
401 int *backwardIntervalBorder;
405 x = currentInterval->
end;
406 endX =
m_d->boundingRect.right();
407 if (x >= endX)
return;
409 intervalBorder = ¤tInterval->
end;
411 backwardInterval.
start = currentInterval->
end + 1;
412 backwardIntervalBorder = &backwardInterval.
end;
414 x = currentInterval->
start;
415 endX =
m_d->boundingRect.left();
416 if (x <= endX)
return;
417 columnIncrement = -1;
418 intervalBorder = ¤tInterval->
start;
420 backwardInterval.
end = currentInterval->
start - 1;
421 backwardIntervalBorder = &backwardInterval.
start;
425 x += columnIncrement;
427 pixelAccessPolicy.m_srcIt->moveTo(x, srcRow);
428 quint8 *pixelPtr =
const_cast<quint8*
>(pixelAccessPolicy.m_srcIt->rawDataConst());
429 const quint8 difference = differencePolicy.difference(pixelPtr);
430 const quint8 opacity = selectionPolicy.opacityFromDifference(difference, x, srcRow);
433 if (!stopOnGap && opacity) {
435 *backwardIntervalBorder = x;
436 pixelAccessPolicy.fillPixel(pixelPtr, opacity, x, srcRow);
438 m_d->fillExtent.setRight(qMax(
m_d->fillExtent.right(), x));
440 m_d->fillExtent.setLeft(qMin(
m_d->fillExtent.left(), x));
447 if (backwardInterval.
isValid()) {
448 m_d->backwardMap.insertInterval(backwardInterval);
452template <
typename DifferencePolicy,
typename SelectionPolicy,
typename PixelAccessPolicy>
454 DifferencePolicy &differencePolicy,
455 SelectionPolicy &selectionPolicy,
456 PixelAccessPolicy &pixelAccessPolicy)
458 m_d->backwardMap.cropInterval(&interval);
460 if (!interval.
isValid())
return;
462 int firstX = interval.
start;
463 int lastX = interval.
end;
465 int row = interval.
row;
470 int numPixelsLeft = 0;
472 const int pixelSize =
m_d->device->pixelSize();
477 if (numPixelsLeft <= 0) {
478 pixelAccessPolicy.m_srcIt->moveTo(x, row);
479 numPixelsLeft = pixelAccessPolicy.m_srcIt->numContiguousColumns(x) - 1;
480 dataPtr =
const_cast<quint8*
>(pixelAccessPolicy.m_srcIt->rawDataConst());
483 dataPtr += pixelSize;
486 quint8 *pixelPtr = dataPtr;
487 const quint8 difference = differencePolicy.difference(pixelPtr);
488 const quint8 opacity = selectionPolicy.opacityFromDifference(difference, x, row);
491 if (!stopOnGap && opacity) {
492 if (!currentForwardInterval.
isValid()) {
493 currentForwardInterval.
start = x;
494 currentForwardInterval.
end = x;
495 currentForwardInterval.
row = nextRow;
497 currentForwardInterval.
end = x;
500 pixelAccessPolicy.fillPixel(pixelPtr, opacity, x, row);
501 m_d->fillExtent =
m_d->fillExtent.united(QRect(x, row, 1, 1));
505 differencePolicy, selectionPolicy, pixelAccessPolicy);
510 differencePolicy, selectionPolicy, pixelAccessPolicy);
514 if (currentForwardInterval.
isValid()) {
515 m_d->forwardStack.push(currentForwardInterval);
523 if (currentForwardInterval.
isValid()) {
524 m_d->forwardStack.push(currentForwardInterval);
528template <
typename DifferencePolicy,
typename SelectionPolicy,
typename PixelAccessPolicy>
530 SelectionPolicy &selectionPolicy,
531 PixelAccessPolicy &pixelAccessPolicy)
535 while (!
m_d->closeGapQueue.empty()) {
536 const CloseGapFillPoint
p =
m_d->closeGapQueue.top();
537 m_d->closeGapQueue.pop();
540 if ((
p.x < 0) || (
p.x >=
m_d->boundingRect.width()) || (
p.y < 0) || (
p.y >=
m_d->boundingRect.height())) {
544 pixelAccessPolicy.m_srcIt->moveTo(
p.x,
p.y);
545 quint8 *pixelPtr =
const_cast<quint8*
>(pixelAccessPolicy.m_srcIt->rawDataConst());
546 const quint8 difference = differencePolicy.difference(pixelPtr);
547 const quint8 opacity = selectionPolicy.opacityFromDifference(difference,
p.x,
p.y);
553 m_d->filledSelectionIterator->moveTo(
p.x,
p.y);
554 if (*
m_d->filledSelectionIterator->rawDataConst() == opacity) {
558 const quint32 previousDistance =
p.distance;
560 const bool allowExpand =
p.allowExpand && (
distance >= previousDistance);
561 const float relativeDiff =
static_cast<float>(
distance) / previousDistance;
575 static constexpr float SpreadTolerance = 1.3f;
577 if ((relativeDiff < SpreadTolerance) || allowExpand) {
587 pixelAccessPolicy.fillPixel(pixelPtr, opacity,
p.x,
p.y);
588 m_d->fillExtent =
m_d->fillExtent.united(QRect(
p.x,
p.y, 1, 1));
593 CloseGapFillPoint next;
595 next.allowExpand = allowExpand;
599 m_d->closeGapQueue.push(next);
603 m_d->closeGapQueue.push(next);
607 m_d->closeGapQueue.push(next);
611 m_d->closeGapQueue.push(next);
621template <
typename DifferencePolicy,
typename SelectionPolicy,
typename PixelAccessPolicy>
623 SelectionPolicy &selectionPolicy,
624 PixelAccessPolicy &pixelAccessPolicy)
628 int gapSize =
m_d->closeGap;
634 QElapsedTimer timerTotal;
635 QElapsedTimer timerScanlineFill;
636 QElapsedTimer timerGapClosingFill;
637 quint64 totalScanlineFillNanos = 0;
638 quint64 totalGapClosingFillNanos = 0;
647 return fillOpacity(differencePolicy, selectionPolicy, pixelAccessPolicy, devicePtr,
rect);
652 m_d->gapMapSp = KisGapMapSP(
new KisGapMap(gapSize,
m_d->boundingRect, opacityFunc));
655 m_d->fillExtent = QRect();
661 m_d->forwardStack.push(startInterval);
672 bool firstPass =
true;
675 timerScanlineFill.start();
682 while (!
m_d->forwardStack.isEmpty()) {
683 while (!
m_d->forwardStack.isEmpty()) {
686 if (interval.
row >
m_d->boundingRect.bottom() ||
687 interval.
row <
m_d->boundingRect.top()) {
692 processLine(interval,
m_d->rowIncrement, differencePolicy, selectionPolicy, pixelAccessPolicy);
694 m_d->swapDirection();
698 m_d->forwardStack.push(startInterval);
704 totalScanlineFillNanos += timerScanlineFill.nsecsElapsed();
705 timerGapClosingFill.start();
712 if (!
m_d->closeGapQueue.empty()) {
713 startInterval =
closeGapPass(differencePolicy, selectionPolicy, pixelAccessPolicy);
715 m_d->forwardStack.push(startInterval);
720 totalGapClosingFillNanos += timerGapClosingFill.nsecsElapsed();
722 }
while (!
m_d->forwardStack.isEmpty());
725 static constexpr quint64 MillisDivisor = 1000000ull;
726 const quint64 totalTime = timerTotal.nsecsElapsed();
727 const quint64 overheadTime = (totalTime - totalScanlineFillNanos - totalGapClosingFillNanos);
728 qDebug() <<
"init overhead =" << qSetRealNumberPrecision(3)
729 <<
static_cast<double>(overheadTime) / MillisDivisor <<
"ms ("
730 <<
static_cast<double>(overheadTime) / totalTime <<
")";
731 qDebug() <<
"fill (scanline) =" << (totalScanlineFillNanos / MillisDivisor) <<
"ms ("
732 << qSetRealNumberPrecision(3) <<
static_cast<double>(totalScanlineFillNanos) / totalTime <<
")";
733 qDebug() <<
"fill (gap) =" << (totalGapClosingFillNanos / MillisDivisor) <<
"ms ("
734 << qSetRealNumberPrecision(3) <<
static_cast<double>(totalGapClosingFillNanos) / totalTime <<
")";
735 qDebug() <<
"fill total =" << (totalTime / MillisDivisor) <<
"ms";
736#if KIS_GAP_MAP_MEASURE_ELAPSED_TIME
738 qDebug() <<
"incl. opacity load" <<
m_d->gapMapSp->opacityElapsedMillis() <<
"ms";
739 qDebug() <<
"incl. distance load" <<
m_d->gapMapSp->distanceElapsedMillis() <<
"ms";
742 qDebug() <<
"----------------------------------------";
746template <
template <
typename SrcPixelType>
typename OptimizedDifferencePolicy,
747 typename SlowDifferencePolicy,
748 typename SelectionPolicy,
typename PixelAccessPolicy>
750 SelectionPolicy &selectionPolicy,
751 PixelAccessPolicy &pixelAccessPolicy)
755 if (pixelSize == 1) {
756 OptimizedDifferencePolicy<quint8> dp(srcColor,
m_d->threshold);
757 runImpl(dp, selectionPolicy, pixelAccessPolicy);
758 }
else if (pixelSize == 2) {
759 OptimizedDifferencePolicy<quint16> dp(srcColor,
m_d->threshold);
760 runImpl(dp, selectionPolicy, pixelAccessPolicy);
761 }
else if (pixelSize == 4) {
762 OptimizedDifferencePolicy<quint32> dp(srcColor,
m_d->threshold);
763 runImpl(dp, selectionPolicy, pixelAccessPolicy);
764 }
else if (pixelSize == 8) {
765 OptimizedDifferencePolicy<quint64> dp(srcColor,
m_d->threshold);
766 runImpl(dp, selectionPolicy, pixelAccessPolicy);
768 SlowDifferencePolicy dp(srcColor,
m_d->threshold);
769 runImpl(dp, selectionPolicy, pixelAccessPolicy);
776 KoColor fillColor(originalFillColor);
782 FillWithColorPixelAccessPolicy pap(
m_d->device, fillColor);
784 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
790 KoColor srcColor(boundaryColor);
792 KoColor fillColor(originalFillColor);
798 FillWithColorPixelAccessPolicy pap(
m_d->device, fillColor);
800 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
807 KoColor fillColor(originalFillColor);
813 FillWithColorExternalPixelAccessPolicy pap(
m_d->device, fillColor, externalDevice);
815 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
821 KoColor srcColor(boundaryColor);
823 KoColor fillColor(originalFillColor);
829 FillWithColorExternalPixelAccessPolicy pap(
m_d->device, fillColor, externalDevice);
831 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
839 const int softness = 100 -
m_d->opacitySpread;
843 CopyToSelectionPixelAccessPolicy pap(
m_d->device, pixelSelection);
845 if (
m_d->closeGap > 0) {
850 MaskedSelectionPolicy<HardSelectionPolicy>
852 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
855 MaskedSelectionPolicy<SoftSelectionPolicy>
857 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
866 const int softness = 100 -
m_d->opacitySpread;
870 CopyToSelectionPixelAccessPolicy pap(
m_d->device, pixelSelection);
872 if (
m_d->closeGap > 0) {
878 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
882 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
889 KoColor srcColor(boundaryColor);
892 const int softness = 100 -
m_d->opacitySpread;
896 CopyToSelectionPixelAccessPolicy pap(
m_d->device, pixelSelection);
898 if (
m_d->closeGap > 0) {
903 MaskedSelectionPolicy<SelectAllUntilColorHardSelectionPolicy>
905 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
908 MaskedSelectionPolicy<SelectAllUntilColorSoftSelectionPolicy>
910 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
917 KoColor srcColor(boundaryColor);
920 const int softness = 100 -
m_d->opacitySpread;
924 CopyToSelectionPixelAccessPolicy pap(
m_d->device, pixelSelection);
926 if (
m_d->closeGap > 0) {
931 SelectionPolicy<SelectAllUntilColorHardSelectionPolicy>
933 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
936 SelectionPolicy<SelectAllUntilColorSoftSelectionPolicy>
938 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
945 KoColor srcColor(boundaryColor);
948 const int softness = 100 -
m_d->opacitySpread;
952 CopyToSelectionPixelAccessPolicy pap(
m_d->device, pixelSelection);
954 if (
m_d->closeGap > 0) {
959 MaskedSelectionPolicy<SelectAllUntilColorHardSelectionPolicy>
965 MaskedSelectionPolicy<SelectAllUntilColorSoftSelectionPolicy>
975 KoColor srcColor(boundaryColor);
978 const int softness = 100 -
m_d->opacitySpread;
982 CopyToSelectionPixelAccessPolicy pap(
m_d->device, pixelSelection);
984 if (
m_d->closeGap > 0) {
989 SelectionPolicy<SelectAllUntilColorHardSelectionPolicy>
995 SelectionPolicy<SelectAllUntilColorSoftSelectionPolicy>
1005 const int pixelSize =
m_d->device->pixelSize();
1010 FillWithColorPixelAccessPolicy pap(
m_d->device, srcColor);
1013 if (
m_d->closeGap > 0) {
1014 m_d->filledSelectionIterator =
m_d->device->createRandomAccessorNG();
1017 if (pixelSize == 1) {
1020 }
else if (pixelSize == 2) {
1023 }
else if (pixelSize == 4) {
1026 }
else if (pixelSize == 8) {
1040 const quint8 referenceValue = *
m_d->device->pixel(
m_d->startPoint).data();
1044 GroupSplitDifferencePolicy dp(referenceValue);
1045 GroupSplitSelectionPolicy sp(
m_d->threshold);
1046 GroupSplitPixelAccessPolicy pap(
m_d->device, groupMapDevice, groupIndex);
1059template <
typename DifferencePolicy,
typename SelectionPolicy,
typename PixelAccessPolicy>
1061 SelectionPolicy &selectionPolicy,
1062 PixelAccessPolicy &pixelAccessPolicy,
1064 const QRect&
rect)
const
1069 "FATAL: The fill bounds must start at (0,0)");
1071 "FATAL: The rect is not fully inside the fill bounds");
1075 const int pixelSize =
m_d->device->pixelSize();
1076 bool hasOpaquePixels =
false;
1079 constexpr int OpacityOffset = 2;
1081 for (
int y =
rect.top(); y <=
rect.bottom(); ++y) {
1082 int numPixelsLeft = 0;
1085 for (
int x =
rect.left(); x <=
rect.right(); ++x) {
1086 if (numPixelsLeft <= 0) {
1087 pixelAccessPolicy.m_srcIt->
moveTo(x, y);
1088 numPixelsLeft = pixelAccessPolicy.m_srcIt->numContiguousColumns(x) - 1;
1089 dataPtr =
const_cast<quint8*
>(pixelAccessPolicy.m_srcIt->rawDataConst());
1092 dataPtr += pixelSize;
1095 const quint8 difference = differencePolicy.difference(dataPtr);
1096 const quint8 opacity = selectionPolicy.opacityFromDifference(difference, x, y);
1099 hasOpaquePixels =
true;
1102 quint8* outPtr = accessor->
rawData() + OpacityOffset;
1109 return hasOpaquePixels;
1114 KoColor srcColor(QColor(0,0,0,0),
m_d->device->colorSpace());
1115 KoColor fillColor(QColor(200,200,200,200),
m_d->device->colorSpace());
1121 FillWithColorPixelAccessPolicy pap(
m_d->device, fillColor);
1133 return &
m_d->backwardMap;
qreal distance(const QPointF &p1, const QPointF &p2)
bool operator>(const KoID &v1, const KoID &v2)
virtual quint8 * rawData()=0
ALWAYS_INLINE quint8 opacityFromDifference(quint8 difference) const
QStack< KisFillInterval > fetchAllIntervals(int rowCorrection=0) const
static constexpr quint16 DISTANCE_INFINITE
quint32 pixelSize() const
KisRandomConstAccessorSP createRandomConstAccessorNG() const
KisRandomAccessorSP createRandomAccessorNG()
virtual void moveTo(qint32 x, qint32 y)=0
virtual quint32 pixelSize() const =0
void convertTo(const KoColorSpace *cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
static KoColor createTransparent(const KoColorSpace *cs)
const KoColorSpace * colorSpace() const
return the current colorSpace
#define KIS_SAFE_ASSERT_RECOVER(cond)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
#define KIS_ASSERT_RECOVER_RETURN(cond)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
const quint8 MAX_SELECTED
const quint8 MIN_SELECTED
KisSharedPtr< KisRandomAccessorNG > KisRandomAccessorSP
KisSharedPtr< KisRandomConstAccessorNG > KisRandomConstAccessorSP
void fillSelectionUntilColor(KisPixelSelectionSP pixelSelection, const KoColor &boundaryColor, KisPaintDeviceSP boundarySelection)
bool fillOpacity(DifferencePolicy &differencePolicy, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy, KisPaintDevice *const devicePtr, const QRect &rect) const
GreaterPriorityQueue< CloseGapFillPoint > closeGapQueue
void fillUntilColor(const KoColor &fillColor, const KoColor &boundaryColor)
KisFillInterval closeGapPass(DifferencePolicy &differencePolicy, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy)
void setCloseGap(int closeGap)
void processLine(KisFillInterval interval, const int rowIncrement, DifferencePolicy &differencePolicy, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy)
KisGapMapSP gapMapSp
maintains the distance and opacity maps required for the algorithm
int closeGap
try to close gaps up to this size in pixels
void clearNonZeroComponent()
void runImpl(DifferencePolicy &differencePolicy, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy)
KisRandomAccessorSP filledSelectionIterator
void testingProcessLine(const KisFillInterval &processInterval)
void fill(const KoColor &fillColor)
void fillContiguousGroup(KisPaintDeviceSP groupMapDevice, qint32 groupIndex)
void fillSelection(KisPixelSelectionSP pixelSelection, KisPaintDeviceSP boundarySelection)
void selectDifferencePolicyAndRun(const KoColor &srcColor, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy)
KisScanlineFill(KisPaintDeviceSP device, const QPoint &startPoint, const QRect &boundingRect)
bool tryPushingCloseGapSeed(int x, int y, bool allowExpand)
QStack< KisFillInterval > forwardStack
KisFillIntervalMap backwardMap
std::priority_queue< T, std::vector< T >, std::greater< T > > GreaterPriorityQueue
void fillSelectionUntilColorOrTransparent(KisPixelSelectionSP pixelSelection, const KoColor &boundaryColor, KisPaintDeviceSP boundarySelection)
void setThreshold(int threshold)
KisFillIntervalMap * testingGetBackwardIntervals() const
QVector< KisFillInterval > testingGetForwardIntervals() const
void extendedPass(KisFillInterval *currentInterval, int srcRow, bool extendRight, DifferencePolicy &differencePolicy, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy)
const QScopedPointer< Private > m_d
void setOpacitySpread(int opacitySpread)