Krita Source Code Documentation
Loading...
Searching...
No Matches
KoPathSegmentChangeStrategy.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 * SPDX-FileCopyrightText: 2009 Jan Hambrecht <jaham@gmx.net>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
8#include "KoPathShape.h"
9#include "KoPathPoint.h"
10#include "KoPathTool.h"
11#include "KoSnapGuide.h"
14#include <KoCanvasBase.h>
15#include <klocalizedstring.h>
16#include <limits>
17#include <math.h>
18#include <KisBezierUtils.h>
19#include <kis_command_utils.h>
20
21KoPathSegmentChangeStrategy::KoPathSegmentChangeStrategy(KoPathTool *tool, const QPointF &pos, const KoPathPointData &segment, qreal segmentParam)
23, m_originalPosition(pos)
24, m_lastPosition(pos)
25, m_tool(tool)
26, m_segmentParam(segmentParam)
27, m_pointData1(segment)
28, m_pointData2(segment)
29{
30 // The following value is a bit arbitrary, it would be more mathematically correct to use
31 // "std::numeric_limits<qreal>::epsilon()", but if the value is too small, when the user
32 // click near a control point it is relatively easy to create a path shape of almost
33 // infinite size, which blocks the application for a long period of time. A bigger value
34 // is mathematically incorrect, but it avoids to block application, it also avoid to create
35 // an huge path shape by accident, and anyway, but it does not prevent the user to create one
36 // if they choose so.
37 const qreal eps = 1e-2;
38 // force segment parameter range to avoid division by zero
39 m_segmentParam = qBound(eps, m_segmentParam, qreal(1.0)-eps);
40
41 m_path = segment.pathShape;
45}
46
50
51void KoPathSegmentChangeStrategy::handleMouseMove(const QPointF &mouseLocation, Qt::KeyboardModifiers modifiers)
52{
53 QPointF snappedPosition = m_tool->canvas()->snapGuide()->snap(mouseLocation, modifiers);
54 QPointF localPos = m_path->documentToShape(snappedPosition);
55
56 if (m_segment.degree() == 1) {
57 // line segment is converted to a curve
59 cmd.redo();
60 }
61
62 QPointF move1, move2;
63
64 if (m_segment.degree() == 2) {
65 // interpolate quadratic segment between segment start, mouse position and segment end
67 localPos,
70 if (ipol.isValid()) {
71 move1 = move2 = ipol.controlPoints()[1] - m_segment.controlPoints()[1];
72 }
73 }
74 else if (m_segment.degree() == 3) {
75 QPointF lastLocalPos = m_path->documentToShape(m_lastPosition);
76 QPointF delta = localPos - lastLocalPos;
77
78 std::tie(move2, move1) =
80 }
81
84 cmd.redo();
85 }
88 cmd.redo();
89 }
91
92 m_ctrlPoint1Move += move1;
93 m_ctrlPoint2Move += move2;
94
95 // save last mouse position
96 m_lastPosition = snappedPosition;
97}
98
99void KoPathSegmentChangeStrategy::finishInteraction(Qt::KeyboardModifiers modifiers)
100{
101 Q_UNUSED(modifiers);
102}
103
105{
106 bool hasControlPoint1 = m_segment.second()->activeControlPoint1();
107 bool hasControlPoint2 = m_segment.first()->activeControlPoint2();
108
109 KUndo2Command * cmd = new KUndo2Command(kundo2_i18n("Change Segment"));
110 if (m_originalSegmentDegree == 1) {
112 }
113
114 if (hasControlPoint2) {
116 }
117 if (hasControlPoint1) {
119 }
120
121 if (cmd) {
123 }
124 return nullptr;
125}
KoSnapGuide * snapGuide
The undo / redo command for path point moving.
Describe a KoPathPoint by a KoPathShape and its indices.
KoPathPointIndex pointIndex
position of the point in the path shape
KoPathShape * pathShape
path shape the path point belongs too
QPointF point
@ ControlPoint2
the second control point
Definition KoPathPoint.h:51
@ ControlPoint1
the first control point
Definition KoPathPoint.h:50
bool activeControlPoint1
bool activeControlPoint2
KoPathSegmentChangeStrategy(KoPathTool *tool, const QPointF &pos, const KoPathPointData &segment, qreal segmentParam)
KoPathTool * m_tool
pointer to the path tool
void handleMouseMove(const QPointF &mouseLocation, Qt::KeyboardModifiers modifiers) override
void finishInteraction(Qt::KeyboardModifiers modifiers) override
The undo / redo command for changing segments to curves/lines.
void redo() override
redo the command
A KoPathSegment consist of two neighboring KoPathPoints.
KoPathPoint * first
int degree() const
Returns the degree of the segment: 1 = line, 2 = quadratic, 3 = cubic, -1 = invalid.
static KoPathSegment interpolate(const QPointF &p0, const QPointF &p1, const QPointF &p2, qreal t)
KoPathPoint * second
bool isValid() const
Returns if segment is valid, e.g. has two valid points.
QList< QPointF > controlPoints() const
Returns ordered list of control points.
virtual QPointF normalize()
Normalizes the path data.
KoPathSegment segmentByIndex(const KoPathPointIndex &pointIndex) const
Returns the segment specified by a path point index.
KoPathPointIndex pathPointIndex(const KoPathPoint *point) const
Returns the path point index of a given path point.
QPointF documentToShape(const QPointF &point) const
Transforms point from document coordinates to shape coordinates.
Definition KoShape.cpp:1211
QPointF snap(const QPointF &mousePosition, Qt::KeyboardModifiers modifiers)
snaps the mouse position, returns if mouse was snapped
KoCanvasBase * canvas() const
Returns the canvas the tool is working on.
const qreal eps
KUndo2MagicString kundo2_i18n(const char *text)
std::pair< QPointF, QPointF > offsetSegment(qreal t, const QPointF &offset)
moves point t of the curve by offset offset