Krita Source Code Documentation
Loading...
Searching...
No Matches
KritaUtils Namespace Reference

Classes

struct  ExportFileJob
 
struct  is_appendable_container
 
struct  is_container
 

Enumerations

enum  BackgroudSavingStartResult {
  Success = 0 , Failure = 1 , AnotherSavingInProgress = 2 , ImageLockFailure = 3 ,
  Cancelled = 4
}
 
enum  DeviceCopyMode { CopySnapshot = 0 , CopyAllFrames }
 
enum  SaveFlag { SaveNone = 0 , SaveShowWarnings = 0x1 , SaveIsExporting = 0x2 , SaveInAutosaveMode = 0x4 }
 
enum  ThresholdMode { ThresholdNone = 0 , ThresholdFloor , ThresholdCeil , ThresholdMaxOut }
 

Functions

template<typename Func , typename Job >
void addJobBarrier (QVector< Job * > &jobs, Func func)
 
template<typename Func , typename Job >
void addJobBarrier (QVector< Job * > &jobs, int lod, Func func)
 
template<typename Func , typename Job >
void addJobBarrierExclusive (QVector< Job * > &jobs, Func func)
 
template<typename Func , typename Job >
void addJobBarrierExclusiveNoCancel (QVector< Job * > &jobs, Func func)
 
template<typename Func , typename Job >
void addJobBarrierNoCancel (QVector< Job * > &jobs, Func func)
 
template<typename Func , typename Job >
void addJobConcurrent (QVector< Job * > &jobs, Func func)
 
template<typename Func , typename Job >
void addJobConcurrent (QVector< Job * > &jobs, int lod, Func func)
 
template<typename Func , typename Job >
void addJobConcurrentNoCancel (QVector< Job * > &jobs, Func func)
 
template<typename Func , typename Job >
void addJobSequential (QVector< Job * > &jobs, Func func)
 
template<typename Func , typename Job >
void addJobSequential (QVector< Job * > &jobs, int lod, Func func)
 
template<typename Func , typename Job >
void addJobSequentialExclusive (QVector< Job * > &jobs, Func func)
 
template<typename Func , typename Job >
void addJobSequentialExclusive (QVector< Job * > &jobs, int lod, Func func)
 
template<typename Func , typename Job >
void addJobSequentialExclusiveNoCancel (QVector< Job * > &jobs, Func func)
 
template<typename Func , typename Job >
void addJobSequentialNoCancel (QVector< Job * > &jobs, Func func)
 
template<typename Func , typename Job >
void addJobUniquelyConcurrent (QVector< Job * > &jobs, Func func)
 
template<typename Func , typename Job >
void addJobUniquelyConcurrent (QVector< Job * > &jobs, int lod, Func func)
 
template<typename Func , typename Job >
void addJobUniquelyConcurrentNoCancel (QVector< Job * > &jobs, Func func)
 
void applyToAlpha8Device (KisPaintDeviceSP dev, const QRect &rc, std::function< void(quint8)> func)
 
bool checkInTriangle (const QRectF &rect, const QPolygonF &triangle)
 
bool compareChannelFlags (QBitArray f1, QBitArray f2)
 
template<class T >
bool compareListsUnordered (const QList< T > &a, const QList< T > &b)
 
QImage convertQImageToGrayA (const QImage &image)
 
qreal estimatePortionOfTransparentPixels (KisPaintDeviceSP dev, const QRect &rect, qreal samplePortion)
 
boost::optional< QPointF > fetchControlPoint (KoPathPoint *pt, bool takeFirst)
 
void filterAlpha8Device (KisPaintDeviceSP dev, const QRect &rc, std::function< quint8(quint8)> func)
 
template<class C , typename KeepIfFunction >
auto filterContainer (C &container, KeepIfFunction keepIf) -> decltype(bool(keepIf(container[0])), void())
 
template<class C >
void makeContainerUnique (C &container)
 
void makeSymmetric (KoPathPoint *pt, bool copyFromFirst)
 
qreal KRITAIMAGE_EXPORT maxDimensionPortion (const QRectF &bounds, qreal portion, qreal minValue)
 
QBitArray mergeChannelFlags (const QBitArray &childFlags, const QBitArray &parentFlags)
 
qreal mergeOpacityF (qreal opacity, qreal parentOpacity)
 
quint8 mergeOpacityU8 (quint8 opacity, quint8 parentOpacity)
 
void mirrorDab (Qt::Orientation dir, const QPoint &center, KisRenderedDab *dab, bool skipMirrorPixels)
 
void mirrorDab (Qt::Orientation dir, const QPointF &center, KisRenderedDab *dab, bool skipMirrorPixels)
 
void mirrorPoint (Qt::Orientation dir, const QPoint &center, QPointF *pt)
 
void mirrorPoint (Qt::Orientation dir, const QPointF &center, QPointF *pt)
 
void mirrorRect (Qt::Orientation dir, const QPoint &center, QRect *rc)
 
void mirrorRect (Qt::Orientation dir, const QPointF &center, QRect *rc)
 
KisNodeSP nearestNodeAfterRemoval (KisNodeSP node)
 
QSize optimalPatchSize ()
 
QTransform pathShapeBooleanSpaceWorkaround (KisImageSP image)
 
QString KRITAIMAGE_EXPORT prettyFormatReal (qreal value)
 
template<class PixelProcessor >
void processTwoDevices (const QRect &rc, KisRandomConstAccessorSP srcIt, KisRandomAccessorSP dstIt, const int srcPixelSize, const int dstPixelSize, PixelProcessor pixelProcessor)
 
template<class PixelProcessor >
void processTwoDevicesWithStrides (const QRect &rc, KisRandomConstAccessorSP srcIt, KisRandomAccessorSP dstIt, PixelProcessor pixelProcessor)
 
QVector< QPoint > rasterizeHLine (const QPoint &startPoint, const QPoint &endPoint)
 
template<typename Visitor >
void rasterizeHLine (const QPoint &startPoint, const QPoint &endPoint, Visitor visitor)
 
QVector< QPoint > rasterizeLineDDA (const QPoint &startPoint, const QPoint &endPoint)
 
template<typename Visitor >
void rasterizeLineDDA (const QPoint &startPoint, const QPoint &endPoint, Visitor visitor)
 
QVector< QPoint > rasterizePolygonDDA (const QVector< QPoint > &polygonPoints)
 
template<typename Visitor >
void rasterizePolygonDDA (const QVector< QPoint > &polygonPoints, Visitor visitor)
 
QVector< QPoint > rasterizePolylineDDA (const QVector< QPoint > &polylinePoints)
 
template<typename Visitor >
void rasterizePolylineDDA (const QVector< QPoint > &polylinePoints, Visitor visitor)
 
QVector< QPoint > rasterizeVLine (const QPoint &startPoint, const QPoint &endPoint)
 
template<typename Visitor >
void rasterizeVLine (const QPoint &startPoint, const QPoint &endPoint, Visitor visitor)
 
void renderExactRect (QPainter *p, const QRect &rc)
 
void renderExactRect (QPainter *p, const QRect &rc, const QPen &pen)
 
QString resolveAbsoluteFilePath (const QString &baseDir, const QString &filePath)
 Resolve absolute file path from a file path and base dir.
 
void restoreControlPoint (KoPathPoint *pt, bool restoreFirst, boost::optional< QPointF > savedPoint)
 
QList< QPainterPath > splitDisjointPaths (const QPainterPath &path)
 
KisRegion splitPath (const QPainterPath &path)
 
QVector< QRect > splitRectIntoPatches (const QRect &rc, const QSize &patchSize)
 
QVector< QRect > splitRectIntoPatchesTight (const QRect &rc, const QSize &patchSize)
 
QVector< QRect > splitRegionIntoPatches (const KisRegion &region, const QSize &patchSize)
 
QVector< QRect > KRITAIMAGE_EXPORT splitRegionIntoPatches (const QRegion &region, const QSize &patchSize)
 
KisRegion splitTriangles (const QPointF &center, const QVector< QPointF > &points)
 
void thresholdOpacity (KisPaintDeviceSP device, const QRect &rect, ThresholdMode mode)
 
void thresholdOpacityAlpha8 (KisPaintDeviceSP device, const QRect &rect, ThresholdMode mode)
 
QString KRITAIMAGE_EXPORT toLocalizedOnOff (bool value)
 
QPainterPath tryCloseTornSubpathsAfterIntersection (QPainterPath path)
 
KisImportExportErrorCode workaroundUnsuitableImageColorSpace (KisImageSP image, KisImportUserFeedbackInterface *feedbackInterface, KisImageBarrierLock &lock)
 

Enumeration Type Documentation

◆ BackgroudSavingStartResult

Enumerator
Success 
Failure 
AnotherSavingInProgress 
ImageLockFailure 
Cancelled 

Definition at line 31 of file KisImportExportUtils.h.

31 {
32 Success = 0,
33 Failure = 1,
36 Cancelled = 4
37};

◆ DeviceCopyMode

Enumerator
CopySnapshot 
CopyAllFrames 

Definition at line 51 of file kis_paint_device.h.

◆ SaveFlag

Enumerator
SaveNone 
SaveShowWarnings 
SaveIsExporting 
SaveInAutosaveMode 

Definition at line 24 of file KisImportExportUtils.h.

◆ ThresholdMode

Enumerator
ThresholdNone 
ThresholdFloor 
ThresholdCeil 
ThresholdMaxOut 

Definition at line 131 of file krita_utils.h.

131 {
132 ThresholdNone = 0,
136 };

Function Documentation

◆ addJobBarrier() [1/2]

template<typename Func , typename Job >
void KritaUtils::addJobBarrier ( QVector< Job * > & jobs,
Func func )

◆ addJobBarrier() [2/2]

template<typename Func , typename Job >
void KritaUtils::addJobBarrier ( QVector< Job * > & jobs,
int lod,
Func func )

Definition at line 71 of file KisRunnableStrokeJobUtils.h.

71 {
73 data->setLevelOfDetailOverride(lod);
74 jobs.append(data);
75}

References KisStrokeJobData::BARRIER.

◆ addJobBarrierExclusive()

template<typename Func , typename Job >
void KritaUtils::addJobBarrierExclusive ( QVector< Job * > & jobs,
Func func )

◆ addJobBarrierExclusiveNoCancel()

template<typename Func , typename Job >
void KritaUtils::addJobBarrierExclusiveNoCancel ( QVector< Job * > & jobs,
Func func )

Definition at line 115 of file KisRunnableStrokeJobUtils.h.

115 {
117 data->setCancellable(false);
118 jobs.append(data);
119}

References KisStrokeJobData::BARRIER, and KisStrokeJobData::EXCLUSIVE.

◆ addJobBarrierNoCancel()

template<typename Func , typename Job >
void KritaUtils::addJobBarrierNoCancel ( QVector< Job * > & jobs,
Func func )

Definition at line 108 of file KisRunnableStrokeJobUtils.h.

108 {
110 data->setCancellable(false);
111 jobs.append(data);
112}

References KisStrokeJobData::BARRIER.

◆ addJobConcurrent() [1/2]

template<typename Func , typename Job >
void KritaUtils::addJobConcurrent ( QVector< Job * > & jobs,
Func func )

◆ addJobConcurrent() [2/2]

template<typename Func , typename Job >
void KritaUtils::addJobConcurrent ( QVector< Job * > & jobs,
int lod,
Func func )

Definition at line 64 of file KisRunnableStrokeJobUtils.h.

64 {
66 data->setLevelOfDetailOverride(lod);
67 jobs.append(data);
68}

References KisStrokeJobData::CONCURRENT.

◆ addJobConcurrentNoCancel()

template<typename Func , typename Job >
void KritaUtils::addJobConcurrentNoCancel ( QVector< Job * > & jobs,
Func func )

Definition at line 101 of file KisRunnableStrokeJobUtils.h.

101 {
103 data->setCancellable(false);
104 jobs.append(data);
105}

References KisStrokeJobData::CONCURRENT.

◆ addJobSequential() [1/2]

template<typename Func , typename Job >
void KritaUtils::addJobSequential ( QVector< Job * > & jobs,
Func func )

◆ addJobSequential() [2/2]

template<typename Func , typename Job >
void KritaUtils::addJobSequential ( QVector< Job * > & jobs,
int lod,
Func func )

Definition at line 50 of file KisRunnableStrokeJobUtils.h.

50 {
52 data->setLevelOfDetailOverride(lod);
53 jobs.append(data);
54}

References KisStrokeJobData::SEQUENTIAL.

◆ addJobSequentialExclusive() [1/2]

template<typename Func , typename Job >
void KritaUtils::addJobSequentialExclusive ( QVector< Job * > & jobs,
Func func )

◆ addJobSequentialExclusive() [2/2]

template<typename Func , typename Job >
void KritaUtils::addJobSequentialExclusive ( QVector< Job * > & jobs,
int lod,
Func func )

Definition at line 57 of file KisRunnableStrokeJobUtils.h.

57 {
59 data->setLevelOfDetailOverride(lod);
60 jobs.append(data);
61}

References KisStrokeJobData::EXCLUSIVE, and KisStrokeJobData::SEQUENTIAL.

◆ addJobSequentialExclusiveNoCancel()

template<typename Func , typename Job >
void KritaUtils::addJobSequentialExclusiveNoCancel ( QVector< Job * > & jobs,
Func func )

Definition at line 93 of file KisRunnableStrokeJobUtils.h.

93 {
95 data->setCancellable(false);
96 jobs.append(data);
97}

References KisStrokeJobData::EXCLUSIVE, and KisStrokeJobData::SEQUENTIAL.

◆ addJobSequentialNoCancel()

template<typename Func , typename Job >
void KritaUtils::addJobSequentialNoCancel ( QVector< Job * > & jobs,
Func func )

Definition at line 86 of file KisRunnableStrokeJobUtils.h.

86 {
88 data->setCancellable(false);
89 jobs.append(data);
90}

References KisStrokeJobData::SEQUENTIAL.

◆ addJobUniquelyConcurrent() [1/2]

template<typename Func , typename Job >
void KritaUtils::addJobUniquelyConcurrent ( QVector< Job * > & jobs,
Func func )

◆ addJobUniquelyConcurrent() [2/2]

template<typename Func , typename Job >
void KritaUtils::addJobUniquelyConcurrent ( QVector< Job * > & jobs,
int lod,
Func func )

Definition at line 78 of file KisRunnableStrokeJobUtils.h.

78 {
80 data->setLevelOfDetailOverride(lod);
81 jobs.append(data);
82}

References KisStrokeJobData::UNIQUELY_CONCURRENT.

◆ addJobUniquelyConcurrentNoCancel()

template<typename Func , typename Job >
void KritaUtils::addJobUniquelyConcurrentNoCancel ( QVector< Job * > & jobs,
Func func )

Definition at line 122 of file KisRunnableStrokeJobUtils.h.

122 {
124 data->setCancellable(false);
125 jobs.append(data);
126}

References KisStrokeJobData::UNIQUELY_CONCURRENT.

◆ applyToAlpha8Device()

void KRITAIMAGE_EXPORT KritaUtils::applyToAlpha8Device ( KisPaintDeviceSP dev,
const QRect & rc,
std::function< void(quint8)> func )

Definition at line 324 of file krita_utils.cpp.

324 {
325 KisSequentialConstIterator dstIt(dev, rc);
326 while (dstIt.nextPixel()) {
327 const quint8 *dstPtr = dstIt.rawDataConst();
328 func(*dstPtr);
329 }
330 }

References KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nextPixel(), and KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::rawDataConst().

◆ checkInTriangle()

bool KritaUtils::checkInTriangle ( const QRectF & rect,
const QPolygonF & triangle )

Definition at line 97 of file krita_utils.cpp.

99 {
100 return triangle.intersected(rect).boundingRect().isValid();
101 }

◆ compareChannelFlags()

bool KRITAIMAGE_EXPORT KritaUtils::compareChannelFlags ( QBitArray f1,
QBitArray f2 )

Definition at line 260 of file krita_utils.cpp.

261 {
262 if (f1.isNull() && f2.isNull()) return true;
263
264 if (f1.isNull()) {
265 f1.fill(true, f2.size());
266 }
267
268 if (f2.isNull()) {
269 f2.fill(true, f1.size());
270 }
271
272 return f1 == f2;
273 }

◆ compareListsUnordered()

template<class T >
bool KritaUtils::compareListsUnordered ( const QList< T > & a,
const QList< T > & b )

Definition at line 17 of file krita_container_utils.h.

17 {
18 if (a.size() != b.size()) return false;
19
20 Q_FOREACH(const T &t, a) {
21 if (!b.contains(t)) return false;
22 }
23
24 return true;
25}

◆ convertQImageToGrayA()

QImage KRITAIMAGE_EXPORT KritaUtils::convertQImageToGrayA ( const QImage & image)

Definition at line 307 of file krita_utils.cpp.

308 {
309 QImage dstImage(image.size(), QImage::Format_ARGB32);
310
311 // TODO: if someone feel bored, a more optimized version of this would be welcome
312 const QSize size = image.size();
313 for(int y = 0; y < size.height(); ++y) {
314 for(int x = 0; x < size.width(); ++x) {
315 const QRgb pixel = image.pixel(x,y);
316 const int gray = qGray(pixel);
317 dstImage.setPixel(x, y, qRgba(gray, gray, gray, qAlpha(pixel)));
318 }
319 }
320
321 return dstImage;
322 }
unsigned int QRgb

◆ estimatePortionOfTransparentPixels()

qreal KRITAIMAGE_EXPORT KritaUtils::estimatePortionOfTransparentPixels ( KisPaintDeviceSP dev,
const QRect & rect,
qreal samplePortion )

Definition at line 340 of file krita_utils.cpp.

340 {
341 const KoColorSpace *cs = dev->colorSpace();
342
343 const qreal linearPortion = std::sqrt(samplePortion);
344 const qreal ratio = qreal(rect.width()) / rect.height();
345 const int xStep = qMax(1, qRound(1.0 / linearPortion * ratio));
346 const int yStep = qMax(1, qRound(1.0 / linearPortion / ratio));
347
348 int numTransparentPixels = 0;
349 int numPixels = 0;
350
352 for (int y = rect.y(); y <= rect.bottom(); y += yStep) {
353 for (int x = rect.x(); x <= rect.right(); x += xStep) {
354 it->moveTo(x, y);
355 const quint8 alpha = cs->opacityU8(it->rawDataConst());
356
357 if (alpha != OPACITY_OPAQUE_U8) {
358 numTransparentPixels++;
359 }
360
361 numPixels++;
362 }
363 }
364
365 if (numPixels == 0) {
366 return 0; // avoid dividing by 0
367 }
368 return qreal(numTransparentPixels) / numPixels;
369 }
const quint8 OPACITY_OPAQUE_U8
virtual const quint8 * rawDataConst() const =0
KisRandomConstAccessorSP createRandomConstAccessorNG() const
const KoColorSpace * colorSpace() const
virtual void moveTo(qint32 x, qint32 y)=0
virtual quint8 opacityU8(const quint8 *pixel) const =0

References KisPaintDevice::colorSpace(), KisPaintDevice::createRandomConstAccessorNG(), KisRandomConstAccessorNG::moveTo(), OPACITY_OPAQUE_U8, KoColorSpace::opacityU8(), and KisBaseConstAccessor::rawDataConst().

◆ fetchControlPoint()

boost::optional< QPointF > KritaUtils::fetchControlPoint ( KoPathPoint * pt,
bool takeFirst )

Definition at line 11 of file KoPathMergeUtils.cpp.

12{
13 boost::optional<QPointF> result;
14
15 if (takeFirst) {
16 if (pt->activeControlPoint1()) {
17 result = pt->controlPoint1();
18 }
19 } else {
20 if (pt->activeControlPoint2()) {
21 result = pt->controlPoint2();
22 }
23 }
24
25 return result;
26}
QPointF controlPoint1
bool activeControlPoint1
bool activeControlPoint2
QPointF controlPoint2

References KoPathPoint::activeControlPoint1, KoPathPoint::activeControlPoint2, KoPathPoint::controlPoint1, and KoPathPoint::controlPoint2.

◆ filterAlpha8Device()

void KRITAIMAGE_EXPORT KritaUtils::filterAlpha8Device ( KisPaintDeviceSP dev,
const QRect & rc,
std::function< quint8(quint8)> func )

Definition at line 332 of file krita_utils.cpp.

332 {
333 KisSequentialIterator dstIt(dev, rc);
334 while (dstIt.nextPixel()) {
335 quint8 *dstPtr = dstIt.rawData();
336 *dstPtr = func(*dstPtr);
337 }
338 }

References KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nextPixel(), and KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::rawData().

◆ filterContainer()

template<class C , typename KeepIfFunction >
auto KritaUtils::filterContainer ( C & container,
KeepIfFunction keepIf ) -> decltype(bool(keepIf(container[0])), void())

Definition at line 39 of file krita_container_utils.h.

40 {
41
42 auto newEnd = std::remove_if(container.begin(), container.end(), [keepIf] (typename C::reference p) { return !keepIf(p); });
43 while (newEnd != container.end()) {
44 newEnd = container.erase(newEnd);
45 }
46}
const Params2D p

References p.

◆ makeContainerUnique()

template<class C >
void KritaUtils::makeContainerUnique ( C & container)

Definition at line 28 of file krita_container_utils.h.

28 {
29 std::sort(container.begin(), container.end());
30 auto newEnd = std::unique(container.begin(), container.end());
31
32 while (newEnd != container.end()) {
33 newEnd = container.erase(newEnd);
34 }
35}

◆ makeSymmetric()

void KritaUtils::makeSymmetric ( KoPathPoint * pt,
bool copyFromFirst )

Definition at line 28 of file KoPathMergeUtils.cpp.

29{
30 if (copyFromFirst) {
31 if (pt->activeControlPoint1()) {
32 pt->setControlPoint2(2.0 * pt->point() - pt->controlPoint1());
33 }
34 } else {
35 if (pt->activeControlPoint2()) {
36 pt->setControlPoint1(2.0 * pt->point() - pt->controlPoint2());
37 }
38 }
39
41}
void setControlPoint1(const QPointF &point)
Set the control point 1.
QPointF point
void setProperty(PointProperty property)
Sets a single property of a point.
void setControlPoint2(const QPointF &point)
Set the control point 2.
@ IsSymmetric
it is symmetric, like smooth but control points have same distance to point
Definition KoPathPoint.h:42

References KoPathPoint::activeControlPoint1, KoPathPoint::activeControlPoint2, KoPathPoint::controlPoint1, KoPathPoint::controlPoint2, KoPathPoint::IsSymmetric, KoPathPoint::point, KoPathPoint::setControlPoint1(), KoPathPoint::setControlPoint2(), and KoPathPoint::setProperty().

◆ maxDimensionPortion()

qreal KRITAIMAGE_EXPORT KritaUtils::maxDimensionPortion ( const QRectF & bounds,
qreal portion,
qreal minValue )

Definition at line 190 of file krita_utils.cpp.

191 {
192 qreal maxDimension = qMax(bounds.width(), bounds.height());
193 return qMax(portion * maxDimension, minValue);
194 }
#define bounds(x, a, b)

References bounds.

◆ mergeChannelFlags()

QBitArray KRITAIMAGE_EXPORT KritaUtils::mergeChannelFlags ( const QBitArray & childFlags,
const QBitArray & parentFlags )

Definition at line 243 of file krita_utils.cpp.

244 {
245 QBitArray flags = childFlags;
246
247 if (!flags.isEmpty() &&
248 !parentFlags.isEmpty() &&
249 flags.size() == parentFlags.size()) {
250
251 flags &= parentFlags;
252
253 } else if (!parentFlags.isEmpty()) {
254 flags = parentFlags;
255 }
256
257 return flags;
258 }

◆ mergeOpacityF()

qreal KRITAIMAGE_EXPORT KritaUtils::mergeOpacityF ( qreal opacity,
qreal parentOpacity )

Definition at line 235 of file krita_utils.cpp.

236 {
237 if (!qFuzzyCompare(parentOpacity, OPACITY_OPAQUE_F)) {
238 opacity *= parentOpacity;
239 }
240 return opacity;
241 }
const qreal OPACITY_OPAQUE_F
static bool qFuzzyCompare(half p1, half p2)

References OPACITY_OPAQUE_F, and qFuzzyCompare().

◆ mergeOpacityU8()

quint8 KRITAIMAGE_EXPORT KritaUtils::mergeOpacityU8 ( quint8 opacity,
quint8 parentOpacity )

Definition at line 227 of file krita_utils.cpp.

228 {
229 if (parentOpacity != OPACITY_OPAQUE_U8) {
230 opacity = (int(opacity) * parentOpacity) / OPACITY_OPAQUE_U8;
231 }
232 return opacity;
233 }

References OPACITY_OPAQUE_U8.

◆ mirrorDab() [1/2]

void KRITAIMAGE_EXPORT KritaUtils::mirrorDab ( Qt::Orientation dir,
const QPoint & center,
KisRenderedDab * dab,
bool skipMirrorPixels )

Definition at line 371 of file krita_utils.cpp.

372 {
373 const QRect rc = dab->realBounds();
374
375 if (dir == Qt::Horizontal) {
376 const int mirrorX = -((rc.x() + rc.width()) - center.x()) + center.x();
377
378 if (!skipMirrorPixels) {
379 dab->device->mirror(true, false);
380 }
381 dab->offset.rx() = mirrorX;
382 } else /* if (dir == Qt::Vertical) */ {
383 const int mirrorY = -((rc.y() + rc.height()) - center.y()) + center.y();
384
385 if (!skipMirrorPixels) {
386 dab->device->mirror(false, true);
387 }
388 dab->offset.ry() = mirrorY;
389 }
390 }
void mirror(bool horizontal, bool vertical)
KisFixedPaintDeviceSP device
QRect realBounds() const

References KisRenderedDab::device, KisFixedPaintDevice::mirror(), KisRenderedDab::offset, and KisRenderedDab::realBounds().

◆ mirrorDab() [2/2]

void KRITAIMAGE_EXPORT KritaUtils::mirrorDab ( Qt::Orientation dir,
const QPointF & center,
KisRenderedDab * dab,
bool skipMirrorPixels )

Definition at line 392 of file krita_utils.cpp.

393 {
394 const QRect rc = dab->realBounds();
395
396 if (dir == Qt::Horizontal) {
397 const int mirrorX = -((rc.x() + rc.width()) - center.x()) + center.x();
398
399 if (!skipMirrorPixels) {
400 dab->device->mirror(true, false);
401 }
402 dab->offset.rx() = mirrorX;
403 } else /* if (dir == Qt::Vertical) */ {
404 const int mirrorY = -((rc.y() + rc.height()) - center.y()) + center.y();
405
406 if (!skipMirrorPixels) {
407 dab->device->mirror(false, true);
408 }
409 dab->offset.ry() = mirrorY;
410 }
411 }

References KisRenderedDab::device, KisFixedPaintDevice::mirror(), KisRenderedDab::offset, and KisRenderedDab::realBounds().

◆ mirrorPoint() [1/2]

void KRITAIMAGE_EXPORT KritaUtils::mirrorPoint ( Qt::Orientation dir,
const QPoint & center,
QPointF * pt )

Definition at line 435 of file krita_utils.cpp.

436 {
437 if (dir == Qt::Horizontal) {
438 pt->rx() = -(pt->x() - qreal(center.x())) + center.x();
439 } else /* if (dir == Qt::Vertical) */ {
440 pt->ry() = -(pt->y() - qreal(center.y())) + center.y();
441 }
442 }

◆ mirrorPoint() [2/2]

void KRITAIMAGE_EXPORT KritaUtils::mirrorPoint ( Qt::Orientation dir,
const QPointF & center,
QPointF * pt )

Definition at line 444 of file krita_utils.cpp.

445 {
446 if (dir == Qt::Horizontal) {
447 pt->rx() = -(pt->x() - qreal(center.x())) + center.x();
448 } else /* if (dir == Qt::Vertical) */ {
449 pt->ry() = -(pt->y() - qreal(center.y())) + center.y();
450 }
451 }

◆ mirrorRect() [1/2]

void KRITAIMAGE_EXPORT KritaUtils::mirrorRect ( Qt::Orientation dir,
const QPoint & center,
QRect * rc )

Definition at line 413 of file krita_utils.cpp.

414 {
415 if (dir == Qt::Horizontal) {
416 const int mirrorX = -((rc->x() + rc->width()) - center.x()) + center.x();
417 rc->moveLeft(mirrorX);
418 } else /* if (dir == Qt::Vertical) */ {
419 const int mirrorY = -((rc->y() + rc->height()) - center.y()) + center.y();
420 rc->moveTop(mirrorY);
421 }
422 }

◆ mirrorRect() [2/2]

void KRITAIMAGE_EXPORT KritaUtils::mirrorRect ( Qt::Orientation dir,
const QPointF & center,
QRect * rc )

Definition at line 424 of file krita_utils.cpp.

425 {
426 if (dir == Qt::Horizontal) {
427 const int mirrorX = -((rc->x() + rc->width()) - center.x()) + center.x();
428 rc->moveLeft(mirrorX);
429 } else /* if (dir == Qt::Vertical) */ {
430 const int mirrorY = -((rc->y() + rc->height()) - center.y()) + center.y();
431 rc->moveTop(mirrorY);
432 }
433 }

◆ nearestNodeAfterRemoval()

KisNodeSP KRITAIMAGE_EXPORT KritaUtils::nearestNodeAfterRemoval ( KisNodeSP node)

Definition at line 279 of file krita_utils.cpp.

280 {
281 KisNodeSP newNode = node->nextSibling();
282
283 if (!newNode) {
284 newNode = node->prevSibling();
285 }
286
287 if (!newNode) {
288 newNode = node->parent();
289 }
290
291 return newNode;
292 }
KisNodeSP prevSibling() const
Definition kis_node.cpp:402
KisNodeWSP parent
Definition kis_node.cpp:86
KisNodeSP nextSibling() const
Definition kis_node.cpp:408

References KisNode::nextSibling(), KisNode::parent, and KisNode::prevSibling().

◆ optimalPatchSize()

QSize KRITAIMAGE_EXPORT KritaUtils::optimalPatchSize ( )

Definition at line 35 of file krita_utils.cpp.

36 {
37 KisImageConfig cfg(true);
38 return QSize(cfg.updatePatchWidth(),
39 cfg.updatePatchHeight());
40 }

References KisImageConfig::updatePatchHeight(), and KisImageConfig::updatePatchWidth().

◆ pathShapeBooleanSpaceWorkaround()

QTransform KRITAIMAGE_EXPORT KritaUtils::pathShapeBooleanSpaceWorkaround ( KisImageSP image)

Returns a special transformation that converts vector shape coordinates ('pt') into a special coordinate space, where all path boolean operations should happen.

The problem is that Qt's path boolean operation do not support curves, therefore all the curves are converted into lines (see QPathSegments::addPath()). The curves are split into lines using absolute size of the curve for the threshold. Therefore, when applying boolean operations we should convert them into 'image pixel' coordinate space first.

See https://bugs.kde.org/show_bug.cgi?id=411056

Definition at line 453 of file krita_utils.cpp.

454 {
455 return QTransform::fromScale(image->xRes(), image->yRes());
456 }
double xRes() const
double yRes() const

References KisImage::xRes(), and KisImage::yRes().

◆ prettyFormatReal()

QString KRITAIMAGE_EXPORT KritaUtils::prettyFormatReal ( qreal value)

Definition at line 185 of file krita_utils.cpp.

186 {
187 return QLocale().toString(value, 'f', 1);
188 }
float value(const T *src, size_t ch)

References value().

◆ processTwoDevices()

template<class PixelProcessor >
void KritaUtils::processTwoDevices ( const QRect & rc,
KisRandomConstAccessorSP srcIt,
KisRandomAccessorSP dstIt,
const int srcPixelSize,
const int dstPixelSize,
PixelProcessor pixelProcessor )

this is a special helper function for iterating through pixels in an extremely efficient way. One should either pass a functor or a lambda to it.

Definition at line 22 of file KisFastDeviceProcessingUtils.h.

28{
29 qint32 dstY = rc.y();
30 qint32 rowsRemaining = rc.height();
31
32 while (rowsRemaining > 0) {
33 qint32 dstX = rc.x();
34
35 qint32 numContiguousSrcRows = srcIt->numContiguousRows(dstY);
36 qint32 numContiguousDstRows = dstIt->numContiguousRows(dstY);
37 qint32 rows = std::min({rowsRemaining, numContiguousSrcRows, numContiguousDstRows});
38
39 qint32 columnsRemaining = rc.width();
40
41 while (columnsRemaining > 0) {
42
43 qint32 numContiguousSrcColumns = srcIt->numContiguousColumns(dstX);
44 qint32 numContiguousDstColumns = dstIt->numContiguousColumns(dstX);
45 qint32 columns = std::min({columnsRemaining, numContiguousSrcColumns, numContiguousDstColumns});
46
47 qint32 dstRowStride = dstIt->rowStride(dstX, dstY);
48 qint32 srcRowStride = srcIt->rowStride(dstX, dstY);
49
50 dstIt->moveTo(dstX, dstY);
51 srcIt->moveTo(dstX, dstY);
52
53 quint8 *dstRowStart = dstIt->rawData();
54 const quint8 *srcRowStart = srcIt->rawDataConst();
55
56 for (int i = 0; i < rows; i++) {
57 const quint8 *srcPtr = reinterpret_cast<const quint8*>(srcRowStart);
58 quint8 *dstPtr = reinterpret_cast<quint8*>(dstRowStart);
59
60 for (int j = 0; j < columns; j++) {
61 pixelProcessor(srcPtr, dstPtr);
62
63 srcPtr += srcPixelSize;
64 dstPtr += dstPixelSize;
65 }
66
67 srcRowStart += srcRowStride;
68 dstRowStart += dstRowStride;
69 }
70
71 dstX += columns;
72 columnsRemaining -= columns;
73 }
74
75 dstY += rows;
76 rowsRemaining -= rows;
77 }
78}
virtual quint8 * rawData()=0
virtual qint32 rowStride(qint32 x, qint32 y) const =0
virtual qint32 numContiguousRows(qint32 y) const =0
virtual qint32 numContiguousColumns(qint32 x) const =0

References KisRandomConstAccessorNG::moveTo(), KisRandomConstAccessorNG::numContiguousColumns(), KisRandomConstAccessorNG::numContiguousRows(), KisBaseAccessor::rawData(), KisBaseConstAccessor::rawDataConst(), and KisRandomConstAccessorNG::rowStride().

◆ processTwoDevicesWithStrides()

template<class PixelProcessor >
void KritaUtils::processTwoDevicesWithStrides ( const QRect & rc,
KisRandomConstAccessorSP srcIt,
KisRandomAccessorSP dstIt,
PixelProcessor pixelProcessor )

this is a special helper function for iterating through pixels in an extremely efficient way using strides. One should either pass a functor or a lambda to it.

Definition at line 86 of file KisFastDeviceProcessingUtils.h.

90{
91 qint32 dstY = rc.y();
92 qint32 rowsRemaining = rc.height();
93
94 while (rowsRemaining > 0) {
95 qint32 dstX = rc.x();
96
97 qint32 numContiguousSrcRows = srcIt->numContiguousRows(dstY);
98 qint32 numContiguousDstRows = dstIt->numContiguousRows(dstY);
99 qint32 rows = std::min({rowsRemaining, numContiguousSrcRows, numContiguousDstRows});
100
101 qint32 columnsRemaining = rc.width();
102
103 while (columnsRemaining > 0) {
104
105 qint32 numContiguousSrcColumns = srcIt->numContiguousColumns(dstX);
106 qint32 numContiguousDstColumns = dstIt->numContiguousColumns(dstX);
107 qint32 columns = std::min({columnsRemaining, numContiguousSrcColumns, numContiguousDstColumns});
108
109 qint32 dstRowStride = dstIt->rowStride(dstX, dstY);
110 qint32 srcRowStride = srcIt->rowStride(dstX, dstY);
111
112 dstIt->moveTo(dstX, dstY);
113 srcIt->moveTo(dstX, dstY);
114
115 quint8 *dstRowStart = dstIt->rawData();
116 const quint8 *srcRowStart = srcIt->rawDataConst();
117
118 pixelProcessor(srcRowStart, srcRowStride,
119 dstRowStart, dstRowStride,
120 rows, columns);
121
122 dstX += columns;
123 columnsRemaining -= columns;
124 }
125
126 dstY += rows;
127 rowsRemaining -= rows;
128 }
129}

References KisRandomConstAccessorNG::moveTo(), KisRandomConstAccessorNG::numContiguousColumns(), KisRandomConstAccessorNG::numContiguousRows(), KisBaseAccessor::rawData(), KisBaseConstAccessor::rawDataConst(), and KisRandomConstAccessorNG::rowStride().

◆ rasterizeHLine() [1/2]

QVector< QPoint > KRITAIMAGE_EXPORT KritaUtils::rasterizeHLine ( const QPoint & startPoint,
const QPoint & endPoint )

Definition at line 520 of file krita_utils.cpp.

521 {
522 QVector<QPoint> points;
523 rasterizeHLine(startPoint, endPoint, [&points](const QPoint &point) { points.append(point); });
524 return points;
525 }
QVector< QPoint > rasterizeHLine(const QPoint &startPoint, const QPoint &endPoint)

References rasterizeHLine().

◆ rasterizeHLine() [2/2]

template<typename Visitor >
void KritaUtils::rasterizeHLine ( const QPoint & startPoint,
const QPoint & endPoint,
Visitor visitor )

Definition at line 142 of file krita_utils.h.

143 {
144 QVector<QPoint> points;
145 int startX, endX;
146 if (startPoint.x() < endPoint.x()) {
147 startX = startPoint.x();
148 endX = endPoint.x();
149 } else {
150 startX = endPoint.x();
151 endX = startPoint.x();
152 }
153 for (int x = startX; x <= endX; ++x) {
154 visitor(QPoint(x, startPoint.y()));
155 }
156 }

◆ rasterizeLineDDA() [1/2]

QVector< QPoint > KRITAIMAGE_EXPORT KritaUtils::rasterizeLineDDA ( const QPoint & startPoint,
const QPoint & endPoint )

Definition at line 534 of file krita_utils.cpp.

535 {
536 QVector<QPoint> points;
537 rasterizeLineDDA(startPoint, endPoint, [&points](const QPoint &point) { points.append(point); });
538 return points;
539 }
QVector< QPoint > rasterizeLineDDA(const QPoint &startPoint, const QPoint &endPoint)

References rasterizeLineDDA().

◆ rasterizeLineDDA() [2/2]

template<typename Visitor >
void KritaUtils::rasterizeLineDDA ( const QPoint & startPoint,
const QPoint & endPoint,
Visitor visitor )

Definition at line 176 of file krita_utils.h.

177 {
178 QVector<QPoint> points;
179
180 if (startPoint == endPoint) {
181 visitor(startPoint);
182 return;
183 }
184 if (startPoint.y() == endPoint.y()) {
185 rasterizeHLine(startPoint, endPoint, visitor);
186 return;
187 }
188 if (startPoint.x() == endPoint.x()) {
189 rasterizeVLine(startPoint, endPoint, visitor);
190 return;
191 }
192
193 const QPoint delta = endPoint - startPoint;
194 QPoint currentPosition = startPoint;
195 QPointF currentPositionF = startPoint;
196 qreal m = static_cast<qreal>(delta.y()) / static_cast<qreal>(delta.x());
197 int increment;
198
199 if (std::abs(m) > 1.0) {
200 if (delta.y() > 0) {
201 m = 1.0 / m;
202 increment = 1;
203 } else {
204 m = -1.0 / m;
205 increment = -1;
206 }
207 while (currentPosition.y() != endPoint.y()) {
208 currentPositionF.setX(currentPositionF.x() + m);
209 currentPosition = QPoint(static_cast<int>(qRound(currentPositionF.x())),
210 currentPosition.y() + increment);
211 visitor(currentPosition);
212 }
213 } else {
214 if (delta.x() > 0) {
215 increment = 1;
216 } else {
217 increment = -1;
218 m = -m;
219 }
220 while (currentPosition.x() != endPoint.x()) {
221 currentPositionF.setY(currentPositionF.y() + m);
222 currentPosition = QPoint(currentPosition.x() + increment,
223 static_cast<int>(qRound(currentPositionF.y())));
224 visitor(currentPosition);
225 }
226 }
227 }
QVector< QPoint > rasterizeVLine(const QPoint &startPoint, const QPoint &endPoint)

References rasterizeHLine(), and rasterizeVLine().

◆ rasterizePolygonDDA() [1/2]

QVector< QPoint > KRITAIMAGE_EXPORT KritaUtils::rasterizePolygonDDA ( const QVector< QPoint > & polygonPoints)

Definition at line 548 of file krita_utils.cpp.

549 {
550 QVector<QPoint> points;
551 rasterizePolygonDDA(polygonPoints, [&points](const QPoint &point) { points.append(point); });
552 return points;
553 }
QVector< QPoint > rasterizePolygonDDA(const QVector< QPoint > &polygonPoints)

References rasterizePolygonDDA().

◆ rasterizePolygonDDA() [2/2]

template<typename Visitor >
void KritaUtils::rasterizePolygonDDA ( const QVector< QPoint > & polygonPoints,
Visitor visitor )

Definition at line 260 of file krita_utils.h.

261 {
262 // this is a line
263 if (polygonPoints.size() < 3) {
264 rasterizeLineDDA(polygonPoints.first(), polygonPoints.last(), visitor);
265 return;
266 }
267 // rasterize all segments except the last one
268 QPoint lastSegmentStart;
269 if (polygonPoints.first() == polygonPoints.last()) {
270 rasterizePolylineDDA(polygonPoints.mid(0, polygonPoints.size() - 1), visitor);
271 lastSegmentStart = polygonPoints[polygonPoints.size() - 2];
272 } else {
273 rasterizePolylineDDA(polygonPoints, visitor);
274 lastSegmentStart = polygonPoints[polygonPoints.size() - 1];
275 }
276 // close the polygon
277 {
278 QVector<QPoint> points;
279 auto addPoint = [&points](const QPoint &point) -> void { points.append(point); };
280 rasterizeLineDDA(lastSegmentStart, polygonPoints.first(), addPoint);
281 for (int i = 1; i < points.size() - 1; ++i) {
282 visitor(points[i]);
283 }
284 }
285 }
QVector< QPoint > rasterizePolylineDDA(const QVector< QPoint > &polylinePoints)

References rasterizeLineDDA(), and rasterizePolylineDDA().

◆ rasterizePolylineDDA() [1/2]

QVector< QPoint > KRITAIMAGE_EXPORT KritaUtils::rasterizePolylineDDA ( const QVector< QPoint > & polylinePoints)

Definition at line 541 of file krita_utils.cpp.

542 {
543 QVector<QPoint> points;
544 rasterizePolylineDDA(polylinePoints, [&points](const QPoint &point) { points.append(point); });
545 return points;
546 }

References rasterizePolylineDDA().

◆ rasterizePolylineDDA() [2/2]

template<typename Visitor >
void KritaUtils::rasterizePolylineDDA ( const QVector< QPoint > & polylinePoints,
Visitor visitor )

Definition at line 230 of file krita_utils.h.

231 {
232 if (polylinePoints.size() == 0) {
233 return;
234 }
235 if (polylinePoints.size() == 1) {
236 visitor(polylinePoints.first());
237 return;
238 }
239
240 // copy all points from the first segment
241 rasterizeLineDDA(polylinePoints[0], polylinePoints[1], visitor);
242 // for the rest of the segments, copy all points except the first one
243 // (it is the same as the last point in the previous segment)
244 for (int i = 1; i < polylinePoints.size() - 1; ++i) {
245 int pointIndex = 0;
247 polylinePoints[i], polylinePoints[i + 1],
248 [&pointIndex, &visitor](const QPoint &point) -> void
249 {
250 if (pointIndex > 0) {
251 visitor(point);
252 }
253 ++pointIndex;
254 }
255 );
256 }
257 }

References rasterizeLineDDA().

◆ rasterizeVLine() [1/2]

QVector< QPoint > KRITAIMAGE_EXPORT KritaUtils::rasterizeVLine ( const QPoint & startPoint,
const QPoint & endPoint )

Definition at line 527 of file krita_utils.cpp.

528 {
529 QVector<QPoint> points;
530 rasterizeVLine(startPoint, endPoint, [&points](const QPoint &point) { points.append(point); });
531 return points;
532 }

References rasterizeVLine().

◆ rasterizeVLine() [2/2]

template<typename Visitor >
void KritaUtils::rasterizeVLine ( const QPoint & startPoint,
const QPoint & endPoint,
Visitor visitor )

Definition at line 159 of file krita_utils.h.

160 {
161 QVector<QPoint> points;
162 int startY, endY;
163 if (startPoint.y() < endPoint.y()) {
164 startY = startPoint.y();
165 endY = endPoint.y();
166 } else {
167 startY = endPoint.y();
168 endY = startPoint.y();
169 }
170 for (int y = startY; y <= endY; ++y) {
171 visitor(QPoint(startPoint.x(), y));
172 }
173 }

◆ renderExactRect() [1/2]

void KRITAIMAGE_EXPORT KritaUtils::renderExactRect ( QPainter * p,
const QRect & rc )

When drawing a rect Qt uses quite a weird algorithm. It draws 4 lines: o at X-es: rect.x() and rect.right() + 1 o at Y-s: rect.y() and rect.bottom() + 1

Which means that bottom and right lines of the rect are painted outside the virtual rectangle the rect defines. This methods overcome this issue by painting the adjusted rect.

Definition at line 294 of file krita_utils.cpp.

295 {
296 p->drawRect(rc.adjusted(0,0,-1,-1));
297 }

References p.

◆ renderExactRect() [2/2]

void KRITAIMAGE_EXPORT KritaUtils::renderExactRect ( QPainter * p,
const QRect & rc,
const QPen & pen )
See also
renderExactRect(QPainter *p, const QRect &rc)

Definition at line 299 of file krita_utils.cpp.

300 {
301 QPen oldPen = p->pen();
302 p->setPen(pen);
303 renderExactRect(p, rc);
304 p->setPen(oldPen);
305 }
void renderExactRect(QPainter *p, const QRect &rc)

References p, and renderExactRect().

◆ resolveAbsoluteFilePath()

QString KRITAGLOBAL_EXPORT KritaUtils::resolveAbsoluteFilePath ( const QString & baseDir,
const QString & filePath )

Resolve absolute file path from a file path and base dir.

If the filePath is absolute, just return this path, otherwise try to merge baseDir and filePath to form an absolute file path

Definition at line 15 of file KisFileUtils.cpp.

16{
17 if (QFileInfo(fileName).isAbsolute()) {
18 return fileName;
19 }
20
21 QFileInfo fallbackBaseDirInfo(baseDir);
22
23 return QFileInfo(QDir(fallbackBaseDirInfo.isDir() ?
24 fallbackBaseDirInfo.absoluteFilePath() :
25 fallbackBaseDirInfo.absolutePath()),
26 fileName).absoluteFilePath();
27}

◆ restoreControlPoint()

void KritaUtils::restoreControlPoint ( KoPathPoint * pt,
bool restoreFirst,
boost::optional< QPointF > savedPoint )

Definition at line 43 of file KoPathMergeUtils.cpp.

44{
45 if (restoreFirst) {
46 if (savedPoint) {
47 pt->setControlPoint1(*savedPoint);
48 } else {
50 }
51 } else {
52 if (savedPoint) {
53 pt->setControlPoint2(*savedPoint);
54 } else {
56 }
57 }
58}
void removeControlPoint1()
Removes the first control point.
void removeControlPoint2()
Removes the second control point.

References KoPathPoint::removeControlPoint1(), KoPathPoint::removeControlPoint2(), KoPathPoint::setControlPoint1(), and KoPathPoint::setControlPoint2().

◆ splitDisjointPaths()

QList< QPainterPath > KRITAIMAGE_EXPORT KritaUtils::splitDisjointPaths ( const QPainterPath & path)

Split a path path into a set of disjoint (non-intersectable) paths if possible.

It tries to follow odd-even fill rule, but has a small problem: If you have three selections included into each other twice, then the smallest selection will be included into the final subpath, although it shouldn't according to odd-even-fill rule. It is still to be fixed.

Definition at line 196 of file krita_utils.cpp.

197 {
198 QList<QPainterPath> resultList;
199 QList<QPolygonF> inputPolygons = path.toSubpathPolygons();
200
201 Q_FOREACH (const QPolygonF &poly, inputPolygons) {
202 QPainterPath testPath;
203 testPath.addPolygon(poly);
204
205 if (resultList.isEmpty()) {
206 resultList.append(testPath);
207 continue;
208 }
209
210 QPainterPath mergedPath = testPath;
211
212 for (auto it = resultList.begin(); it != resultList.end(); /*noop*/) {
213 if (it->intersects(testPath)) {
214 mergedPath.addPath(*it);
215 it = resultList.erase(it);
216 } else {
217 ++it;
218 }
219 }
220
221 resultList.append(mergedPath);
222 }
223
224 return resultList;
225 }

◆ splitPath()

KRITAIMAGE_EXPORT KisRegion KritaUtils::splitPath ( const QPainterPath & path)

Definition at line 153 of file krita_utils.cpp.

154 {
155 QVector<QRect> dirtyRects;
156 QRect totalRect = path.boundingRect().toAlignedRect();
157
158 // adjust the rect for antialiasing to work
159 totalRect = totalRect.adjusted(-1,-1,1,1);
160
161 const int step = 64;
162 const int right = totalRect.x() + totalRect.width();
163 const int bottom = totalRect.y() + totalRect.height();
164
165 for (int y = totalRect.y(); y < bottom;) {
166 int nextY = qMin((y + step) & ~(step-1), bottom);
167
168 for (int x = totalRect.x(); x < right;) {
169 int nextX = qMin((x + step) & ~(step-1), right);
170
171 QRect rect(x, y, nextX - x, nextY - y);
172
173 if(path.intersects(rect)) {
174 dirtyRects << rect;
175 }
176
177 x = nextX;
178 }
179 y = nextY;
180 }
181
182 return KisRegion(std::move(dirtyRects));
183 }

◆ splitRectIntoPatches()

QVector< QRect > KRITAIMAGE_EXPORT KritaUtils::splitRectIntoPatches ( const QRect & rc,
const QSize & patchSize )

Definition at line 42 of file krita_utils.cpp.

43 {
44 using namespace KisAlgebra2D;
45
46
47 QVector<QRect> patches;
48
49 const qint32 firstCol = divideFloor(rc.x(), patchSize.width());
50 const qint32 firstRow = divideFloor(rc.y(), patchSize.height());
51
52 // TODO: check if -1 is needed here
53 const qint32 lastCol = divideFloor(rc.x() + rc.width(), patchSize.width());
54 const qint32 lastRow = divideFloor(rc.y() + rc.height(), patchSize.height());
55
56 for(qint32 i = firstRow; i <= lastRow; i++) {
57 for(qint32 j = firstCol; j <= lastCol; j++) {
58 QRect maxPatchRect(j * patchSize.width(), i * patchSize.height(),
59 patchSize.width(), patchSize.height());
60 QRect patchRect = rc & maxPatchRect;
61
62 if (!patchRect.isEmpty()) {
63 patches.append(patchRect);
64 }
65 }
66 }
67
68 return patches;
69 }

◆ splitRectIntoPatchesTight()

QVector< QRect > KRITAIMAGE_EXPORT KritaUtils::splitRectIntoPatchesTight ( const QRect & rc,
const QSize & patchSize )

Definition at line 71 of file krita_utils.cpp.

72 {
73 QVector<QRect> patches;
74
75 for (qint32 y = rc.y(); y < rc.y() + rc.height(); y += patchSize.height()) {
76 for (qint32 x = rc.x(); x < rc.x() + rc.width(); x += patchSize.width()) {
77 patches << QRect(x, y,
78 qMin(rc.x() + rc.width() - x, patchSize.width()),
79 qMin(rc.y() + rc.height() - y, patchSize.height()));
80 }
81 }
82
83 return patches;
84 }

◆ splitRegionIntoPatches() [1/2]

QVector< QRect > KRITAIMAGE_EXPORT KritaUtils::splitRegionIntoPatches ( const KisRegion & region,
const QSize & patchSize )

Definition at line 86 of file krita_utils.cpp.

87 {
88 QVector<QRect> patches;
89
90 Q_FOREACH (const QRect rect, region.rects()) {
91 patches << KritaUtils::splitRectIntoPatches(rect, patchSize);
92 }
93
94 return patches;
95 }
QVector< QRect > rects() const
QVector< QRect > splitRectIntoPatches(const QRect &rc, const QSize &patchSize)

References KisRegion::rects(), and splitRectIntoPatches().

◆ splitRegionIntoPatches() [2/2]

QVector< QRect > KRITAIMAGE_EXPORT KritaUtils::splitRegionIntoPatches ( const QRegion & region,
const QSize & patchSize )

◆ splitTriangles()

KRITAIMAGE_EXPORT KisRegion KritaUtils::splitTriangles ( const QPointF & center,
const QVector< QPointF > & points )

Definition at line 104 of file krita_utils.cpp.

106 {
107
108 Q_ASSERT(points.size());
109 Q_ASSERT(!(points.size() & 1));
110
111 QVector<QPolygonF> triangles;
112 QRect totalRect;
113
114 for (int i = 0; i < points.size(); i += 2) {
115 QPolygonF triangle;
116 triangle << center;
117 triangle << points[i];
118 triangle << points[i+1];
119
120 totalRect |= triangle.boundingRect().toAlignedRect();
121 triangles << triangle;
122 }
123
124
125 const int step = 64;
126 const int right = totalRect.x() + totalRect.width();
127 const int bottom = totalRect.y() + totalRect.height();
128
129 QVector<QRect> dirtyRects;
130
131 for (int y = totalRect.y(); y < bottom;) {
132 int nextY = qMin((y + step) & ~(step-1), bottom);
133
134 for (int x = totalRect.x(); x < right;) {
135 int nextX = qMin((x + step) & ~(step-1), right);
136
137 QRect rect(x, y, nextX - x, nextY - y);
138
139 Q_FOREACH (const QPolygonF &triangle, triangles) {
140 if(checkInTriangle(rect, triangle)) {
141 dirtyRects << rect;
142 break;
143 }
144 }
145
146 x = nextX;
147 }
148 y = nextY;
149 }
150 return KisRegion(std::move(dirtyRects));
151 }

References checkInTriangle().

◆ thresholdOpacity()

void KritaUtils::thresholdOpacity ( KisPaintDeviceSP device,
const QRect & rect,
ThresholdMode mode )

Definition at line 475 of file krita_utils.cpp.

476 {
477 const KoColorSpace *cs = device->colorSpace();
478
479 if (mode == ThresholdCeil) {
480 KisSequentialIterator it(device, rect);
481 while (it.nextPixel()) {
482 if (cs->opacityU8(it.rawDataConst()) > 0) {
483 cs->setOpacity(it.rawData(), quint8(255), 1);
484 }
485 }
486 } else if (mode == ThresholdFloor) {
487 KisSequentialIterator it(device, rect);
488 while (it.nextPixel()) {
489 if (cs->opacityU8(it.rawDataConst()) < 255) {
490 cs->setOpacity(it.rawData(), quint8(0), 1);
491 }
492 }
493 } else if (mode == ThresholdMaxOut) {
494 KisSequentialIterator it(device, rect);
495 int numConseqPixels = it.nConseqPixels();
496 while (it.nextPixels(numConseqPixels)) {
497 numConseqPixels = it.nConseqPixels();
498 cs->setOpacity(it.rawData(), quint8(255), numConseqPixels);
499 }
500 }
501 }
virtual void setOpacity(quint8 *pixels, quint8 alpha, qint32 nPixels) const =0

References KisPaintDevice::colorSpace(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nConseqPixels(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nextPixel(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nextPixels(), KoColorSpace::opacityU8(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::rawData(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::rawDataConst(), KoColorSpace::setOpacity(), ThresholdCeil, ThresholdFloor, and ThresholdMaxOut.

◆ thresholdOpacityAlpha8()

void KritaUtils::thresholdOpacityAlpha8 ( KisPaintDeviceSP device,
const QRect & rect,
ThresholdMode mode )

Definition at line 503 of file krita_utils.cpp.

504 {
505 if (mode == ThresholdCeil) {
506 filterAlpha8Device(device, rect,
507 [] (quint8 value) {
508 return value > 0 ? 255 : value;
509 });
510 } else if (mode == ThresholdFloor) {
511 filterAlpha8Device(device, rect,
512 [] (quint8 value) {
513 return value < 255 ? 0 : value;
514 });
515 } else if (mode == ThresholdMaxOut) {
516 device->fill(rect, KoColor(Qt::white, device->colorSpace()));
517 }
518 }
void fill(const QRect &rc, const KoColor &color)
void filterAlpha8Device(KisPaintDeviceSP dev, const QRect &rc, std::function< quint8(quint8)> func)

References KisPaintDevice::colorSpace(), KisPaintDevice::fill(), filterAlpha8Device(), ThresholdCeil, ThresholdFloor, ThresholdMaxOut, and value().

◆ toLocalizedOnOff()

QString KRITAIMAGE_EXPORT KritaUtils::toLocalizedOnOff ( bool value)

Definition at line 275 of file krita_utils.cpp.

275 {
276 return value ? i18n("on") : i18n("off");
277 }

References value().

◆ tryCloseTornSubpathsAfterIntersection()

QPainterPath KRITAIMAGE_EXPORT KritaUtils::tryCloseTornSubpathsAfterIntersection ( QPainterPath path)

Sometimes, when intersecting two paths, QPainterPath does not close some of the subpaths. It causes glitches when rendering them on screen. So we should just close them explicitly.

Note: after intersecting the paths all bezier curves are already converted to polylines, so it should be safe to go through the polygons.

See: https://bugs.kde.org/show_bug.cgi?id=408369

Definition at line 458 of file krita_utils.cpp.

459 {
460 path.setFillRule(Qt::WindingFill);
461 QList<QPolygonF> polys = path.toSubpathPolygons();
462
463 path = QPainterPath();
464 path.setFillRule(Qt::WindingFill);
465 Q_FOREACH (QPolygonF poly, polys) {
466 ENTER_FUNCTION() << ppVar(poly.isClosed());
467 if (!poly.isClosed()) {
468 poly.append(poly.first());
469 }
470 path.addPolygon(poly);
471 }
472 return path;
473 }
#define ENTER_FUNCTION()
Definition kis_debug.h:178
#define ppVar(var)
Definition kis_debug.h:155

References ENTER_FUNCTION, and ppVar.

◆ workaroundUnsuitableImageColorSpace()

KisImportExportErrorCode KRITAUI_EXPORT KritaUtils::workaroundUnsuitableImageColorSpace ( KisImageSP image,
KisImportUserFeedbackInterface * feedbackInterface,
KisImageBarrierLock & lock )

When the image has a colorspace that is not suitable for displaying, Krita should convert that into something more useful. This tool function asks the user about the desired working color space and converts into it.

The profile has no reverse mapping into for the described color space, so we cannot use it in Krita. We need to ask the user to convert the image right on loading

Here is an extremely tricky part! First we start the conversion stroke, and only after that we unlock the image. The point is that KisDelayedUpdateNodeInterface-based nodes are forbidden to start their update jobs while the image is locked, so this guarantees that no stroke will be started before we actually convert the image into something usable

Definition at line 18 of file KisImportExportUtils.cpp.

21{
22 const KoColorSpace *replacementColorSpace = 0;
24 KoColorConversionTransformation::ConversionFlags replacementColorSpaceConversionFlags = KoColorConversionTransformation::internalConversionFlags();
25
26 const KoColorSpace *colorSpace = image->colorSpace();
27 const KoColorProfile *profile = colorSpace->profile();
28
29 if (profile && !profile->isSuitableForOutput()) {
33
34 KIS_SAFE_ASSERT_RECOVER_NOOP(feedbackInterface);
35 if (feedbackInterface) {
37 feedbackInterface->askUser([&] (QWidget *parent) {
38
39 KisColorSpaceConversionDialog * dlgColorSpaceConversion = new KisColorSpaceConversionDialog(parent, "ColorSpaceConversion");
40 Q_CHECK_PTR(dlgColorSpaceConversion);
41
42 const KoColorSpace* fallbackColorSpace =
44 colorSpace->colorModelId().id(),
45 colorSpace->colorDepthId().id(),
46 nullptr);
47
48 dlgColorSpaceConversion->setCaption(i18n("Convert image color space on import"));
49 dlgColorSpaceConversion->m_page->lblHeadlineWarning->setText(
50 i18nc("the argument is the ICC profile name",
51 "The image has a profile attached that Krita cannot edit images "
52 "in (\"%1\"), please select a space to convert to for editing: \n"
53 , profile->name()));
54 dlgColorSpaceConversion->m_page->lblHeadlineWarning->setVisible(true);
55
56 dlgColorSpaceConversion->setInitialColorSpace(fallbackColorSpace, 0);
57
58 if (dlgColorSpaceConversion->exec() == QDialog::Accepted) {
59
60 replacementColorSpace = dlgColorSpaceConversion->colorSpace();
61 replacementColorSpaceIntent = dlgColorSpaceConversion->conversionIntent();
62 replacementColorSpaceConversionFlags= dlgColorSpaceConversion->conversionFlags();
63 } else {
64 return false;
65 }
66
67 return true;
68 });
69
74 }
75 }
76 }
77
78 if (replacementColorSpace) {
87 image->convertImageColorSpace(replacementColorSpace,
88 replacementColorSpaceIntent,
89 replacementColorSpaceConversionFlags);
90 lock.unlock();
91 image->waitForDone();
92 }
93
95}
KoColorConversionTransformation::Intent conversionIntent() const
void setInitialColorSpace(const KoColorSpace *cs, KisImageSP entireImage)
KoColorConversionTransformation::ConversionFlags conversionFlags() const
void waitForDone()
const KoColorSpace * colorSpace() const
void convertImageColorSpace(const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
virtual Result askUser(AskCallback callback)=0
ask the user a question about the loading process
virtual KoID colorModelId() const =0
virtual KoID colorDepthId() const =0
virtual const KoColorProfile * profile() const =0
virtual void setCaption(const QString &caption)
Definition KoDialog.cpp:498
QString id() const
Definition KoID.cpp:63
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
virtual bool isSuitableForOutput() const =0
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()

References KisImportUserFeedbackInterface::askUser(), ImportExportCodes::Cancelled, KoColorSpace::colorDepthId(), KoColorSpace::colorModelId(), KisImage::colorSpace(), KisColorSpaceConversionDialog::colorSpace(), KoColorSpaceRegistry::colorSpace(), KisColorSpaceConversionDialog::conversionFlags(), KisColorSpaceConversionDialog::conversionIntent(), KisImage::convertImageColorSpace(), ImportExportCodes::FormatColorSpaceUnsupported, KoID::id(), KoColorSpaceRegistry::instance(), KoColorConversionTransformation::internalConversionFlags(), KoColorConversionTransformation::internalRenderingIntent(), KoColorProfile::isSuitableForOutput(), KIS_SAFE_ASSERT_RECOVER_NOOP, KisColorSpaceConversionDialog::m_page, KoColorProfile::name, ImportExportCodes::OK, KoColorSpace::profile(), KoDialog::setCaption(), KisColorSpaceConversionDialog::setInitialColorSpace(), KisImportUserFeedbackInterface::SuppressedByBatchMode, KisImportUserFeedbackInterface::UserCancelled, and KisImage::waitForDone().