Commit f352cc1d authored by Dmitry Kazakov's avatar Dmitry Kazakov

Refactor KisSequentialIterator to use java-style iteration

This patch touches quite a lot of stuff throughout the entire Krita,
please report any crashes you get because of that!

Technical details:

The sequential iterator (alongside the hline and vline) iterators had
an inherent problem: when called with an empty rect it just crashed
with SIGSEGV (hlive and vline iterators just have a hack to read/write
at least one pixel when called with an empty rect). This problem happens
because of the structure of API we use: we call nextPixel() **after** the
first cycle of iteration, that is we will read/write at least one pixel
even when the requested rect is empty(!).

Now the iterator inserts one "virtual" pixel before every iteration that
allows the user to call nextPixel() **before** the the first iteration
and stop the cycle in case the check fails.

See example code snippets in kis_sequential_iterator.h

CC:kimageshop@kde.org
BUG:388272
parent 434e1a69
......@@ -49,14 +49,14 @@ void KisBContrastBenchmark::initTestCase()
int r,g,b;
KisSequentialIterator it(m_device, QRect(0, 0, GMP_IMAGE_WIDTH, GMP_IMAGE_HEIGHT));
do {
while (it.nextPixel()) {
r = rand() % 255;
g = rand() % 255;
b = rand() % 255;
m_color.fromQColor(QColor(r,g,b));
memcpy(it.rawData(), m_color.data(), m_colorSpace->pixelSize());
} while (it.nextPixel());
}
}
......
......@@ -49,14 +49,14 @@ void KisBlurBenchmark::initTestCase()
int r,g,b;
KisSequentialIterator it(m_device, QRect(0,0,GMP_IMAGE_WIDTH, GMP_IMAGE_HEIGHT));
do {
while (it.nextPixel()) {
r = rand() % 255;
g = rand() % 255;
b = rand() % 255;
m_color.fromQColor(QColor(r,g,b));
memcpy(it.rawData(), m_color.data(), m_colorSpace->pixelSize());
} while (it.nextPixel());
}
}
void KisBlurBenchmark::cleanupTestCase()
......
......@@ -50,14 +50,14 @@ void KisLevelFilterBenchmark::initTestCase()
int r,g,b;
KisSequentialIterator it(m_device, QRect(0,0,GMP_IMAGE_WIDTH, GMP_IMAGE_HEIGHT));
do {
while (it.nextPixel()) {
r = rand() % 255;
g = rand() % 255;
b = rand() % 255;
m_color.fromQColor(QColor(r,g,b));
memcpy(it.rawData(), m_color.data(), m_colorSpace->pixelSize());
} while (it.nextPixel());
}
}
void KisLevelFilterBenchmark::cleanupTestCase()
......
......@@ -52,10 +52,10 @@ namespace Acs {
KisSequentialIterator it(realPixelCache, pickRect);
do {
while (it.nextPixel()) {
color = picker->colorAt(it.x(), it.y());
memcpy(it.rawData(), color.data(), pixelSize);
} while (it.nextPixel());
}
// NOTE: toQImage() function of the converter copies exactBounds() only!
......
......@@ -67,15 +67,15 @@ void KisColorTransformationFilter::processImpl(KisPaintDeviceSP device,
KisSequentialIterator it(device, applyRect);
int p = 0;
int conseq;
do {
conseq = it.nConseqPixels();
int conseq = it.nConseqPixels();
while (it.nextPixels(conseq)) {
conseq = it.nConseqPixels();
colorTransformation->transform(it.oldRawData(), it.rawData(), conseq);
if (progressUpdater) progressUpdater->setValue(p += conseq);
}
} while(it.nextPixels(conseq));
if (!colorTransformationConfiguration) {
delete colorTransformation;
}
......
......@@ -241,7 +241,7 @@ void KisEdgeDetectionKernel::applyEdgeDetection(KisPaintDeviceSP device,
QVector<float> xNormalised(channels);
QVector<float> finalNorm(channels);
do {
while(yItterator.nextPixel() && xItterator.nextPixel() && finalIt.nextPixel()) {
device->colorSpace()->normalisedChannelsValue(yItterator.rawData(), yNormalised);
device->colorSpace()->normalisedChannelsValue(xItterator.rawData(), xNormalised);
device->colorSpace()->normalisedChannelsValue(finalIt.rawData(), finalNorm);
......@@ -273,7 +273,7 @@ void KisEdgeDetectionKernel::applyEdgeDetection(KisPaintDeviceSP device,
memcpy(finalIt.rawData(), f, pixelSize);
}
} while(yItterator.nextPixel() && xItterator.nextPixel() && finalIt.nextPixel());
}
} else {
KisConvolutionKernelSP kernel;
qreal center = 0;
......@@ -306,7 +306,7 @@ void KisEdgeDetectionKernel::applyEdgeDetection(KisPaintDeviceSP device,
const int pixelSize = device->colorSpace()->pixelSize();
const int channels = device->colorSpace()->colorChannelCount();
QVector<float> normalised(channels);
do {
while (itterator.nextPixel() && finalIt.nextPixel()) {
device->colorSpace()->normalisedChannelsValue(itterator.rawData(), normalised);
KoColor col(finalIt.rawData(), device->colorSpace());
qreal alpha = 0;
......@@ -317,7 +317,7 @@ void KisEdgeDetectionKernel::applyEdgeDetection(KisPaintDeviceSP device,
col.setOpacity(alpha);
memcpy(finalIt.rawData(), col.data(), pixelSize);
} while(itterator.nextPixel() && finalIt.nextPixel());
}
} else {
KisConvolutionPainter kernelP(device);
......@@ -381,7 +381,7 @@ void KisEdgeDetectionKernel::convertToNormalMap(KisPaintDeviceSP device,
QVector<float> xNormalised(channels);
QVector<float> finalNorm(channels);
do {
while(yItterator.nextPixel() && xItterator.nextPixel() && finalIt.nextPixel()) {
device->colorSpace()->normalisedChannelsValue(yItterator.rawData(), yNormalised);
device->colorSpace()->normalisedChannelsValue(xItterator.rawData(), xNormalised);
......@@ -400,5 +400,5 @@ void KisEdgeDetectionKernel::convertToNormalMap(KisPaintDeviceSP device,
device->colorSpace()->fromNormalisedChannelsValue(pixel, finalNorm);
memcpy(finalIt.rawData(), pixel, pixelSize);
} while(yItterator.nextPixel() && xItterator.nextPixel() && finalIt.nextPixel());
}
}
......@@ -716,7 +716,7 @@ bool KisGradientPainter::paintGradient(const QPointF& gradientVectorStart,
const int rightCol = processRect.right();
KisProgressUpdateHelper progressHelper(progressUpdater(), 100, processRect.height());
do {
while (it.nextPixel()) {
double t = shapeStrategy->valueAt(it.x(), it.y());
t = repeatStrategy->valueAt(t);
......@@ -729,7 +729,7 @@ bool KisGradientPainter::paintGradient(const QPointF& gradientVectorStart,
if (it.x() == rightCol) {
progressHelper.step();
}
} while (it.nextPixel());
}
bitBlt(processRect.topLeft(), dev, processRect);
}
......
......@@ -195,7 +195,7 @@ struct PaintDevicePolygonOp
int y = boundRect.top();
interp.setY(y);
do {
while (dstIt.nextPixel()) {
int newY = dstIt.y();
if (y != newY) {
......@@ -221,7 +221,7 @@ struct PaintDevicePolygonOp
srcAcc->sampledOldRawData(dstIt.rawData());
}
} while (dstIt.nextPixel());
}
}
......
......@@ -90,17 +90,19 @@ void KisHistogram::updateHistogram()
// Let the producer do it's work
m_producer->clear();
int i;
// XXX: the original code depended on their being a selection mask in the iterator
// if the paint device had a selection. When we changed that to passing an
// explicit selection to the createRectIterator call, that broke because
// paint devices didn't know about their selections anymore.
// updateHistogram should get a selection parameter.
do {
i = srcIt.nConseqPixels();
m_producer->addRegionToBin(srcIt.oldRawData(), 0, i, cs);
} while (srcIt.nextPixels(i));
int numConseqPixels = srcIt.nConseqPixels();
while (srcIt.nextPixels(numConseqPixels)) {
numConseqPixels = srcIt.nConseqPixels();
m_producer->addRegionToBin(srcIt.oldRawData(), 0, numConseqPixels, cs);
}
computeHistogram();
}
......
......@@ -64,7 +64,7 @@ void KisMarkerPainter::fillHalfBrushDiff(const QPointF &p1, const QPointF &p2, c
boundRect = KisAlgebra2D::cutOffRect(boundRect, plane2);
KisSequentialIterator it(m_d->device, boundRect.toAlignedRect());
do {
while (it.nextPixel()) {
QPoint pt(it.x(), it.y());
qreal value1 = plane1.value(pt);
......@@ -88,7 +88,7 @@ void KisMarkerPainter::fillHalfBrushDiff(const QPointF &p1, const QPointF &p2, c
currentColor.setOpacity(srcAlpha);
memcpy(it.rawData(), currentColor.data(), pixelSize);
}
} while(it.nextPixel());
}
}
void KisMarkerPainter::fillFullCircle(const QPointF &center, qreal radius)
......@@ -105,7 +105,7 @@ void KisMarkerPainter::fillFullCircle(const QPointF &center, qreal radius)
KisAlgebra2D::OuterCircle outer(center, radius);
KisSequentialIterator it(m_d->device, boundRect.toAlignedRect());
do {
while (it.nextPixel()) {
QPoint pt(it.x(), it.y());
qreal value3 = outer.fadeSq(pt);
......@@ -118,7 +118,7 @@ void KisMarkerPainter::fillFullCircle(const QPointF &center, qreal radius)
currentColor.setOpacity(srcAlpha);
memcpy(it.rawData(), currentColor.data(), pixelSize);
}
} while(it.nextPixel());
}
}
void KisMarkerPainter::fillCirclesDiff(const QPointF &c1, qreal r1,
......
......@@ -742,7 +742,7 @@ void KisPaintDevice::Private::updateLodDataStruct(LodDataStruct *_dst, const QRe
while (rowsRemaining > 0) {
int colsRemaining = srcRect.width();
while (colsRemaining > 0) {
while (colsRemaining > 0 && srcIntIt.nextPixel()) {
memcpy(blendDataPtr, srcIntIt.rawDataConst(), pixelSize);
blendDataPtr += pixelSize;
......@@ -753,7 +753,6 @@ void KisPaintDevice::Private::updateLodDataStruct(LodDataStruct *_dst, const QRe
columnsAccumulated = 0;
}
srcIntIt.nextPixel();
colsRemaining--;
}
......@@ -763,11 +762,13 @@ void KisPaintDevice::Private::updateLodDataStruct(LodDataStruct *_dst, const QRe
// blend and write the final data
blendDataPtr = blendData.data();
for (int i = 0; i < dstRect.width(); i++) {
mixOp->mixColors(blendDataPtr, weights.data(), srcCellSize, dstIntIt.rawData());
int colsRemaining = dstRect.width();
while (colsRemaining > 0 && dstIntIt.nextPixel()) {
mixOp->mixColors(blendDataPtr, weights.data(), srcCellSize, dstIntIt.rawData());
blendDataPtr += srcCellStride;
dstIntIt.nextPixel();
colsRemaining--;
}
// reset counters
......
......@@ -161,9 +161,14 @@ public:
InternalSequentialConstIterator srcIt(DirectDataAccessPolicy(m_dataManager.data(), cacheInvalidator()), rc);
InternalSequentialIterator dstIt(DirectDataAccessPolicy(dstDataManager.data(), cacheInvalidator()), rc);
int nConseqPixels = 0;
int nConseqPixels = srcIt.nConseqPixels();
// since we are accessing data managers directly, the colums are always aligned
KIS_SAFE_ASSERT_RECOVER_NOOP(srcIt.nConseqPixels() == dstIt.nConseqPixels());
while(srcIt.nextPixels(nConseqPixels) &&
dstIt.nextPixels(nConseqPixels)) {
do {
nConseqPixels = srcIt.nConseqPixels();
const quint8 *srcData = srcIt.rawDataConst();
......@@ -173,10 +178,7 @@ public:
dstColorSpace,
nConseqPixels,
renderingIntent, conversionFlags);
} while(srcIt.nextPixels(nConseqPixels) &&
dstIt.nextPixels(nConseqPixels));
}
}
// becomes owned by the parent
......
......@@ -217,7 +217,7 @@ KisPaintDeviceSP KisPainter::convertToAlphaAsAlpha(KisPaintDeviceSP src)
KisSequentialConstIterator srcIt(src, processRect);
KisSequentialIterator dstIt(dst, processRect);
do {
while (srcIt.nextPixel() && dstIt.nextPixel()) {
const quint8 *srcPtr = srcIt.rawDataConst();
quint8 *alpha8Ptr = dstIt.rawData();
......@@ -225,7 +225,7 @@ KisPaintDeviceSP KisPainter::convertToAlphaAsAlpha(KisPaintDeviceSP src)
const quint8 alpha = srcCS->opacityU8(srcPtr);
*alpha8Ptr = KoColorSpaceMaths<quint8>::multiply(alpha, KoColorSpaceMathsTraits<quint8>::unitValue - white);
} while (srcIt.nextPixel() && dstIt.nextPixel());
}
return dst;
}
......@@ -241,12 +241,12 @@ KisPaintDeviceSP KisPainter::convertToAlphaAsGray(KisPaintDeviceSP src)
KisSequentialConstIterator srcIt(src, processRect);
KisSequentialIterator dstIt(dst, processRect);
do {
while (srcIt.nextPixel() && dstIt.nextPixel()) {
const quint8 *srcPtr = srcIt.rawDataConst();
quint8 *alpha8Ptr = dstIt.rawData();
*alpha8Ptr = srcCS->intensity8(srcPtr);
} while (srcIt.nextPixel() && dstIt.nextPixel());
}
return dst;
}
......@@ -265,11 +265,11 @@ bool KisPainter::checkDeviceHasTransparency(KisPaintDeviceSP dev)
const KoColorSpace *cs = dev->colorSpace();
KisSequentialConstIterator it(dev, deviceBounds);
do {
while(it.nextPixel()) {
if (cs->opacityU8(it.rawDataConst()) != OPACITY_OPAQUE_U8) {
return true;
}
} while(it.nextPixel());
}
return false;
}
......
......@@ -162,12 +162,12 @@ void KisPixelSelection::copyAlphaFrom(KisPaintDeviceSP src, const QRect &process
KisSequentialConstIterator srcIt(src, processRect);
KisSequentialIterator dstIt(this, processRect);
do {
while (srcIt.nextPixel() && dstIt.nextPixel()) {
const quint8 *srcPtr = srcIt.rawDataConst();
quint8 *alpha8Ptr = dstIt.rawData();
*alpha8Ptr = srcCS->opacityU8(srcPtr);
} while (srcIt.nextPixel() && dstIt.nextPixel());
}
m_d->outlineCacheValid = false;
m_d->outlineCache = QPainterPath();
......@@ -296,9 +296,9 @@ void KisPixelSelection::invert()
if (!rc.isEmpty()) {
KisSequentialIterator it(this, rc);
do {
while(it.nextPixel()) {
*(it.rawData()) = MAX_SELECTED - *(it.rawData());
} while (it.nextPixel());
}
}
quint8 defPixel = MAX_SELECTED - *defaultPixel().data();
setDefaultPixel(KoColor(&defPixel, colorSpace()));
......@@ -473,7 +473,7 @@ QImage deviceToQImage(KisPaintDeviceSP device,
const qreal alphaScale = maskColor.alphaF();
KisSequentialIterator it(device, rc);
do {
while(it.nextPixel()) {
quint8 value = (MAX_SELECTED - *(it.rawData())) * alphaScale;
color.setAlpha(value);
......@@ -481,7 +481,7 @@ QImage deviceToQImage(KisPaintDeviceSP device,
pt -= rc.topLeft();
image.setPixel(pt.x(), pt.y(), color.rgba());
} while (it.nextPixel());
}
return image;
}
......
......@@ -52,12 +52,12 @@ struct ReadOnlyIteratorPolicy {
typedef KisHLineConstIteratorSP IteratorTypeSP;
ReadOnlyIteratorPolicy(SourcePolicy source, const QRect &rect) {
m_iter = source.createConstIterator(rect);
m_iter = !rect.isEmpty() ? source.createConstIterator(rect) : 0;
}
ALWAYS_INLINE void updatePointersCache() {
m_rawDataConst = m_iter->rawDataConst();
m_oldRawData = m_iter->oldRawData();
m_rawDataConst = m_iter ? m_iter->rawDataConst() : 0;
m_oldRawData = m_iter ? m_iter->oldRawData() : 0;
}
ALWAYS_INLINE const quint8* rawDataConst() const {
......@@ -80,12 +80,12 @@ struct WritableIteratorPolicy {
typedef KisHLineIteratorSP IteratorTypeSP;
WritableIteratorPolicy(SourcePolicy source, const QRect &rect) {
m_iter = source.createIterator(rect);
m_iter = !rect.isEmpty() ? source.createIterator(rect) : 0;
}
ALWAYS_INLINE void updatePointersCache() {
m_rawData = m_iter->rawData();
m_oldRawData = m_iter->oldRawData();
m_rawData = m_iter ? m_iter->rawData() : 0;
m_oldRawData = m_iter ? m_iter->oldRawData() : 0;
}
ALWAYS_INLINE quint8* rawData() {
......@@ -117,6 +117,49 @@ private:
* pixel-by-pixel processing it is about twice faster(!) than a usual
* hline iterator.
*
* The follows the "java-style" iterators rules. Before requesting the
* first pixel from the iterator you should call nextPixel() to "jump over"
* this first pixel. After the jump is accomplished, you can easily request
* the "jumped over" pixel data.
*
* The modified rules apply when the user wants accesses censequent pixels
* in one go. The user first asks the iterator for the number of available
* consequent pixels, and then calls nextPixels(numConseqPixels). In this
* case, iterator inserts a "virtual" pixel that one should jump over before
* doing any real iteration.
*
* Iteration in pixel-by-pixel manner:
*
* \code{.cpp}
* KisSequentialConstIterator it(dev, rect);
* while (it.nextPixel()) {
* quint *ptr = it.rawDataConst();
* // work with ptr...
* }
* \endcode
*
* Iteration with strides:
*
* \code{.cpp}
* KisSequentialConstIterator it(dev, rect);
*
* // Here we jump over the first "virtual" pixel,
* // which helps us to avoid an empty rect problem
*
* int numConseqPixels = it.nConseqPixels();
* while (it.nextPixels(numConseqPixels)) {
*
* // get real number of conseq pixels
*
* numConseqPixels = it.nConseqPixels();
* quint *ptr = it.rawDataConst();
*
* // process the data
* processPixelData(tr, numConseqPixels);
* }
* \endcode
*
*
* Implementation:
*
* The iterator is implemented using a policy pattern. The class
......@@ -137,16 +180,19 @@ public:
m_rowsLeft(rect.height() - 1),
m_columnOffset(0),
m_iteratorX(0),
m_iteratorY(0)
m_iteratorY(0),
m_isStarted(false)
{
m_columnsLeft = m_numConseqPixels = m_policy.m_iter->nConseqPixels();
m_columnsLeft = m_numConseqPixels =
m_policy.m_iter ? m_policy.m_iter->nConseqPixels() : 0;
m_policy.updatePointersCache();
m_iteratorX = m_policy.m_iter->x();
m_iteratorY = m_policy.m_iter->y();
m_iteratorX = m_policy.m_iter ? m_policy.m_iter->x() : 0;
m_iteratorY = m_policy.m_iter ? m_policy.m_iter->y() : 0;
}
inline int nConseqPixels() const {
return m_columnsLeft;
return m_isStarted ? m_columnsLeft : 1;
}
inline bool nextPixels(int numPixels) {
......@@ -160,9 +206,14 @@ public:
}
inline bool nextPixel() {
if (!m_isStarted) {
m_isStarted = true;
return m_policy.m_iter;
}
m_columnsLeft--;
if (m_columnsLeft) {
if (m_columnsLeft > 0) {
m_columnOffset += m_pixelSize;
return true;
} else {
......@@ -219,6 +270,8 @@ private:
int m_columnOffset;
int m_iteratorX;
int m_iteratorY;
bool m_isStarted;
};
typedef KisSequentialIteratorBase<ReadOnlyIteratorPolicy<> > KisSequentialConstIterator;
......
......@@ -402,18 +402,18 @@ namespace KritaUtils
void applyToAlpha8Device(KisPaintDeviceSP dev, const QRect &rc, std::function<void(quint8)> func) {
KisSequentialConstIterator dstIt(dev, rc);
do {
while (dstIt.nextPixel()) {
const quint8 *dstPtr = dstIt.rawDataConst();
func(*dstPtr);
} while (dstIt.nextPixel());
}
}
void filterAlpha8Device(KisPaintDeviceSP dev, const QRect &rc, std::function<quint8(quint8)> func) {
KisSequentialIterator dstIt(dev, rc);
do {
while (dstIt.nextPixel()) {
quint8 *dstPtr = dstIt.rawData();
*dstPtr = func(*dstPtr);
} while (dstIt.nextPixel());
}
}
qreal estimatePortionOfTransparentPixels(KisPaintDeviceSP dev, const QRect &rect, qreal samplePortion) {
......
......@@ -55,23 +55,23 @@ generateRandomSelection(const QRect &rc)
boost::mt11213b uniformSource;
if (uniformSource.max() >= 0x00FFFFFF) {
do {
while (dstIt.nextPixel()) {
int randValue = uniformSource();
*dstIt.rawData() = (quint8) randValue;
if (!dstIt.nextPixel()) break;
if (!dstIt.nextPixel()) break;
randValue >>= 8;
*dstIt.rawData() = (quint8) randValue;
if (!dstIt.nextPixel()) break;
if (!dstIt.nextPixel()) break;
randValue >>= 8;
*dstIt.rawData() = (quint8) randValue;
} while(dstIt.nextPixel());
}
} else {
do {
while (dstIt.nextPixel()) {
*dstIt.rawData() = (quint8) uniformSource();
} while(dstIt.nextPixel());
}
}
return selection;
......
......@@ -148,11 +148,11 @@ void mapPixelValues(KisPixelSelectionSP srcSelection,
KisSequentialConstIterator srcIt(srcSelection, applyRect);
KisSequentialIterator dstIt(dstSelection, applyRect);
do {
while (srcIt.nextPixel() && dstIt.nextPixel()) {
const quint8 *srcPtr = srcIt.rawDataConst();
quint8 *dstPtr = dstIt.rawData();
*dstPtr = mapTable[*srcPtr];
} while(srcIt.nextPixel() && dstIt.nextPixel());
}
}
template <class MapOp>
......@@ -173,10 +173,10 @@ void mapPixelValues(KisPixelSelectionSP dstSelection,
KisSequentialIterator dstIt(dstSelection, applyRect);
do {
while (dstIt.nextPixel()) {
quint8 *dstPtr = dstIt.rawData();
*dstPtr = mapTable[*dstPtr];
} while(dstIt.nextPixel());
}
}
struct BevelEmbossRectCalculator
......
......@@ -104,21 +104,19 @@ void blendAndOffsetSatinSelection(KisPixelSelectionSP dstSelection,
KisSequentialIterator srcIt1(srcSelection, applyRect.translated(offset));
KisSequentialIterator srcIt2(srcSelection, applyRect.translated(-offset));
KisSequentialIterator dstIt(dstSelection, applyRect);
do {
while(dstIt.nextPixel() && srcIt1.nextPixel() && srcIt2.nextPixel()) {
quint8 *dstPixelPtr = dstIt.rawData();
quint8 *src1PixelPtr = srcIt1.rawData();
quint8 *src2PixelPtr = srcIt2.rawData();
if (!invert) {
*dstPixelPtr = *dstPixelPtr * qAbs(*src1PixelPtr - *src2PixelPtr) >> 8;
} else {
*dstPixelPtr = *dstPixelPtr * (255 - qAbs(*src1PixelPtr - *src2PixelPtr)) >> 8;
}
} while(dstIt.nextPixel() &&
srcIt1.nextPixel() &&
srcIt2.nextPixel());
}
}
void applySatin(KisPaintDeviceSP srcDevice,
......
......@@ -72,11 +72,11 @@ namespace KisLsUtils
KisSequentialConstIterator srcIt(device, srcRect);
KisSequentialIterator dstIt(selection, srcRect);
do {
while (srcIt.nextPixel() && dstIt.nextPixel()) {
quint8 *dstPtr = dstIt.rawData();
const quint8* srcPtr = srcIt.rawDataConst();
*dstPtr = cs->opacityU8(srcPtr);
} while(srcIt.nextPixel() && dstIt.nextPixel());
}
return baseSelection;
}
......@@ -86,20 +86,20 @@ namespace KisLsUtils
KisSequentialIterator dstIt(selection, applyRect);
if (edgeHidden) {
do {
while(dstIt.nextPixel()) {
quint8 *pixelPtr = dstIt.rawData();
*pixelPtr =
(*pixelPtr < 24) ?
*pixelPtr * 10 : 0xFF;
} while(dstIt.nextPixel());
}
} else {
do {
while(dstIt.nextPixel()) {
quint8 *pixelPtr = dstIt.rawData();
*pixelPtr = 0xFF;
} while(dstIt.nextPixel());
}
}
}
......@@ -190,7 +190,10 @@ namespace KisLsUtils
if (edgeHidden) {
do {
while (selIt.nextPixel() &&
dstIt.nextPixel() &&
indexFetcher.nextPixel()) {
quint8 selAlpha = *selIt.rawDataConst();
int gradientIndex = indexFetcher.popOneIndex(selAlpha);
const KoColor &color = table[gradientIndex];
......@@ -203,20 +206,18 @@ namespace KisLsUtils
cs->setOpacity(dstIt.rawData(), tableAlpha, 1);
}
} while(selIt.nextPixel() &&
dstIt.nextPixel() &&
indexFetcher.nextPixel());
}
} else {