9#include <QtCore/qmath.h>
13#include <QPainterPath>
49 const qint32 firstCol = divideFloor(rc.x(), patchSize.width());
50 const qint32 firstRow = divideFloor(rc.y(), patchSize.height());
53 const qint32 lastCol = divideFloor(rc.x() + rc.width(), patchSize.width());
54 const qint32 lastRow = divideFloor(rc.y() + rc.height(), patchSize.height());
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;
62 if (!patchRect.isEmpty()) {
63 patches.append(patchRect);
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()));
90 Q_FOREACH (
const QRect
rect, region.
rects()) {
98 const QPolygonF &triangle)
100 return triangle.intersected(
rect).boundingRect().isValid();
108 Q_ASSERT(points.size());
109 Q_ASSERT(!(points.size() & 1));
114 for (
int i = 0; i < points.size(); i += 2) {
117 triangle << points[i];
118 triangle << points[i+1];
120 totalRect |= triangle.boundingRect().toAlignedRect();
121 triangles << triangle;
126 const int right = totalRect.x() + totalRect.width();
127 const int bottom = totalRect.y() + totalRect.height();
131 for (
int y = totalRect.y(); y < bottom;) {
132 int nextY = qMin((y + step) & ~(step-1), bottom);
134 for (
int x = totalRect.x(); x < right;) {
135 int nextX = qMin((x + step) & ~(step-1), right);
137 QRect
rect(x, y, nextX - x, nextY - y);
139 Q_FOREACH (
const QPolygonF &triangle, triangles) {
156 QRect totalRect = path.boundingRect().toAlignedRect();
159 totalRect = totalRect.adjusted(-1,-1,1,1);
162 const int right = totalRect.x() + totalRect.width();
163 const int bottom = totalRect.y() + totalRect.height();
165 for (
int y = totalRect.y(); y < bottom;) {
166 int nextY = qMin((y + step) & ~(step-1), bottom);
168 for (
int x = totalRect.x(); x < right;) {
169 int nextX = qMin((x + step) & ~(step-1), right);
171 QRect
rect(x, y, nextX - x, nextY - y);
173 if(path.intersects(
rect)) {
187 return QLocale().toString(
value,
'f', 1);
192 qreal maxDimension = qMax(
bounds.width(),
bounds.height());
193 return qMax(portion * maxDimension, minValue);
197 const QPointF &startPoint,
198 const QPointF &endPoint,
200 qreal distanceThreshold,
203 qreal
length = (endPoint - startPoint).manhattanLength();
205 if (lastSegment ||
length > distanceThreshold) {
207 qreal wrappedLength =
208 (endPoint - QPointF(path.elementAt(0))).manhattanLength();
210 if (
length < distanceThreshold ||
211 wrappedLength < distanceThreshold) {
224 path.lineTo(endPoint);
233 QPainterPath newPath;
237 int count = path.elementCount();
238 for (
int i = 0; i < count; i++) {
239 QPainterPath::Element e = path.elementAt(i);
240 QPointF endPoint = QPointF(e.x, e.y);
243 case QPainterPath::MoveToElement:
244 newPath.moveTo(endPoint);
246 case QPainterPath::LineToElement:
248 distance, lengthThreshold, i == count - 1)) {
250 newPath.lineTo(endPoint);
253 case QPainterPath::CurveToElement: {
254 Q_ASSERT(i + 2 < count);
257 distance, lengthThreshold, i == count - 1)) {
259 e = path.elementAt(i + 1);
260 Q_ASSERT(e.type == QPainterPath::CurveToDataElement);
261 QPointF ctrl1 = QPointF(e.x, e.y);
262 e = path.elementAt(i + 2);
263 Q_ASSERT(e.type == QPainterPath::CurveToDataElement);
264 QPointF ctrl2 = QPointF(e.x, e.y);
265 newPath.cubicTo(ctrl1, ctrl2, endPoint);
273 startPoint = endPoint;
284 Q_FOREACH (
const QPolygonF &poly, inputPolygons) {
285 QPainterPath testPath;
286 testPath.addPolygon(poly);
288 if (resultList.isEmpty()) {
289 resultList.append(testPath);
293 QPainterPath mergedPath = testPath;
295 for (
auto it = resultList.begin(); it != resultList.end(); ) {
296 if (it->intersects(testPath)) {
297 mergedPath.addPath(*it);
298 it = resultList.erase(it);
304 resultList.append(mergedPath);
321 opacity *= parentOpacity;
328 QBitArray flags = childFlags;
330 if (!flags.isEmpty() &&
331 !parentFlags.isEmpty() &&
332 flags.size() == parentFlags.size()) {
334 flags &= parentFlags;
336 }
else if (!parentFlags.isEmpty()) {
345 if (f1.isNull() && f2.isNull())
return true;
348 f1.fill(
true, f2.size());
352 f2.fill(
true, f1.size());
359 return value ? i18n(
"on") : i18n(
"off");
379 p->drawRect(rc.adjusted(0,0,-1,-1));
384 QPen oldPen =
p->pen();
392 QImage dstImage(image.size(), QImage::Format_ARGB32);
395 const QSize size = image.size();
396 for(
int y = 0; y < size.height(); ++y) {
397 for(
int x = 0; x < size.width(); ++x) {
398 const QRgb pixel = image.pixel(x,y);
399 const int gray = qGray(pixel);
400 dstImage.setPixel(x, y, qRgba(gray, gray, gray, qAlpha(pixel)));
418 quint8 *dstPtr = dstIt.
rawData();
419 *dstPtr = func(*dstPtr);
426 const qreal linearPortion = std::sqrt(samplePortion);
427 const qreal ratio = qreal(
rect.width()) /
rect.height();
428 const int xStep = qMax(1, qRound(1.0 / linearPortion * ratio));
429 const int yStep = qMax(1, qRound(1.0 / linearPortion / ratio));
431 int numTransparentPixels = 0;
435 for (
int y =
rect.y(); y <=
rect.bottom(); y += yStep) {
436 for (
int x =
rect.x(); x <=
rect.right(); x += xStep) {
441 numTransparentPixels++;
448 if (numPixels == 0) {
451 return qreal(numTransparentPixels) / numPixels;
458 if (dir == Qt::Horizontal) {
459 const int mirrorX = -((rc.x() + rc.width()) - center.x()) + center.x();
461 if (!skipMirrorPixels) {
464 dab->
offset.rx() = mirrorX;
466 const int mirrorY = -((rc.y() + rc.height()) - center.y()) + center.y();
468 if (!skipMirrorPixels) {
471 dab->
offset.ry() = mirrorY;
479 if (dir == Qt::Horizontal) {
480 const int mirrorX = -((rc.x() + rc.width()) - center.x()) + center.x();
482 if (!skipMirrorPixels) {
485 dab->
offset.rx() = mirrorX;
487 const int mirrorY = -((rc.y() + rc.height()) - center.y()) + center.y();
489 if (!skipMirrorPixels) {
492 dab->
offset.ry() = mirrorY;
496 void mirrorRect(Qt::Orientation dir,
const QPoint ¢er, QRect *rc)
498 if (dir == Qt::Horizontal) {
499 const int mirrorX = -((rc->x() + rc->width()) - center.x()) + center.x();
500 rc->moveLeft(mirrorX);
502 const int mirrorY = -((rc->y() + rc->height()) - center.y()) + center.y();
503 rc->moveTop(mirrorY);
507 void mirrorRect(Qt::Orientation dir,
const QPointF ¢er, QRect *rc)
509 if (dir == Qt::Horizontal) {
510 const int mirrorX = -((rc->x() + rc->width()) - center.x()) + center.x();
511 rc->moveLeft(mirrorX);
513 const int mirrorY = -((rc->y() + rc->height()) - center.y()) + center.y();
514 rc->moveTop(mirrorY);
518 void mirrorPoint(Qt::Orientation dir,
const QPoint ¢er, QPointF *pt)
520 if (dir == Qt::Horizontal) {
521 pt->rx() = -(pt->x() - qreal(center.x())) + center.x();
523 pt->ry() = -(pt->y() - qreal(center.y())) + center.y();
527 void mirrorPoint(Qt::Orientation dir,
const QPointF ¢er, QPointF *pt)
529 if (dir == Qt::Horizontal) {
530 pt->rx() = -(pt->x() - qreal(center.x())) + center.x();
532 pt->ry() = -(pt->y() - qreal(center.y())) + center.y();
538 return QTransform::fromScale(image->
xRes(), image->
yRes());
543 path.setFillRule(Qt::WindingFill);
546 path = QPainterPath();
547 path.setFillRule(Qt::WindingFill);
548 Q_FOREACH (QPolygonF poly, polys) {
550 if (!poly.isClosed()) {
551 poly.append(poly.first());
553 path.addPolygon(poly);
606 rasterizeHLine(startPoint, endPoint, [&points](
const QPoint &point) { points.append(point); });
613 rasterizeVLine(startPoint, endPoint, [&points](
const QPoint &point) { points.append(point); });
620 rasterizeLineDDA(startPoint, endPoint, [&points](
const QPoint &point) { points.append(point); });
634 rasterizePolygonDDA(polygonPoints, [&points](
const QPoint &point) { points.append(point); });
qreal length(const QPointF &vec)
float value(const T *src, size_t ch)
const qreal OPACITY_OPAQUE_F
const quint8 OPACITY_OPAQUE_U8
qreal distance(const QPointF &p1, const QPointF &p2)
virtual const quint8 * rawDataConst() const =0
void mirror(bool horizontal, bool vertical)
int updatePatchWidth() const
int updatePatchHeight() const
KisRandomConstAccessorSP createRandomConstAccessorNG() const
void fill(const QRect &rc, const KoColor &color)
const KoColorSpace * colorSpace() const
virtual void moveTo(qint32 x, qint32 y)=0
QVector< QRect > rects() const
bool nextPixels(int numPixels)
ALWAYS_INLINE quint8 * rawData()
int nConseqPixels() const
ALWAYS_INLINE const quint8 * rawDataConst() const
virtual void setOpacity(quint8 *pixels, quint8 alpha, qint32 nPixels) const =0
virtual quint8 opacityU8(const quint8 *pixel) const =0
static bool qFuzzyCompare(half p1, half p2)
qreal KRITAIMAGE_EXPORT maxDimensionPortion(const QRectF &bounds, qreal portion, qreal minValue)
QVector< QRect > splitRectIntoPatches(const QRect &rc, const QSize &patchSize)
quint8 mergeOpacityU8(quint8 opacity, quint8 parentOpacity)
void filterAlpha8Device(KisPaintDeviceSP dev, const QRect &rc, std::function< quint8(quint8)> func)
QPainterPath trySimplifyPath(const QPainterPath &path, qreal lengthThreshold)
bool compareChannelFlags(QBitArray f1, QBitArray f2)
QString KRITAIMAGE_EXPORT toLocalizedOnOff(bool value)
void thresholdOpacity(KisPaintDeviceSP device, const QRect &rect, ThresholdMode mode)
QVector< QPoint > rasterizeLineDDA(const QPoint &startPoint, const QPoint &endPoint)
QString KRITAIMAGE_EXPORT prettyFormatReal(qreal value)
KisRegion splitPath(const QPainterPath &path)
QVector< QPoint > rasterizePolygonDDA(const QVector< QPoint > &polygonPoints)
QTransform pathShapeBooleanSpaceWorkaround(KisImageSP image)
KisNodeSP nearestNodeAfterRemoval(KisNodeSP node)
qreal mergeOpacityF(qreal opacity, qreal parentOpacity)
QImage convertQImageToGrayA(const QImage &image)
QPainterPath tryCloseTornSubpathsAfterIntersection(QPainterPath path)
QVector< QRect > splitRegionIntoPatches(const KisRegion ®ion, const QSize &patchSize)
qreal estimatePortionOfTransparentPixels(KisPaintDeviceSP dev, const QRect &rect, qreal samplePortion)
void mirrorDab(Qt::Orientation dir, const QPoint ¢er, KisRenderedDab *dab, bool skipMirrorPixels)
bool checkInTriangle(const QRectF &rect, const QPolygonF &triangle)
QList< QPainterPath > splitDisjointPaths(const QPainterPath &path)
void applyToAlpha8Device(KisPaintDeviceSP dev, const QRect &rc, std::function< void(quint8)> func)
QBitArray mergeChannelFlags(const QBitArray &childFlags, const QBitArray &parentFlags)
QVector< QPoint > rasterizeVLine(const QPoint &startPoint, const QPoint &endPoint)
KisRegion splitTriangles(const QPointF ¢er, const QVector< QPointF > &points)
QVector< QRect > splitRectIntoPatchesTight(const QRect &rc, const QSize &patchSize)
void thresholdOpacityAlpha8(KisPaintDeviceSP device, const QRect &rect, ThresholdMode mode)
bool tryMergePoints(QPainterPath &path, const QPointF &startPoint, const QPointF &endPoint, qreal &distance, qreal distanceThreshold, bool lastSegment)
void mirrorPoint(Qt::Orientation dir, const QPoint ¢er, QPointF *pt)
void mirrorRect(Qt::Orientation dir, const QPoint ¢er, QRect *rc)
void renderExactRect(QPainter *p, const QRect &rc)
QVector< QPoint > rasterizeHLine(const QPoint &startPoint, const QPoint &endPoint)
QVector< QPoint > rasterizePolylineDDA(const QVector< QPoint > &polylinePoints)
KisNodeSP prevSibling() const
KisNodeSP nextSibling() const
KisFixedPaintDeviceSP device