Krita Source Code Documentation
Loading...
Searching...
No Matches
KoPathBreakAtPointCommand.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 * SPDX-FileCopyrightText: 2006 Jan Hambrecht <jaham@gmx.net>
3 * SPDX-FileCopyrightText: 2006, 2007 Thorsten Zachmann <zachmann@kde.org>
4 *
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
9
10#include "KoPathPoint.h"
11#include <klocalizedstring.h>
12
13/*
14 * The algorithm to break a multiple open or closed subpaths is:
15 * Subpath is closed
16 * - open behind the last point in the subpath
17 * - go on like as described in Not closed
18 * Not closed
19 * - break from the back of the subpath
20 */
22 : KUndo2Command(parent)
23 , m_deletePoints(true)
24{
25 QList<KoPathPointData> sortedPointDataList(pointDataList);
26 std::sort(sortedPointDataList.begin(), sortedPointDataList.end());
27 setText(kundo2_i18n("Break subpath at points"));
28
29 QList<KoPathPointData>::const_iterator it(sortedPointDataList.constBegin());
30 for (; it != sortedPointDataList.constEnd(); ++it) {
31 KoPathShape * pathShape = it->pathShape;
32 KoPathPoint * point = pathShape->pointByIndex(it->pointIndex);
33 if(! point)
34 continue;
35
36 // check if subpath is closed and the point is start or end point of the subpath
37 if(! pathShape->isClosedSubpath(it->pointIndex.first)) {
38 if(it->pointIndex.second == 0
39 || it->pointIndex.second == pathShape->subpathPointCount(it->pointIndex.first)) {
40 continue;
41 }
42 }
43
44 m_pointDataList.append(*it);
45 m_points.push_back(new KoPathPoint(*point));
46 m_closedIndex.push_back(KoPathPointIndex(-1, 0));
47 }
48
49 KoPathPointData last(0, KoPathPointIndex(-1, -1));
50 for (int i = m_pointDataList.size() - 1; i >= 0; --i) {
51 const KoPathPointData &current = m_pointDataList.at(i);
52
53 if (last.pathShape != current.pathShape || last.pointIndex.first != current.pointIndex.first) {
54 last = current;
55 if (current.pathShape->isClosedSubpath(current.pointIndex.first)) {
56 // the break will happen before the inserted point so we have to increment by 1
57 m_closedIndex[i] = current.pointIndex;
58 ++m_closedIndex[i].second;
59 }
60 }
61 }
62}
63
70
72{
74 KoPathPointData last(0, KoPathPointIndex(-1, -1));
75
76 // offset, needed when path was opened
77 int offset = 0;
78 for (int i = m_pointDataList.size() - 1; i >= 0; --i) {
79 const KoPathPointData & pd = m_pointDataList.at(i);
80 KoPathShape * pathShape = pd.pathShape;
81
82 KoPathPointIndex pointIndex = pd.pointIndex;
83 if (last.pathShape != pathShape || last.pointIndex.first != pointIndex.first) {
84 offset = 0;
85 }
86
87 pointIndex.second = pointIndex.second + offset + 1;
88 pathShape->insertPoint(m_points[i], pointIndex);
89
90 if (m_closedIndex.at(i).first != -1) {
91 m_closedIndex[i] = pathShape->openSubpath(m_closedIndex.at(i));
92 offset = m_closedIndex.at(i).second;
93 } else {
94 KoPathPointIndex breakIndex = pd.pointIndex;
95 breakIndex.second += offset;
96 pathShape->breakAfter(breakIndex);
97 m_closedIndex[i].second = offset;
98 }
99
100 if (last.pathShape != pathShape) {
101 if (last.pathShape) {
102 last.pathShape->update();
103 }
104 last = pd;
105 }
106 }
107 if (last.pathShape) {
108 last.pathShape->update();
109 }
110
111 m_deletePoints = false;
112}
113
115{
117 KoPathShape * lastPathShape = 0;
118
119 QMap<KoPathShape *, QList<KoPathPointIndex>> pointsMap;
120
121 for (int i = 0; i < m_pointDataList.size(); ++i) {
122 const KoPathPointData & pd = m_pointDataList.at(i);
123 KoPathShape * pathShape = pd.pathShape;
124 KoPathPointIndex pointIndex = pd.pointIndex;
125 ++pointIndex.second;
126 if (m_closedIndex.at(i).first != -1) {
127 m_closedIndex[i] = pathShape->closeSubpath(m_closedIndex.at(i));
128 } else {
129 pointIndex.second = pointIndex.second + m_closedIndex.at(i).second;
130 pathShape->join(pd.pointIndex.first);
131 }
132
133 m_points[i] = pathShape->removePoint(pointIndex);
134
135 pointsMap[pathShape].append(pd.pointIndex);
136
137 if (lastPathShape != pathShape) {
138 if (lastPathShape) {
139 lastPathShape->update();
140 }
141 lastPathShape = pathShape;
142 }
143 }
144 if (lastPathShape) {
145 lastPathShape->update();
146 }
147
148 for (auto it = pointsMap.constBegin(); it != pointsMap.constEnd(); ++it) {
149 it.key()->recommendPointSelectionChange(it.value());
150 }
151
152 m_deletePoints = true;
153}
QPair< int, int > KoPathPointIndex
Definition KoPathShape.h:28
virtual void undo()
void setText(const KUndo2MagicString &text)
virtual void redo()
QList< KoPathPointData > m_pointDataList
QList< KoPathPointIndex > m_closedIndex
void redo() override
redo the command
void undo() override
revert the actions done in redo
KoPathBreakAtPointCommand(const QList< KoPathPointData > &pointDataList, KUndo2Command *parent=0)
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
A KoPathPoint represents a point in a path.
The position of a path point within a path shape.
Definition KoPathShape.h:63
bool breakAfter(const KoPathPointIndex &pointIndex)
Breaks the path after the point index.
int subpathPointCount(int subpathIndex) const
Returns the number of points in a subpath.
bool isClosedSubpath(int subpathIndex) const
Checks if a subpath is closed.
bool join(int subpathIndex)
Joins the given subpath with the following one.
KoPathPointIndex closeSubpath(const KoPathPointIndex &pointIndex)
Close a open subpath.
KoPathPointIndex openSubpath(const KoPathPointIndex &pointIndex)
Opens a closed subpath.
KoPathPoint * removePoint(const KoPathPointIndex &pointIndex)
Removes a point from the path.
KoPathPoint * pointByIndex(const KoPathPointIndex &pointIndex) const
Returns the path point specified by a path point index.
bool insertPoint(KoPathPoint *point, const KoPathPointIndex &pointIndex)
Inserts a new point into the given subpath at the specified position.
void update() const override
reimplemented
KUndo2MagicString kundo2_i18n(const char *text)