Commit af13a646 authored by Dmitry Kazakov's avatar Dmitry Kazakov
Browse files

[FEATURE] Implement mirroring for Quick Brush

The patch implements mirroring capabilities for Quick Brush.
It just paints multiple "quick" strokes at the same time.

BUG:372636
parent 810c2bd2
......@@ -2956,30 +2956,61 @@ void KisPainter::mirrorDab(Qt::Orientation direction, KisRenderedDab *dab) const
KritaUtils::mirrorDab(direction, effectiveAxesCenter, dab);
}
const QVector<QRect> KisPainter::calculateAllMirroredRects(const QRect &rc)
namespace {
inline void mirrorOneObject(Qt::Orientation dir, const QPoint &center, QRect *rc) {
KritaUtils::mirrorRect(dir, center, rc);
}
inline void mirrorOneObject(Qt::Orientation dir, const QPoint &center, QPointF *pt) {
KritaUtils::mirrorPoint(dir, center, pt);
}
inline void mirrorOneObject(Qt::Orientation dir, const QPoint &center, QPair<QPointF, QPointF> *pair) {
KritaUtils::mirrorPoint(dir, center, &pair->first);
KritaUtils::mirrorPoint(dir, center, &pair->second);
}
}
template<class T> QVector<T> KisPainter::Private::calculateMirroredObjects(const T &object)
{
QVector<QRect> rects;
QVector<T> result;
KisLodTransform t(d->device);
QPoint effectiveAxesCenter = t.map(d->axesCenter).toPoint();
KisLodTransform t(this->device);
const QPoint effectiveAxesCenter = t.map(this->axesCenter).toPoint();
QRect baseRect = rc;
rects << baseRect;
T baseObject = object;
result << baseObject;
if (d->mirrorHorizontally && d->mirrorVertically){
KritaUtils::mirrorRect(Qt::Horizontal, effectiveAxesCenter, &baseRect);
rects << baseRect;
KritaUtils::mirrorRect(Qt::Vertical, effectiveAxesCenter, &baseRect);
rects << baseRect;
KritaUtils::mirrorRect(Qt::Horizontal, effectiveAxesCenter, &baseRect);
rects << baseRect;
} else if (d->mirrorHorizontally) {
KritaUtils::mirrorRect(Qt::Horizontal, effectiveAxesCenter, &baseRect);
rects << baseRect;
} else if (d->mirrorVertically) {
KritaUtils::mirrorRect(Qt::Vertical, effectiveAxesCenter, &baseRect);
rects << baseRect;
if (this->mirrorHorizontally && this->mirrorVertically){
mirrorOneObject(Qt::Horizontal, effectiveAxesCenter, &baseObject);
result << baseObject;
mirrorOneObject(Qt::Vertical, effectiveAxesCenter, &baseObject);
result << baseObject;
mirrorOneObject(Qt::Horizontal, effectiveAxesCenter, &baseObject);
result << baseObject;
} else if (this->mirrorHorizontally) {
mirrorOneObject(Qt::Horizontal, effectiveAxesCenter, &baseObject);
result << baseObject;
} else if (this->mirrorVertically) {
mirrorOneObject(Qt::Vertical, effectiveAxesCenter, &baseObject);
result << baseObject;
}
return rects;
return result;
}
const QVector<QRect> KisPainter::calculateAllMirroredRects(const QRect &rc)
{
return d->calculateMirroredObjects(rc);
}
const QVector<QPointF> KisPainter::calculateAllMirroredPoints(const QPointF &pos)
{
return d->calculateMirroredObjects(pos);
}
const QVector<QPair<QPointF, QPointF>> KisPainter::calculateAllMirroredPoints(const QPair<QPointF, QPointF> &pair)
{
return d->calculateMirroredObjects(pair);
}
......@@ -674,6 +674,18 @@ public:
*/
const QVector<QRect> calculateAllMirroredRects(const QRect &rc);
/**
* Calculate the list of the mirrored points according to the current
* mirroring configuration.
*/
const QVector<QPointF> calculateAllMirroredPoints(const QPointF &pos);
/**
* Calculate the list of the mirrored point pairs according to the current
* mirroring configuration.
*/
const QVector<QPair<QPointF, QPointF>> calculateAllMirroredPoints(const QPair<QPointF, QPointF> &pair);
/// Set the current pattern
void setPattern(const KoPattern * pattern);
......
......@@ -100,6 +100,8 @@ struct Q_DECL_HIDDEN KisPainter::Private {
const KoColorSpace *srcColorSpace,
KoCompositeOp::ParameterInfo &localParamInfo);
template<class T> QVector<T> calculateMirroredObjects(const T &object);
};
#endif // KISPAINTERPRIVATE_H
......@@ -476,6 +476,15 @@ namespace KritaUtils
}
}
void mirrorPoint(Qt::Orientation dir, const QPoint &center, QPointF *pt)
{
if (dir == Qt::Horizontal) {
pt->rx() = -(pt->x() - qreal(center.x())) + center.x();
} else /* if (dir == Qt::Vertical) */ {
pt->ry() = -(pt->y() - qreal(center.y())) + center.y();
}
}
qreal colorDifference(const QColor &c1, const QColor &c2)
{
const qreal dr = c1.redF() - c2.redF();
......
......@@ -114,6 +114,7 @@ namespace KritaUtils
void KRITAIMAGE_EXPORT mirrorDab(Qt::Orientation dir, const QPoint &center, KisRenderedDab *dab);
void KRITAIMAGE_EXPORT mirrorRect(Qt::Orientation dir, const QPoint &center, QRect *rc);
void KRITAIMAGE_EXPORT mirrorPoint(Qt::Orientation dir, const QPoint &center, QPointF *pt);
}
#endif /* __KRITA_UTILS_H */
......@@ -90,10 +90,20 @@ KisSpacingInformation KisRoundMarkerOp::paintAt(const KisPaintInformation& info)
KisMarkerPainter gc(painter()->device(), painter()->paintColor());
if (m_firstRun) {
gc.fillFullCircle(pos, radius);
const QVector<QPointF> points =
painter()->calculateAllMirroredPoints(pos);
Q_FOREACH(const QPointF &pt, points) {
gc.fillFullCircle(pt, radius);
}
} else {
gc.fillCirclesDiff(m_lastPaintPos, m_lastRadius,
pos, radius);
const QVector<QPair<QPointF, QPointF>> pairs =
painter()->calculateAllMirroredPoints(qMakePair(m_lastPaintPos, pos));
Q_FOREACH(const auto &pair, pairs) {
gc.fillCirclesDiff(pair.first, m_lastRadius,
pair.second, radius);
}
}
m_firstRun = false;
......@@ -103,7 +113,11 @@ KisSpacingInformation KisRoundMarkerOp::paintAt(const KisPaintInformation& info)
QRectF dirtyRect(pos.x() - radius, pos.y() - radius,
2 * radius, 2 * radius);
dirtyRect = kisGrowRect(dirtyRect, 1);
painter()->addDirtyRect(dirtyRect.toAlignedRect());
const QVector<QRect> allDirtyRects =
painter()->calculateAllMirroredRects(dirtyRect.toAlignedRect());
painter()->addDirtyRects(allDirtyRects);
// QPointF scatteredPos =
// m_scatterOption.apply(info,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment