File indexing completed on 2024-05-12 15:59:08
0001 /* 0002 * SPDX-FileCopyrightText: 2017 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 #include "VectorLayer.h" 0007 #include <kis_shape_layer.h> 0008 #include <kis_image.h> 0009 #include <SvgWriter.h> 0010 #include <SvgParser.h> 0011 #include <QBuffer> 0012 #include <commands/KoShapeCreateCommand.h> 0013 #include <KoShapeGroup.h> 0014 #include <KisDocument.h> 0015 #include <kis_processing_applicator.h> 0016 0017 #include "Krita.h" 0018 #include "GroupShape.h" 0019 0020 VectorLayer::VectorLayer(KoShapeControllerBase* shapeController, KisImageSP image, QString name, QObject *parent) : 0021 Node(image, new KisShapeLayer(shapeController, image, name, OPACITY_OPAQUE_U8), parent) 0022 { 0023 0024 } 0025 0026 VectorLayer::VectorLayer(KisShapeLayerSP layer, QObject *parent): 0027 Node(layer->image(), layer, parent) 0028 { 0029 0030 } 0031 0032 VectorLayer::~VectorLayer() 0033 { 0034 0035 } 0036 0037 QString VectorLayer::type() const 0038 { 0039 return "vectorlayer"; 0040 } 0041 0042 QList<Shape *> VectorLayer::shapes() const 0043 { 0044 QList<Shape*> shapes; 0045 KisShapeLayerSP vector = KisShapeLayerSP(dynamic_cast<KisShapeLayer*>(this->node().data())); 0046 if (vector) { 0047 QList<KoShape*> originalShapes = vector->shapes(); 0048 std::sort(originalShapes.begin(), originalShapes.end(), KoShape::compareShapeZIndex); 0049 for (int i=0; i<vector->shapeCount(); i++) { 0050 if (dynamic_cast<KoShapeGroup*>(originalShapes.at(i))) { 0051 shapes << new GroupShape(dynamic_cast<KoShapeGroup*>(originalShapes.at(i))); 0052 } else { 0053 shapes << new Shape(originalShapes.at(i)); 0054 } 0055 } 0056 } 0057 return shapes; 0058 } 0059 0060 QString VectorLayer::toSvg() 0061 { 0062 QString svgData; 0063 KisShapeLayerSP vector = KisShapeLayerSP(dynamic_cast<KisShapeLayer*>(this->node().data())); 0064 0065 if (vector) { 0066 QBuffer buffer; 0067 QList<KoShape*> originalShapes = vector->shapes(); 0068 0069 std::sort(originalShapes.begin(), originalShapes.end(), KoShape::compareShapeZIndex); 0070 0071 const QSizeF sizeInPx = this->node()->image()->bounds().size(); 0072 const QSizeF pageSize(sizeInPx.width() / this->node()->image()->xRes(), 0073 sizeInPx.height() / this->node()->image()->yRes()); 0074 0075 buffer.open(QIODevice::WriteOnly); 0076 0077 SvgWriter writer(originalShapes); 0078 0079 writer.save(buffer, pageSize); 0080 buffer.close(); 0081 0082 svgData = QString::fromUtf8(buffer.data()); 0083 } 0084 0085 return svgData; 0086 0087 } 0088 0089 QList<Shape *> VectorLayer::addShapesFromSvg(const QString &svgData) 0090 { 0091 QList<Shape*> shapes; 0092 QList<KoShape*> originalShapes; 0093 0094 if (svgData.isEmpty() || !svgData.contains("<svg") ) { 0095 return shapes; 0096 } 0097 0098 KoShapeContainer *container = dynamic_cast<KoShapeContainer*>(this->node().data()); 0099 0100 if (container) { 0101 QSizeF fragmentSize; 0102 QString errorMsg; 0103 int errorLine = 0; 0104 int errorColumn = 0; 0105 0106 QDomDocument dom = SvgParser::createDocumentFromSvg(svgData, &errorMsg, &errorLine, &errorColumn); 0107 0108 if (dom.isNull()) { 0109 qWarning() << "Failed to process an SVG string at" 0110 << errorLine << ":" << errorColumn << "->" << errorMsg; 0111 return shapes; 0112 } 0113 0114 Document *document = Krita::instance()->activeDocument(); 0115 SvgParser parser(document->document()->shapeController()->resourceManager()); 0116 0117 parser.setResolution(this->node()->image()->bounds(), this->node()->image()->xRes() * 72.0); 0118 0119 originalShapes = parser.parseSvg(dom.documentElement(), &fragmentSize); 0120 0121 KUndo2Command *cmd = new KoShapeCreateCommand(document->document()->shapeController(), originalShapes, container); 0122 0123 KisProcessingApplicator::runSingleCommandStroke(this->node()->image(), cmd); 0124 this->node()->image()->waitForDone(); 0125 delete document; 0126 0127 std::sort(originalShapes.begin(), originalShapes.end(), KoShape::compareShapeZIndex); 0128 for (int i=0; i<originalShapes.size(); i++) { 0129 if (dynamic_cast<KoShapeGroup*>(originalShapes.at(i))) { 0130 shapes << new GroupShape(dynamic_cast<KoShapeGroup*>(originalShapes.at(i))); 0131 } else { 0132 shapes << new Shape(originalShapes.at(i)); 0133 } 0134 } 0135 0136 } 0137 0138 return shapes; 0139 }