Krita Source Code Documentation
Loading...
Searching...
No Matches
EnhancedPathCommand Class Reference

#include <EnhancedPathCommand.h>

Public Member Functions

void addParameter (EnhancedPathParameter *parameter)
 Adds a new parameter to the command.
 
 EnhancedPathCommand (const QChar &command, EnhancedPathShape *parent)
 Constructs a new command from the given command type.
 
bool execute ()
 Executes the command on the specified path shape.
 
QString toString () const
 Returns a string representation of the command.
 
 ~EnhancedPathCommand ()
 

Private Member Functions

qreal angleFromPoint (const QPointF &point) const
 Calculates angle from given point.
 
qreal degSweepAngle (qreal start, qreal stop, bool clockwise) const
 Returns sweep angle from start to stop and given direction.
 
KoPathPointlastPathPoint () const
 Returns the last path point of given path.
 
QList< QPointF > pointsFromParameters ()
 Returns a list of points, created from the parameter list.
 
qreal radSweepAngle (qreal start, qreal stop, bool clockwise) const
 Returns sweep angle from start to stop and given direction.
 
QRectF rectFromPoints (const QPointF &tl, const QPointF &br) const
 Returns rectangle from given points.
 

Private Attributes

QChar m_command
 the actual command
 
QList< EnhancedPathParameter * > m_parameters
 the commands parameters
 
EnhancedPathShapem_parent
 the enhanced path owning the command
 

Detailed Description

A EnhancedPathCommand is a command like moveto, curveto, etc. that directly modifies an enhanced paths outline.

Definition at line 23 of file EnhancedPathCommand.h.

Constructor & Destructor Documentation

◆ EnhancedPathCommand()

EnhancedPathCommand::EnhancedPathCommand ( const QChar & command,
EnhancedPathShape * parent )

Constructs a new command from the given command type.

Definition at line 18 of file EnhancedPathCommand.cpp.

19 : m_command(command)
20 , m_parent(parent)
21{
22 Q_ASSERT(m_parent);
23}
QChar m_command
the actual command
EnhancedPathShape * m_parent
the enhanced path owning the command

References m_parent.

◆ ~EnhancedPathCommand()

EnhancedPathCommand::~EnhancedPathCommand ( )

Definition at line 25 of file EnhancedPathCommand.cpp.

26{
27}

Member Function Documentation

◆ addParameter()

void EnhancedPathCommand::addParameter ( EnhancedPathParameter * parameter)

Adds a new parameter to the command.

Definition at line 234 of file EnhancedPathCommand.cpp.

235{
236 if (parameter) {
237 m_parameters.append(parameter);
238 }
239}
QList< EnhancedPathParameter * > m_parameters
the commands parameters

References m_parameters.

◆ angleFromPoint()

qreal EnhancedPathCommand::angleFromPoint ( const QPointF & point) const
private

Calculates angle from given point.

Definition at line 241 of file EnhancedPathCommand.cpp.

242{
243 qreal angle = atan2(point.y(), point.x());
244 if (angle < 0.0) {
245 angle += 2 * M_PI;
246 }
247
248 return 2 * M_PI - angle;
249}
#define M_PI
Definition kis_global.h:111
KRITAIMAGE_EXPORT qreal atan2(qreal y, qreal x)
atan2 replacement

References M_PI.

◆ degSweepAngle()

qreal EnhancedPathCommand::degSweepAngle ( qreal start,
qreal stop,
bool clockwise ) const
private

Returns sweep angle from start to stop and given direction.

Definition at line 272 of file EnhancedPathCommand.cpp.

273{
274 qreal sweepAngle = stop - start;
275 if (fabs(sweepAngle) < 0.1) {
276 return 360.0;
277 }
278 if (clockwise) {
279 // we are moving clockwise to the end angle
280 if (stop > start) {
281 sweepAngle = (stop - start) - 360.0;
282 }
283 } else {
284 // we are moving counter-clockwise to the stop angle
285 if (start > stop) {
286 sweepAngle = 360.0 - (start - stop);
287 }
288 }
289
290 return sweepAngle;
291}

◆ execute()

bool EnhancedPathCommand::execute ( )

Executes the command on the specified path shape.

Definition at line 29 of file EnhancedPathCommand.cpp.

30{
31 /*
32 * The parameters of the commands are in viewbox coordinates, which have
33 * to be converted to the shapes coordinate system by calling viewboxToShape
34 * on the enhanced path the command works on.
35 * Parameters which resemble angles are angles corresponding to the viewbox
36 * coordinate system. Those have to be transformed into angles corresponding
37 * to the normal mathematically coordinate system to be used for the arcTo
38 * drawing routine. This is done by computing (2*M_PI - angle).
39 */
41 const int pointsCount = points.size();
42
43 switch (m_command.unicode()) {
44 // starts new subpath at given position (x y) +
45 case 'M':
46 if (!pointsCount) {
47 return false;
48 }
49 m_parent->moveTo(points[0]);
50 if (pointsCount > 1)
51 for (int i = 1; i < pointsCount; i++) {
52 m_parent->lineTo(points[i]);
53 }
54 break;
55 // line from current point (x y) +
56 case 'L':
57 Q_FOREACH (const QPointF &point, points) {
58 m_parent->lineTo(point);
59 }
60 break;
61 // cubic bezier curve from current point (x1 y1 x2 y2 x y) +
62 case 'C':
63 for (int i = 0; i < pointsCount; i += 3) {
64 m_parent->curveTo(points[i], points[i + 1], points[i + 2]);
65 }
66 break;
67 // closes the current subpath
68 case 'Z':
69 m_parent->close();
70 break;
71 // ends the current set of subpaths
72 case 'N':
73 // N just ends the complete path
74 break;
75 // no fill for current set of subpaths
76 case 'F':
77 // TODO implement me
78 break;
79 // no stroke for current set of subpaths
80 case 'S':
81 // TODO implement me
82 break;
83 // segment of an ellipse (x y w h t0 t1) +
84 case 'T':
85 // same like T but with implied movement to starting point (x y w h t0 t1) +
86 case 'U': {
87 bool lineTo = m_command.unicode() == 'T';
88
89 for (int i = 0; i < pointsCount; i += 3) {
90 const QPointF &radii = points[i + 1];
91 const QPointF &angles = points[i + 2] / rad2deg;
92 // compute the ellipses starting point
93 QPointF start(radii.x() * cos(angles.x()), -1 * radii.y() * sin(angles.x()));
94 qreal sweepAngle = degSweepAngle(points[i + 2].x(), points[i + 2].y(), false);
95
96 if (lineTo) {
97 m_parent->lineTo(points[i] + start);
98 } else {
99 m_parent->moveTo(points[i] + start);
100 }
101
102 m_parent->arcTo(radii.x(), radii.y(), points[i + 2].x(), sweepAngle);
103 }
104 break;
105 }
106 // counter-clockwise arc (x1 y1 x2 y2 x3 y3 x y) +
107 case 'A':
108 // the same as A, with implied moveto to the starting point (x1 y1 x2 y2 x3 y3 x y) +
109 case 'B':
110 // clockwise arc (x1 y1 x2 y2 x3 y3 x y) +
111 case 'W':
112 // the same as W, but implied moveto (x1 y1 x2 y2 x3 y3 x y) +
113 case 'V': {
114 bool lineTo = ((m_command.unicode() == 'A') || (m_command.unicode() == 'W'));
115 bool clockwise = ((m_command.unicode() == 'W') || (m_command.unicode() == 'V'));
116 for (int i = 0; i < pointsCount; i += 4) {
117 QRectF bbox = rectFromPoints(points[i], points[i + 1]);
118 QPointF center = bbox.center();
119 qreal rx = 0.5 * bbox.width();
120 qreal ry = 0.5 * bbox.height();
121
122 if (rx == 0) {
123 rx = 1;
124 }
125
126 if (ry == 0) {
127 ry = 1;
128 }
129
130 QPointF startRadialVector = points[i + 2] - center;
131 QPointF endRadialVector = points[i + 3] - center;
132
133 // convert from ellipse space to unit-circle space
134 qreal x0 = startRadialVector.x() / rx;
135 qreal y0 = startRadialVector.y() / ry;
136
137 qreal x1 = endRadialVector.x() / rx;
138 qreal y1 = endRadialVector.y() / ry;
139
140 qreal startAngle = angleFromPoint(QPointF(x0, y0));
141 qreal stopAngle = angleFromPoint(QPointF(x1, y1));
142
143 // we are moving counter-clockwise to the end angle
144 qreal sweepAngle = radSweepAngle(startAngle, stopAngle, clockwise);
145 // compute the starting point to draw the line to
146 // as the point x3 y3 is not on the ellipse, spec says the point define radial vector
147 QPointF startPoint(rx * cos(startAngle), ry * sin(2 * M_PI - startAngle));
148
149 // if A or W is first command in enhanced path
150 // move to the starting point
151 bool isFirstCommandInPath = (m_parent->subpathCount() == 0);
152 bool isFirstCommandInSubpath = m_parent->isClosedSubpath(m_parent->subpathCount() - 1);
153
154 if (lineTo && !isFirstCommandInPath && !isFirstCommandInSubpath) {
155 m_parent->lineTo(center + startPoint);
156 } else {
157 m_parent->moveTo(center + startPoint);
158 }
159
160 m_parent->arcTo(rx, ry, startAngle * rad2deg, sweepAngle * rad2deg);
161 }
162 break;
163 }
164 // elliptical quadrant (initial segment tangential to x-axis) (x y) +
165 case 'X': {
166 KoPathPoint *lastPoint = lastPathPoint();
167 bool xDir = true;
168 foreach (const QPointF &point, points) {
169 qreal rx = point.x() - lastPoint->point().x();
170 qreal ry = point.y() - lastPoint->point().y();
171 qreal startAngle = xDir ? (ry > 0.0 ? 90.0 : 270.0) : (rx < 0.0 ? 0.0 : 180.0);
172 qreal sweepAngle = xDir ? (rx * ry < 0.0 ? 90.0 : -90.0) : (rx * ry > 0.0 ? 90.0 : -90.0);
173 lastPoint = m_parent->arcTo(fabs(rx), fabs(ry), startAngle, sweepAngle);
174 xDir = !xDir;
175 }
176 break;
177 }
178 // elliptical quadrant (initial segment tangential to y-axis) (x y) +
179 case 'Y': {
180 KoPathPoint *lastPoint = lastPathPoint();
181 bool xDir = false;
182 foreach (const QPointF &point, points) {
183 qreal rx = point.x() - lastPoint->point().x();
184 qreal ry = point.y() - lastPoint->point().y();
185 qreal startAngle = xDir ? (ry > 0.0 ? 90.0 : 270.0) : (rx < 0.0 ? 0.0 : 180.0);
186 qreal sweepAngle = xDir ? (rx * ry < 0.0 ? 90.0 : -90.0) : (rx * ry > 0.0 ? 90.0 : -90.0);
187 lastPoint = m_parent->arcTo(fabs(rx), fabs(ry), startAngle, sweepAngle);
188 xDir = !xDir;
189 }
190 break;
191 }
192 // quadratic bezier curve (x1 y1 x y)+
193 case 'Q':
194 for (int i = 0; i < pointsCount; i += 2) {
195 m_parent->curveTo(points[i], points[i + 1]);
196 }
197 break;
198 default:
199 break;
200 }
201 return true;
202}
const qreal rad2deg
QRectF rectFromPoints(const QPointF &tl, const QPointF &br) const
Returns rectangle from given points.
KoPathPoint * lastPathPoint() const
Returns the last path point of given path.
QList< QPointF > pointsFromParameters()
Returns a list of points, created from the parameter list.
qreal radSweepAngle(qreal start, qreal stop, bool clockwise) const
Returns sweep angle from start to stop and given direction.
qreal degSweepAngle(qreal start, qreal stop, bool clockwise) const
Returns sweep angle from start to stop and given direction.
qreal angleFromPoint(const QPointF &point) const
Calculates angle from given point.
A KoPathPoint represents a point in a path.
QPointF point
bool isClosedSubpath(int subpathIndex) const
Checks if a subpath is closed.
KoPathPoint * lineTo(const QPointF &p)
Adds a new line segment.
void close()
Closes the current subpath.
KoPathPoint * moveTo(const QPointF &p)
Starts a new Subpath.
KoPathPoint * arcTo(qreal rx, qreal ry, qreal startAngle, qreal sweepAngle)
Add an arc.
KoPathPoint * curveTo(const QPointF &c1, const QPointF &c2, const QPointF &p)
Adds a new cubic Bezier curve segment.
int subpathCount() const
Returns the number of subpaths in the path.

References angleFromPoint(), KoPathShape::arcTo(), KoPathShape::close(), KoPathShape::curveTo(), degSweepAngle(), KoPathShape::isClosedSubpath(), lastPathPoint(), KoPathShape::lineTo(), m_command, m_parent, M_PI, KoPathShape::moveTo(), KoPathPoint::point, pointsFromParameters(), rad2deg, radSweepAngle(), rectFromPoints(), and KoPathShape::subpathCount().

◆ lastPathPoint()

KoPathPoint * EnhancedPathCommand::lastPathPoint ( ) const
private

Returns the last path point of given path.

Definition at line 293 of file EnhancedPathCommand.cpp.

294{
295 KoPathPoint *lastPoint = 0;
296 int subpathCount = m_parent->subpathCount();
297 if (subpathCount) {
298 int subpathPointCount = m_parent->subpathPointCount(subpathCount - 1);
299 lastPoint = m_parent->pointByIndex(KoPathPointIndex(subpathCount - 1, subpathPointCount - 1));
300 }
301 return lastPoint;
302}
QPair< int, int > KoPathPointIndex
Definition KoPathShape.h:28
int subpathPointCount(int subpathIndex) const
Returns the number of points in a subpath.
KoPathPoint * pointByIndex(const KoPathPointIndex &pointIndex) const
Returns the path point specified by a path point index.

References m_parent, KoPathShape::pointByIndex(), KoPathShape::subpathCount(), and KoPathShape::subpathPointCount().

◆ pointsFromParameters()

QList< QPointF > EnhancedPathCommand::pointsFromParameters ( )
private

Returns a list of points, created from the parameter list.

Definition at line 204 of file EnhancedPathCommand.cpp.

205{
206 QList<QPointF> points;
207 QPointF p;
208
209 int paramCount = m_parameters.count();
210 for (int i = 0; i < paramCount - 1; i += 2) {
211 p.setX(m_parameters[i]->evaluate());
212 p.setY(m_parameters[i + 1]->evaluate());
213 points.append(p);
214 }
215
216 int mod = 1;
217 if (m_command.unicode() == 'C' || m_command.unicode() == 'U'
218 || m_command.unicode() == 'T') {
219 mod = 3;
220 } else if (m_command.unicode() == 'A' || m_command.unicode() == 'B'
221 || m_command.unicode() == 'W' || m_command.unicode() == 'V') {
222 mod = 4;
223 } else if (m_command.unicode() == 'Q') {
224 mod = 2;
225 }
226 if ((points.count() % mod) != 0) { // invalid command
227 qWarning() << "Invalid point count for command" << m_command << "ignoring" << "count:" << points.count() << "mod:" << mod;
228 return QList<QPointF>();
229 }
230
231 return points;
232}
const Params2D p
KoColorSpaceMathsTraits< T >::compositetype mod(T a, T b)

References m_command, m_parameters, and p.

◆ radSweepAngle()

qreal EnhancedPathCommand::radSweepAngle ( qreal start,
qreal stop,
bool clockwise ) const
private

Returns sweep angle from start to stop and given direction.

Definition at line 251 of file EnhancedPathCommand.cpp.

252{
253 qreal sweepAngle = stop - start;
254 if (fabs(sweepAngle) < 0.1) {
255 return 2 * M_PI;
256 }
257 if (clockwise) {
258 // we are moving clockwise to the end angle
259 if (stop > start) {
260 sweepAngle = (stop - start) - 2 * M_PI;
261 }
262 } else {
263 // we are moving counter-clockwise to the stop angle
264 if (start > stop) {
265 sweepAngle = 2 * M_PI - (start - stop);
266 }
267 }
268
269 return sweepAngle;
270}

References M_PI.

◆ rectFromPoints()

QRectF EnhancedPathCommand::rectFromPoints ( const QPointF & tl,
const QPointF & br ) const
private

Returns rectangle from given points.

Definition at line 304 of file EnhancedPathCommand.cpp.

305{
306 return QRectF(tl, QSizeF(br.x() - tl.x(), br.y() - tl.y())).normalized();
307}

◆ toString()

QString EnhancedPathCommand::toString ( ) const

Returns a string representation of the command.

Definition at line 309 of file EnhancedPathCommand.cpp.

310{
311 QString cmd = m_command;
312
313 Q_FOREACH (EnhancedPathParameter *p, m_parameters) {
314 cmd += p->toString() + ' ';
315 }
316
317 return cmd.trimmed();
318}
The abstract parameter class.

References m_command, m_parameters, and p.

Member Data Documentation

◆ m_command

QChar EnhancedPathCommand::m_command
private

the actual command

Definition at line 49 of file EnhancedPathCommand.h.

◆ m_parameters

QList<EnhancedPathParameter *> EnhancedPathCommand::m_parameters
private

the commands parameters

Definition at line 50 of file EnhancedPathCommand.h.

◆ m_parent

EnhancedPathShape* EnhancedPathCommand::m_parent
private

the enhanced path owning the command

Definition at line 51 of file EnhancedPathCommand.h.


The documentation for this class was generated from the following files: