Krita Source Code Documentation
Loading...
Searching...
No Matches
ParallelRulerAssistant.cc
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2008 Cyrille Berger <cberger@cberger.net>
3 * SPDX-FileCopyrightText: 2010 Geoffry Song <goffrie@gmail.com>
4 * SPDX-FileCopyrightText: 2014 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
5 * SPDX-FileCopyrightText: 2017 Scott Petrovic <scottpetrovic@gmail.com>
6 *
7 * SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9
11
12#include "kis_debug.h"
13#include <klocalizedstring.h>
14
15#include <QPainter>
16#include <QPainterPath>
17#include <QLinearGradient>
18#include <QTransform>
19
20#include <kis_canvas2.h>
22#include <kis_algebra_2d.h>
23#include <kis_dom_utils.h>
24
25#include <math.h>
26
28 : KisPaintingAssistant("parallel ruler", i18n("Parallel Ruler assistant"))
29{
30}
31
32KisPaintingAssistantSP ParallelRulerAssistant::clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const
33{
34 return KisPaintingAssistantSP(new ParallelRulerAssistant(*this, handleMap));
35}
36
37ParallelRulerAssistant::ParallelRulerAssistant(const ParallelRulerAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap)
38 : KisPaintingAssistant(rhs, handleMap)
39{
40}
41
42QPointF ParallelRulerAssistant::project(const QPointF& pt, const QPointF& strokeBegin, qreal /*moveThresholdPt*/)
43{
44 Q_ASSERT(isAssistantComplete());
45
46 if (isLocal() && isAssistantComplete()) {
47 if (getLocalRect().contains(pt)) {
49 } else if (isLocal() && !m_hasBeenInsideLocalRect) {
50 return QPointF(qQNaN(), qQNaN());
51 }
52 }
53
54 //dbgKrita<<strokeBegin<< ", " <<*handles()[0];
55 QLineF snapLine = QLineF(*handles()[0], *handles()[1]);
56 QPointF translation = (*handles()[0]-strokeBegin)*-1.0;
57 snapLine = snapLine.translated(translation);
58
59 qreal dx = snapLine.dx();
60 qreal dy = snapLine.dy();
61
62 const qreal
63 dx2 = dx * dx,
64 dy2 = dy * dy,
65 invsqrlen = 1.0 / (dx2 + dy2);
66 QPointF r(dx2 * pt.x() + dy2 * snapLine.x1() + dx * dy * (pt.y() - snapLine.y1()),
67 dx2 * snapLine.y1() + dy2 * pt.y() + dx * dy * (pt.x() - snapLine.x1()));
68 r *= invsqrlen;
69 return r;
70}
71
72QPointF ParallelRulerAssistant::adjustPosition(const QPointF& pt, const QPointF& strokeBegin, const bool /*snapToAny*/, qreal moveThresholdPt)
73{
74 return project(pt, strokeBegin, moveThresholdPt);
75}
76
77void ParallelRulerAssistant::adjustLine(QPointF &point, QPointF &strokeBegin)
78{
79 point = project(point, strokeBegin, 0.0);
80}
81
82void ParallelRulerAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached, KisCanvas2* canvas, bool assistantVisible, bool previewVisible)
83{
84 gc.save();
85 gc.resetTransform();
86
87 QTransform initialTransform = converter->documentToWidgetTransform();
88 QRectF local = getLocalRect();
89 QRectF localTransformed = initialTransform.mapRect(local);
90 const QRect viewport= gc.viewport();
91 QPolygonF viewportAndLocal = !localTransformed.isEmpty() ? QPolygonF(QRectF(viewport)).intersected(localTransformed) : QRectF(viewport);
92
93
94
95 if (assistantVisible && isLocal() && isAssistantComplete()) {
96 QPainterPath path;
97 // note: be careful; bottom and right only work with RectF, not Rect
98 path.moveTo(initialTransform.map(local.topLeft()));
99
100 path.lineTo(initialTransform.map(local.topRight()));
101 path.lineTo(initialTransform.map(local.bottomRight()));
102 path.lineTo(initialTransform.map(local.bottomLeft()));
103 path.lineTo(initialTransform.map(local.topLeft()));
104 drawPath(gc, path, isSnappingActive());//and we draw the preview.
105 }
106
107
108 if (isAssistantComplete() && isSnappingActive() && previewVisible==true) {
109 //don't draw if invalid.
110 QLineF snapLine= QLineF(initialTransform.map(*handles()[0]), initialTransform.map(*handles()[1]));
111
112 QPointF mousePos = effectiveBrushPosition(converter, canvas);
113
114 QPointF translation = (initialTransform.map(*handles()[0])-mousePos)*-1.0;
115 snapLine= snapLine.translated(translation);
116
117 KisAlgebra2D::cropLineToConvexPolygon(snapLine, viewportAndLocal, true, true);
118
119
120 QPainterPath path;
121 path.moveTo(snapLine.p1());
122 path.lineTo(snapLine.p2());
123
124 drawPreview(gc, path);//and we draw the preview.
125 }
126 gc.restore();
127
128 KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached, canvas, assistantVisible, previewVisible);
129
130}
131
132void ParallelRulerAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible)
133{
134 if (assistantVisible == false || handles().size() < 2) {
135 return;
136 }
137
138 QTransform initialTransform = converter->documentToWidgetTransform();
139
140 // Draw the line
141 QPointF p1 = *handles()[0];
142 QPointF p2 = *handles()[1];
143
144 gc.setTransform(initialTransform);
145 QPainterPath path;
146 path.moveTo(p1);
147 path.lineTo(p2);
148 drawPath(gc, path, isSnappingActive());
149
150}
151
153{
154 return handles().size() > 2 ? handles()[2] : 0;
155}
156
158{
159 return handles().size() > 3 ? handles()[3] : 0;
160}
161
163{
164 if (handles().size() > 1) {
165 return (*handles()[0] + *handles()[1]) * 0.5;
166 } else if (handles().size() > 0) {
168 return *handles()[0];
169 } else {
170 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(false, QPointF(0, 0));
171 return QPointF(0, 0);
172 }
173}
174
176{
177 return handles().size() >= numHandles();
178}
179
181{
182 return true;
183}
184
185void ParallelRulerAssistant::saveCustomXml(QXmlStreamWriter *xml)
186{
187 xml->writeStartElement("isLocal");
188 xml->writeAttribute("value", KisDomUtils::toString( (int)this->isLocal()));
189 xml->writeEndElement();
190}
191
192bool ParallelRulerAssistant::loadCustomXml(QXmlStreamReader *xml)
193{
194 if (xml && xml->name() == "isLocal") {
195 this->setLocal((bool)KisDomUtils::toInt(xml->attributes().value("value").toString()));
196 }
197 return true;
198}
199
203
207
209{
210 return "parallel ruler";
211}
212
214{
215 return i18n("Parallel Ruler");
216}
217
QPointF p2
QPointF p1
QPointF effectiveBrushPosition(const KisCoordinatesConverter *converter, KisCanvas2 *canvas) const
Query the effective brush position to be used for preview lines. This is intended to be used for pain...
void drawPath(QPainter &painter, const QPainterPath &path, bool drawActive=true)
void drawPreview(QPainter &painter, const QPainterPath &path)
QRectF getLocalRect() const
getLocalRect The function deals with local handles not being topLeft and bottomRight gracefully and r...
virtual void drawAssistant(QPainter &gc, const QRectF &updateRect, const KisCoordinatesConverter *converter, bool cached, KisCanvas2 *canvas=0, bool assistantVisible=true, bool previewVisible=true)
void setLocal(bool value)
setLocal
const QList< KisPaintingAssistantHandleSP > & handles() const
KisPaintingAssistant * createPaintingAssistant() const override
QPointF getDefaultEditorPosition() const override
QPointF project(const QPointF &pt, const QPointF &strokeBegin, qreal moveThresholdPt)
void adjustLine(QPointF &point, QPointF &strokeBegin) override
KisPaintingAssistantSP clone(QMap< KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP > &handleMap) const override
int numHandles() const override
void drawCache(QPainter &gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override
performance layer where the graphics can be drawn from a cache instead of generated every render upda...
void drawAssistant(QPainter &gc, const QRectF &updateRect, const KisCoordinatesConverter *converter, bool cached=true, KisCanvas2 *canvas=0, bool assistantVisible=true, bool previewVisible=true) override
bool loadCustomXml(QXmlStreamReader *xml) override
KisPaintingAssistantHandleSP secondLocalHandle() const override
secondLocalHandle Note: this doesn't guarantee it will be the bottomRight corner! For that,...
QPointF adjustPosition(const QPointF &point, const QPointF &strokeBegin, const bool snapToAny, qreal moveThresholdPt) override
void saveCustomXml(QXmlStreamWriter *xml) override
KisPaintingAssistantHandleSP firstLocalHandle() const override
firstLocalHandle Note: this doesn't guarantee it will be the topleft corner! For that,...
bool canBeLocal() const override
canBeLocal
bool isAssistantComplete() const override
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
QSharedPointer< KisPaintingAssistant > KisPaintingAssistantSP
Definition kis_types.h:189
void cropLineToConvexPolygon(QLineF &line, const QPolygonF polygon, bool extendFirst, bool extendSecond)
int toInt(const QString &str, bool *ok=nullptr)
QString toString(const QString &value)