Krita Source Code Documentation
Loading...
Searching...
No Matches
EllipseAssistant.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: 2017 Scott Petrovic <scottpetrovic@gmail.com>
5 *
6 * SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8
9#include "EllipseAssistant.h"
10
11#include <klocalizedstring.h>
12#include "kis_debug.h"
13#include <QPainter>
14#include <QPainterPath>
15#include <QLinearGradient>
16#include <QTransform>
17
18#include <kis_canvas2.h>
20#include "kis_algebra_2d.h"
21
22#include <math.h>
23
25 : KisPaintingAssistant("ellipse", i18n("Ellipse assistant"))
26{
27}
28
29EllipseAssistant::EllipseAssistant(const EllipseAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap)
30 : KisPaintingAssistant(rhs, handleMap)
31 , e(rhs.e)
32{
33}
34
35KisPaintingAssistantSP EllipseAssistant::clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const
36{
37 return KisPaintingAssistantSP(new EllipseAssistant(*this, handleMap));
38}
39
40QPointF EllipseAssistant::project(const QPointF& pt) const
41{
42 Q_ASSERT(isAssistantComplete());
43 e.set(*handles()[0], *handles()[1], *handles()[2]);
44 return e.project(pt);
45}
46
47QPointF EllipseAssistant::adjustPosition(const QPointF& pt, const QPointF& /*strokeBegin*/, const bool /*snapToAny*/, qreal /*moveThresholdPt*/)
48{
49 return project(pt);
50
51}
52
53void EllipseAssistant::adjustLine(QPointF &point, QPointF &strokeBegin)
54{
55 const QPointF p1 = point;
56 const QPointF p2 = strokeBegin;
57
58 Q_ASSERT(isAssistantComplete());
59 e.set(*handles()[0], *handles()[1], *handles()[2]);
60
61 QPointF p3 = e.project(p1);
62 QPointF p4 = e.project(p2);
63 point = p3;
64 strokeBegin = p4;
65}
66
67void EllipseAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached, KisCanvas2* canvas, bool assistantVisible, bool previewVisible)
68{
69 gc.save();
70 gc.resetTransform();
71 QPoint mousePos;
72
73 if (canvas){
74 //simplest, cheapest way to get the mouse-position//
75 mousePos= canvas->canvasWidget()->mapFromGlobal(QCursor::pos());
76 }
77 else {
78 //...of course, you need to have access to a canvas-widget for that.//
79 mousePos = QCursor::pos();//this'll give an offset//
80 dbgFile<<"canvas does not exist in the ellipse assistant, you may have passed arguments incorrectly:"<<canvas;
81 }
82
83 QTransform initialTransform = converter->documentToWidgetTransform();
84
85 if (isSnappingActive() && boundingRect().contains(initialTransform.inverted().map(mousePos), false) && previewVisible==true){
86
88 if (e.set(*handles()[0], *handles()[1], *handles()[2])) {
89 // valid ellipse
90 gc.setTransform(initialTransform);
91 gc.setTransform(e.getInverse(), true);
92 QPainterPath path;
93 //path.moveTo(QPointF(-e.semiMajor(), 0)); path.lineTo(QPointF(e.semiMajor(), 0));
94 //path.moveTo(QPointF(0, -e.semiMinor())); path.lineTo(QPointF(0, e.semiMinor()));
95 // Draw the ellipse
96 path.addEllipse(QPointF(0, 0), e.semiMajor(), e.semiMinor());
97 drawPreview(gc, path);
98 }
99 }
100 }
101 gc.restore();
102 KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached, canvas, assistantVisible, previewVisible);
103
104}
105
106
107void EllipseAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible)
108{
109
110 if (assistantVisible == false || handles().size() < 2){
111 return;
112 }
113
114 QTransform initialTransform = converter->documentToWidgetTransform();
115
116 if (handles().size() == 2) {
117 // just draw the axis
118 gc.setTransform(initialTransform);
119 QPainterPath path;
120 path.moveTo(*handles()[0]);
121 path.lineTo(*handles()[1]);
122 drawPath(gc, path, isSnappingActive());
123 return;
124 }
125 if (e.set(*handles()[0], *handles()[1], *handles()[2])) {
126 // valid ellipse
127
128 gc.setTransform(initialTransform);
129 gc.setTransform(e.getInverse(), true);
130 QPainterPath path;
131 path.moveTo(QPointF(-e.semiMajor(), 0)); path.lineTo(QPointF(e.semiMajor(), 0));
132 path.moveTo(QPointF(0, -e.semiMinor())); path.lineTo(QPointF(0, e.semiMinor()));
133 // Draw the ellipse
134 path.addEllipse(QPointF(0, 0), e.semiMajor(), e.semiMinor());
135 drawPath(gc, path, isSnappingActive());
136 }
137}
138
140{
141 if (!isAssistantComplete()) {
143 }
144
145 if (e.set(*handles()[0], *handles()[1], *handles()[2])) {
146 return e.boundingRect().adjusted(-2, -2, 2, 2).toAlignedRect();
147 } else {
148 return QRect();
149 }
150}
151
153{
154 return (*handles()[0] + *handles()[1]) * 0.5;
155}
156
158{
159 return handles().size() >= 3;
160}
161
162void EllipseAssistant::transform(const QTransform &transform)
163{
164 e.set(*handles()[0], *handles()[1], *handles()[2]);
165
166 QPointF newAxes;
167 QTransform newTransform;
168
169 std::tie(newAxes, newTransform) = KisAlgebra2D::transformEllipse(QPointF(e.semiMajor(), e.semiMinor()), e.getInverse() * transform);
170
171 const QPointF p1 = newTransform.map(QPointF(newAxes.x(), 0));
172 const QPointF p2 = newTransform.map(QPointF(-newAxes.x(), 0));
173 const QPointF p3 = newTransform.map(QPointF(0, newAxes.y()));
174
175 *handles()[0] = p1;
176 *handles()[1] = p2;
177 *handles()[2] = p3;
178
179 uncache();
180}
181
185
189
191{
192 return "ellipse";
193}
194
196{
197 return i18n("Ellipse");
198}
199
QPointF p2
QPointF p3
QPointF p1
QString id() const override
KisPaintingAssistant * createPaintingAssistant() const override
QString name() const override
bool isAssistantComplete() const override
QPointF getDefaultEditorPosition() const override
QPointF adjustPosition(const QPointF &point, const QPointF &strokeBegin, const bool snapToAny, qreal moveThresholdPt) override
QRect boundingRect() 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...
QPointF project(const QPointF &pt) const
void adjustLine(QPointF &point, QPointF &strokeBegin) override
void drawAssistant(QPainter &gc, const QRectF &updateRect, const KisCoordinatesConverter *converter, bool cached, KisCanvas2 *canvas, bool assistantVisible=true, bool previewVisible=true) override
void transform(const QTransform &transform) override
KisPaintingAssistantSP clone(QMap< KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP > &handleMap) const override
qreal semiMajor() const
Definition Ellipse.h:33
const QTransform & getInverse() const
Definition Ellipse.h:32
bool set(const QPointF &m1, const QPointF &m2, const QPointF &p)
Definition Ellipse.cc:23
QRectF boundingRect() const
Definition Ellipse.cc:62
qreal semiMinor() const
Definition Ellipse.h:34
QPointF project(const QPointF &) const
Definition Ellipse.cc:39
KisAbstractCanvasWidget * canvasWidget
virtual QRect boundingRect() const
void drawPath(QPainter &painter, const QPainterPath &path, bool drawActive=true)
void drawPreview(QPainter &painter, const QPainterPath &path)
virtual void drawAssistant(QPainter &gc, const QRectF &updateRect, const KisCoordinatesConverter *converter, bool cached, KisCanvas2 *canvas=0, bool assistantVisible=true, bool previewVisible=true)
const QList< KisPaintingAssistantHandleSP > & handles() const
#define dbgFile
Definition kis_debug.h:53
QSharedPointer< KisPaintingAssistant > KisPaintingAssistantSP
Definition kis_types.h:189
std::pair< QPointF, QTransform > transformEllipse(const QPointF &axes, const QTransform &fullLocalToGlobal)