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

The distance information must be associated with the painter

Each painter of the multihand tool must have its own distance information.
Otherwise the result of the painting is quite random. Now we store both
KisPainter and KisDistanceInformation in a single struct and operate
with them as a single struct as well.

BUG:283606
parent bb040fea
......@@ -42,26 +42,31 @@ protected:
KisImageWSP image) {
Q_UNUSED(image);
return new FreehandStrokeStrategy(indirectPainting, resources, painter);
m_painterInfo =
new FreehandStrokeStrategy::PainterInfo(painter,
new KisDistanceInformation());
return new FreehandStrokeStrategy(indirectPainting, resources, m_painterInfo);
}
void addPaintingJobs(KisImageWSP image, KisResourcesSnapshotSP resources,
KisPainter *painter) {
Q_ASSERT(painter == m_painterInfo->painter);
KisPaintInformation pi1;
KisPaintInformation pi2;
m_dragDistance.clear();
pi1 = KisPaintInformation(QPointF(200, 200));
pi2 = KisPaintInformation(QPointF(300, 300));
image->addJob(strokeId(),
new FreehandStrokeStrategy::Data(resources->currentNode(),
painter, pi1, pi2,
m_dragDistance));
m_painterInfo, pi1, pi2));
}
private:
KisDistanceInformation m_dragDistance;
FreehandStrokeStrategy::PainterInfo *m_painterInfo;
};
void FreehandStrokeTest::testAutobrushStroke()
......
......@@ -27,7 +27,6 @@
#include "kis_painting_information_builder.h"
#include "kis_recording_adapter.h"
#include "kis_image.h"
#include "strokes/freehand_stroke.h"
#include "kis_painter.h"
......@@ -42,12 +41,11 @@ struct KisToolFreehandHelper::Private
bool hasPaintAtLeastOnce;
KisDistanceInformation dragDistance;
QTime strokeTime;
QTimer strokeTimeoutTimer;
QVector<KisPainter*> painters;
QVector<PainterInfo*> painterInfos;
KisResourcesSnapshotSP resources;
KisStrokeId strokeId;
......@@ -104,11 +102,10 @@ void KisToolFreehandHelper::initPaint(KoPointerEvent *event,
m_d->previousTangent = QPointF();
m_d->hasPaintAtLeastOnce = false;
m_d->dragDistance.clear();
m_d->strokeTime.start();
createPainters(m_d->painters);
createPainters(m_d->painterInfos);
m_d->resources = new KisResourcesSnapshot(image,
undoAdapter,
resourceManager);
......@@ -125,7 +122,7 @@ void KisToolFreehandHelper::initPaint(KoPointerEvent *event,
KisStrokeStrategy *stroke =
new FreehandStrokeStrategy(indirectPainting,
m_d->resources, m_d->painters);
m_d->resources, m_d->painterInfos);
m_d->strokeId = m_d->strokesFacade->startStroke(stroke);
......@@ -157,7 +154,7 @@ void KisToolFreehandHelper::paint(KoPointerEvent *event)
qreal scaleFactor = (m_d->previousPaintInformation.currentTime() - m_d->olderPaintInformation.currentTime());
QPointF control1 = m_d->olderPaintInformation.pos() + m_d->previousTangent * scaleFactor;
QPointF control2 = m_d->previousPaintInformation.pos() - newTangent * scaleFactor;
paintBezierCurve(m_d->painters,
paintBezierCurve(m_d->painterInfos,
m_d->olderPaintInformation,
control1,
control2,
......@@ -167,7 +164,7 @@ void KisToolFreehandHelper::paint(KoPointerEvent *event)
m_d->olderPaintInformation = m_d->previousPaintInformation;
m_d->strokeTimeoutTimer.start(100);
} else {
paintLine(m_d->painters, m_d->previousPaintInformation, info);
paintLine(m_d->painterInfos, m_d->previousPaintInformation, info);
}
m_d->previousPaintInformation = info;
......@@ -180,7 +177,7 @@ void KisToolFreehandHelper::paint(KoPointerEvent *event)
void KisToolFreehandHelper::endPaint()
{
if (!m_d->hasPaintAtLeastOnce) {
paintAt(m_d->painters, m_d->previousPaintInformation);
paintAt(m_d->painterInfos, m_d->previousPaintInformation);
} else if (m_d->smooth) {
finishStroke();
}
......@@ -196,7 +193,7 @@ void KisToolFreehandHelper::endPaint()
* Please note that we are not in MT here, so no mutex
* is needed
*/
m_d->painters.clear();
m_d->painterInfos.clear();
m_d->strokesFacade->endStroke(m_d->strokeId);
......@@ -207,7 +204,7 @@ void KisToolFreehandHelper::endPaint()
const KisPaintOp* KisToolFreehandHelper::currentPaintOp() const
{
return !m_d->painters.isEmpty() ? m_d->painters.first()->paintOp() : 0;
return !m_d->painterInfos.isEmpty() ? m_d->painterInfos.first()->painter->paintOp() : 0;
}
......@@ -220,7 +217,7 @@ void KisToolFreehandHelper::finishStroke()
qreal scaleFactor = (m_d->previousPaintInformation.currentTime() - m_d->olderPaintInformation.currentTime());
QPointF control1 = m_d->olderPaintInformation.pos() + m_d->previousTangent * scaleFactor;
QPointF control2 = m_d->previousPaintInformation.pos() - newTangent;
paintBezierCurve(m_d->painters,
paintBezierCurve(m_d->painterInfos,
m_d->olderPaintInformation,
control1,
control2,
......@@ -230,41 +227,39 @@ void KisToolFreehandHelper::finishStroke()
void KisToolFreehandHelper::doAirbrushing()
{
if(!m_d->painters.isEmpty()) {
paintAt(m_d->painters, m_d->previousPaintInformation);
if(!m_d->painterInfos.isEmpty()) {
paintAt(m_d->painterInfos, m_d->previousPaintInformation);
}
}
void KisToolFreehandHelper::paintAt(KisPainter *painter,
void KisToolFreehandHelper::paintAt(PainterInfo *painterInfo,
const KisPaintInformation &pi)
{
m_d->hasPaintAtLeastOnce = true;
m_d->strokesFacade->addJob(m_d->strokeId,
new FreehandStrokeStrategy::Data(m_d->resources->currentNode(),
painter, pi,
m_d->dragDistance));
painterInfo, pi));
if(m_d->recordingAdapter) {
m_d->recordingAdapter->addPoint(pi);
}
}
void KisToolFreehandHelper::paintLine(KisPainter *painter,
void KisToolFreehandHelper::paintLine(PainterInfo *painterInfo,
const KisPaintInformation &pi1,
const KisPaintInformation &pi2)
{
m_d->hasPaintAtLeastOnce = true;
m_d->strokesFacade->addJob(m_d->strokeId,
new FreehandStrokeStrategy::Data(m_d->resources->currentNode(),
painter, pi1, pi2,
m_d->dragDistance));
painterInfo, pi1, pi2));
if(m_d->recordingAdapter) {
m_d->recordingAdapter->addLine(pi1, pi2);
}
}
void KisToolFreehandHelper::paintBezierCurve(KisPainter *painter,
void KisToolFreehandHelper::paintBezierCurve(PainterInfo *painterInfo,
const KisPaintInformation &pi1,
const QPointF &control1,
const QPointF &control2,
......@@ -273,39 +268,38 @@ void KisToolFreehandHelper::paintBezierCurve(KisPainter *painter,
m_d->hasPaintAtLeastOnce = true;
m_d->strokesFacade->addJob(m_d->strokeId,
new FreehandStrokeStrategy::Data(m_d->resources->currentNode(),
painter,
pi1, control1, control2, pi2,
m_d->dragDistance));
painterInfo,
pi1, control1, control2, pi2));
if(m_d->recordingAdapter) {
m_d->recordingAdapter->addCurve(pi1, control1, control2, pi2);
}
}
void KisToolFreehandHelper::createPainters(QVector<KisPainter*> &painters)
void KisToolFreehandHelper::createPainters(QVector<PainterInfo*> &painterInfos)
{
painters << new KisPainter();
painterInfos << new PainterInfo(new KisPainter(), new KisDistanceInformation());
}
void KisToolFreehandHelper::paintAt(const QVector<KisPainter*> &painters,
void KisToolFreehandHelper::paintAt(const QVector<PainterInfo*> &painterInfos,
const KisPaintInformation &pi)
{
paintAt(painters.first(), pi);
paintAt(painterInfos.first(), pi);
}
void KisToolFreehandHelper::paintLine(const QVector<KisPainter*> &painters,
void KisToolFreehandHelper::paintLine(const QVector<PainterInfo*> &painterInfos,
const KisPaintInformation &pi1,
const KisPaintInformation &pi2)
{
paintLine(painters.first(), pi1, pi2);
paintLine(painterInfos.first(), pi1, pi2);
}
void KisToolFreehandHelper::paintBezierCurve(const QVector<KisPainter*> &painters,
void KisToolFreehandHelper::paintBezierCurve(const QVector<PainterInfo*> &painterInfos,
const KisPaintInformation &pi1,
const QPointF &control1,
const QPointF &control2,
const KisPaintInformation &pi2)
{
paintBezierCurve(painters.first(), pi1, control1, control2, pi2);
paintBezierCurve(painterInfos.first(), pi1, control1, control2, pi2);
}
......@@ -24,6 +24,8 @@
#include "kis_types.h"
#include "krita_export.h"
#include "kis_paint_information.h"
#include "strokes/freehand_stroke.h"
class KoPointerEvent;
class KoCanvasResourceManager;
......@@ -39,6 +41,9 @@ class KRITAUI_EXPORT KisToolFreehandHelper : public QObject
{
Q_OBJECT
protected:
typedef FreehandStrokeStrategy::PainterInfo PainterInfo;
public:
KisToolFreehandHelper(KisPaintingInformationBuilder *infoBuilder,
KisRecordingAdapter *recordingAdapter = 0);
......@@ -58,29 +63,29 @@ public:
const KisPaintOp* currentPaintOp() const;
protected:
virtual void createPainters(QVector<KisPainter*> &painters);
virtual void createPainters(QVector<PainterInfo*> &painterInfos);
virtual void paintAt(const QVector<KisPainter*> &painters,
virtual void paintAt(const QVector<PainterInfo*> &painterInfos,
const KisPaintInformation &pi);
virtual void paintLine(const QVector<KisPainter*> &painters,
virtual void paintLine(const QVector<PainterInfo*> &painterInfos,
const KisPaintInformation &pi1,
const KisPaintInformation &pi2);
virtual void paintBezierCurve(const QVector<KisPainter*> &painters,
virtual void paintBezierCurve(const QVector<PainterInfo*> &painterInfos,
const KisPaintInformation &pi1,
const QPointF &control1,
const QPointF &control2,
const KisPaintInformation &pi2);
protected:
void paintAt(KisPainter *painter, const KisPaintInformation &pi);
void paintAt(PainterInfo *painterInfo, const KisPaintInformation &pi);
void paintLine(KisPainter *painter,
void paintLine(PainterInfo *painterInfo,
const KisPaintInformation &pi1,
const KisPaintInformation &pi2);
void paintBezierCurve(KisPainter *painter,
void paintBezierCurve(PainterInfo *painterInfo,
const KisPaintInformation &pi1,
const QPointF &control1,
const QPointF &control2,
......
......@@ -40,17 +40,17 @@ void KisToolMultihandHelper::setupTransformations(const QVector<QTransform> &tra
m_d->transformations = transformations;
}
void KisToolMultihandHelper::createPainters(QVector<KisPainter*> &painters)
void KisToolMultihandHelper::createPainters(QVector<PainterInfo*> &painterInfos)
{
for (int i = 0; i < m_d->transformations.size(); i++) {
painters << new KisPainter();
painterInfos << new PainterInfo(new KisPainter(), new KisDistanceInformation());
}
}
void KisToolMultihandHelper::paintAt(const QVector<KisPainter*> &painters,
void KisToolMultihandHelper::paintAt(const QVector<PainterInfo*> &painterInfos,
const KisPaintInformation &pi)
{
Q_ASSERT(painters.size() == m_d->transformations.size());
Q_ASSERT(painterInfos.size() == m_d->transformations.size());
for (int i = 0; i < m_d->transformations.size(); i++) {
const QTransform &transform = m_d->transformations[i];
......@@ -58,15 +58,15 @@ void KisToolMultihandHelper::paintAt(const QVector<KisPainter*> &painters,
KisPaintInformation __pi = pi;
__pi.setPos(transform.map(__pi.pos()));
paintAt(painters[i], __pi);
paintAt(painterInfos[i], __pi);
}
}
void KisToolMultihandHelper::paintLine(const QVector<KisPainter*> &painters,
void KisToolMultihandHelper::paintLine(const QVector<PainterInfo*> &painterInfos,
const KisPaintInformation &pi1,
const KisPaintInformation &pi2)
{
Q_ASSERT(painters.size() == m_d->transformations.size());
Q_ASSERT(painterInfos.size() == m_d->transformations.size());
for (int i = 0; i < m_d->transformations.size(); i++) {
const QTransform &transform = m_d->transformations[i];
......@@ -76,17 +76,17 @@ void KisToolMultihandHelper::paintLine(const QVector<KisPainter*> &painters,
__pi1.setPos(transform.map(__pi1.pos()));
__pi2.setPos(transform.map(__pi2.pos()));
paintLine(painters[i], __pi1, __pi2);
paintLine(painterInfos[i], __pi1, __pi2);
}
}
void KisToolMultihandHelper::paintBezierCurve(const QVector<KisPainter*> &painters,
void KisToolMultihandHelper::paintBezierCurve(const QVector<PainterInfo*> &painterInfos,
const KisPaintInformation &pi1,
const QPointF &control1,
const QPointF &control2,
const KisPaintInformation &pi2)
{
Q_ASSERT(painters.size() == m_d->transformations.size());
Q_ASSERT(painterInfos.size() == m_d->transformations.size());
for (int i = 0; i < m_d->transformations.size(); i++) {
const QTransform &transform = m_d->transformations[i];
......@@ -99,6 +99,6 @@ void KisToolMultihandHelper::paintBezierCurve(const QVector<KisPainter*> &painte
QPointF __control1 = transform.map(control1);
QPointF __control2 = transform.map(control2);
paintBezierCurve(painters[i], __pi1, __control1, __control2, __pi2);
paintBezierCurve(painterInfos[i], __pi1, __control1, __control2, __pi2);
}
}
......@@ -33,16 +33,16 @@ public:
void setupTransformations(const QVector<QTransform> &transformations);
protected:
void createPainters(QVector<KisPainter*> &painters);
void createPainters(QVector<PainterInfo*> &painterInfos);
void paintAt(const QVector<KisPainter*> &painters,
void paintAt(const QVector<PainterInfo*> &painterInfos,
const KisPaintInformation &pi);
void paintLine(const QVector<KisPainter*> &painters,
void paintLine(const QVector<PainterInfo*> &painterInfos,
const KisPaintInformation &pi1,
const KisPaintInformation &pi2);
void paintBezierCurve(const QVector<KisPainter*> &painters,
void paintBezierCurve(const QVector<PainterInfo*> &painterInfos,
const KisPaintInformation &pi1,
const QPointF &control1,
const QPointF &control2,
......
......@@ -27,18 +27,18 @@
FreehandStrokeStrategy::FreehandStrokeStrategy(bool needsIndirectPainting,
KisResourcesSnapshotSP resources,
KisPainter *painter)
PainterInfo *painterInfo)
: KisPainterBasedStrokeStrategy("FREEHAND_STROKE", "Freehand stroke",
resources, painter)
resources, painterInfo)
{
init(needsIndirectPainting);
}
FreehandStrokeStrategy::FreehandStrokeStrategy(bool needsIndirectPainting,
KisResourcesSnapshotSP resources,
QVector<KisPainter*> painters)
QVector<PainterInfo*> painterInfos)
: KisPainterBasedStrokeStrategy("FREEHAND_STROKE", "Freehand stroke",
resources, painters)
resources, painterInfos)
{
init(needsIndirectPainting);
}
......@@ -52,26 +52,27 @@ void FreehandStrokeStrategy::init(bool needsIndirectPainting)
void FreehandStrokeStrategy::doStrokeCallback(KisStrokeJobData *data)
{
Data *d = dynamic_cast<Data*>(data);
PainterInfo *info = d->painterInfo;
switch(d->type) {
case Data::POINT:
d->dragDistance = KisDistanceInformation(0,0);
d->painter->paintAt(d->pi1);
d->node->setDirty(d->painter->takeDirtyRegion());
*info->dragDistance = KisDistanceInformation(0,0);
info->painter->paintAt(d->pi1);
d->node->setDirty(info->painter->takeDirtyRegion());
break;
case Data::LINE:
d->dragDistance =
d->painter->paintLine(d->pi1, d->pi2, d->dragDistance);
d->node->setDirty(d->painter->takeDirtyRegion());
*info->dragDistance =
info->painter->paintLine(d->pi1, d->pi2, *info->dragDistance);
d->node->setDirty(info->painter->takeDirtyRegion());
break;
case Data::CURVE:
d->dragDistance =
d->painter->paintBezierCurve(d->pi1,
d->control1,
d->control2,
d->pi2,
d->dragDistance);
d->node->setDirty(d->painter->takeDirtyRegion());
*info->dragDistance =
info->painter->paintBezierCurve(d->pi1,
d->control1,
d->control2,
d->pi2,
*info->dragDistance);
d->node->setDirty(info->painter->takeDirtyRegion());
break;
};
}
......@@ -40,56 +40,48 @@ public:
CURVE
};
Data(KisNodeSP _node, KisPainter *_painter,
const KisPaintInformation &_pi,
KisDistanceInformation &_dragDistance)
: node(_node), painter(_painter),
type(POINT), pi1(_pi),
dragDistance(_dragDistance)
Data(KisNodeSP _node, PainterInfo *_painterInfo,
const KisPaintInformation &_pi)
: node(_node), painterInfo(_painterInfo),
type(POINT), pi1(_pi)
{}
Data(KisNodeSP _node, KisPainter *_painter,
Data(KisNodeSP _node, PainterInfo *_painterInfo,
const KisPaintInformation &_pi1,
const KisPaintInformation &_pi2,
KisDistanceInformation &_dragDistance)
: node(_node), painter(_painter),
type(LINE), pi1(_pi1), pi2(_pi2),
dragDistance(_dragDistance)
const KisPaintInformation &_pi2)
: node(_node), painterInfo(_painterInfo),
type(LINE), pi1(_pi1), pi2(_pi2)
{}
Data(KisNodeSP _node, KisPainter *_painter,
Data(KisNodeSP _node, PainterInfo *_painterInfo,
const KisPaintInformation &_pi1,
const QPointF &_control1,
const QPointF &_control2,
const KisPaintInformation &_pi2,
KisDistanceInformation &_dragDistance)
: node(_node), painter(_painter),
const KisPaintInformation &_pi2)
: node(_node), painterInfo(_painterInfo),
type(CURVE), pi1(_pi1), pi2(_pi2),
control1(_control1), control2(_control2),
dragDistance(_dragDistance)
control1(_control1), control2(_control2)
{}
KisNodeSP node;
KisPainter *painter;
PainterInfo *painterInfo;
DabType type;
KisPaintInformation pi1;
KisPaintInformation pi2;
QPointF control1;
QPointF control2;
KisDistanceInformation &dragDistance;
};
public:
FreehandStrokeStrategy(bool needsIndirectPainting,
KisResourcesSnapshotSP resources,
KisPainter *painter);
PainterInfo *painterInfo);
FreehandStrokeStrategy(bool needsIndirectPainting,
KisResourcesSnapshotSP resources,
QVector<KisPainter*> painters);
QVector<PainterInfo*> painterInfos);
void doStrokeCallback(KisStrokeJobData *data);
......
......@@ -26,14 +26,28 @@
#include "kis_selection.h"
#include "kis_transaction.h"
#include "kis_image.h"
#include "kis_distance_information.h"
KisPainterBasedStrokeStrategy::PainterInfo::PainterInfo(KisPainter *_painter, KisDistanceInformation *_dragDistance)
: painter(_painter), dragDistance(_dragDistance)
{
}
KisPainterBasedStrokeStrategy::PainterInfo::~PainterInfo()
{
delete(painter);
delete(dragDistance);
}
KisPainterBasedStrokeStrategy::KisPainterBasedStrokeStrategy(const QString &id,
const QString &name,
KisResourcesSnapshotSP resources,
QVector<KisPainter*> painters)
QVector<PainterInfo*> painterInfos)
: KisSimpleStrokeStrategy(id, name),
m_resources(resources),
m_painters(painters),
m_painterInfos(painterInfos),
m_transaction(0)
{
init();
......@@ -42,10 +56,10 @@ KisPainterBasedStrokeStrategy::KisPainterBasedStrokeStrategy(const QString &id,
KisPainterBasedStrokeStrategy::KisPainterBasedStrokeStrategy(const QString &id,
const QString &name,
KisResourcesSnapshotSP resources,
KisPainter *painter)
PainterInfo *painterInfo)
: KisSimpleStrokeStrategy(id, name),
m_resources(resources),
m_painters(QVector<KisPainter*>() << painter),
m_painterInfos(QVector<PainterInfo*>() << painterInfo),
m_transaction(0)
{
init();
......@@ -62,7 +76,9 @@ void KisPainterBasedStrokeStrategy::initPainters(KisPaintDeviceSP targetDevice,
KisSelectionSP selection,
bool hasIndirectPainting)
{
foreach(KisPainter *painter, m_painters) {
foreach(PainterInfo *info, m_painterInfos) {
KisPainter *painter = info->painter;
painter->begin(targetDevice, selection);
m_resources->setupPainter(painter);
......@@ -76,10 +92,11 @@ void KisPainterBasedStrokeStrategy::initPainters(KisPaintDeviceSP targetDevice,
void KisPainterBasedStrokeStrategy::deletePainters()
{
foreach(KisPainter *painter, m_painters) {
delete painter;
foreach(PainterInfo *info, m_painterInfos) {
delete info;
}
m_painters.clear();
m_painterInfos.clear();
}
void KisPainterBasedStrokeStrategy::initStrokeCallback()
......
......@@ -23,21 +23,36 @@
#include "kis_resources_snapshot.h"
class KisPainter;
class KisDistanceInformation;
class KisTransaction;
class KRITAUI_EXPORT KisPainterBasedStrokeStrategy : public KisSimpleStrokeStrategy
{
public:
/**
* The distance information should be associated with each
* painter individually, so we strore and manipulate with
* them together using the structure PainterInfo