Krita Source Code Documentation
Loading...
Searching...
No Matches
VectorLayer.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2017 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6#include "VectorLayer.h"
7#include <kis_shape_layer.h>
8#include <kis_image.h>
9#include <SvgWriter.h>
10#include <SvgParser.h>
11#include <QBuffer>
14#include <KoShapeGroup.h>
15#include <KisDocument.h>
17#include <kis_group_layer.h>
18
19#include "Krita.h"
20#include "GroupShape.h"
21#include "LibKisUtils.h"
22
23
24VectorLayer::VectorLayer(KoShapeControllerBase* shapeController, KisImageSP image, QString name, QObject *parent) :
25 Node(image, new KisShapeLayer(shapeController, image, name, OPACITY_OPAQUE_U8), parent)
26{
27
28}
29
31 Node(layer->image(), layer, parent)
32{
33
34}
35
40
41QString VectorLayer::type() const
42{
43 return "vectorlayer";
44}
45
47{
49 KisShapeLayerSP vector = KisShapeLayerSP(dynamic_cast<KisShapeLayer*>(this->node().data()));
50 if (vector) {
51 QList<KoShape*> originalShapes = vector->shapes();
52 std::sort(originalShapes.begin(), originalShapes.end(), KoShape::compareShapeZIndex);
53 for (int i=0; i<vector->shapeCount(); i++) {
54 if (dynamic_cast<KoShapeGroup*>(originalShapes.at(i))) {
55 shapes << new GroupShape(dynamic_cast<KoShapeGroup*>(originalShapes.at(i)));
56 } else {
57 shapes << new Shape(originalShapes.at(i));
58 }
59 }
60 }
61 return shapes;
62}
63
65{
66 QString svgData;
67 KisShapeLayerSP vector = KisShapeLayerSP(dynamic_cast<KisShapeLayer*>(this->node().data()));
68
69 if (vector) {
70 QBuffer buffer;
71 QList<KoShape*> originalShapes = vector->shapes();
72
73 std::sort(originalShapes.begin(), originalShapes.end(), KoShape::compareShapeZIndex);
74
75 const QSizeF sizeInPx = this->node()->image()->bounds().size();
76 const QSizeF pageSize(sizeInPx.width() / this->node()->image()->xRes(),
77 sizeInPx.height() / this->node()->image()->yRes());
78
79 buffer.open(QIODevice::WriteOnly);
80
81 SvgWriter writer(originalShapes);
82
83 writer.save(buffer, pageSize);
84 buffer.close();
85
86 svgData = QString::fromUtf8(buffer.data());
87 }
88
89 return svgData;
90
91}
92
94{
96 QList<KoShape*> originalShapes;
97
98 if (svgData.isEmpty() || !svgData.contains("<svg") ) {
99 return shapes;
100 }
101
102 KoShapeContainer *container = dynamic_cast<KoShapeContainer*>(this->node().data());
103
104 if (container) {
105 QSizeF fragmentSize;
106 QString errorMsg;
107 int errorLine = 0;
108 int errorColumn = 0;
109
110 QDomDocument dom = SvgParser::createDocumentFromSvg(svgData, &errorMsg, &errorLine, &errorColumn);
111
112 if (dom.isNull()) {
113 qWarning() << "Failed to process an SVG string at"
114 << errorLine << ":" << errorColumn << "->" << errorMsg;
115 return shapes;
116 }
117
118 Document *document = Krita::instance()->activeDocument();
119
120 if (!document) {
121 document = LibKisUtils::findNodeInDocuments(this->node());
122 if (!document) {
123 return shapes;
124 }
125 }
126
127 SvgParser parser(document->document()->shapeController()->resourceManager());
128
129 parser.setResolution(this->node()->image()->bounds(), this->node()->image()->xRes() * 72.0);
130
131 originalShapes = parser.parseSvg(dom.documentElement(), &fragmentSize);
132
133 KUndo2Command *cmd = new KoShapeCreateCommand(document->document()->shapeController(), originalShapes, container);
134
136 this->node()->image()->waitForDone();
137 delete document;
138
139 std::sort(originalShapes.begin(), originalShapes.end(), KoShape::compareShapeZIndex);
140 for (int i=0; i<originalShapes.size(); i++) {
141 if (dynamic_cast<KoShapeGroup*>(originalShapes.at(i))) {
142 shapes << new GroupShape(dynamic_cast<KoShapeGroup*>(originalShapes.at(i)));
143 } else {
144 shapes << new Shape(originalShapes.at(i));
145 }
146 }
147
148 }
149
150 return shapes;
151}
152
153Shape* VectorLayer::shapeAtPosition(const QPointF &position) const
154{
155 KisShapeLayerSP vector = KisShapeLayerSP(dynamic_cast<KisShapeLayer*>(this->node().data()));
156
157 if (!vector) return 0;
158
159 KoShape* shape = vector->shapeManager()->shapeAt(position);
160
161 if (!shape) return 0;
162
163 if (dynamic_cast<KoShapeGroup*>(shape)) {
164 return new GroupShape(dynamic_cast<KoShapeGroup*>(shape));
165 } else {
166 return new Shape(shape);
167 }
168
169}
170
171QList<Shape *> VectorLayer::shapesInRect(const QRectF &rect, bool omitHiddenShapes, bool containedMode) const {
173 KisShapeLayerSP vector = KisShapeLayerSP(dynamic_cast<KisShapeLayer*>(this->node().data()));
174
175 if (vector) {
176 QList<KoShape *> originalShapes = vector->shapeManager()->shapesAt(rect, omitHiddenShapes, containedMode);
177
178 std::sort(originalShapes.begin(), originalShapes.end(), KoShape::compareShapeZIndex);
179 for (int i=0; i<originalShapes.size(); i++) {
180 if (dynamic_cast<KoShapeGroup*>(originalShapes.at(i))) {
181 shapes << new GroupShape(dynamic_cast<KoShapeGroup*>(originalShapes.at(i)));
182 } else {
183 shapes << new Shape(originalShapes.at(i));
184 }
185 }
186 }
187 return shapes;
188}
189
190Shape* VectorLayer::createGroupShape(const QString &name, QList<Shape *> shapes) const
191{
192 if (shapes.isEmpty()) return 0;
193
194 QList<KoShape *> originalShapes;
195 KoShapeContainer *container = dynamic_cast<KoShapeContainer*>(this->node().data());
196
197 if (!container) return 0;
198
199 for (Shape* shape : shapes) {
200 KoShape *originalShape = shape->shape();
201
202 if (originalShape && originalShape->parent() == container) {
203 originalShapes << originalShape;
204 } else {
205 qWarning() << "Attempt to add an invalid shape.";
206 return 0;
207 }
208 }
209
210 if (originalShapes.isEmpty()) return 0;
211
212 Document *document = Krita::instance()->activeDocument();
213
214 if (!document) {
215 document = LibKisUtils::findNodeInDocuments(this->node());
216 if (!document) return 0;
217 }
218
219 KoShapeGroup *group = new KoShapeGroup();
220 const int groupZIndex = originalShapes.last()->zIndex();
221
222 group->setZIndex(groupZIndex);
223 group->setName(name);
224
225 KUndo2Command *cmd = new KUndo2Command(kundo2_i18n("Group shapes"));
226 new KoShapeCreateCommand(document->document()->shapeController(), group, container, cmd);
227 new KoShapeGroupCommand(group, originalShapes, true, cmd);
228
230 this->node()->image()->waitForDone();
231 delete document;
232
233 return new GroupShape(group);
234}
235
236
238{
239 KisShapeLayerSP vectorLayer = KisShapeLayerSP(dynamic_cast<KisShapeLayer*>(this->node().data()));
240 return vectorLayer->antialiased();
241}
242
243void VectorLayer::setAntialiased(const bool antialiased)
244{
245 KisShapeLayerSP vectorLayer = KisShapeLayerSP(dynamic_cast<KisShapeLayer*>(this->node().data()));
246 vectorLayer->setAntialiased(antialiased);
247}
const quint8 OPACITY_OPAQUE_U8
The GroupShape class A group shape is a vector object with child shapes.
Definition GroupShape.h:21
void waitForDone()
QRect bounds() const override
static void runSingleCommandStroke(KisImageSP image, KUndo2Command *cmd, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
runSingleCommandStroke creates a stroke and runs cmd in it. The text() field of cmd is used as a titl...
bool antialiased() const
KoShapeManager * shapeManager() const
void setAntialiased(const bool antialiased)
QList< KoShape * > shapes() const
The undo / redo command for creating shapes.
The undo / redo command for grouping shapes.
QList< KoShape * > shapesAt(const QRectF &rect, bool omitHiddenShapes=true, bool containedMode=false)
KoShape * shapeAt(const QPointF &position, KoFlake::ShapeSelection selection=KoFlake::ShapeOnTop, bool omitHiddenShapes=true)
void setName(const QString &name)
Definition KoShape.cpp:1155
void setZIndex(qint16 zIndex)
Definition KoShape.cpp:954
static bool compareShapeZIndex(KoShape *s1, KoShape *s2)
Definition KoShape.cpp:434
KoShapeContainer * parent() const
Definition KoShape.cpp:1039
Document * activeDocument() const
Definition Krita.cpp:104
static Krita * instance()
instance retrieve the singleton instance of the Application object.
Definition Krita.cpp:390
Definition Node.h:24
QPoint position() const
position returns the position of the paint device of this node. The position is always 0,...
Definition Node.cpp:628
KisNodeSP node() const
Definition Node.cpp:827
KisImageSP image() const
Definition Node.cpp:822
friend class VectorLayer
Definition Node.h:702
QString name() const
Definition Node.cpp:428
QRect bounds() const
bounds return the exact bounds of the node's paint device
Definition Node.cpp:615
The Shape class The shape class is a wrapper around Krita's vector objects.
Definition Shape.h:38
static QDomDocument createDocumentFromSvg(QIODevice *device, QString *errorMsg=0, int *errorLine=0, int *errorColumn=0)
QList< KoShape * > parseSvg(const QDomElement &e, QSizeF *fragmentSize=0)
Parses a svg fragment, returning the list of top level child shapes.
void setResolution(const QRectF boundsInPixels, qreal pixelsPerInch)
Implements exporting shapes to SVG.
Definition SvgWriter.h:33
bool save(QIODevice &outputDevice, const QSizeF &pageSize)
Writes svg to specified output device.
Definition SvgWriter.cpp:82
bool isAntialiased() const
return antialiasing status for the Vector layer
virtual QString type() const override
type Krita has several types of nodes, split in layers and masks. Group layers can contain other laye...
QList< Shape * > addShapesFromSvg(const QString &svg)
addShapesFromSvg add shapes to the layer from a valid svg.
QList< Shape * > shapesInRect(const QRectF &rect, bool omitHiddenShapes=true, bool containedMode=false) const
shapeInRect get all non-group shapes that the shape's boundingBox() intersects or is contained within...
QList< Shape * > shapes() const
shapes
QString toSvg()
toSvg convert the shapes in the layer to svg.
Shape * createGroupShape(const QString &name, QList< Shape * > shapes) const
createGroupShape combine a list of top level shapes into a group.
~VectorLayer() override
void setAntialiased(const bool antialiased)
set antialiasing status for the Vector layer
Shape * shapeAtPosition(const QPointF &position) const
shapeAtPoint check if the position is located within any non-group shape's boundingBox() on the curre...
KisSharedPtr< KisShapeLayer > KisShapeLayerSP
Definition kis_types.h:125
KUndo2MagicString kundo2_i18n(const char *text)
Document * findNodeInDocuments(KisNodeSP kisnode)
KisImageWSP image