Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_tool_line_helper.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <QtMath>
10
11#include "kis_algebra_2d.h"
13#include "kis_image.h"
14
17
32
34 KoCanvasResourceProvider *resourceManager,
35 const KUndo2MagicString &transactionText)
36 : KisToolFreehandHelper(infoBuilder,
37 resourceManager,
38 transactionText,
39 new KisSmoothingOptions(false)),
40 m_d(new Private(infoBuilder))
41{
42}
43
48
53
58
60 KisStrokesFacade *strokesFacade)
61{
62 if (!m_d->enabled) return;
63
65 if (m_d->linePoints.isEmpty()) return;
66
67 qreal startAngle = 0.0;
68 if (m_d->linePoints.length() > 1) {
70 m_d->linePoints[1].pos(),
71 0.0);
72 }
73
75 .value<KisPaintOpPresetSP>();
76
77 if (preset->settings()->paintOpSize() <= 1) {
78 KisPaintInformation begin = m_d->linePoints.first();
80 m_d->linePoints.clear();
81 m_d->linePoints.append(begin);
82 m_d->linePoints.append(end);
84 }
85
88
89 initPaintImpl(startAngle, *it, resourceManager(), image, node, strokesFacade);
90 ++it;
91
92 while (it != end) {
93 paintLine(*(it - 1), *it);
94 ++it;
95 }
96}
97
99{
100 if (!m_d->enabled) return;
101
102 // Ignore the elapsed stroke time, so that the line tool will behave as if the whole stroke is
103 // drawn at once. This should prevent any possible spurious dabs caused by airbrushing features.
106
107 if (!m_d->useSensors) {
108 pi = KisPaintInformation(pi.pos());
109 }
110
111 m_d->linePoints.append(pi);
112}
113
114void KisToolLineHelper::addPoint(KoPointerEvent *event, const QPointF &overridePos)
115{
116 if (!m_d->enabled) return;
117
118 // Ignore the elapsed stroke time, so that the line tool will behave as if the whole stroke is
119 // drawn at once. This should prevent any possible spurious dabs caused by airbrushing features.
121 m_d->infoBuilder->continueStroke(event, 0);
122
123 addPoint(pi, overridePos);
124}
125
126void KisToolLineHelper::addPoint(KisPaintInformation pi, const QPointF &overridePos)
127{
128 if (!m_d->enabled) return;
129 if (!m_d->useSensors) {
130 pi = KisPaintInformation(pi.pos());
131 }
132
133 if (!overridePos.isNull()) {
134 pi.setPos(overridePos);
135 }
136
137 if (m_d->linePoints.size() > 1) {
138 const QPointF startPos = m_d->linePoints.first().pos();
139 const QPointF endPos = pi.pos();
140
141 if (!KisAlgebra2D::fuzzyPointCompare(startPos, endPos)) {
142 const qreal maxDistance = kisDistance(startPos, endPos);
143 const QPointF unit = (endPos - startPos) / maxDistance;
144
146 ++it;
147 while (it != m_d->linePoints.end()) {
148 qreal dist = kisDistance(startPos, it->pos());
149 if (dist < maxDistance) {
150 QPointF pos = startPos + unit * dist;
151 it->setPos(pos);
152 ++it;
153 } else {
154 it = m_d->linePoints.erase(it);
155 }
156 }
157 } else {
158 m_d->linePoints.clear();
159 }
160 }
161
162 m_d->linePoints.append(pi);
163
164}
165
166void KisToolLineHelper::translatePoints(const QPointF &offset)
167{
168 if (!m_d->enabled) return;
169
171 while (it != m_d->linePoints.end()) {
172 it->setPos(it->pos() + offset);
173 ++it;
174 }
175}
176
177void KisToolLineHelper::movePointsTo(const QPointF &startPoint, const QPointF &endPoint)
178{
179 if (m_d->linePoints.size() <= 1 ) {
180 return;
181 }
182
183 if (KisAlgebra2D::fuzzyPointCompare(startPoint, endPoint)) {
184 return;
185 }
186
187 if (m_d->linePoints.size() > 1) {
188 const qreal maxDistance = kisDistance(startPoint, endPoint);
189 const QPointF unit = (endPoint - startPoint) / maxDistance;
190
192 ++it;
193 while (it != m_d->linePoints.end()) {
194 qreal dist = kisDistance(startPoint, it->pos());
195 QPointF pos = startPoint + unit * dist;
196 it->setPos(pos);
197 ++it;
198 }
199 }
200}
201
203{
204 if (!m_d->enabled) return;
206
207 endPaint();
208 clearPoints();
209}
210
211
213{
214 if (!m_d->enabled) return;
216
217 cancelPaint();
218 clearPoints();
219}
220
221
223{
224 m_d->linePoints.clear();
225}
226
227
229{
230 if (!m_d->enabled) return;
231
232 cancelPaint();
233}
234
236{
237 int x = qFloor(points.first().pos().x());
238 int y = qFloor(points.first().pos().y());
239
240 int x2 = qFloor(points.last().pos().x());
241 int y2 = qFloor(points.last().pos().y());
242
243 // Width and height of the line
244 int xd = x2 - x;
245 int yd = y2 - y;
246
247 float m = 0;
248 bool lockAxis = true;
249
250 if (xd == 0) {
251 m = 2.0;
252 } else if ( yd != 0) {
253 lockAxis = false;
254 m = (float)yd / (float)xd;
255 }
256
257 float fx = x;
258 float fy = y;
259
260 int inc;
261 int dist;
262
263 if (fabs(m) > 1.0f) {
264 inc = (yd > 0) ? 1 : -1;
265 m = (lockAxis)? 0 : 1.0f / m;
266 m *= inc;
267
268 for (int i = 0; i < points.size(); i++){
269 dist = abs(qFloor(points.at(i).pos().y()) - y);
270 fy = y + (dist * inc);
271 fx = qRound(x + (dist * m));
272 points[i].setPos(QPointF(fx,fy));
273 }
274
275 } else {
276 inc = (xd > 0) ? 1 : -1;
277 m *= inc;
278
279 for (int i = 0; i < points.size(); i++){
280 dist = abs(qFloor(points.at(i).pos().x()) - x);
281 fx = x + (dist * inc);
282 fy = qRound(y + (dist * m));
283 points[i].setPos(QPointF(fx,fy));
284 }
285 }
286}
float value(const T *src, size_t ch)
void setPos(const QPointF &p)
const QPointF & pos() const
KisPaintInformation continueStroke(KoPointerEvent *event, int timeElapsed)
KisPaintInformation startStroke(KoPointerEvent *event, int timeElapsed, const KoCanvasResourceProvider *manager)
void initPaintImpl(qreal startAngle, const KisPaintInformation &pi, KoCanvasResourceProvider *resourceManager, KisImageWSP image, KisNodeSP node, KisStrokesFacade *strokesFacade, KisNodeSP overrideNode=0, KisDefaultBoundsBaseSP bounds=0)
KoCanvasResourceProvider * resourceManager() const
void paintLine(int strokeInfoId, const KisPaintInformation &pi1, const KisPaintInformation &pi2)
KisToolLineHelper(KisPaintingInformationBuilder *infoBuilder, KoCanvasResourceProvider *resourceManager, const KUndo2MagicString &transactionText)
void adjustPointsToDDA(QVector< KisPaintInformation > &points)
void translatePoints(const QPointF &offset)
void setUseSensors(bool value)
void movePointsTo(const QPointF &startPoint, const QPointF &endPoint)
void setEnabled(bool value)
void repaintLine(KisImageWSP image, KisNodeSP node, KisStrokesFacade *strokesFacade)
void start(KoPointerEvent *event, KoCanvasResourceProvider *resourceManager)
void addPoint(KoPointerEvent *event, const QPointF &overridePos=QPointF())
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75
qreal kisDistance(const QPointF &pt1, const QPointF &pt2)
Definition kis_global.h:190
qreal directionBetweenPoints(const QPointF &p1, const QPointF &p2, qreal defaultAngle)
bool fuzzyPointCompare(const QPointF &p1, const QPointF &p2)
QVector< KisPaintInformation > linePoints
KisPaintingInformationBuilder * infoBuilder
Private(KisPaintingInformationBuilder *_infoBuilder)