Krita Source Code Documentation
Loading...
Searching...
No Matches
KisScanlineFill Class Reference

#include <kis_scanline_fill.h>

+ Inheritance diagram for KisScanlineFill:

Public Types

template<class T >
using GreaterPriorityQueue = std::priority_queue<T, std::vector<T>, std::greater<T>>
 

Public Member Functions

void clearNonZeroComponent ()
 
void fill (const KoColor &fillColor)
 
void fill (const KoColor &fillColor, KisPaintDeviceSP externalDevice)
 
void fillContiguousGroup (KisPaintDeviceSP groupMapDevice, qint32 groupIndex)
 
QRect fillExtent () const
 
void fillSelection (KisPixelSelectionSP pixelSelection)
 
void fillSelection (KisPixelSelectionSP pixelSelection, KisPaintDeviceSP boundarySelection)
 
void fillSelectionUntilColor (KisPixelSelectionSP pixelSelection, const KoColor &boundaryColor)
 
void fillSelectionUntilColor (KisPixelSelectionSP pixelSelection, const KoColor &boundaryColor, KisPaintDeviceSP boundarySelection)
 
void fillSelectionUntilColorOrTransparent (KisPixelSelectionSP pixelSelection, const KoColor &boundaryColor)
 
void fillSelectionUntilColorOrTransparent (KisPixelSelectionSP pixelSelection, const KoColor &boundaryColor, KisPaintDeviceSP boundarySelection)
 
void fillUntilColor (const KoColor &fillColor, const KoColor &boundaryColor)
 
void fillUntilColor (const KoColor &fillColor, const KoColor &boundaryColor, KisPaintDeviceSP externalDevice)
 
 KisScanlineFill (KisPaintDeviceSP device, const QPoint &startPoint, const QRect &boundingRect)
 
void setCloseGap (int closeGap)
 
void setOpacitySpread (int opacitySpread)
 
void setThreshold (int threshold)
 
void swapDirection ()
 
 ~KisScanlineFill ()
 
- Public Member Functions inherited from Private
 Private (KisCanvas2 *c)
 

Public Attributes

KisFillIntervalMap backwardMap
 
QRect boundingRect
 
int closeGap
 try to close gaps up to this size in pixels
 
GreaterPriorityQueue< CloseGapFillPoint > closeGapQueue
 
KisPaintDeviceSP device
 
KisRandomAccessorSP filledSelectionIterator
 
QRect fillExtent
 
QStack< KisFillIntervalforwardStack
 
KisGapMapSP gapMapSp
 maintains the distance and opacity maps required for the algorithm
 
int opacitySpread
 
int rowIncrement
 
QPoint startPoint
 
int threshold
 
- Public Attributes inherited from Private
KisCanvas2canvas
 
int displayedFrame
 
int intendedFrame
 

Private Member Functions

template<typename DifferencePolicy , typename SelectionPolicy , typename PixelAccessPolicy >
KisFillInterval closeGapPass (DifferencePolicy &differencePolicy, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy)
 
template<typename DifferencePolicy , typename SelectionPolicy , typename PixelAccessPolicy >
void extendedPass (KisFillInterval *currentInterval, int srcRow, bool extendRight, DifferencePolicy &differencePolicy, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy)
 
template<typename DifferencePolicy , typename SelectionPolicy , typename PixelAccessPolicy >
bool fillOpacity (DifferencePolicy &differencePolicy, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy, KisPaintDevice *const devicePtr, const QRect &rect) const
 
template<typename DifferencePolicy , typename SelectionPolicy , typename PixelAccessPolicy >
void processLine (KisFillInterval interval, const int rowIncrement, DifferencePolicy &differencePolicy, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy)
 
template<typename DifferencePolicy , typename SelectionPolicy , typename PixelAccessPolicy >
void runImpl (DifferencePolicy &differencePolicy, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy)
 
template<template< typename SrcPixelType > typename OptimizedDifferencePolicy, typename SlowDifferencePolicy , typename SelectionPolicy , typename PixelAccessPolicy >
void selectDifferencePolicyAndRun (const KoColor &srcColor, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy)
 
KisFillIntervalMaptestingGetBackwardIntervals () const
 
QVector< KisFillIntervaltestingGetForwardIntervals () const
 
void testingProcessLine (const KisFillInterval &processInterval)
 
bool tryPushingCloseGapSeed (int x, int y, bool allowExpand)
 

Private Attributes

const QScopedPointer< Privatem_d
 

Friends

class KisScanlineFillTest
 

Detailed Description

Definition at line 277 of file kis_scanline_fill.cpp.

Member Typedef Documentation

◆ GreaterPriorityQueue

template<class T >
using KisScanlineFill::GreaterPriorityQueue = std::priority_queue<T, std::vector<T>, std::greater<T>>

Definition at line 297 of file kis_scanline_fill.cpp.

Constructor & Destructor Documentation

◆ KisScanlineFill()

KisScanlineFill::KisScanlineFill ( KisPaintDeviceSP device,
const QPoint & startPoint,
const QRect & boundingRect )

Definition at line 317 of file kis_scanline_fill.cpp.

318 : m_d(new Private)
319{
320 m_d->device = device;
321 m_d->startPoint = startPoint;
322 m_d->boundingRect = boundingRect;
323
324 m_d->rowIncrement = 1;
325
326 m_d->threshold = 0;
327 m_d->opacitySpread = 0;
328 m_d->closeGap = 0;
329}
KisPaintDeviceSP device
const QScopedPointer< Private > m_d

References boundingRect, device, m_d, and startPoint.

◆ ~KisScanlineFill()

KisScanlineFill::~KisScanlineFill ( )

Definition at line 331 of file kis_scanline_fill.cpp.

332{
333}

Member Function Documentation

◆ clearNonZeroComponent()

void KisScanlineFill::clearNonZeroComponent ( )

Clear the contiguous non-zero area of the device

WARNING: the threshold parameter is not counted!

Definition at line 1003 of file kis_scanline_fill.cpp.

1004{
1005 const int pixelSize = m_d->device->pixelSize();
1006 KoColor srcColor = KoColor::createTransparent(m_d->device->colorSpace());
1007
1008 using namespace KisColorSelectionPolicies;
1009
1010 FillWithColorPixelAccessPolicy pap(m_d->device, srcColor);
1011 SelectionPolicy<HardSelectionPolicy> sp(HardSelectionPolicy(m_d->threshold));
1012
1013 if (m_d->closeGap > 0) {
1014 m_d->filledSelectionIterator = m_d->device->createRandomAccessorNG();
1015 }
1016
1017 if (pixelSize == 1) {
1019 runImpl(dp, sp, pap);
1020 } else if (pixelSize == 2) {
1022 runImpl(dp, sp, pap);
1023 } else if (pixelSize == 4) {
1025 runImpl(dp, sp, pap);
1026 } else if (pixelSize == 8) {
1028 runImpl(dp, sp, pap);
1029 } else {
1030 SlowIsNonNullDifferencePolicy dp(pixelSize);
1031 runImpl(dp, sp, pap);
1032 }
1033}
static KoColor createTransparent(const KoColorSpace *cs)
Definition KoColor.cpp:681
void runImpl(DifferencePolicy &differencePolicy, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy)

References KoColor::createTransparent(), m_d, and runImpl().

◆ closeGapPass()

template<typename DifferencePolicy , typename SelectionPolicy , typename PixelAccessPolicy >
KisFillInterval KisScanlineFill::closeGapPass ( DifferencePolicy & differencePolicy,
SelectionPolicy & selectionPolicy,
PixelAccessPolicy & pixelAccessPolicy )
private

Definition at line 529 of file kis_scanline_fill.cpp.

532{
533 KisFillInterval interval;
534
535 while (!m_d->closeGapQueue.empty()) {
536 const CloseGapFillPoint p = m_d->closeGapQueue.top();
537 m_d->closeGapQueue.pop();
538
539 // KisGapMap enforces x/y start at (0, 0).
540 if ((p.x < 0) || (p.x >= m_d->boundingRect.width()) || (p.y < 0) || (p.y >= m_d->boundingRect.height())) {
541 continue;
542 }
543
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);
548
549 // The initial pixel (before the fill) is non-opaque, so we try to fill it.
550 if (opacity) {
551 // However, check if it has already been filled during the ongoing operation.
552 // If the test below is true, then the pixel is already in the selection.
553 m_d->filledSelectionIterator->moveTo(p.x, p.y);
554 if (*m_d->filledSelectionIterator->rawDataConst() == opacity) {
555 continue;
556 }
557
558 const quint32 previousDistance = p.distance;
559 const quint32 distance = m_d->gapMapSp->distance(p.x, p.y);
560 const bool allowExpand = p.allowExpand && (distance >= previousDistance);
561 const float relativeDiff = static_cast<float>(distance) / previousDistance;
562
563 // This ratio determines whether the fill can spread to pixels with
564 // a different gap distance compared to the previous pixel.
565 //
566 // <1.0 is a pixel closer to a gap, or more in a corner of lineart.
567 // =1.0 is the same distance.
568 // >1.0 is a pixel that is farther from a gap, or away from tight corners.
569 //
570 // At high gap sizes, the distance map can vary slightly and the fill could
571 // leave out empty pixels. To prevent that, we allow spilling to a more distant
572 // pixels as well, up to a given tolerance. If the value is too high,
573 // the fill will spill too much.
574
575 static constexpr float SpreadTolerance = 1.3f;
576
577 if ((relativeDiff < SpreadTolerance) || allowExpand) {
579 // Only return one interval at a time. Otherwise, just skip this pixel.
580 if (!interval.isValid()) {
581 interval.start = p.x;
582 interval.end = p.x;
583 interval.row = p.y;
584 }
585 // We still continue the loop, to process all the pixels we can fill.
586 } else {
587 pixelAccessPolicy.fillPixel(pixelPtr, opacity, p.x, p.y);
588 m_d->fillExtent = m_d->fillExtent.united(QRect(p.x, p.y, 1, 1));
589
590 // Forward the context information to the next pixels.
591 // Spread the fill in four directions: up, down, left, right.
592
593 CloseGapFillPoint next;
594 next.distance = distance;
595 next.allowExpand = allowExpand;
596
597 next.x = p.x - 1;
598 next.y = p.y;
599 m_d->closeGapQueue.push(next);
600
601 next.x = p.x + 1;
602 next.y = p.y;
603 m_d->closeGapQueue.push(next);
604
605 next.x = p.x;
606 next.y = p.y - 1;
607 m_d->closeGapQueue.push(next);
608
609 next.x = p.x;
610 next.y = p.y + 1;
611 m_d->closeGapQueue.push(next);
612 }
613 }
614 }
615 }
616
617 // If valid, the scanline fill will take over next.
618 return interval;
619}
const Params2D p
qreal distance(const QPointF &p1, const QPointF &p2)
bool isValid() const
static constexpr quint16 DISTANCE_INFINITE
Definition kis_gap_map.h:84
QAction * next(const QObject *recvr, const char *slot, QObject *parent)

References distance(), KisGapMap::DISTANCE_INFINITE, KisFillInterval::end, KisFillInterval::isValid(), m_d, p, KisFillInterval::row, and KisFillInterval::start.

◆ extendedPass()

template<typename DifferencePolicy , typename SelectionPolicy , typename PixelAccessPolicy >
void KisScanlineFill::extendedPass ( KisFillInterval * currentInterval,
int srcRow,
bool extendRight,
DifferencePolicy & differencePolicy,
SelectionPolicy & selectionPolicy,
PixelAccessPolicy & pixelAccessPolicy )
private

Definition at line 392 of file kis_scanline_fill.cpp.

396{
397 int x;
398 int endX;
399 int columnIncrement;
400 int *intervalBorder;
401 int *backwardIntervalBorder;
402 KisFillInterval backwardInterval(currentInterval->start, currentInterval->end, srcRow);
403
404 if (extendRight) {
405 x = currentInterval->end;
406 endX = m_d->boundingRect.right();
407 if (x >= endX) return;
408 columnIncrement = 1;
409 intervalBorder = &currentInterval->end;
410
411 backwardInterval.start = currentInterval->end + 1;
412 backwardIntervalBorder = &backwardInterval.end;
413 } else {
414 x = currentInterval->start;
415 endX = m_d->boundingRect.left();
416 if (x <= endX) return;
417 columnIncrement = -1;
418 intervalBorder = &currentInterval->start;
419
420 backwardInterval.end = currentInterval->start - 1;
421 backwardIntervalBorder = &backwardInterval.start;
422 }
423
424 do {
425 x += columnIncrement;
426
427 pixelAccessPolicy.m_srcIt->moveTo(x, srcRow);
428 quint8 *pixelPtr = const_cast<quint8*>(pixelAccessPolicy.m_srcIt->rawDataConst()); // TODO: avoid doing const_cast
429 const quint8 difference = differencePolicy.difference(pixelPtr);
430 const quint8 opacity = selectionPolicy.opacityFromDifference(difference, x, srcRow);
431 const bool stopOnGap = tryPushingCloseGapSeed(x, srcRow, false);
432
433 if (!stopOnGap && opacity) {
434 *intervalBorder = x;
435 *backwardIntervalBorder = x;
436 pixelAccessPolicy.fillPixel(pixelPtr, opacity, x, srcRow);
437 if (extendRight) {
438 m_d->fillExtent.setRight(qMax(m_d->fillExtent.right(), x));
439 } else {
440 m_d->fillExtent.setLeft(qMin(m_d->fillExtent.left(), x));
441 }
442 } else {
443 break;
444 }
445 } while (x != endX);
446
447 if (backwardInterval.isValid()) {
448 m_d->backwardMap.insertInterval(backwardInterval);
449 }
450}
bool tryPushingCloseGapSeed(int x, int y, bool allowExpand)

References KisFillInterval::end, KisFillInterval::isValid(), m_d, KisFillInterval::start, and tryPushingCloseGapSeed().

◆ fill() [1/2]

void KisScanlineFill::fill ( const KoColor & fillColor)

Fill the source device with fillColor

Definition at line 773 of file kis_scanline_fill.cpp.

774{
775 KoColor srcColor(m_d->device->pixel(m_d->startPoint));
776 KoColor fillColor(originalFillColor);
777 fillColor.convertTo(m_d->device->colorSpace());
778
779 using namespace KisColorSelectionPolicies;
780
781 SelectionPolicy<HardSelectionPolicy> sp(HardSelectionPolicy(m_d->threshold));
782 FillWithColorPixelAccessPolicy pap(m_d->device, fillColor);
783
784 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
785 (srcColor, sp, pap);
786}
void convertTo(const KoColorSpace *cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
Definition KoColor.cpp:136

References KoColor::convertTo(), and m_d.

◆ fill() [2/2]

void KisScanlineFill::fill ( const KoColor & fillColor,
KisPaintDeviceSP externalDevice )

Fill externalDevice with fillColor basing on the contents of the source device.

Definition at line 804 of file kis_scanline_fill.cpp.

805{
806 KoColor srcColor(m_d->device->pixel(m_d->startPoint));
807 KoColor fillColor(originalFillColor);
808 fillColor.convertTo(m_d->device->colorSpace());
809
810 using namespace KisColorSelectionPolicies;
811
812 SelectionPolicy<HardSelectionPolicy> sp(HardSelectionPolicy(m_d->threshold));
813 FillWithColorExternalPixelAccessPolicy pap(m_d->device, fillColor, externalDevice);
814
815 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
816 (srcColor, sp, pap);
817}

References KoColor::convertTo(), and m_d.

◆ fillContiguousGroup()

void KisScanlineFill::fillContiguousGroup ( KisPaintDeviceSP groupMapDevice,
qint32 groupIndex )

A special filler algorithm for the Watershed initialization routine:

1) Clear the contiguous area in the destination device 2) At the same time, fill the corresponding area of groupMapDevice with value groupIndex 3) groupMapDevice must store 4 bytes per pixel

Definition at line 1035 of file kis_scanline_fill.cpp.

1036{
1037 KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->device->pixelSize() == 1);
1038 KIS_SAFE_ASSERT_RECOVER_RETURN(groupMapDevice->pixelSize() == 4);
1039
1040 const quint8 referenceValue = *m_d->device->pixel(m_d->startPoint).data();
1041
1042 using namespace KisColorSelectionPolicies;
1043
1044 GroupSplitDifferencePolicy dp(referenceValue);
1045 GroupSplitSelectionPolicy sp(m_d->threshold);
1046 GroupSplitPixelAccessPolicy pap(m_d->device, groupMapDevice, groupIndex);
1047
1048 runImpl(dp, sp, pap);
1049}
quint32 pixelSize() const
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128

References KIS_SAFE_ASSERT_RECOVER_RETURN, m_d, KisPaintDevice::pixelSize(), and runImpl().

◆ fillExtent()

QRect KisScanlineFill::fillExtent ( ) const

Returns the extent of the last filled region

◆ fillOpacity()

template<typename DifferencePolicy , typename SelectionPolicy , typename PixelAccessPolicy >
bool KisScanlineFill::fillOpacity ( DifferencePolicy & differencePolicy,
SelectionPolicy & selectionPolicy,
PixelAccessPolicy & pixelAccessPolicy,
KisPaintDevice *const devicePtr,
const QRect & rect ) const
private

This opacity-only fill is used by KisGapMap.

Using the same policies as the main fill, load the opacity values for a rect of the main filled region. The rect typically corresponds to a tile of an opacity map maintained by KisGapMap, and is loaded on-demand during an ongoing runImpl() loop.

Definition at line 1060 of file kis_scanline_fill.cpp.

1065{
1066#if 0
1067 // These asserts affect the performance.
1068 KIS_SAFE_ASSERT_RECOVER_RETURN((m_d->boundingRect.left() == 0) && (m_d->boundingRect.top() == 0) &&
1069 "FATAL: The fill bounds must start at (0,0)");
1070 KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->boundingRect.contains(rect) &&
1071 "FATAL: The rect is not fully inside the fill bounds");
1072#endif
1073 KisRandomAccessorSP accessor = devicePtr->createRandomAccessorNG();
1074
1075 const int pixelSize = m_d->device->pixelSize();
1076 bool hasOpaquePixels = false;
1077
1078 // We are relying on the knowledge of KisGapMap's paint device data organization.
1079 constexpr int OpacityOffset = 2;
1080
1081 for (int y = rect.top(); y <= rect.bottom(); ++y) {
1082 int numPixelsLeft = 0;
1083 quint8* dataPtr;
1084
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());
1090 } else {
1091 numPixelsLeft--;
1092 dataPtr += pixelSize;
1093 }
1094
1095 const quint8 difference = differencePolicy.difference(dataPtr);
1096 const quint8 opacity = selectionPolicy.opacityFromDifference(difference, x, y);
1097
1098 if (opacity == MIN_SELECTED) {
1099 hasOpaquePixels = true;
1100
1101 accessor->moveTo(x, y);
1102 quint8* outPtr = accessor->rawData() + OpacityOffset;
1103
1104 *outPtr = opacity;
1105 }
1106 }
1107 }
1108
1109 return hasOpaquePixels;
1110}
virtual quint8 * rawData()=0
KisRandomAccessorSP createRandomAccessorNG()
virtual void moveTo(qint32 x, qint32 y)=0
const quint8 MIN_SELECTED
Definition kis_global.h:33

References KisPaintDevice::createRandomAccessorNG(), KIS_SAFE_ASSERT_RECOVER_RETURN, m_d, MIN_SELECTED, KisRandomConstAccessorNG::moveTo(), and KisBaseAccessor::rawData().

◆ fillSelection() [1/2]

void KisScanlineFill::fillSelection ( KisPixelSelectionSP pixelSelection)

Fill pixelSelection with the opacity of the contiguous area

Definition at line 862 of file kis_scanline_fill.cpp.

863{
864 KoColor srcColor(m_d->device->pixel(m_d->startPoint));
865
866 const int softness = 100 - m_d->opacitySpread;
867
868 using namespace KisColorSelectionPolicies;
869
870 CopyToSelectionPixelAccessPolicy pap(m_d->device, pixelSelection);
871
872 if (m_d->closeGap > 0) {
873 m_d->filledSelectionIterator = pixelSelection->createRandomAccessorNG();
874 }
875
876 if (softness == 0) {
877 SelectionPolicy<HardSelectionPolicy> sp(HardSelectionPolicy(m_d->threshold));
878 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
879 (srcColor, sp, pap);
880 } else {
881 SelectionPolicy<SoftSelectionPolicy> sp(SoftSelectionPolicy(m_d->threshold, softness));
882 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
883 (srcColor, sp, pap);
884 }
885}

References KisPaintDevice::createRandomAccessorNG(), and m_d.

◆ fillSelection() [2/2]

void KisScanlineFill::fillSelection ( KisPixelSelectionSP pixelSelection,
KisPaintDeviceSP boundarySelection )

Fill pixelSelection with the opacity of the contiguous area. This method uses an existing selection as boundary for the flood fill.

Definition at line 835 of file kis_scanline_fill.cpp.

836{
837 KoColor srcColor(m_d->device->pixel(m_d->startPoint));
838
839 const int softness = 100 - m_d->opacitySpread;
840
841 using namespace KisColorSelectionPolicies;
842
843 CopyToSelectionPixelAccessPolicy pap(m_d->device, pixelSelection);
844
845 if (m_d->closeGap > 0) {
846 m_d->filledSelectionIterator = pixelSelection->createRandomAccessorNG();
847 }
848
849 if (softness == 0) {
850 MaskedSelectionPolicy<HardSelectionPolicy>
851 sp(HardSelectionPolicy(m_d->threshold), boundarySelection);
852 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
853 (srcColor, sp, pap);
854 } else {
855 MaskedSelectionPolicy<SoftSelectionPolicy>
856 sp(SoftSelectionPolicy(m_d->threshold, softness), boundarySelection);
857 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
858 (srcColor, sp, pap);
859 }
860}

References KisPaintDevice::createRandomAccessorNG(), and m_d.

◆ fillSelectionUntilColor() [1/2]

void KisScanlineFill::fillSelectionUntilColor ( KisPixelSelectionSP pixelSelection,
const KoColor & boundaryColor )

Fill pixelSelection with the opacity of the contiguous area, which encompass all the connected pixels as long as the color in the pixels of the source device is not similar to boundaryColor.

Definition at line 915 of file kis_scanline_fill.cpp.

916{
917 KoColor srcColor(boundaryColor);
918 srcColor.convertTo(m_d->device->colorSpace());
919
920 const int softness = 100 - m_d->opacitySpread;
921
922 using namespace KisColorSelectionPolicies;
923
924 CopyToSelectionPixelAccessPolicy pap(m_d->device, pixelSelection);
925
926 if (m_d->closeGap > 0) {
927 m_d->filledSelectionIterator = pixelSelection->createRandomAccessorNG();
928 }
929
930 if (softness == 0) {
931 SelectionPolicy<SelectAllUntilColorHardSelectionPolicy>
933 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
934 (srcColor, sp, pap);
935 } else {
936 SelectionPolicy<SelectAllUntilColorSoftSelectionPolicy>
937 sp(SelectAllUntilColorSoftSelectionPolicy(m_d->threshold, softness));
938 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
939 (srcColor, sp, pap);
940 }
941}

References KoColor::convertTo(), KisPaintDevice::createRandomAccessorNG(), and m_d.

◆ fillSelectionUntilColor() [2/2]

void KisScanlineFill::fillSelectionUntilColor ( KisPixelSelectionSP pixelSelection,
const KoColor & boundaryColor,
KisPaintDeviceSP boundarySelection )

Fill pixelSelection with the opacity of the contiguous area, which encompass all the connected pixels as long as the color in the pixels of the source device is not similar to boundaryColor. This method uses an existing selection as boundary for the flood fill.

Definition at line 887 of file kis_scanline_fill.cpp.

888{
889 KoColor srcColor(boundaryColor);
890 srcColor.convertTo(m_d->device->colorSpace());
891
892 const int softness = 100 - m_d->opacitySpread;
893
894 using namespace KisColorSelectionPolicies;
895
896 CopyToSelectionPixelAccessPolicy pap(m_d->device, pixelSelection);
897
898 if (m_d->closeGap > 0) {
899 m_d->filledSelectionIterator = pixelSelection->createRandomAccessorNG();
900 }
901
902 if (softness == 0) {
903 MaskedSelectionPolicy<SelectAllUntilColorHardSelectionPolicy>
904 sp(SelectAllUntilColorHardSelectionPolicy(m_d->threshold), boundarySelection);
905 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
906 (srcColor, sp, pap);
907 } else {
908 MaskedSelectionPolicy<SelectAllUntilColorSoftSelectionPolicy>
909 sp(SelectAllUntilColorSoftSelectionPolicy(m_d->threshold, softness), boundarySelection);
910 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
911 (srcColor, sp, pap);
912 }
913}

References KoColor::convertTo(), KisPaintDevice::createRandomAccessorNG(), and m_d.

◆ fillSelectionUntilColorOrTransparent() [1/2]

void KisScanlineFill::fillSelectionUntilColorOrTransparent ( KisPixelSelectionSP pixelSelection,
const KoColor & boundaryColor )

Fill pixelSelection with the opacity of the contiguous area, which encompass all the connected pixels as long as the color in the pixels of the source device is not similar to boundaryColor or transparent.

Definition at line 973 of file kis_scanline_fill.cpp.

974{
975 KoColor srcColor(boundaryColor);
976 srcColor.convertTo(m_d->device->colorSpace());
977
978 const int softness = 100 - m_d->opacitySpread;
979
980 using namespace KisColorSelectionPolicies;
981
982 CopyToSelectionPixelAccessPolicy pap(m_d->device, pixelSelection);
983
984 if (m_d->closeGap > 0) {
985 m_d->filledSelectionIterator = pixelSelection->createRandomAccessorNG();
986 }
987
988 if (softness == 0) {
989 SelectionPolicy<SelectAllUntilColorHardSelectionPolicy>
993 (srcColor, sp, pap);
994 } else {
995 SelectionPolicy<SelectAllUntilColorSoftSelectionPolicy>
996 sp(SelectAllUntilColorSoftSelectionPolicy(m_d->threshold, softness));
999 (srcColor, sp, pap);
1000 }
1001}
void selectDifferencePolicyAndRun(const KoColor &srcColor, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy)

References KoColor::convertTo(), KisPaintDevice::createRandomAccessorNG(), m_d, and selectDifferencePolicyAndRun().

◆ fillSelectionUntilColorOrTransparent() [2/2]

void KisScanlineFill::fillSelectionUntilColorOrTransparent ( KisPixelSelectionSP pixelSelection,
const KoColor & boundaryColor,
KisPaintDeviceSP boundarySelection )

Fill pixelSelection with the opacity of the contiguous area, which encompass all the connected pixels as long as the color in the pixels of the source device is not similar to boundaryColor or transparent. This method uses an existing selection as boundary for the flood fill.

Definition at line 943 of file kis_scanline_fill.cpp.

944{
945 KoColor srcColor(boundaryColor);
946 srcColor.convertTo(m_d->device->colorSpace());
947
948 const int softness = 100 - m_d->opacitySpread;
949
950 using namespace KisColorSelectionPolicies;
951
952 CopyToSelectionPixelAccessPolicy pap(m_d->device, pixelSelection);
953
954 if (m_d->closeGap > 0) {
955 m_d->filledSelectionIterator = pixelSelection->createRandomAccessorNG();
956 }
957
958 if (softness == 0) {
959 MaskedSelectionPolicy<SelectAllUntilColorHardSelectionPolicy>
960 sp(SelectAllUntilColorHardSelectionPolicy(m_d->threshold), boundarySelection);
963 (srcColor, sp, pap);
964 } else {
965 MaskedSelectionPolicy<SelectAllUntilColorSoftSelectionPolicy>
966 sp(SelectAllUntilColorSoftSelectionPolicy(m_d->threshold, softness), boundarySelection);
969 (srcColor, sp, pap);
970 }
971}

References KoColor::convertTo(), KisPaintDevice::createRandomAccessorNG(), m_d, and selectDifferencePolicyAndRun().

◆ fillUntilColor() [1/2]

void KisScanlineFill::fillUntilColor ( const KoColor & fillColor,
const KoColor & boundaryColor )

Fill the source device with fillColor until boundaryColor is reached

Definition at line 788 of file kis_scanline_fill.cpp.

789{
790 KoColor srcColor(boundaryColor);
791 srcColor.convertTo(m_d->device->colorSpace());
792 KoColor fillColor(originalFillColor);
793 fillColor.convertTo(m_d->device->colorSpace());
794
795 using namespace KisColorSelectionPolicies;
796
797 SelectionPolicy<SelectAllUntilColorHardSelectionPolicy> sp(SelectAllUntilColorHardSelectionPolicy(m_d->threshold));
798 FillWithColorPixelAccessPolicy pap(m_d->device, fillColor);
799
800 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
801 (srcColor, sp, pap);
802}

References KoColor::convertTo(), and m_d.

◆ fillUntilColor() [2/2]

void KisScanlineFill::fillUntilColor ( const KoColor & fillColor,
const KoColor & boundaryColor,
KisPaintDeviceSP externalDevice )

Fill externalDevice with fillColor basing on the contents of the source device. Fills until boundaryColor is reached

Definition at line 819 of file kis_scanline_fill.cpp.

820{
821 KoColor srcColor(boundaryColor);
822 srcColor.convertTo(m_d->device->colorSpace());
823 KoColor fillColor(originalFillColor);
824 fillColor.convertTo(m_d->device->colorSpace());
825
826 using namespace KisColorSelectionPolicies;
827
828 SelectionPolicy<SelectAllUntilColorHardSelectionPolicy> sp(SelectAllUntilColorHardSelectionPolicy(m_d->threshold));
829 FillWithColorExternalPixelAccessPolicy pap(m_d->device, fillColor, externalDevice);
830
831 selectDifferencePolicyAndRun<OptimizedDifferencePolicy, SlowDifferencePolicy>
832 (srcColor, sp, pap);
833}

References KoColor::convertTo(), and m_d.

◆ processLine()

template<typename DifferencePolicy , typename SelectionPolicy , typename PixelAccessPolicy >
void KisScanlineFill::processLine ( KisFillInterval interval,
const int rowIncrement,
DifferencePolicy & differencePolicy,
SelectionPolicy & selectionPolicy,
PixelAccessPolicy & pixelAccessPolicy )
private

Definition at line 453 of file kis_scanline_fill.cpp.

457{
458 m_d->backwardMap.cropInterval(&interval);
459
460 if (!interval.isValid()) return;
461
462 int firstX = interval.start;
463 int lastX = interval.end;
464 int x = firstX;
465 int row = interval.row;
466 int nextRow = row + rowIncrement;
467
468 KisFillInterval currentForwardInterval;
469
470 int numPixelsLeft = 0;
471 quint8 *dataPtr = 0;
472 const int pixelSize = m_d->device->pixelSize();
473
474 while(x <= lastX) {
475 // a bit of optimization for not calling slow random accessor
476 // methods too often
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());
481 } else {
482 numPixelsLeft--;
483 dataPtr += pixelSize;
484 }
485
486 quint8 *pixelPtr = dataPtr;
487 const quint8 difference = differencePolicy.difference(pixelPtr);
488 const quint8 opacity = selectionPolicy.opacityFromDifference(difference, x, row);
489 const bool stopOnGap = tryPushingCloseGapSeed(x, row, false);
490
491 if (!stopOnGap && opacity) {
492 if (!currentForwardInterval.isValid()) {
493 currentForwardInterval.start = x;
494 currentForwardInterval.end = x;
495 currentForwardInterval.row = nextRow;
496 } else {
497 currentForwardInterval.end = x;
498 }
499
500 pixelAccessPolicy.fillPixel(pixelPtr, opacity, x, row);
501 m_d->fillExtent = m_d->fillExtent.united(QRect(x, row, 1, 1));
502
503 if (x == firstX) {
504 extendedPass(&currentForwardInterval, row, false,
505 differencePolicy, selectionPolicy, pixelAccessPolicy);
506 }
507
508 if (x == lastX) {
509 extendedPass(&currentForwardInterval, row, true,
510 differencePolicy, selectionPolicy, pixelAccessPolicy);
511 }
512
513 } else {
514 if (currentForwardInterval.isValid()) {
515 m_d->forwardStack.push(currentForwardInterval);
516 currentForwardInterval.invalidate();
517 }
518 }
519
520 x++;
521 }
522
523 if (currentForwardInterval.isValid()) {
524 m_d->forwardStack.push(currentForwardInterval);
525 }
526}
void extendedPass(KisFillInterval *currentInterval, int srcRow, bool extendRight, DifferencePolicy &differencePolicy, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy)

References KisFillInterval::end, extendedPass(), KisFillInterval::invalidate(), KisFillInterval::isValid(), m_d, KisFillInterval::row, rowIncrement, KisFillInterval::start, and tryPushingCloseGapSeed().

◆ runImpl()

template<typename DifferencePolicy , typename SelectionPolicy , typename PixelAccessPolicy >
void KisScanlineFill::runImpl ( DifferencePolicy & differencePolicy,
SelectionPolicy & selectionPolicy,
PixelAccessPolicy & pixelAccessPolicy )
private

In the end of the first pass we should add an interval containing the starting pixel, but directed into the opposite direction. We cannot do it in the very beginning because the intervals are offset by 1 pixel during every swap operation.

Definition at line 622 of file kis_scanline_fill.cpp.

625{
626 KIS_ASSERT_RECOVER_RETURN(m_d->forwardStack.isEmpty());
627
628 int gapSize = m_d->closeGap;
629 KIS_SAFE_ASSERT_RECOVER(gapSize == 0 || (gapSize > 0 && m_d->filledSelectionIterator)) {
630 gapSize = 0;
631 }
632
633#if MEASURE_FILL_TIME
634 QElapsedTimer timerTotal;
635 QElapsedTimer timerScanlineFill;
636 QElapsedTimer timerGapClosingFill;
637 quint64 totalScanlineFillNanos = 0;
638 quint64 totalGapClosingFillNanos = 0;
639
640 timerTotal.start();
641#endif
642
643 if (gapSize > 0) {
644 // We need to reuse the complex policies used by this class and only provide the final
645 // "projection" of opacity for the distance map calculation.
646 auto opacityFunc = [&](KisPaintDevice* devicePtr, const QRect& rect) {
647 return fillOpacity(differencePolicy, selectionPolicy, pixelAccessPolicy, devicePtr, rect);
648 };
649
650 // Prime the resources. The computations are made lazily, when distance at a pixel is requested.
651 // Resources are freed automatically when the object is destroyed, that is together with the KisScanlineFill object.
652 m_d->gapMapSp = KisGapMapSP(new KisGapMap(gapSize, m_d->boundingRect, opacityFunc));
653 }
654
655 m_d->fillExtent = QRect();
656
657 KisFillInterval startInterval(m_d->startPoint.x(), m_d->startPoint.x(), m_d->startPoint.y());
658
659 // Decide if we should start with a scanline fill or a gap closing fill.
660 if (!tryPushingCloseGapSeed(startInterval.start, startInterval.row, true)) {
661 m_d->forwardStack.push(startInterval);
662 }
663
664 // The outer loop is to continue scanline filling after a gap closing fill.
665 do {
672 bool firstPass = true;
673
674#if MEASURE_FILL_TIME
675 timerScanlineFill.start();
676#endif
677
678 // The scanline fill can only fill the pixels that are "in the open",
679 // that is have DISTANCE_INFINITE. Gap pixels will be pushed to
680 // the gap closing fill's queue.
681
682 while (!m_d->forwardStack.isEmpty()) {
683 while (!m_d->forwardStack.isEmpty()) {
684 KisFillInterval interval = m_d->forwardStack.pop();
685
686 if (interval.row > m_d->boundingRect.bottom() ||
687 interval.row < m_d->boundingRect.top()) {
688
689 continue;
690 }
691
692 processLine(interval, m_d->rowIncrement, differencePolicy, selectionPolicy, pixelAccessPolicy);
693 }
694 m_d->swapDirection();
695
696 if (firstPass) {
697 startInterval.row--;
698 m_d->forwardStack.push(startInterval);
699 firstPass = false;
700 }
701 }
702
703#if MEASURE_FILL_TIME
704 totalScanlineFillNanos += timerScanlineFill.nsecsElapsed();
705 timerGapClosingFill.start();
706#endif
707
708 // Perform a gap closing pass. This pass can in turn feed the scanline fill's
709 // forward stack. It can only fiill pixels with distance < DISTANCE_INFINITE.
710 // This way, both passes complement each other to complete the fill.
711
712 if (!m_d->closeGapQueue.empty()) {
713 startInterval = closeGapPass(differencePolicy, selectionPolicy, pixelAccessPolicy);
714 if (startInterval.isValid()) {
715 m_d->forwardStack.push(startInterval);
716 }
717 }
718
719#if MEASURE_FILL_TIME
720 totalGapClosingFillNanos += timerGapClosingFill.nsecsElapsed();
721#endif
722 } while (!m_d->forwardStack.isEmpty());
723
724#if MEASURE_FILL_TIME
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
737 if (gapSize > 0) {
738 qDebug() << "incl. opacity load" << m_d->gapMapSp->opacityElapsedMillis() << "ms";
739 qDebug() << "incl. distance load" << m_d->gapMapSp->distanceElapsedMillis() << "ms";
740 }
741#endif
742 qDebug() << "----------------------------------------";
743#endif
744}
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75
bool fillOpacity(DifferencePolicy &differencePolicy, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy, KisPaintDevice *const devicePtr, const QRect &rect) const
KisFillInterval closeGapPass(DifferencePolicy &differencePolicy, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy)
void processLine(KisFillInterval interval, const int rowIncrement, DifferencePolicy &differencePolicy, SelectionPolicy &selectionPolicy, PixelAccessPolicy &pixelAccessPolicy)

References closeGapPass(), fillOpacity(), KisFillInterval::isValid(), KIS_ASSERT_RECOVER_RETURN, KIS_SAFE_ASSERT_RECOVER, m_d, processLine(), KisFillInterval::row, KisFillInterval::start, and tryPushingCloseGapSeed().

◆ selectDifferencePolicyAndRun()

template<template< typename SrcPixelType > typename OptimizedDifferencePolicy, typename SlowDifferencePolicy , typename SelectionPolicy , typename PixelAccessPolicy >
void KisScanlineFill::selectDifferencePolicyAndRun ( const KoColor & srcColor,
SelectionPolicy & selectionPolicy,
PixelAccessPolicy & pixelAccessPolicy )
private

Definition at line 749 of file kis_scanline_fill.cpp.

752{
753 const int pixelSize = srcColor.colorSpace()->pixelSize();
754
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);
767 } else {
768 SlowDifferencePolicy dp(srcColor, m_d->threshold);
769 runImpl(dp, selectionPolicy, pixelAccessPolicy);
770 }
771}
virtual quint32 pixelSize() const =0
const KoColorSpace * colorSpace() const
return the current colorSpace
Definition KoColor.h:82

References KoColor::colorSpace(), m_d, KoColorSpace::pixelSize(), and runImpl().

◆ setCloseGap()

void KisScanlineFill::setCloseGap ( int closeGap)

Set the close gap size in pixels for the flood fill. The value 0 behaves like a regular fill. Values 1 and larger will cause a gap map to be computed for the area and then used for the fill. The gaps are small areas of non-opaque pixels that are roughly not larger than the selected gap size. If such a gap is detected, the fill will stop spreading beyond that area.

Definition at line 345 of file kis_scanline_fill.cpp.

346{
347 m_d->closeGap = closeGap;
348}
int closeGap
try to close gaps up to this size in pixels

References closeGap, and m_d.

◆ setOpacitySpread()

void KisScanlineFill::setOpacitySpread ( int opacitySpread)

Set the opacity spread for floodfill. The range is 0-100: 0% means that the fully opaque area only encompasses the pixels exactly equal to the seed point with the other pixels of the selected region being semi-transparent (depending on how similar they are to the seed pixel) up to the region boundary (given by the threshold value). 100 means that the fully opaque area will encompass all the pixels of the selected region up to the contour. Any value in between will make the fully opaque portion of the region vary in size, with semi-transparent pixels in between it and the region boundary

Definition at line 340 of file kis_scanline_fill.cpp.

341{
342 m_d->opacitySpread = opacitySpread;
343}

References m_d, and opacitySpread.

◆ setThreshold()

void KisScanlineFill::setThreshold ( int threshold)

Set the threshold of the filling operation

Used in all functions except clearNonZeroComponent()

Definition at line 335 of file kis_scanline_fill.cpp.

336{
337 m_d->threshold = threshold;
338}

References m_d, and threshold.

◆ swapDirection()

void KisScanlineFill::swapDirection ( )
inline

Definition at line 305 of file kis_scanline_fill.cpp.

305 {
306 rowIncrement *= -1;
308 "FATAL: the forward stack must be empty "
309 "on a direction swap");
310
313 }
QStack< KisFillInterval > fetchAllIntervals(int rowCorrection=0) const
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
QStack< KisFillInterval > forwardStack
KisFillIntervalMap backwardMap

References KisFillIntervalMap::clear(), KisFillIntervalMap::fetchAllIntervals(), and KIS_SAFE_ASSERT_RECOVER_NOOP.

◆ testingGetBackwardIntervals()

KisFillIntervalMap * KisScanlineFill::testingGetBackwardIntervals ( ) const
private

Definition at line 1131 of file kis_scanline_fill.cpp.

1132{
1133 return &m_d->backwardMap;
1134}

References m_d.

◆ testingGetForwardIntervals()

QVector< KisFillInterval > KisScanlineFill::testingGetForwardIntervals ( ) const
private

Definition at line 1126 of file kis_scanline_fill.cpp.

1127{
1128 return QVector<KisFillInterval>(m_d->forwardStack);
1129}

References m_d.

◆ testingProcessLine()

void KisScanlineFill::testingProcessLine ( const KisFillInterval & processInterval)
private

Definition at line 1112 of file kis_scanline_fill.cpp.

1113{
1114 KoColor srcColor(QColor(0,0,0,0), m_d->device->colorSpace());
1115 KoColor fillColor(QColor(200,200,200,200), m_d->device->colorSpace());
1116
1117 using namespace KisColorSelectionPolicies;
1118
1119 OptimizedDifferencePolicy<quint32> dp(srcColor, m_d->threshold);
1120 SelectionPolicy<HardSelectionPolicy> sp(HardSelectionPolicy(m_d->threshold));
1121 FillWithColorPixelAccessPolicy pap(m_d->device, fillColor);
1122
1123 processLine(processInterval, 1, dp, sp, pap);
1124}

References m_d, and processLine().

◆ tryPushingCloseGapSeed()

bool KisScanlineFill::tryPushingCloseGapSeed ( int x,
int y,
bool allowExpand )
inlineprivate

Used with the scanline fill algorithm.

Determine if the (x, y) pixel is near a gap (i.e., has non-INFINITE distance). All gap pixels are pushed onto the gap closing fill queue, while the scanline fill proceeds with regular pixels.

Parameters
allowExpandis only true for the initial gap closing seed.
Returns
true if a gap closing pixel was pushed; the scanline fill must not fill this pixel.

Definition at line 368 of file kis_scanline_fill.cpp.

369{
370 bool pushed = false;
371
372 if (m_d->gapMapSp && m_d->gapMapSp->gapSize() > 0) {
373 const quint32 distance = m_d->gapMapSp->distance(x, y);
374
376 pushed = true;
377
378 CloseGapFillPoint seed;
379 seed.x = x;
380 seed.y = y;
381 seed.distance = distance;
382 seed.allowExpand = allowExpand;
383
384 m_d->closeGapQueue.push(seed);
385 }
386 }
387
388 return pushed;
389}

References distance(), KisGapMap::DISTANCE_INFINITE, and m_d.

Friends And Related Symbol Documentation

◆ KisScanlineFillTest

friend class KisScanlineFillTest
friend

Definition at line 141 of file kis_scanline_fill.h.

Member Data Documentation

◆ backwardMap

KisFillIntervalMap KisScanlineFill::backwardMap

Definition at line 286 of file kis_scanline_fill.cpp.

◆ boundingRect

QRect KisScanlineFill::boundingRect

Definition at line 281 of file kis_scanline_fill.cpp.

◆ closeGap

int KisScanlineFill::closeGap

try to close gaps up to this size in pixels

Definition at line 289 of file kis_scanline_fill.cpp.

◆ closeGapQueue

GreaterPriorityQueue<CloseGapFillPoint> KisScanlineFill::closeGapQueue

Definition at line 298 of file kis_scanline_fill.cpp.

◆ device

KisPaintDeviceSP KisScanlineFill::device

Definition at line 279 of file kis_scanline_fill.cpp.

◆ filledSelectionIterator

KisRandomAccessorSP KisScanlineFill::filledSelectionIterator

Definition at line 302 of file kis_scanline_fill.cpp.

◆ fillExtent

QRect KisScanlineFill::fillExtent

Definition at line 292 of file kis_scanline_fill.cpp.

◆ forwardStack

QStack<KisFillInterval> KisScanlineFill::forwardStack

Definition at line 287 of file kis_scanline_fill.cpp.

◆ gapMapSp

KisGapMapSP KisScanlineFill::gapMapSp

maintains the distance and opacity maps required for the algorithm

Definition at line 290 of file kis_scanline_fill.cpp.

◆ m_d

const QScopedPointer<Private> KisScanlineFill::m_d
private

Definition at line 188 of file kis_scanline_fill.h.

◆ opacitySpread

int KisScanlineFill::opacitySpread

Definition at line 283 of file kis_scanline_fill.cpp.

◆ rowIncrement

int KisScanlineFill::rowIncrement

Definition at line 285 of file kis_scanline_fill.cpp.

◆ startPoint

QPoint KisScanlineFill::startPoint

Definition at line 280 of file kis_scanline_fill.cpp.

◆ threshold

int KisScanlineFill::threshold

Definition at line 282 of file kis_scanline_fill.cpp.


The documentation for this class was generated from the following files: