27 : origCage(_origCage),
29 pixelPrecision(_pixelPrecision)
57 return allSrcPoints.isEmpty();
64 int *numExistingPoints);
75 : m_d(new
Private(origCage, progress, pixelPrecision))
77 m_d->srcBounds = deviceNonDefaultRegion;
81 const QPointF &srcImageOffset,
85 : m_d(new
Private(origCage, progress, pixelPrecision))
89 m_d->srcBounds = QRectF(
m_d->srcImageOffset,
m_d->srcImage.size()).toAlignedRect();
98 m_d->transfCage = transformedCage;
111 int prevCol,
int prevRow,
112 int colIndex,
int rowIndex) {
119 QPointF pt(col, row);
145 if (
m_d->origCage.size() < 3)
return;
147 const QPolygonF srcPolygon(
m_d->origCage);
150 srcBounds &= srcPolygon.boundingRect().toAlignedRect();
160 const int numPoints = pointsOp.
m_points.size();
164 m_d->allToValidPointsMap.resize(pointsOp.
m_points.size());
169 for (
int i = 0; i < numPoints; i++) {
170 const QPointF &pt = pointsOp.
m_points[i];
174 m_d->validPoints[validIdx] = pt;
175 m_d->allToValidPointsMap[i] = validIdx;
178 m_d->allToValidPointsMap[i] = -1;
184 m_d->cage.precalculateGreenCoordinates(
m_d->origCage,
m_d->validPoints);
187QVector<QPointF> KisCageTransformWorker::Private::calculateTransformedPoints()
189 cage.generateTransformedCageNormals(transfCage);
191 const int numValidPoints = validPoints.size();
194 for (
int i = 0; i < numValidPoints; i++) {
195 transformedPoints[i] = cage.transformedPoint(i, transfCage);
197 if (qIsNaN(transformedPoints[i].x()) ||
198 qIsNaN(transformedPoints[i].y())) {
199 warnKrita <<
"WARNING: One grid point has been removed from consideration" << validPoints[i];
200 transformedPoints[i] = validPoints[i];
205 return transformedPoints;
209calculateMappedIndexes(
int col,
int row,
210 int *numExistingPoints)
212 *numExistingPoints = 0;
216 for (
int i = 0; i < 4; i++) {
217 cellIndexes[i] = allToValidPointsMap[cellIndexes[i]];
218 *numExistingPoints += cellIndexes[i] >= 0;
226int KisCageTransformWorker::Private::
227tryGetValidIndex(
const QPoint &cellPt)
230 if (cellPt.x() >= 0 &&
232 cellPt.x() < gridSize.width() - 1 &&
233 cellPt.y() < gridSize.height() - 1) {
251 int *numExistingPoints)
const {
253 return m_d->calculateMappedIndexes(col, row, numExistingPoints);
257 return m_d->tryGetValidIndex(cellPt);
274 const qreal margin = 0.30;
278 const int minStep = 3;
279 const int maxSamples = 200;
281 const int totalPixels = rc.width() * rc.height();
282 const int realStep = qMax(minStep, totalPixels / maxSamples);
283 const QPolygonF cagePolygon(
m_d->origCage);
285 for (
int i = 0; i < totalPixels; i += realStep) {
286 const int x = rc.x() + i % rc.width();
287 const int y = rc.y() + i / rc.width();
289 const QPointF pt(x, y);
290 if (cagePolygon.containsPoint(pt, Qt::OddEvenFill)) {
291 cageSamplePoints << pt;
295 if (cageSamplePoints.isEmpty()) {
303 const int numValidPoints = cageSamplePoints.size();
306 int failedPoints = 0;
308 for (
int i = 0; i < numValidPoints; i++) {
311 if (qIsNaN(transformedPoints[i].x()) ||
312 qIsNaN(transformedPoints[i].y())) {
314 transformedPoints[i] = cageSamplePoints[i];
333 if (
m_d->isGridEmpty())
return;
358 Private::MapIndexesOp indexesOp(
m_d.data());
372 if (
m_d->isGridEmpty())
return QImage();
375 m_d->origCage.size() ==
m_d->transfCage.size()) {
390 Q_FOREACH (
const QPointF &pt, transformedPoints) {
397 QPointF dstQImageOffset = dstBounds.topLeft();
398 *newOffset = dstQImageOffset;
400 QRect dstBoundsI = dstBounds.toAlignedRect();
403 QImage dstImage(dstBoundsI.size(),
m_d->srcImage.format());
406 QImage tempImage(dstImage);
410 QPainter gc(&dstImage);
411 gc.drawImage(-dstQImageOffset +
m_d->srcImageOffset,
m_d->srcImage);
412 gc.setBrush(Qt::black);
413 gc.setPen(Qt::black);
414 gc.setCompositionMode(QPainter::CompositionMode_Clear);
415 gc.drawPolygon(QPolygonF(
m_d->origCage).translated(-dstQImageOffset));
420 Private::MapIndexesOp indexesOp(
m_d.data());
428 QPainter gc(&dstImage);
429 gc.drawImage(QPoint(), tempImage);
const KoColorSpace * colorSpace() const
void clearSelection(KisSelectionSP selection)
@ FillStyleForegroundColor
void setStrokeStyle(StrokeStyle strokeStyle)
Set the current brush stroke style.
void paintPolygon(const vQPointF &points)
void bitBlt(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight)
void setFillStyle(FillStyle fillStyle)
Set the current style with which to fill.
void setPaintColor(const KoColor &color)
void setAntiAliasPolygonFill(bool antiAliasPolygonFill)
Set whether a polygon's filled area should be anti-aliased or not. The default is true.
#define KIS_ASSERT_RECOVER(cond)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
#define KIS_ASSERT_RECOVER_RETURN(cond)
#define KIS_ASSERT_RECOVER_NOOP(cond)
Rect blowRect(const Rect &rect, qreal coeff)
QRect approximateRectFromPoints(const QVector< QPoint > &points)
void adjustIfOnPolygonBoundary(const QPolygonF &poly, int polygonDirection, QPointF *pt)
void accumulateBounds(const Point &pt, Rect *bounds)
int polygonDirection(const QVector< T > &polygon)
void generateTransformedCageNormals(const QVector< QPointF > &transformedCage)
QPointF transformedPoint(int pointIndex, const QVector< QPointF > &transformedCage)
void precalculateGreenCoordinates(const QVector< QPointF > &originalCage, const QVector< QPointF > &points)
KisPixelSelectionSP pixelSelection
QVector< QPointF > m_points
PointsFetcherOp(const QPolygonF &cagePolygon)
void processPoint(int col, int row, int prevCol, int prevRow, int colIndex, int rowIndex)
QVector< bool > m_pointValid