Krita Source Code Documentation
Loading...
Searching...
No Matches
KisPropagateColorsFilter.cpp
Go to the documentation of this file.
1/*
2 * KDE. Krita Project.
3 *
4 * SPDX-FileCopyrightText: 2024 Deif Lou <ginoba@gmail.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include <cmath>
10
12#include <KoUpdater.h>
18
22
34
35template <quint32 DiagonalDistance, bool BoundedExpansion, bool ExpandAlpha>
37{
38 constexpr static quint32 infinity {0xFFFFFF};
39 constexpr static quint32 orthogonalDistance {256};
40 constexpr static quint32 diagonalDistance {DiagonalDistance};
41
46 const QRect rect;
47 const quint32 expansionAmount;
48
50 const QRect &applyRect,
51 qreal expansionAmount)
56 , rect(applyRect)
57 , expansionAmount(static_cast<quint32>(qRound(expansionAmount * 256.0)))
58 {}
59
60 void initializePixel(quint32 *distancePixel, quint8 *devicePixel) const
61 {
62 const quint8 alpha = sourceDeviceColorSpace->opacityU8(devicePixel);
63 *distancePixel = alpha == 0 ? infinity : 0;
64
65 if constexpr (ExpandAlpha) {
66 if (alpha > 0) {
68 }
69 }
70 }
71
72 void setPixel(quint32 *distancePixel, quint8 *devicePixel,
73 quint32 distance, const quint8 *neighborDevicePixel) const
74 {
75 if (distance >= *distancePixel) {
76 return;
77 }
78 if constexpr (BoundedExpansion) {
80 return;
81 }
82 }
83
84 *distancePixel = distance;
85 memcpy(devicePixel, neighborDevicePixel, sourceDevicePixelSize);
86
87 if constexpr (!ExpandAlpha) {
89 }
90 }
91
92 void updatePixel(quint32 *distancePixel, quint8 *devicePixel,
93 const quint32 *neighborDistancePixel, const quint8 *neighborDevicePixel,
94 quint32 relativeDistance) const
95 {
96 const quint32 newDistance = *neighborDistancePixel + relativeDistance;
97 setPixel(distancePixel, devicePixel, newDistance, neighborDevicePixel);
98 }
99
100 void updatePixel(quint32 *distancePixel, quint8 *devicePixel,
101 const quint32 *neighborDistancePixel1, const quint8 *neighborDevicePixel1,
102 const quint32 *neighborDistancePixel2, const quint8 *neighborDevicePixel2,
103 quint32 relativeDistance1, quint32 relativeDistance2) const
104 {
105 const quint32 newDistance1 = *neighborDistancePixel1 + relativeDistance1;
106 const quint32 newDistance2 = *neighborDistancePixel2 + relativeDistance2;
107
108 if (newDistance1 < newDistance2) {
109 setPixel(distancePixel, devicePixel, newDistance1, neighborDevicePixel1);
110 } else {
111 setPixel(distancePixel, devicePixel, newDistance2, neighborDevicePixel2);
112 }
113 }
114
115 void updatePixel(quint32 *distancePixel, quint8 *devicePixel,
116 const quint32 *neighborDistancePixel1, const quint8 *neighborDevicePixel1,
117 const quint32 *neighborDistancePixel2, const quint8 *neighborDevicePixel2,
118 const quint32 *neighborDistancePixel3, const quint8 *neighborDevicePixel3,
119 quint32 relativeDistance1, quint32 relativeDistance2, quint32 relativeDistance3) const
120 {
121 const quint32 newDistance1 = *neighborDistancePixel1 + relativeDistance1;
122 const quint32 newDistance2 = *neighborDistancePixel2 + relativeDistance2;
123 const quint32 newDistance3 = *neighborDistancePixel3 + relativeDistance3;
124
125 if (newDistance1 < newDistance2) {
126 if (newDistance1 < newDistance3) {
127 setPixel(distancePixel, devicePixel, newDistance1, neighborDevicePixel1);
128 } else {
129 setPixel(distancePixel, devicePixel, newDistance3, neighborDevicePixel3);
130 }
131 } else {
132 if (newDistance2 < newDistance3) {
133 setPixel(distancePixel, devicePixel, newDistance2, neighborDevicePixel2);
134 } else {
135 setPixel(distancePixel, devicePixel, newDistance3, neighborDevicePixel3);
136 }
137 }
138 }
139
140 void updatePixel(quint32 *distancePixel, quint8 *devicePixel,
141 const quint32 *neighborDistancePixel1, const quint8 *neighborDevicePixel1,
142 const quint32 *neighborDistancePixel2, const quint8 *neighborDevicePixel2,
143 const quint32 *neighborDistancePixel3, const quint8 *neighborDevicePixel3,
144 const quint32 *neighborDistancePixel4, const quint8 *neighborDevicePixel4,
145 quint32 relativeDistance1, quint32 relativeDistance2,
146 quint32 relativeDistance3, quint32 relativeDistance4) const
147 {
148 const quint32 newDistance1 = *neighborDistancePixel1 + relativeDistance1;
149 const quint32 newDistance2 = *neighborDistancePixel2 + relativeDistance2;
150 const quint32 newDistance3 = *neighborDistancePixel3 + relativeDistance3;
151 const quint32 newDistance4 = *neighborDistancePixel4 + relativeDistance4;
152
153 if (newDistance1 < newDistance2) {
154 if (newDistance1 < newDistance3) {
155 if (newDistance1 < newDistance4) {
156 setPixel(distancePixel, devicePixel, newDistance1, neighborDevicePixel1);
157 } else {
158 setPixel(distancePixel, devicePixel, newDistance4, neighborDevicePixel4);
159 }
160 } else {
161 if (newDistance3 < newDistance4) {
162 setPixel(distancePixel, devicePixel, newDistance3, neighborDevicePixel3);
163 } else {
164 setPixel(distancePixel, devicePixel, newDistance4, neighborDevicePixel4);
165 }
166 }
167 } else {
168 if (newDistance2 < newDistance3) {
169 if (newDistance2 < newDistance4) {
170 setPixel(distancePixel, devicePixel, newDistance2, neighborDevicePixel2);
171 } else {
172 setPixel(distancePixel, devicePixel, newDistance4, neighborDevicePixel4);
173 }
174 } else {
175 if (newDistance3 < newDistance4) {
176 setPixel(distancePixel, devicePixel, newDistance3, neighborDevicePixel3);
177 } else {
178 setPixel(distancePixel, devicePixel, newDistance4, neighborDevicePixel4);
179 }
180 }
181 }
182 }
183};
184
185static void swapRowPointers(quint8 **distanceMapRow1,
186 quint8 **distanceMapRow2,
187 quint8 **deviceRow1,
188 quint8 **deviceRow2)
189{
190 quint8 *temp = *distanceMapRow1;
191 *distanceMapRow1 = *distanceMapRow2;
192 *distanceMapRow2 = temp;
193 temp = *deviceRow1;
194 *deviceRow1 = *deviceRow2;
195 *deviceRow2 = temp;
196}
197
199{
200 constexpr static qint32 maximumProgress {100 << 16};
201 constexpr static qint32 scaledHalfUnit {0x7FFF};
203 const qint32 progressStep;
205
211
217
223};
224
225template <typename ExpansionStrategy>
226void expand(ExpansionStrategy &expansionStrategy, KoUpdater *progressUpdater)
227{
228 ScaledProgress progress(expansionStrategy.rect.height() * 2, progressUpdater);
229
230 QVector<quint8> distanceMapRows(expansionStrategy.rect.width() * 4 * 2);
231 QVector<quint8> deviceRows(expansionStrategy.rect.width() * expansionStrategy.sourceDevicePixelSize * 2);
232 quint8 *distanceMapRow1, *distanceMapRow2;
233 quint8 *deviceRow1, *deviceRow2;
234
235 // Forwards pass
236 distanceMapRow1 = distanceMapRows.data();
237 distanceMapRow2 = distanceMapRows.data() + expansionStrategy.rect.width() * 4;
238 deviceRow1 = deviceRows.data();
239 deviceRow2 = deviceRows.data() + expansionStrategy.rect.width() * expansionStrategy.sourceDevicePixelSize;
240 // Top row
241 expansionStrategy.distanceMap->readBytes(distanceMapRow1, expansionStrategy.rect.left(),
242 expansionStrategy.rect.top(), expansionStrategy.rect.width(), 1);
243 expansionStrategy.sourceDevice->readBytes(deviceRow1, expansionStrategy.rect.left(),
244 expansionStrategy.rect.top(), expansionStrategy.rect.width(), 1);
245 // Left pixel
246 expansionStrategy.initializePixel(reinterpret_cast<quint32*>(distanceMapRow1), deviceRow1);
247 // Middle pixels
248 {
249 quint32 *distancePixel = reinterpret_cast<quint32*>(distanceMapRow1) + 1;
250 quint8 *devicePixel = deviceRow1 + expansionStrategy.sourceDevicePixelSize;
251 for (qint32 x = 1; x < expansionStrategy.rect.width();
252 ++x, ++distancePixel, devicePixel += expansionStrategy.sourceDevicePixelSize) {
253
254 expansionStrategy.initializePixel(distancePixel, devicePixel);
255 if (*distancePixel == 0) {
256 continue;
257 }
258 expansionStrategy.updatePixel(
259 distancePixel, devicePixel,
260 distancePixel - 1, devicePixel - expansionStrategy.sourceDevicePixelSize,
261 expansionStrategy.orthogonalDistance
262 );
263 }
264 }
265 expansionStrategy.distanceMap->writeBytes(distanceMapRow1, expansionStrategy.rect.left(),
266 expansionStrategy.rect.top(), expansionStrategy.rect.width(), 1);
267 expansionStrategy.sourceDevice->writeBytes(deviceRow1, expansionStrategy.rect.left(),
268 expansionStrategy.rect.top(), expansionStrategy.rect.width(), 1);
269 progress.stepUp();
270 // Rest of rows
271 for (qint32 y = expansionStrategy.rect.top() + 1; y <= expansionStrategy.rect.bottom(); ++y) {
272 expansionStrategy.distanceMap->readBytes(distanceMapRow2, expansionStrategy.rect.left(),
273 y, expansionStrategy.rect.width(), 1);
274 expansionStrategy.sourceDevice->readBytes(deviceRow2, expansionStrategy.rect.left(), y,
275 expansionStrategy.rect.width(), 1);
276
277 quint32 *topDistancePixel = reinterpret_cast<quint32*>(distanceMapRow1);
278 quint32 *distancePixel = reinterpret_cast<quint32*>(distanceMapRow2);
279 quint8 *topDevicePixel = deviceRow1;
280 quint8 *devicePixel = deviceRow2;
281 // Left pixel
282 {
283 expansionStrategy.initializePixel(distancePixel, devicePixel);
284 if (*distancePixel != 0) {
285 if (expansionStrategy.rect.width() > 1) {
286 expansionStrategy.updatePixel(
287 distancePixel, devicePixel,
288 topDistancePixel, topDevicePixel,
289 topDistancePixel + 1, topDevicePixel + expansionStrategy.sourceDevicePixelSize,
290 expansionStrategy.orthogonalDistance, expansionStrategy.diagonalDistance
291 );
292 } else {
293 expansionStrategy.updatePixel(
294 distancePixel, devicePixel,
295 topDistancePixel, topDevicePixel,
296 expansionStrategy.orthogonalDistance
297 );
298 }
299 }
300 ++topDistancePixel;
301 ++distancePixel;
302 topDevicePixel += expansionStrategy.sourceDevicePixelSize;
303 devicePixel += expansionStrategy.sourceDevicePixelSize;
304 }
305 // Middle pixels
306 for (qint32 x = 1; x < expansionStrategy.rect.width() - 1;
307 ++x, ++topDistancePixel, ++distancePixel,
308 topDevicePixel += expansionStrategy.sourceDevicePixelSize,
309 devicePixel += expansionStrategy.sourceDevicePixelSize) {
310
311 expansionStrategy.initializePixel(distancePixel, devicePixel);
312 if (*distancePixel == 0) {
313 continue;
314 }
315 expansionStrategy.updatePixel(
316 distancePixel, devicePixel,
317 topDistancePixel - 1,topDevicePixel - expansionStrategy.sourceDevicePixelSize,
318 topDistancePixel, topDevicePixel,
319 topDistancePixel + 1, topDevicePixel + expansionStrategy.sourceDevicePixelSize,
320 distancePixel - 1, devicePixel - expansionStrategy.sourceDevicePixelSize,
321 expansionStrategy.diagonalDistance, expansionStrategy.orthogonalDistance,
322 expansionStrategy.diagonalDistance, expansionStrategy.orthogonalDistance
323 );
324 }
325 // Right pixel
326 expansionStrategy.initializePixel(distancePixel, devicePixel);
327 if (expansionStrategy.rect.width() > 1 && *distancePixel != 0) {
328 expansionStrategy.updatePixel(
329 distancePixel, devicePixel,
330 topDistancePixel - 1, topDevicePixel - expansionStrategy.sourceDevicePixelSize,
331 distancePixel - 1, devicePixel - expansionStrategy.sourceDevicePixelSize,
332 topDistancePixel, topDevicePixel,
333 expansionStrategy.diagonalDistance, expansionStrategy.orthogonalDistance,
334 expansionStrategy.orthogonalDistance
335 );
336 }
337 // Write new pixels
338 expansionStrategy.distanceMap->writeBytes(distanceMapRow2, expansionStrategy.rect.left(),
339 y, expansionStrategy.rect.width(), 1);
340 expansionStrategy.sourceDevice->writeBytes(deviceRow2, expansionStrategy.rect.left(),
341 y, expansionStrategy.rect.width(), 1);
342 // Swap pointers
343 swapRowPointers(&distanceMapRow1, &distanceMapRow2, &deviceRow1, &deviceRow2);
344
345 progress.stepUp();
346 }
347
348 // Backwards pass
349 // Bottom row
350 // Right pixel (no op)
351 // Middle pixels
352 {
353 quint32 *distancePixel = reinterpret_cast<quint32*>(distanceMapRow1) + expansionStrategy.rect.width() - 2;
354 quint8 *devicePixel =
355 deviceRow1 + expansionStrategy.sourceDevicePixelSize * (expansionStrategy.rect.width() - 2);
356 for (qint32 x = 1; x < expansionStrategy.rect.width();
357 ++x, --distancePixel, devicePixel -= expansionStrategy.sourceDevicePixelSize) {
358
359 if (*distancePixel == 0) {
360 continue;
361 }
362 expansionStrategy.updatePixel(
363 distancePixel, devicePixel,
364 distancePixel + 1, devicePixel + expansionStrategy.sourceDevicePixelSize,
365 expansionStrategy.orthogonalDistance
366 );
367 }
368 }
369 expansionStrategy.distanceMap->writeBytes(distanceMapRow1, expansionStrategy.rect.left(),
370 expansionStrategy.rect.bottom(), expansionStrategy.rect.width(), 1);
371 expansionStrategy.sourceDevice->writeBytes(deviceRow1, expansionStrategy.rect.left(),
372 expansionStrategy.rect.bottom(), expansionStrategy.rect.width(), 1);
373 progress.stepUp();
374 // Rest of rows
375 for (qint32 y = expansionStrategy.rect.bottom() - 1; y >= expansionStrategy.rect.top(); --y) {
376 expansionStrategy.distanceMap->readBytes(distanceMapRow2, expansionStrategy.rect.left(),
377 y, expansionStrategy.rect.width(), 1);
378 expansionStrategy.sourceDevice->readBytes(deviceRow2, expansionStrategy.rect.left(),
379 y, expansionStrategy.rect.width(), 1);
380
381 quint32 *bottomDistancePixel =
382 reinterpret_cast<quint32*>(distanceMapRow1) + expansionStrategy.rect.width() - 1;
383 quint32 *distancePixel =
384 reinterpret_cast<quint32*>(distanceMapRow2) + expansionStrategy.rect.width() - 1;
385 quint8 *bottomDevicePixel =
386 deviceRow1 + expansionStrategy.sourceDevicePixelSize * (expansionStrategy.rect.width() - 1);
387 quint8 *devicePixel =
388 deviceRow2 + expansionStrategy.sourceDevicePixelSize * (expansionStrategy.rect.width() - 1);
389 // Right pixel
390 {
391 if (*distancePixel != 0) {
392 if (expansionStrategy.rect.width() > 1) {
393 expansionStrategy.updatePixel(
394 distancePixel, devicePixel,
395 bottomDistancePixel, bottomDevicePixel,
396 bottomDistancePixel - 1, bottomDevicePixel - expansionStrategy.sourceDevicePixelSize,
397 expansionStrategy.orthogonalDistance, expansionStrategy.diagonalDistance
398 );
399 } else {
400 expansionStrategy.updatePixel(
401 distancePixel, devicePixel,
402 bottomDistancePixel, bottomDevicePixel,
403 expansionStrategy.orthogonalDistance
404 );
405 }
406 }
407 --bottomDistancePixel;
408 --distancePixel;
409 bottomDevicePixel -= expansionStrategy.sourceDevicePixelSize;
410 devicePixel -= expansionStrategy.sourceDevicePixelSize;
411 }
412 // Middle pixels
413 for (qint32 x = 1; x < expansionStrategy.rect.width() - 1;
414 ++x, --bottomDistancePixel, --distancePixel,
415 bottomDevicePixel -= expansionStrategy.sourceDevicePixelSize,
416 devicePixel -= expansionStrategy.sourceDevicePixelSize) {
417
418 if (*distancePixel == 0) {
419 continue;
420 }
421 expansionStrategy.updatePixel(
422 distancePixel, devicePixel,
423 bottomDistancePixel + 1, bottomDevicePixel + expansionStrategy.sourceDevicePixelSize,
424 bottomDistancePixel, bottomDevicePixel,
425 bottomDistancePixel - 1, bottomDevicePixel - expansionStrategy.sourceDevicePixelSize,
426 distancePixel + 1, devicePixel + expansionStrategy.sourceDevicePixelSize,
427 expansionStrategy.diagonalDistance, expansionStrategy.orthogonalDistance,
428 expansionStrategy.diagonalDistance, expansionStrategy.orthogonalDistance
429 );
430 }
431 // Left pixel
432 if (expansionStrategy.rect.width() > 1 && *distancePixel != 0) {
433 expansionStrategy.updatePixel(
434 distancePixel, devicePixel,
435 bottomDistancePixel + 1, bottomDevicePixel + expansionStrategy.sourceDevicePixelSize,
436 bottomDistancePixel, bottomDevicePixel,
437 distancePixel + 1, devicePixel + expansionStrategy.sourceDevicePixelSize,
438 expansionStrategy.diagonalDistance, expansionStrategy.orthogonalDistance,
439 expansionStrategy.orthogonalDistance
440 );
441 }
442 // Write new pixels
443 expansionStrategy.distanceMap->writeBytes(distanceMapRow2, expansionStrategy.rect.left(),
444 y, expansionStrategy.rect.width(), 1);
445 expansionStrategy.sourceDevice->writeBytes(deviceRow2, expansionStrategy.rect.left(), y,
446 expansionStrategy.rect.width(), 1);
447 // Swap pointers
448 swapRowPointers(&distanceMapRow1, &distanceMapRow2, &deviceRow1, &deviceRow2);
449
450 progress.stepUp();
451 }
452
453 progress.complete();
454}
455
456template <quint32 DiagonalDistance, bool BoundedExpansion>
458 const QRect &applyRect,
459 const KisPropagateColorsFilterConfiguration *filterConfig,
460 KoUpdater *progressUpdater)
461{
462 const KisPropagateColorsFilterConfiguration::AlphaChannelMode alphaChannelMode = filterConfig->alphaChannelMode();
463
466 device, applyRect, filterConfig->expansionAmount()
467 );
468 expand(expansionStrategy, progressUpdater);
469 } else {
471 device, applyRect, filterConfig->expansionAmount()
472 );
473 expand(expansionStrategy, progressUpdater);
474 }
475}
476
477template <quint32 DiagonalDistance>
479 const QRect &applyRect,
480 const KisPropagateColorsFilterConfiguration *filterConfig,
481 KoUpdater *progressUpdater)
482{
483 const KisPropagateColorsFilterConfiguration::ExpansionMode expansionMode = filterConfig->expansionMode();
484
486 selectStrategyAndExpand2<DiagonalDistance, true>(device, applyRect, filterConfig, progressUpdater);
487 } else {
488 selectStrategyAndExpand2<DiagonalDistance, false>(device, applyRect, filterConfig, progressUpdater);
489 }
490}
491
493 const QRect &applyRect,
494 const KisFilterConfigurationSP config,
495 KoUpdater *progressUpdater) const
496{
497 const KisPropagateColorsFilterConfiguration *filterConfig =
498 dynamic_cast<const KisPropagateColorsFilterConfiguration*>(config.data());
499
500 Q_ASSERT(device);
501 KIS_SAFE_ASSERT_RECOVER_RETURN(filterConfig);
502
503 const KisPropagateColorsFilterConfiguration::DistanceMetric distanceMetric = filterConfig->distanceMetric();
504
506 selectStrategyAndExpand1<256>(device, applyRect, filterConfig, progressUpdater);
508 selectStrategyAndExpand1<512>(device, applyRect, filterConfig, progressUpdater);
509 } else {
510 // 362 is sqrt(2) * 256, rounded
511 selectStrategyAndExpand1<362>(device, applyRect, filterConfig, progressUpdater);
512 }
513}
514
519
521 const KisPaintDeviceSP,
522 bool) const
523{
524 return new KisPropagateColorsConfigWidget(parent);
525}
526
534
535QRect KisPropagateColorsFilter::neededRect(const QRect &rect, const KisFilterConfigurationSP config, int) const
536{
537 const KisPropagateColorsFilterConfiguration *filterConfig =
538 dynamic_cast<const KisPropagateColorsFilterConfiguration*>(config.data());
539
541 return rect;
542 }
543
544 const qint32 expansionAmount = static_cast<qint32>(std::ceil(filterConfig->expansionAmount()));
545
546 return rect.adjusted(-expansionAmount, -expansionAmount, expansionAmount, expansionAmount);
547}
548
549QRect KisPropagateColorsFilter::changedRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const
550{
551 return neededRect(rect, config, lod);
552}
void selectStrategyAndExpand2(KisPaintDeviceSP device, const QRect &applyRect, const KisPropagateColorsFilterConfiguration *filterConfig, KoUpdater *progressUpdater)
static void swapRowPointers(quint8 **distanceMapRow1, quint8 **distanceMapRow2, quint8 **deviceRow1, quint8 **deviceRow2)
void expand(ExpansionStrategy &expansionStrategy, KoUpdater *progressUpdater)
void selectStrategyAndExpand1(KisPaintDeviceSP device, const QRect &applyRect, const KisPropagateColorsFilterConfiguration *filterConfig, KoUpdater *progressUpdater)
const quint8 OPACITY_TRANSPARENT_U8
const quint8 OPACITY_OPAQUE_U8
qreal distance(const QPointF &p1, const QPointF &p2)
PythonPluginManager * instance
void setSupportsLevelOfDetail(bool value)
KisConfigWidget * createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev, bool useForMasks) const override
QRect neededRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const override
KisFilterConfigurationSP factoryConfiguration(KisResourcesInterfaceSP resourcesInterface) const override
bool needsTransparentPixels(const KisFilterConfigurationSP config, const KoColorSpace *cs) const override
QRect changedRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const override
void processImpl(KisPaintDeviceSP device, const QRect &applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const override
virtual void setOpacity(quint8 *pixels, quint8 alpha, qint32 nPixels) const =0
virtual quint8 opacityU8(const quint8 *pixel) const =0
Definition KoID.h:30
void setProgress(int percent)
Definition KoUpdater.cpp:38
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
const KoID FiltersCategoryColorId("color_filters", ki18nc("The category of color transfer filters, like color to alpha. Noun.", "Colors"))
const KoColorSpace * sourceDeviceColorSpace
static constexpr quint32 infinity
GenericExpansionStrategy(KisPaintDeviceSP sourceDevice, const QRect &applyRect, qreal expansionAmount)
void updatePixel(quint32 *distancePixel, quint8 *devicePixel, const quint32 *neighborDistancePixel1, const quint8 *neighborDevicePixel1, const quint32 *neighborDistancePixel2, const quint8 *neighborDevicePixel2, quint32 relativeDistance1, quint32 relativeDistance2) const
void initializePixel(quint32 *distancePixel, quint8 *devicePixel) const
void setPixel(quint32 *distancePixel, quint8 *devicePixel, quint32 distance, const quint8 *neighborDevicePixel) const
void updatePixel(quint32 *distancePixel, quint8 *devicePixel, const quint32 *neighborDistancePixel1, const quint8 *neighborDevicePixel1, const quint32 *neighborDistancePixel2, const quint8 *neighborDevicePixel2, const quint32 *neighborDistancePixel3, const quint8 *neighborDevicePixel3, quint32 relativeDistance1, quint32 relativeDistance2, quint32 relativeDistance3) const
static constexpr quint32 orthogonalDistance
void updatePixel(quint32 *distancePixel, quint8 *devicePixel, const quint32 *neighborDistancePixel, const quint8 *neighborDevicePixel, quint32 relativeDistance) const
static constexpr quint32 diagonalDistance
void updatePixel(quint32 *distancePixel, quint8 *devicePixel, const quint32 *neighborDistancePixel1, const quint8 *neighborDevicePixel1, const quint32 *neighborDistancePixel2, const quint8 *neighborDevicePixel2, const quint32 *neighborDistancePixel3, const quint8 *neighborDevicePixel3, const quint32 *neighborDistancePixel4, const quint8 *neighborDevicePixel4, quint32 relativeDistance1, quint32 relativeDistance2, quint32 relativeDistance3, quint32 relativeDistance4) const
void setSupportsThreading(bool v)
void setSupportsAdjustmentLayers(bool v)
void setSupportsPainting(bool v)
static constexpr qint32 maximumProgress
static constexpr qint32 scaledHalfUnit
ScaledProgress(qint32 steps, KoUpdater *progressUpdater)