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

Implements exporting shapes to SVG. More...

#include <SvgWriter.h>

Public Member Functions

bool save (const QString &filename, const QSizeF &pageSize, bool writeInlineImages)
 Writes svg to the specified file.
 
bool save (QIODevice &outputDevice, const QSizeF &pageSize)
 Writes svg to specified output device.
 
bool saveDetached (QIODevice &outputDevice)
 
bool saveDetached (SvgSavingContext &savingContext)
 
void setDocumentDescription (QString description)
 
void setDocumentTitle (QString title)
 
 SvgWriter (const QList< KoShape * > &toplevelShapes)
 Creates svg writer to export specified shapes.
 
 SvgWriter (const QList< KoShapeLayer * > &layers)
 Creates svg writer to export specified layers.
 
virtual ~SvgWriter ()
 Destroys the svg writer.
 

Private Member Functions

void saveGeneric (KoShape *shape, SvgSavingContext &context)
 
void saveGroup (KoShapeGroup *group, SvgSavingContext &context)
 
void saveLayer (KoShapeLayer *layer, SvgSavingContext &context)
 
void savePath (KoPathShape *path, SvgSavingContext &context)
 
void saveShape (KoShape *shape, SvgSavingContext &context)
 
void saveShapes (const QList< KoShape * > shapes, SvgSavingContext &savingContext)
 

Private Attributes

QString m_documentDescription
 
QString m_documentTitle
 
QList< KoShape * > m_toplevelShapes
 
bool m_writeInlineImages
 

Detailed Description

Implements exporting shapes to SVG.

Definition at line 32 of file SvgWriter.h.

Constructor & Destructor Documentation

◆ SvgWriter() [1/2]

SvgWriter::SvgWriter ( const QList< KoShapeLayer * > & layers)

Creates svg writer to export specified layers.

Definition at line 47 of file SvgWriter.cpp.

49{
50 Q_FOREACH (KoShapeLayer *layer, layers)
51 m_toplevelShapes.append(layer);
52}
bool m_writeInlineImages
Definition SvgWriter.h:67
QList< KoShape * > m_toplevelShapes
Definition SvgWriter.h:66

References m_toplevelShapes.

◆ SvgWriter() [2/2]

SvgWriter::SvgWriter ( const QList< KoShape * > & toplevelShapes)

Creates svg writer to export specified shapes.

Definition at line 54 of file SvgWriter.cpp.

55 : m_toplevelShapes(toplevelShapes)
57{
58}

◆ ~SvgWriter()

SvgWriter::~SvgWriter ( )
virtual

Destroys the svg writer.

Definition at line 60 of file SvgWriter.cpp.

61{
62
63}

Member Function Documentation

◆ save() [1/2]

bool SvgWriter::save ( const QString & filename,
const QSizeF & pageSize,
bool writeInlineImages )

Writes svg to the specified file.

Definition at line 65 of file SvgWriter.cpp.

66{
67 QFile fileOut(filename);
68 if (!fileOut.open(QIODevice::WriteOnly))
69 return false;
70
71 m_writeInlineImages = writeInlineImages;
72
73 const bool success = save(fileOut, pageSize);
74
76
77 fileOut.close();
78
79 return success;
80}
bool save(QIODevice &outputDevice, const QSizeF &pageSize)
Writes svg to specified output device.
Definition SvgWriter.cpp:82

References m_writeInlineImages, and save().

◆ save() [2/2]

bool SvgWriter::save ( QIODevice & outputDevice,
const QSizeF & pageSize )

Writes svg to specified output device.

Definition at line 82 of file SvgWriter.cpp.

83{
84 if (m_toplevelShapes.isEmpty()) {
85 return false;
86 }
87
88 QTextStream svgStream(&outputDevice);
90
91 // standard header:
92 svgStream << "<?xml version=\"1.0\" standalone=\"no\"?>" << Qt::endl;
93 svgStream << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" ";
94 svgStream << "\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">" << Qt::endl;
95
96 // add some PR. one line is more than enough.
97 svgStream << "<!-- Created using Krita: https://krita.org -->" << Qt::endl;
98
99 svgStream << "<svg xmlns=\"http://www.w3.org/2000/svg\" \n";
100 svgStream << " xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n";
101 svgStream << QString(" xmlns:krita=\"%1\"\n").arg(KoXmlNS::krita);
102 svgStream << " xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"\n";
103 svgStream << " width=\"" << pageSize.width() << "pt\"\n";
104 svgStream << " height=\"" << pageSize.height() << "pt\"\n";
105 svgStream << " viewBox=\"0 0 "
106 << pageSize.width() << " " << pageSize.height()
107 << "\"";
108 svgStream << ">" << Qt::endl;
109
110 if (!m_documentTitle.isNull() && !m_documentTitle.isEmpty()) {
111 svgStream << "<title>" << m_documentTitle << "</title>" << Qt::endl;
112 }
113
114 if (!m_documentDescription.isNull() && !m_documentDescription.isEmpty()) {
115 svgStream << "<desc>" << m_documentDescription << "</desc>" << Qt::endl;
116 }
117
118 {
119 SvgSavingContext savingContext(outputDevice, m_writeInlineImages);
120 saveShapes(m_toplevelShapes, savingContext);
121 }
122
123 // end tag:
124 svgStream << Qt::endl << "</svg>" << Qt::endl;
125
126 return true;
127}
static const QString krita
Definition KoXmlNS.h:48
Context for saving svg files.
void saveShapes(const QList< KoShape * > shapes, SvgSavingContext &savingContext)
QString m_documentDescription
Definition SvgWriter.h:69
QString m_documentTitle
Definition SvgWriter.h:68
void setUtf8OnStream(QTextStream &stream)

References KoXmlNS::krita, m_documentDescription, m_documentTitle, m_toplevelShapes, m_writeInlineImages, saveShapes(), and KisPortingUtils::setUtf8OnStream().

◆ saveDetached() [1/2]

bool SvgWriter::saveDetached ( QIODevice & outputDevice)

Definition at line 129 of file SvgWriter.cpp.

130{
131 if (m_toplevelShapes.isEmpty())
132 return false;
133
134 SvgSavingContext savingContext(outputDevice, m_writeInlineImages);
135 saveShapes(m_toplevelShapes, savingContext);
136
137 return true;
138}

References m_toplevelShapes, m_writeInlineImages, and saveShapes().

◆ saveDetached() [2/2]

bool SvgWriter::saveDetached ( SvgSavingContext & savingContext)

Definition at line 140 of file SvgWriter.cpp.

141{
142 if (m_toplevelShapes.isEmpty())
143 return false;
144
145 saveShapes(m_toplevelShapes, savingContext);
146
147 return true;
148}

References m_toplevelShapes, and saveShapes().

◆ saveGeneric()

void SvgWriter::saveGeneric ( KoShape * shape,
SvgSavingContext & context )
private

HACK ALERT: Qt (and Krita 3.x) has a weird bug, it assumes that all font sizes are defined in 96 ppi resolution, even though your the resolution in QSvgGenerator is manually set to 72 ppi. So here we do a tricky thing: we set a fake resolution to (72 * 72 / 96) = 54 ppi, which guarantees that the text, when painted in 96 ppi, will be actually painted in 72 ppi.

BUG: 389802

Definition at line 242 of file SvgWriter.cpp.

243{
245
246 const QRectF bbox = shape->boundingRect();
247
248 // paint shape to the image
249 KoShapePainter painter;
250 painter.setShapes(QList<KoShape*>()<< shape);
251
252 // generate svg from shape
253 QBuffer svgBuffer;
254 QSvgGenerator svgGenerator;
255 svgGenerator.setOutputDevice(&svgBuffer);
256
266 if (shape->shapeId() == "TextShapeID") {
267 svgGenerator.setResolution(54);
268 }
269
270 QPainter svgPainter;
271 svgPainter.begin(&svgGenerator);
272 painter.paint(svgPainter, SvgUtil::toUserSpace(bbox).toRect(), bbox);
273 svgPainter.end();
274
275 // remove anything before the start of the svg element from the buffer
276 int startOfContent = svgBuffer.buffer().indexOf("<svg");
277 if(startOfContent>0) {
278 svgBuffer.buffer().remove(0, startOfContent);
279 }
280
281 // check if painting to svg produced any output
282 if (svgBuffer.buffer().isEmpty()) {
283 // prepare a transparent image, make it twice as big as the original size
284 QImage image(2*bbox.size().toSize(), QImage::Format_ARGB32);
285 image.fill(0);
286 painter.paint(image);
287
288 context.shapeWriter().startElement("image");
289 context.shapeWriter().addAttribute("id", context.getID(shape));
290 context.shapeWriter().addAttribute("x", bbox.x());
291 context.shapeWriter().addAttribute("y", bbox.y());
292 context.shapeWriter().addAttribute("width", bbox.width());
293 context.shapeWriter().addAttribute("height", bbox.height());
294 context.shapeWriter().addAttribute("xlink:href", context.saveImage(image));
295 context.shapeWriter().endElement(); // image
296
297 } else {
298 context.shapeWriter().addCompleteElement(&svgBuffer);
299 }
300
301 // TODO: once we support saving single (flat) odf files
302 // we can embed these here to have full support for generic shapes
303}
void setShapes(const QList< KoShape * > &shapes)
void paint(QPainter &painter)
QString shapeId() const
Definition KoShape.cpp:1057
virtual QRectF boundingRect() const
Get the bounding box of the shape.
Definition KoShape.cpp:335
QString saveImage(const QImage &image)
Saves given image and returns the href used.
QScopedPointer< KoXmlWriter > shapeWriter
QString getID(const KoShape *obj)
Returns the unique id for the given shape.
static double toUserSpace(double value)
Definition SvgUtil.cpp:34
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128

References KoShape::boundingRect(), SvgSavingContext::getID(), KIS_SAFE_ASSERT_RECOVER_RETURN, KoShapePainter::paint(), SvgSavingContext::saveImage(), KoShapePainter::setShapes(), KoShape::shapeId(), SvgSavingContext::shapeWriter, and SvgUtil::toUserSpace().

◆ saveGroup()

void SvgWriter::saveGroup ( KoShapeGroup * group,
SvgSavingContext & context )
private

Definition at line 186 of file SvgWriter.cpp.

187{
188 context.shapeWriter().startElement("g");
189 context.shapeWriter().addAttribute("id", context.getID(group));
190
191 SvgUtil::writeTransformAttributeLazy("transform", group->transformation(), context.shapeWriter());
192
193
194 SvgStyleWriter::saveMetadata(group, context);
195
196 SvgStyleWriter::saveSvgStyle(group, context);
197
198 QList<KoShape*> sortedShapes = group->shapes();
199 std::sort(sortedShapes.begin(), sortedShapes.end(), KoShape::compareShapeZIndex);
200
201 Q_FOREACH (KoShape * shape, sortedShapes) {
202 KoShapeGroup * childGroup = dynamic_cast<KoShapeGroup*>(shape);
203 if (childGroup)
204 saveGroup(childGroup, context);
205 else
206 saveShape(shape, context);
207 }
208
209 context.shapeWriter().endElement();
210}
QList< KoShape * > shapes() const
static bool compareShapeZIndex(KoShape *s1, KoShape *s2)
Definition KoShape.cpp:434
QTransform transformation() const
Returns the shapes local transformation matrix.
Definition KoShape.cpp:424
static void saveSvgStyle(KoShape *shape, SvgSavingContext &context)
Saves the style of the specified shape.
static void saveMetadata(const KoShape *shape, SvgSavingContext &context)
static void writeTransformAttributeLazy(const QString &name, const QTransform &transform, KoXmlWriter &shapeWriter)
Writes a transform as an attribute name iff the transform is not empty.
Definition SvgUtil.cpp:124
void saveGroup(KoShapeGroup *group, SvgSavingContext &context)
void saveShape(KoShape *shape, SvgSavingContext &context)

References KoShape::compareShapeZIndex(), SvgSavingContext::getID(), saveGroup(), SvgStyleWriter::saveMetadata(), saveShape(), SvgStyleWriter::saveSvgStyle(), KoShapeContainer::shapes(), SvgSavingContext::shapeWriter, KoShape::transformation(), and SvgUtil::writeTransformAttributeLazy().

◆ saveLayer()

void SvgWriter::saveLayer ( KoShapeLayer * layer,
SvgSavingContext & context )
private

Definition at line 167 of file SvgWriter.cpp.

168{
169 context.shapeWriter().startElement("g");
170 context.shapeWriter().addAttribute("id", context.getID(layer));
171
172 QList<KoShape*> sortedShapes = layer->shapes();
173 std::sort(sortedShapes.begin(), sortedShapes.end(), KoShape::compareShapeZIndex);
174
175 Q_FOREACH (KoShape * shape, sortedShapes) {
176 KoShapeGroup * group = dynamic_cast<KoShapeGroup*>(shape);
177 if (group)
178 saveGroup(group, context);
179 else
180 saveShape(shape, context);
181 }
182
183 context.shapeWriter().endElement();
184}

References KoShape::compareShapeZIndex(), SvgSavingContext::getID(), saveGroup(), saveShape(), KoShapeContainer::shapes(), and SvgSavingContext::shapeWriter.

◆ savePath()

void SvgWriter::savePath ( KoPathShape * path,
SvgSavingContext & context )
private

Definition at line 227 of file SvgWriter.cpp.

228{
229 context.shapeWriter().startElement("path");
230 context.shapeWriter().addAttribute("id", context.getID(path));
231
232 SvgUtil::writeTransformAttributeLazy("transform", path->transformation(), context.shapeWriter());
233 SvgStyleWriter::saveMetadata(path, context);
234
235 SvgStyleWriter::saveSvgStyle(path, context);
236
237 context.shapeWriter().addAttribute("d", path->toString(context.userSpaceTransform()));
238 context.shapeWriter().addAttribute("sodipodi:nodetypes", path->nodeTypes());
239 context.shapeWriter().endElement();
240}
QTransform userSpaceTransform() const
Returns the transformation used to transform into user space.

References SvgSavingContext::getID(), SvgStyleWriter::saveMetadata(), SvgStyleWriter::saveSvgStyle(), SvgSavingContext::shapeWriter, SvgSavingContext::userSpaceTransform(), and SvgUtil::writeTransformAttributeLazy().

◆ saveShape()

void SvgWriter::saveShape ( KoShape * shape,
SvgSavingContext & context )
private

Definition at line 212 of file SvgWriter.cpp.

213{
214 SvgShape *svgShape = dynamic_cast<SvgShape*>(shape);
215 if (svgShape && svgShape->saveSvg(context))
216 return;
217
218 KoPathShape * path = dynamic_cast<KoPathShape*>(shape);
219 if (path) {
220 savePath(path, context);
221 } else {
222 // generic saving of shape via a switch element
223 saveGeneric(shape, context);
224 }
225}
The position of a path point within a path shape.
Definition KoPathShape.h:63
An interface providing svg loading and saving routines.
Definition SvgShape.h:18
virtual bool saveSvg(SvgSavingContext &context)
Saves data utilizing specified svg saving context.
Definition SvgShape.cpp:14
void saveGeneric(KoShape *shape, SvgSavingContext &context)
void savePath(KoPathShape *path, SvgSavingContext &context)

References saveGeneric(), savePath(), and SvgShape::saveSvg().

◆ saveShapes()

void SvgWriter::saveShapes ( const QList< KoShape * > shapes,
SvgSavingContext & savingContext )
private

Definition at line 150 of file SvgWriter.cpp.

151{
152 // top level shapes
153 Q_FOREACH (KoShape *shape, shapes) {
154 KoShapeLayer *layer = dynamic_cast<KoShapeLayer*>(shape);
155 if(layer) {
156 saveLayer(layer, savingContext);
157 } else {
158 KoShapeGroup *group = dynamic_cast<KoShapeGroup*>(shape);
159 if (group)
160 saveGroup(group, savingContext);
161 else
162 saveShape(shape, savingContext);
163 }
164 }
165}
void saveLayer(KoShapeLayer *layer, SvgSavingContext &context)

References saveGroup(), saveLayer(), and saveShape().

◆ setDocumentDescription()

void SvgWriter::setDocumentDescription ( QString description)

Definition at line 310 of file SvgWriter.cpp.

311{
312 m_documentDescription = description;
313}

References m_documentDescription.

◆ setDocumentTitle()

void SvgWriter::setDocumentTitle ( QString title)

Definition at line 305 of file SvgWriter.cpp.

306{
307 m_documentTitle = title;
308}

References m_documentTitle.

Member Data Documentation

◆ m_documentDescription

QString SvgWriter::m_documentDescription
private

Definition at line 69 of file SvgWriter.h.

◆ m_documentTitle

QString SvgWriter::m_documentTitle
private

Definition at line 68 of file SvgWriter.h.

◆ m_toplevelShapes

QList<KoShape*> SvgWriter::m_toplevelShapes
private

Definition at line 66 of file SvgWriter.h.

◆ m_writeInlineImages

bool SvgWriter::m_writeInlineImages
private

Definition at line 67 of file SvgWriter.h.


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