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

#include <SvgMeshArray.h>

Public Member Functions

bool addPatch (QList< QPair< QString, QColor > > stops, const QPointF initialPoint)
 
QRectF boundingRect () const
 
void createDefaultMesh (const int nrows, const int ncols, const QColor color, const QSizeF size)
 creates a default mesh in OBB coordinates (because it's easier and more logical in this case)
 
QVector< SvgMeshPositiongetConnectedPaths (const SvgMeshPosition &position) const
 Return the paths connected to the corner. Can be thought of as edges connected to a vertex.
 
SvgMeshPatchgetPatch (const int row, const int col) const
 
std::array< QPointF, 4 > getPath (const SvgMeshPatch::Type edge, const int row, const int col) const
 Get the Path Points for a segment of the meshpatch.
 
SvgMeshPath getPath (const SvgMeshPosition &pos) const
 
SvgMeshStop getStop (const SvgMeshPatch::Type edge, const int row, const int col) const
 Get the point of a node in mesharray.
 
SvgMeshStop getStop (const SvgMeshPosition &pos) const
 
void modifyColor (const SvgMeshPosition &position, const QColor &color)
 
void modifyCorner (const SvgMeshPosition &position, const QPointF &newPos)
 
void modifyHandle (const SvgMeshPosition &position, const std::array< QPointF, 4 > &newPath)
 
void newRow ()
 
int numColumns () const
 
int numRows () const
 
void setTransform (const QTransform &matrix)
 
 SvgMeshArray ()
 
 SvgMeshArray (const SvgMeshArray &other)
 
 ~SvgMeshArray ()
 

Private Member Functions

QColor getColor (SvgMeshPatch::Type edge, int row, int col) const
 
QVector< SvgMeshPositiongetSharedPaths (const SvgMeshPosition &position) const
 

Private Attributes

QVector< QVector< SvgMeshPatch * > > m_array
 where each vector is a meshrow
 

Detailed Description

Definition at line 37 of file SvgMeshArray.h.

Constructor & Destructor Documentation

◆ SvgMeshArray() [1/2]

SvgMeshArray::SvgMeshArray ( )

Definition at line 11 of file SvgMeshArray.cpp.

12{
13}

◆ SvgMeshArray() [2/2]

SvgMeshArray::SvgMeshArray ( const SvgMeshArray & other)

Definition at line 15 of file SvgMeshArray.cpp.

16{
17 for (const auto& row: other.m_array) {
18 newRow();
19 for (const auto& patch: row) {
20 m_array.last().append(new SvgMeshPatch(*patch));
21 }
22 }
23}
QVector< QVector< SvgMeshPatch * > > m_array
where each vector is a meshrow

References m_array, and newRow().

◆ ~SvgMeshArray()

SvgMeshArray::~SvgMeshArray ( )

Definition at line 25 of file SvgMeshArray.cpp.

26{
27 for (auto& row: m_array) {
28 for (auto& patch: row) {
29 delete patch;
30 }
31 }
32}

References m_array.

Member Function Documentation

◆ addPatch()

bool SvgMeshArray::addPatch ( QList< QPair< QString, QColor > > stops,
const QPointF initialPoint )

Definition at line 96 of file SvgMeshArray.cpp.

97{
98 // This is function is full of edge-case landmines, please run TestMeshArray after any changes
99 if (stops.size() > 4 || stops.size() < 2)
100 return false;
101
102 SvgMeshPatch *patch = new SvgMeshPatch(initialPoint);
103
104 m_array.last().append(patch);
105
106 int irow = m_array.size() - 1;
107 int icol = m_array.last().size() - 1;
108
109 if (irow == 0 && icol == 0) {
110 patch->addStop(stops[0].first, stops[0].second, SvgMeshPatch::Top);
111 stops.removeFirst();
112 } else if (irow == 0) {
113 // For first row, parse patches
114 patch->addStop(stops[0].first, getColor(SvgMeshPatch::Right, irow, icol - 1), SvgMeshPatch::Top);
115 stops.removeFirst();
116 } else {
117 // path is already defined for rows >= 1
118 QColor color = getStop(SvgMeshPatch::Left, irow - 1, icol).color;
119
120 std::array<QPointF, 4> points = getPath(SvgMeshPatch::Bottom, irow - 1, icol);
121 std::reverse(points.begin(), points.end());
122
123 patch->addStop(points, color, SvgMeshPatch::Top);
124 }
125
126 if (irow > 0) {
127 patch->addStop(stops[0].first, getColor(SvgMeshPatch::Bottom, irow - 1, icol), SvgMeshPatch::Right);
128 stops.removeFirst();
129 } else {
130 patch->addStop(stops[0].first, stops[0].second, SvgMeshPatch::Right);
131 stops.removeFirst();
132 }
133
134 if (icol > 0) {
135 patch->addStop(
136 stops[0].first,
137 stops[0].second,
139 true, getStop(SvgMeshPatch::Bottom, irow, icol - 1).point);
140 stops.removeFirst();
141 } else {
142 patch->addStop(stops[0].first, stops[0].second, SvgMeshPatch::Bottom);
143 stops.removeFirst();
144 }
145
146 // last stop
147 if (icol == 0) {
148 // if stop is in the 0th column, parse path
149 patch->addStop(
150 stops[0].first,
151 stops[0].second,
153 true, getStop(SvgMeshPatch::Top, irow, icol).point);
154 stops.removeFirst();
155 } else {
156 QColor color = getStop(SvgMeshPatch::Bottom, irow, icol - 1).color;
157
158 // reuse Right side of the previous patch
159 std::array<QPointF, 4> points = getPath(SvgMeshPatch::Right, irow, icol - 1);
160 std::reverse(points.begin(), points.end());
161
162 patch->addStop(points, color, SvgMeshPatch::Left);
163 }
164 return true;
165}
QColor getColor(SvgMeshPatch::Type edge, int row, int col) const
std::array< QPointF, 4 > getPath(const SvgMeshPatch::Type edge, const int row, const int col) const
Get the Path Points for a segment of the meshpatch.
SvgMeshStop getStop(const SvgMeshPatch::Type edge, const int row, const int col) const
Get the point of a node in mesharray.
void addStop(const QString &pathStr, QColor color, Type edge, bool pathIncomplete=false, QPointF lastPoint=QPointF())

References SvgMeshPatch::addStop(), SvgMeshPatch::Bottom, SvgMeshStop::color, getColor(), getPath(), getStop(), SvgMeshPatch::Left, m_array, SvgMeshPatch::Right, and SvgMeshPatch::Top.

◆ boundingRect()

QRectF SvgMeshArray::boundingRect ( ) const

Definition at line 238 of file SvgMeshArray.cpp.

239{
240 KIS_ASSERT(numRows() > 0 && numColumns() > 0);
241
242 QPointF topLeft = m_array[0][0]->boundingRect().topLeft();
243 QPointF bottomRight = m_array.last().last()->boundingRect().bottomRight();
244
245 // mesharray may be backwards, in which case we might get the right most value
246 // but we need topLeft for things to work as expected
247 for (int i = 0; i < numRows(); ++i) {
248 for (int j = 0; j < numColumns(); ++j) {
249 QPointF left = m_array[i][j]->boundingRect().topLeft();
250 if (left.x() < topLeft.x()) {
251 topLeft.rx() = left.x();
252 }
253 if ( left.y() < topLeft.y()) {
254 topLeft.ry() = left.y();
255 }
256
257 QPointF right = m_array[i][j]->boundingRect().bottomRight();
258 if (bottomRight.x() < right.x()) {
259 bottomRight.rx() = right.x();
260 }
261 if (bottomRight.y() < right.y()) {
262 bottomRight.ry() = right.y();
263 }
264 }
265 }
266
267 // return extremas
268 return QRectF(topLeft, bottomRight);
269}
int numRows() const
int numColumns() const
#define KIS_ASSERT(cond)
Definition kis_assert.h:33

References KIS_ASSERT, m_array, numColumns(), and numRows().

◆ createDefaultMesh()

void SvgMeshArray::createDefaultMesh ( const int nrows,
const int ncols,
const QColor color,
const QSizeF size )

creates a default mesh in OBB coordinates (because it's easier and more logical in this case)

Definition at line 39 of file SvgMeshArray.cpp.

43{
44 // individual patch size should be:
45 qreal patchWidth = size.width() / ncols;
46 qreal patchHeight = size.height() / nrows;
47
48 // normalize
49 patchWidth /= size.width();
50 patchHeight /= size.height();
51
52 QRectF start(0, 0, patchWidth, patchHeight);
53
54 QColor colors[2] = {Qt::white, color};
55
56 for (int irow = 0; irow < nrows; ++irow) {
57 newRow();
58
59 for (int icol = 0; icol < ncols; ++icol) {
60 SvgMeshPatch *patch = new SvgMeshPatch(start.topLeft());
61 // alternate between colors
62 int index = (irow + icol) % 2;
63
64 patch->addStopLinear({start.topLeft(), start.topRight()},
65 colors[index],
67
68 index = (index + 1) % 2;
69 patch->addStopLinear({start.topRight(), start.bottomRight()},
70 colors[index],
72
73 index = (index + 1) % 2;
74 patch->addStopLinear({start.bottomRight(), start.bottomLeft()},
75 colors[index],
77
78 index = (index + 1) % 2;
79 patch->addStopLinear({start.bottomLeft(), start.topLeft()},
80 colors[index],
82
83 m_array.last().append(patch);
84
85 // TopRight of the previous patch in this row
86 start.setX(patch->getStop(SvgMeshPatch::Right).point.x());
87 start.setWidth(patchWidth);
88 }
89
90 // BottomLeft of the patch is the starting point for new row
91 start.setTopLeft(m_array.last().first()->getStop(SvgMeshPatch::Left).point);
92 start.setSize({patchWidth, patchHeight});
93 }
94}
void addStopLinear(const std::array< QPointF, 2 > &pathPoints, QColor color, Type edge)
Adds linear path to the shape.
SvgMeshStop getStop(Type type) const
returns the starting point of the stop
int size(const Forest< T > &forest)
Definition KisForest.h:1232
QPointF point

References SvgMeshPatch::addStopLinear(), SvgMeshPatch::Bottom, SvgMeshPatch::getStop(), SvgMeshPatch::Left, m_array, newRow(), SvgMeshStop::point, SvgMeshPatch::Right, and SvgMeshPatch::Top.

◆ getColor()

QColor SvgMeshArray::getColor ( SvgMeshPatch::Type edge,
int row,
int col ) const
private

Definition at line 380 of file SvgMeshArray.cpp.

381{
382 return getStop(edge, row, col).color;
383}

References SvgMeshStop::color, and getStop().

◆ getConnectedPaths()

QVector< SvgMeshPosition > SvgMeshArray::getConnectedPaths ( const SvgMeshPosition & position) const

Return the paths connected to the corner. Can be thought of as edges connected to a vertex.

Definition at line 271 of file SvgMeshArray.cpp.

272{
273 QVector<SvgMeshPosition> positions;
274
275 int row = position.row;
276 int col = position.col;
277 SvgMeshPatch::Type type = position.segmentType;
278
279 SvgMeshPatch::Type nextType = static_cast<SvgMeshPatch::Type>(type + 1);
280 SvgMeshPatch::Type previousType = static_cast<SvgMeshPatch::Type>((SvgMeshPatch::Size + type - 1) % SvgMeshPatch::Size);
281
282 if (type == SvgMeshPatch::Top) {
283 if (row == 0) {
284 if (col > 0) {
285 positions << SvgMeshPosition {row, col - 1, type};
286 }
287 } else {
288 if (col > 0) {
289 positions << SvgMeshPosition {row, col - 1, type};
290 positions << SvgMeshPosition {row - 1, col - 1, nextType};
291 }
292 positions << SvgMeshPosition {row - 1, col, previousType};
293 }
294 } else if (type == SvgMeshPatch::Right && row > 0) {
295 positions << SvgMeshPosition {row - 1, col, type};
296
297 } else if (type == SvgMeshPatch::Left && col > 0) {
298 positions << SvgMeshPosition {row, col - 1, previousType};
299 }
300
301 positions << SvgMeshPosition {row, col, previousType};
302 positions << SvgMeshPosition {row, col, type};
303
304 return positions;
305}
Type
Position of stop in the patch.
SvgMeshPatch::Type segmentType

References SvgMeshPosition::col, SvgMeshPatch::Left, SvgMeshPatch::Right, SvgMeshPosition::row, SvgMeshPosition::segmentType, SvgMeshPatch::Size, and SvgMeshPatch::Top.

◆ getPatch()

SvgMeshPatch * SvgMeshArray::getPatch ( const int row,
const int col ) const

Definition at line 209 of file SvgMeshArray.cpp.

210{
211 KIS_ASSERT(row < m_array.size() && col < m_array[row].size()
212 && row >= 0 && col >= 0);
213
214 return m_array[row][col];
215}

References KIS_ASSERT, and m_array.

◆ getPath() [1/2]

std::array< QPointF, 4 > SvgMeshArray::getPath ( const SvgMeshPatch::Type edge,
const int row,
const int col ) const

Get the Path Points for a segment of the meshpatch.

Definition at line 196 of file SvgMeshArray.cpp.

197{
198 KIS_ASSERT(row < m_array.size() && col < m_array[row].size()
199 && row >= 0 && col >= 0);
200
201 return m_array[row][col]->getSegment(edge);
202}

References KIS_ASSERT, and m_array.

◆ getPath() [2/2]

SvgMeshPath SvgMeshArray::getPath ( const SvgMeshPosition & pos) const

Definition at line 204 of file SvgMeshArray.cpp.

205{
206 return getPath(pos.segmentType, pos.row, pos.col);
207}

References SvgMeshPosition::col, getPath(), SvgMeshPosition::row, and SvgMeshPosition::segmentType.

◆ getSharedPaths()

QVector< SvgMeshPosition > SvgMeshArray::getSharedPaths ( const SvgMeshPosition & position) const
private

return the shared path between two patches. NOTE: Not to be confused with getConnectedPaths

Definition at line 345 of file SvgMeshArray.cpp.

346{
347 QVector<SvgMeshPosition> positions;
348
349 int row = position.row;
350 int col = position.col;
351 SvgMeshPatch::Type type = position.segmentType;
352
353 SvgMeshPatch::Type nextType = static_cast<SvgMeshPatch::Type>(type + 1);
354 SvgMeshPatch::Type previousType = static_cast<SvgMeshPatch::Type>((SvgMeshPatch::Size + type - 1) % SvgMeshPatch::Size);
355
356 if (type == SvgMeshPatch::Top) {
357 if (row == 0) {
358 if (col > 0) {
359 positions << SvgMeshPosition {row, col - 1, nextType};
360 }
361 } else {
362 if (col > 0) {
363 positions << SvgMeshPosition {row, col - 1, nextType};
364 positions << SvgMeshPosition {row - 1, col - 1, SvgMeshPatch::Bottom};
365 }
366 positions << SvgMeshPosition {row - 1, col, previousType};
367 }
368 } else if (type == SvgMeshPatch::Right && row > 0) {
369 positions << SvgMeshPosition {row - 1, col, nextType};
370
371 } else if (type == SvgMeshPatch::Left && col > 0) {
372 positions << SvgMeshPosition {row, col - 1, previousType};
373 }
374
375 positions << SvgMeshPosition {row, col, type};
376
377 return positions;
378}

References SvgMeshPatch::Bottom, SvgMeshPosition::col, SvgMeshPatch::Left, SvgMeshPatch::Right, SvgMeshPosition::row, SvgMeshPosition::segmentType, SvgMeshPatch::Size, and SvgMeshPatch::Top.

◆ getStop() [1/2]

SvgMeshStop SvgMeshArray::getStop ( const SvgMeshPatch::Type edge,
const int row,
const int col ) const

Get the point of a node in mesharray.

Definition at line 167 of file SvgMeshArray.cpp.

168{
169 KIS_ASSERT(row < m_array.size() && col < m_array[row].size()
170 && row >= 0 && col >= 0);
171
172 SvgMeshPatch *patch = m_array[row][col];
173 SvgMeshStop node = patch->getStop(edge);
174
175 if (node.isValid()) {
176 return node;
177 }
178
179 switch (patch->countPoints()) {
180 case 3:
181 case 2:
182 if (edge == SvgMeshPatch::Top)
183 return getStop(SvgMeshPatch::Left, row - 1, col);
184 else if (edge == SvgMeshPatch::Left)
185 return getStop(SvgMeshPatch::Bottom, row, col - 1);
186 }
187 Q_ASSERT(false);
188 return SvgMeshStop();
189}
int countPoints() const
bool isValid() const

References SvgMeshPatch::Bottom, SvgMeshPatch::countPoints(), getStop(), SvgMeshPatch::getStop(), SvgMeshStop::isValid(), KIS_ASSERT, SvgMeshPatch::Left, m_array, and SvgMeshPatch::Top.

◆ getStop() [2/2]

SvgMeshStop SvgMeshArray::getStop ( const SvgMeshPosition & pos) const

Definition at line 191 of file SvgMeshArray.cpp.

192{
193 return getStop(pos.segmentType, pos.row, pos.col);
194}

References SvgMeshPosition::col, getStop(), SvgMeshPosition::row, and SvgMeshPosition::segmentType.

◆ modifyColor()

void SvgMeshArray::modifyColor ( const SvgMeshPosition & position,
const QColor & color )

Definition at line 336 of file SvgMeshArray.cpp.

337{
339
340 for (const auto &path: paths) {
341 m_array[path.row][path.col]->setStopColor(path.segmentType, color);
342 }
343}
QVector< SvgMeshPosition > getSharedPaths(const SvgMeshPosition &position) const

References getSharedPaths(), and m_array.

◆ modifyCorner()

void SvgMeshArray::modifyCorner ( const SvgMeshPosition & position,
const QPointF & newPos )

Definition at line 324 of file SvgMeshArray.cpp.

326{
328
329 QPointF delta = m_array[position.row][position.col]->getStop(position.segmentType).point - newPos;
330
331 for (const auto &path: paths) {
332 m_array[path.row][path.col]->modifyCorner(path.segmentType, delta);
333 }
334}

References SvgMeshPosition::col, getSharedPaths(), m_array, SvgMeshPosition::row, and SvgMeshPosition::segmentType.

◆ modifyHandle()

void SvgMeshArray::modifyHandle ( const SvgMeshPosition & position,
const std::array< QPointF, 4 > & newPath )

Definition at line 307 of file SvgMeshArray.cpp.

309{
310 std::array<QPointF, 4> reversed = newPath;
311 std::reverse(reversed.begin(), reversed.end());
312
313 if (position.segmentType == SvgMeshPatch::Top && position.row > 0) {
314 // modify the shared side
315 m_array[position.row - 1][position.col]->modifyPath(SvgMeshPatch::Bottom, reversed);
316
317 } else if (position.segmentType == SvgMeshPatch::Left && position.col > 0) {
318 // modify the shared side as well
319 m_array[position.row][position.col - 1]->modifyPath(SvgMeshPatch::Right, reversed);
320 }
321 m_array[position.row][position.col]->modifyPath(position.segmentType, newPath);
322}

References SvgMeshPatch::Bottom, SvgMeshPosition::col, SvgMeshPatch::Left, m_array, SvgMeshPatch::Right, SvgMeshPosition::row, SvgMeshPosition::segmentType, and SvgMeshPatch::Top.

◆ newRow()

void SvgMeshArray::newRow ( )

Definition at line 34 of file SvgMeshArray.cpp.

35{
36 m_array << QVector<SvgMeshPatch*>();
37}

◆ numColumns()

int SvgMeshArray::numColumns ( ) const

Definition at line 222 of file SvgMeshArray.cpp.

223{
224 if (m_array.isEmpty())
225 return 0;
226 return m_array.first().size();
227}

References m_array.

◆ numRows()

int SvgMeshArray::numRows ( ) const

Definition at line 217 of file SvgMeshArray.cpp.

218{
219 return m_array.size();
220}

References m_array.

◆ setTransform()

void SvgMeshArray::setTransform ( const QTransform & matrix)

Definition at line 229 of file SvgMeshArray.cpp.

230{
231 for (auto& row: m_array) {
232 for (auto& patch: row) {
233 patch->setTransform(matrix);
234 }
235 }
236}

References m_array.

Member Data Documentation

◆ m_array

QVector<QVector<SvgMeshPatch*> > SvgMeshArray::m_array
private

where each vector is a meshrow

Definition at line 91 of file SvgMeshArray.h.


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