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

Helper class to save svg styles. More...

#include <SvgStyleWriter.h>

Static Public Member Functions

static QString embedShape (const KoShape *shape, SvgSavingContext &context)
 
static void saveMetadata (const KoShape *shape, SvgSavingContext &context)
 
static void saveSvgBasicStyle (const bool isVisible, const qreal transparency, const QVector< KoShape::PaintOrder > paintOrder, bool inheritPaintorder, SvgSavingContext &context, bool textShape=false)
 Saves only stroke, fill and transparency of the shape.
 
static void saveSvgFill (QSharedPointer< KoShapeBackground > background, const bool fillRuleEvenOdd, const QRectF outlineRect, const QSizeF size, const QTransform absoluteTransform, SvgSavingContext &context)
 Saves fill style of specified shape.
 
static void saveSvgStroke (KoShapeStrokeModelSP, SvgSavingContext &context)
 Saves stroke style of specified shape.
 
static void saveSvgStyle (KoShape *shape, SvgSavingContext &context)
 Saves the style of the specified shape.
 

Static Protected Member Functions

static void saveSvgClipping (KoShape *shape, SvgSavingContext &context)
 Saves clipping of specified shape.
 
static void saveSvgColorStops (const QGradientStops &colorStops, SvgSavingContext &context)
 Saves gradient color stops.
 
static void saveSvgEffects (KoShape *shape, SvgSavingContext &context)
 Saves effects of specified shape.
 
static QString saveSvgGradient (const QGradient *gradient, const QTransform &gradientTransform, SvgSavingContext &context)
 Saves gradient.
 
static void saveSvgMarkers (KoShape *shape, SvgSavingContext &context)
 Saves markers of the path shape if present.
 
static void saveSvgMasking (KoShape *shape, SvgSavingContext &context)
 Saves masking of specified shape.
 
static QString saveSvgMeshGradient (SvgMeshGradient *gradient, const QTransform &transform, SvgSavingContext &context)
 
static QString saveSvgPattern (QSharedPointer< KoPatternBackground > pattern, const QSizeF shapeSize, const QTransform absoluteTransform, SvgSavingContext &context)
 Saves pattern.
 
static QString saveSvgVectorPattern (QSharedPointer< KoVectorPatternBackground > pattern, const QRectF outlineRect, SvgSavingContext &context)
 

Detailed Description

Helper class to save svg styles.

Definition at line 35 of file SvgStyleWriter.h.

Member Function Documentation

◆ embedShape()

QString SvgStyleWriter::embedShape ( const KoShape * shape,
SvgSavingContext & context )
static

Definition at line 227 of file SvgStyleWriter.cpp.

228{
229 QList<KoShape *> shapes;
230 KoShape* clonedShape = shape->cloneShape();
231 if (!clonedShape) {
232 return QString();
233 }
234 const QString uid = context.createUID("path");
235 clonedShape->setName(uid);
236 shapes.append(clonedShape);
237 embedShapes(shapes, context.styleWriter());
238 return uid;
239}
void embedShapes(const QList< KoShape * > &shapes, KoXmlWriter &outWriter)
void setName(const QString &name)
Definition KoShape.cpp:1155
virtual KoShape * cloneShape() const
creates a deep copy of the shape or shape's subtree
Definition KoShape.cpp:200
QString createUID(const QString &base)
Create a unique id from the specified base text.
QScopedPointer< KoXmlWriter > styleWriter

References KoShape::cloneShape(), SvgSavingContext::createUID(), embedShapes(), KoShape::setName(), and SvgSavingContext::styleWriter.

◆ saveMetadata()

void SvgStyleWriter::saveMetadata ( const KoShape * shape,
SvgSavingContext & context )
static

Definition at line 241 of file SvgStyleWriter.cpp.

242{
243 const QString title = shape->additionalAttribute("title");
244 if (!title.trimmed().isEmpty()) {
245 context.shapeWriter().startElement("title");
246 context.shapeWriter().addTextNode(title);
247 context.shapeWriter().endElement();
248 }
249 const QString desc = shape->additionalAttribute("desc");
250 if (!desc.trimmed().isEmpty()) {
251 context.shapeWriter().startElement("desc");
252 context.shapeWriter().addTextNode(desc);
253 context.shapeWriter().endElement();
254 }
255}
QString additionalAttribute(const QString &name) const
Definition KoShape.cpp:1279
QScopedPointer< KoXmlWriter > shapeWriter

References KoShape::additionalAttribute(), and SvgSavingContext::shapeWriter.

◆ saveSvgBasicStyle()

void SvgStyleWriter::saveSvgBasicStyle ( const bool isVisible,
const qreal transparency,
const QVector< KoShape::PaintOrder > paintOrder,
bool inheritPaintorder,
SvgSavingContext & context,
bool textShape = false )
static

Saves only stroke, fill and transparency of the shape.

Definition at line 73 of file SvgStyleWriter.cpp.

74{
75 if (!isVisible) {
76 context.shapeWriter().addAttribute("display", "none");
77 } else if (transparency > 0.0) {
78 context.shapeWriter().addAttribute("opacity", 1.0 - transparency);
79 }
80 if (!paintOrder.isEmpty() && !inheritPaintorder) {
81
82 const bool notDefault = paintOrder != KoShape::defaultPaintOrder();
83
84 if ((!textShape && notDefault) || textShape) {
85 QStringList order;
86 Q_FOREACH(const KoShape::PaintOrder p, paintOrder) {
87 if (p == KoShape::Fill) {
88 order.append("fill");
89 } else if (p == KoShape::Stroke) {
90 order.append("stroke");
91 } else if (p == KoShape::Markers) {
92 order.append("markers");
93 }
94 }
95 context.shapeWriter().addAttribute("paint-order", order.join(" "));
96 }
97 }
98
99}
const Params2D p
static QVector< PaintOrder > defaultPaintOrder()
default paint order as per SVG specification
Definition KoShape.cpp:784
@ Stroke
Definition KoShape.h:147
@ Markers
Definition KoShape.h:148

References KoShape::defaultPaintOrder(), KoShape::Fill, KoShape::Markers, p, SvgSavingContext::shapeWriter, and KoShape::Stroke.

◆ saveSvgClipping()

void SvgStyleWriter::saveSvgClipping ( KoShape * shape,
SvgSavingContext & context )
staticprotected

Saves clipping of specified shape.

Definition at line 257 of file SvgStyleWriter.cpp.

258{
259 KoClipPath *clipPath = shape->clipPath();
260 if (!clipPath)
261 return;
262
263 const QString uid = context.createUID("clippath");
264
265 context.styleWriter().startElement("clipPath");
266 context.styleWriter().addAttribute("id", uid);
267 context.styleWriter().addAttribute("clipPathUnits", KoFlake::coordinateToString(clipPath->coordinates()));
268
269 embedShapes(clipPath->clipShapes(), context.styleWriter());
270
271 context.styleWriter().endElement(); // clipPath
272
273 context.shapeWriter().addAttribute("clip-path", "url(#" + uid + ")");
274 if (clipPath->clipRule() != Qt::WindingFill)
275 context.shapeWriter().addAttribute("clip-rule", "evenodd");
276}
Clip path used to clip shapes.
KoFlake::CoordinateSystem coordinates
QList< KoShape * > clipShapes() const
Qt::FillRule clipRule
KoClipPath * clipPath() const
Returns the currently set clip path or 0 if there is no clip path set.
Definition KoShape.cpp:1128
QString coordinateToString(CoordinateSystem value)

References KoShape::clipPath(), KoClipPath::clipRule, KoClipPath::clipShapes(), KoClipPath::coordinates, KoFlake::coordinateToString(), SvgSavingContext::createUID(), embedShapes(), SvgSavingContext::shapeWriter, and SvgSavingContext::styleWriter.

◆ saveSvgColorStops()

void SvgStyleWriter::saveSvgColorStops ( const QGradientStops & colorStops,
SvgSavingContext & context )
staticprotected

Saves gradient color stops.

Definition at line 364 of file SvgStyleWriter.cpp.

365{
366 Q_FOREACH (const QGradientStop &stop, colorStops) {
367 context.styleWriter().startElement("stop");
368 context.styleWriter().addAttribute("stop-color", stop.second.name());
369 context.styleWriter().addAttribute("offset", stop.first);
370 context.styleWriter().addAttribute("stop-opacity", stop.second.alphaF());
371 context.styleWriter().endElement();
372 }
373}

References SvgSavingContext::styleWriter.

◆ saveSvgEffects()

void SvgStyleWriter::saveSvgEffects ( KoShape * shape,
SvgSavingContext & context )
staticprotected

Saves effects of specified shape.

Definition at line 198 of file SvgStyleWriter.cpp.

199{
200 KoFilterEffectStack * filterStack = shape->filterEffectStack();
201 if (!filterStack)
202 return;
203
204 QList<KoFilterEffect*> filterEffects = filterStack->filterEffects();
205 if (!filterEffects.count())
206 return;
207
208 const QString uid = context.createUID("filter");
209
210 filterStack->save(context.styleWriter(), uid);
211
212 context.shapeWriter().addAttribute("filter", "url(#" + uid + ")");
213}
This class manages a stack of filter effects.
void save(KoXmlWriter &writer, const QString &filterId)
QList< KoFilterEffect * > filterEffects
KoFilterEffectStack * filterEffectStack() const
Definition KoShape.cpp:1294

References SvgSavingContext::createUID(), KoFilterEffectStack::filterEffects, KoShape::filterEffectStack(), KoFilterEffectStack::save(), SvgSavingContext::shapeWriter, and SvgSavingContext::styleWriter.

◆ saveSvgFill()

void SvgStyleWriter::saveSvgFill ( QSharedPointer< KoShapeBackground > background,
const bool fillRuleEvenOdd,
const QRectF outlineRect,
const QSizeF size,
const QTransform absoluteTransform,
SvgSavingContext & context )
static

Saves fill style of specified shape.

Definition at line 101 of file SvgStyleWriter.cpp.

102{
103 if (! background) {
104 context.shapeWriter().addAttribute("fill", "none");
105 }
106
107 QBrush fill(Qt::NoBrush);
108 QSharedPointer<KoColorBackground> cbg = qSharedPointerDynamicCast<KoColorBackground>(background);
109 if (cbg) {
110 context.shapeWriter().addAttribute("fill", cbg->color().name());
111 if (cbg->color().alphaF() < 1.0)
112 context.shapeWriter().addAttribute("fill-opacity", cbg->color().alphaF());
113 }
114 QSharedPointer<KoGradientBackground> gbg = qSharedPointerDynamicCast<KoGradientBackground>(background);
115 if (gbg) {
116 QString gradientId = saveSvgGradient(gbg->gradient(), gbg->transform(), context);
117 context.shapeWriter().addAttribute("fill", "url(#" + gradientId + ")");
118 }
119 QSharedPointer<KoMeshGradientBackground> mgbg = qSharedPointerDynamicCast<KoMeshGradientBackground>(background);
120 if (mgbg) {
121 QString gradientId = saveSvgMeshGradient(mgbg->gradient(), mgbg->transform(), context);
122 context.shapeWriter().addAttribute("fill", "url(#" + gradientId + ")");
123 }
124 QSharedPointer<KoPatternBackground> pbg = qSharedPointerDynamicCast<KoPatternBackground>(background);
125 if (pbg) {
126 const QString patternId = saveSvgPattern(pbg, size, absoluteTransform, context);
127 context.shapeWriter().addAttribute("fill", "url(#" + patternId + ")");
128 }
129 QSharedPointer<KoVectorPatternBackground> vpbg = qSharedPointerDynamicCast<KoVectorPatternBackground>(background);
130 if (vpbg) {
131 const QString patternId = saveSvgVectorPattern(vpbg, outlineRect, context);
132 context.shapeWriter().addAttribute("fill", "url(#" + patternId + ")");
133 }
134
135 // non-zero is default, so only write fillrule if evenodd is set
136 if (fillRuleEvenOdd)
137 context.shapeWriter().addAttribute("fill-rule", "evenodd");
138}
static QString saveSvgGradient(const QGradient *gradient, const QTransform &gradientTransform, SvgSavingContext &context)
Saves gradient.
static QString saveSvgMeshGradient(SvgMeshGradient *gradient, const QTransform &transform, SvgSavingContext &context)
static QString saveSvgPattern(QSharedPointer< KoPatternBackground > pattern, const QSizeF shapeSize, const QTransform absoluteTransform, SvgSavingContext &context)
Saves pattern.
static QString saveSvgVectorPattern(QSharedPointer< KoVectorPatternBackground > pattern, const QRectF outlineRect, SvgSavingContext &context)

References saveSvgGradient(), saveSvgMeshGradient(), saveSvgPattern(), saveSvgVectorPattern(), and SvgSavingContext::shapeWriter.

◆ saveSvgGradient()

QString SvgStyleWriter::saveSvgGradient ( const QGradient * gradient,
const QTransform & gradientTransform,
SvgSavingContext & context )
staticprotected

Saves gradient.

Definition at line 385 of file SvgStyleWriter.cpp.

386{
387 if (! gradient)
388 return QString();
389
390 const QString spreadMethod[3] = {
391 QString("pad"),
392 QString("reflect"),
393 QString("repeat")
394 };
395
396 const QString uid = context.createUID("gradient");
397
398 if (gradient->type() == QGradient::LinearGradient) {
399 const QLinearGradient * g = static_cast<const QLinearGradient*>(gradient);
400 context.styleWriter().startElement("linearGradient");
401 context.styleWriter().addAttribute("id", uid);
402 SvgUtil::writeTransformAttributeLazy("gradientTransform", gradientTransform, context.styleWriter());
403 context.styleWriter().addAttribute("gradientUnits", convertGradientMode(g->coordinateMode()));
404 context.styleWriter().addAttribute("x1", g->start().x());
405 context.styleWriter().addAttribute("y1", g->start().y());
406 context.styleWriter().addAttribute("x2", g->finalStop().x());
407 context.styleWriter().addAttribute("y2", g->finalStop().y());
408 context.styleWriter().addAttribute("spreadMethod", spreadMethod[g->spread()]);
409 // color stops
410 saveSvgColorStops(gradient->stops(), context);
411 context.styleWriter().endElement();
412 } else if (gradient->type() == QGradient::RadialGradient) {
413 const QRadialGradient * g = static_cast<const QRadialGradient*>(gradient);
414 context.styleWriter().startElement("radialGradient");
415 context.styleWriter().addAttribute("id", uid);
416 SvgUtil::writeTransformAttributeLazy("gradientTransform", gradientTransform, context.styleWriter());
417 context.styleWriter().addAttribute("gradientUnits", convertGradientMode(g->coordinateMode()));
418 context.styleWriter().addAttribute("cx", g->center().x());
419 context.styleWriter().addAttribute("cy", g->center().y());
420 context.styleWriter().addAttribute("fx", g->focalPoint().x());
421 context.styleWriter().addAttribute("fy", g->focalPoint().y());
422 context.styleWriter().addAttribute("r", g->radius());
423 context.styleWriter().addAttribute("spreadMethod", spreadMethod[g->spread()]);
424 // color stops
425 saveSvgColorStops(gradient->stops(), context);
426 context.styleWriter().endElement();
427 } else if (gradient->type() == QGradient::ConicalGradient) {
428 //const QConicalGradient * g = static_cast<const QConicalGradient*>( gradient );
429 // fake conical grad as radial.
430 // fugly but better than data loss.
431 /*
432 printIndentation( m_defs, m_indent2 );
433 *m_defs << "<radialGradient id=\"" << uid << "\" ";
434 *m_defs << "gradientUnits=\"userSpaceOnUse\" ";
435 *m_defs << "cx=\"" << g->center().x() << "\" ";
436 *m_defs << "cy=\"" << g->center().y() << "\" ";
437 *m_defs << "fx=\"" << grad.focalPoint().x() << "\" ";
438 *m_defs << "fy=\"" << grad.focalPoint().y() << "\" ";
439 double r = sqrt( pow( grad.vector().x() - grad.origin().x(), 2 ) + pow( grad.vector().y() - grad.origin().y(), 2 ) );
440 *m_defs << "r=\"" << QString().setNum( r ) << "\" ";
441 *m_defs << spreadMethod[g->spread()];
442 *m_defs << ">" << Qt::endl;
443
444 // color stops
445 getColorStops( gradient->stops() );
446
447 printIndentation( m_defs, m_indent2 );
448 *m_defs << "</radialGradient>" << Qt::endl;
449 *m_body << "url(#" << uid << ")";
450 */
451 }
452
453 return uid;
454}
QString convertGradientMode(QGradient::CoordinateMode mode)
static void saveSvgColorStops(const QGradientStops &colorStops, SvgSavingContext &context)
Saves gradient color stops.
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

References convertGradientMode(), SvgSavingContext::createUID(), saveSvgColorStops(), SvgSavingContext::styleWriter, and SvgUtil::writeTransformAttributeLazy().

◆ saveSvgMarkers()

void SvgStyleWriter::saveSvgMarkers ( KoShape * shape,
SvgSavingContext & context )
staticprotected

Saves markers of the path shape if present.

Definition at line 349 of file SvgStyleWriter.cpp.

350{
351 KoPathShape *pathShape = dynamic_cast<KoPathShape*>(shape);
352 if (!pathShape || !pathShape->hasMarkers()) return;
353
354
355 tryEmbedMarker(pathShape, "marker-start", KoFlake::StartMarker, context);
356 tryEmbedMarker(pathShape, "marker-mid", KoFlake::MidMarker, context);
357 tryEmbedMarker(pathShape, "marker-end", KoFlake::EndMarker, context);
358
359 if (pathShape->autoFillMarkers()) {
360 context.shapeWriter().addAttribute("krita:marker-fill-method", "auto");
361 }
362}
The position of a path point within a path shape.
Definition KoPathShape.h:63
bool autoFillMarkers() const
bool hasMarkers() const
@ EndMarker
Definition KoFlake.h:44
@ StartMarker
Definition KoFlake.h:42
@ MidMarker
Definition KoFlake.h:43

References KoPathShape::autoFillMarkers(), KoFlake::EndMarker, KoPathShape::hasMarkers(), KoFlake::MidMarker, SvgSavingContext::shapeWriter, and KoFlake::StartMarker.

◆ saveSvgMasking()

void SvgStyleWriter::saveSvgMasking ( KoShape * shape,
SvgSavingContext & context )
staticprotected

Saves masking of specified shape.

Definition at line 278 of file SvgStyleWriter.cpp.

279{
280 KoClipMask*clipMask = shape->clipMask();
281 if (!clipMask)
282 return;
283
284 const QString uid = context.createUID("clipmask");
285
286 context.styleWriter().startElement("mask");
287 context.styleWriter().addAttribute("id", uid);
288 context.styleWriter().addAttribute("maskUnits", KoFlake::coordinateToString(clipMask->coordinates()));
289 context.styleWriter().addAttribute("maskContentUnits", KoFlake::coordinateToString(clipMask->contentCoordinates()));
290
291 const QRectF rect = clipMask->maskRect();
292
293 context.styleWriter().addAttribute("x", rect.x());
294 context.styleWriter().addAttribute("y", rect.y());
295 context.styleWriter().addAttribute("width", rect.width());
296 context.styleWriter().addAttribute("height", rect.height());
297
298 embedShapes(clipMask->shapes(), context.styleWriter());
299
300 context.styleWriter().endElement(); // clipMask
301
302 context.shapeWriter().addAttribute("mask", "url(#" + uid + ")");
303}
KoClipMask * clipMask() const
Returns the currently set clip mask or 0 if there is no clip mask set.
Definition KoShape.cpp:1140
QList< KoShape * > shapes
KoFlake::CoordinateSystem coordinates
KoFlake::CoordinateSystem contentCoordinates
QRectF maskRect

References KoShape::clipMask(), KoClipMask::contentCoordinates, KoClipMask::coordinates, KoFlake::coordinateToString(), SvgSavingContext::createUID(), embedShapes(), KoClipMask::maskRect, KoClipMask::shapes, SvgSavingContext::shapeWriter, and SvgSavingContext::styleWriter.

◆ saveSvgMeshGradient()

QString SvgStyleWriter::saveSvgMeshGradient ( SvgMeshGradient * gradient,
const QTransform & transform,
SvgSavingContext & context )
staticprotected

Definition at line 456 of file SvgStyleWriter.cpp.

459{
460 if (!gradient || !gradient->isValid())
461 return QString();
462
463 const QString uid = context.createUID("meshgradient");
464 context.styleWriter().startElement("meshgradient");
465 context.styleWriter().addAttribute("id", uid);
466
467 if (gradient->gradientUnits() == KoFlake::ObjectBoundingBox) {
468 context.styleWriter().addAttribute("gradientUnits", "objectBoundingBox");
469 } else {
470 context.styleWriter().addAttribute("gradientUnits", "userSpaceOnUse");
471 }
472
473 SvgUtil::writeTransformAttributeLazy("transform", transform, context.styleWriter());
474
475 SvgMeshArray *mesharray = gradient->getMeshArray().data();
476 QPointF start = mesharray->getPatch(0, 0)->getStop(SvgMeshPatch::Top).point;
477
478 context.styleWriter().addAttribute("x", start.x());
479 context.styleWriter().addAttribute("y", start.y());
480
481 if (gradient->type() == SvgMeshGradient::BILINEAR) {
482 context.styleWriter().addAttribute("type", "bilinear");
483 } else {
484 context.styleWriter().addAttribute("type", "bicubic");
485 }
486
487 for (int row = 0; row < mesharray->numRows(); ++row) {
488
489 const QString uid = context.createUID("meshrow");
490 context.styleWriter().startElement("meshrow");
491 context.styleWriter().addAttribute("id", uid);
492
493 for (int col = 0; col < mesharray->numColumns(); ++col) {
494
495 const QString uid = context.createUID("meshpatch");
496 context.styleWriter().startElement("meshpatch");
497 context.styleWriter().addAttribute("id", uid);
498
499 SvgMeshPatch *patch = mesharray->getPatch(row, col);
500
501 for (int s = 0; s < 4; ++s) {
502 SvgMeshPatch::Type type = static_cast<SvgMeshPatch::Type> (s);
503
504 // only first row and first col have Top and Left stop, respectively
505 if ((row != 0 && s == SvgMeshPatch::Top) ||
506 (col != 0 && s == SvgMeshPatch::Left)) {
507 continue;
508 }
509
510 context.styleWriter().startElement("stop");
511
512 std::array<QPointF, 4> segment = patch->getSegment(type);
513
514 QString pathstr;
515 QTextStream stream(&pathstr);
517
518 stream.setRealNumberPrecision(10);
519 // TODO: other path type?
520 stream << "C "
521 << segment[1].x() << "," << segment[1].y() << " "
522 << segment[2].x() << "," << segment[2].y() << " "
523 << segment[3].x() << "," << segment[3].y(); // I don't see any harm, inkscape does this too
524
525 context.styleWriter().addAttribute("path", pathstr);
526
527 // don't add color/opacity if stop is in first row and stop == Top (or)
528 // don't add color/opacity if stop is not in first row and stop == Right
529 if ((row != 0 || col == 0 || s != SvgMeshPatch::Top) &&
530 (row == 0 || s != SvgMeshPatch::Right)) {
531
532 SvgMeshStop stop = patch->getStop(type);
533 context.styleWriter().addAttribute("stop-color", stop.color.name());
534 context.styleWriter().addAttribute("stop-opacity", stop.color.alphaF());
535 }
536
537 context.styleWriter().endElement(); // stop
538 }
539
540 context.styleWriter().endElement(); // meshpatch
541 }
542 context.styleWriter().endElement(); // meshrow
543 }
544 context.styleWriter().endElement(); // meshgradient
545
546 return uid;
547}
int numRows() const
int numColumns() const
SvgMeshPatch * getPatch(const int row, const int col) const
SvgMeshGradient::Shading type() const
bool isValid() const
const QScopedPointer< SvgMeshArray > & getMeshArray() const
KoFlake::CoordinateSystem gradientUnits() const
Type
Position of stop in the patch.
SvgMeshStop getStop(Type type) const
returns the starting point of the stop
std::array< QPointF, 4 > getSegment(Type type) const
Get a segment of the path in the meshpatch.
void setUtf8OnStream(QTextStream &stream)
QPointF point

References SvgMeshGradient::BILINEAR, SvgMeshStop::color, SvgSavingContext::createUID(), SvgMeshGradient::getMeshArray(), SvgMeshArray::getPatch(), SvgMeshPatch::getSegment(), SvgMeshPatch::getStop(), SvgMeshGradient::gradientUnits(), SvgMeshGradient::isValid(), SvgMeshPatch::Left, SvgMeshArray::numColumns(), SvgMeshArray::numRows(), KoFlake::ObjectBoundingBox, SvgMeshStop::point, SvgMeshPatch::Right, KisPortingUtils::setUtf8OnStream(), SvgSavingContext::styleWriter, SvgMeshPatch::Top, SvgMeshGradient::type(), and SvgUtil::writeTransformAttributeLazy().

◆ saveSvgPattern()

QString SvgStyleWriter::saveSvgPattern ( QSharedPointer< KoPatternBackground > pattern,
const QSizeF shapeSize,
const QTransform absoluteTransform,
SvgSavingContext & context )
staticprotected

Saves pattern.

Definition at line 549 of file SvgStyleWriter.cpp.

550{
551 const QString uid = context.createUID("pattern");
552
553 const QSizeF patternSize = pattern->patternDisplaySize();
554 const QSize imageSize = pattern->pattern().size();
555
556 // calculate offset in point
557 QPointF offset = pattern->referencePointOffset();
558 offset.rx() = 0.01 * offset.x() * patternSize.width();
559 offset.ry() = 0.01 * offset.y() * patternSize.height();
560
561 // now take the reference point into account
562 switch (pattern->referencePoint()) {
564 break;
566 offset += QPointF(0.5 * shapeSize.width(), 0.0);
567 break;
569 offset += QPointF(shapeSize.width(), 0.0);
570 break;
572 offset += QPointF(0.0, 0.5 * shapeSize.height());
573 break;
575 offset += QPointF(0.5 * shapeSize.width(), 0.5 * shapeSize.height());
576 break;
578 offset += QPointF(shapeSize.width(), 0.5 * shapeSize.height());
579 break;
581 offset += QPointF(0.0, shapeSize.height());
582 break;
584 offset += QPointF(0.5 * shapeSize.width(), shapeSize.height());
585 break;
587 offset += QPointF(shapeSize.width(), shapeSize.height());
588 break;
589 }
590
591 offset = absoluteTransform.map(offset);
592
593 context.styleWriter().startElement("pattern");
594 context.styleWriter().addAttribute("id", uid);
595 context.styleWriter().addAttribute("x", SvgUtil::toUserSpace(offset.x()));
596 context.styleWriter().addAttribute("y", SvgUtil::toUserSpace(offset.y()));
597
598 if (pattern->repeat() == KoPatternBackground::Stretched) {
599 context.styleWriter().addAttribute("width", "100%");
600 context.styleWriter().addAttribute("height", "100%");
601 context.styleWriter().addAttribute("patternUnits", "objectBoundingBox");
602 } else {
603 context.styleWriter().addAttribute("width", SvgUtil::toUserSpace(patternSize.width()));
604 context.styleWriter().addAttribute("height", SvgUtil::toUserSpace(patternSize.height()));
605 context.styleWriter().addAttribute("patternUnits", "userSpaceOnUse");
606 }
607
608 context.styleWriter().addAttribute("viewBox", QString("0 0 %1 %2").arg(KisDomUtils::toString(imageSize.width())).arg(KisDomUtils::toString(imageSize.height())));
609 //*m_defs << " patternContentUnits=\"userSpaceOnUse\"";
610
611 context.styleWriter().startElement("image");
612 context.styleWriter().addAttribute("x", "0");
613 context.styleWriter().addAttribute("y", "0");
614 context.styleWriter().addAttribute("width", QString("%1px").arg(KisDomUtils::toString(imageSize.width())));
615 context.styleWriter().addAttribute("height", QString("%1px").arg(KisDomUtils::toString(imageSize.height())));
616
617 QBuffer buffer;
618 buffer.open(QIODevice::WriteOnly);
619 if (pattern->pattern().save(&buffer, "PNG")) {
620 const QString mimeType = KisMimeDatabase::mimeTypeForSuffix("*.png");
621 context.styleWriter().addAttribute("xlink:href", "data:"+ mimeType + ";base64," + buffer.data().toBase64());
622 }
623
624 context.styleWriter().endElement(); // image
625 context.styleWriter().endElement(); // pattern
626
627 return uid;
628}
static QString mimeTypeForSuffix(const QString &suffix)
Find the mimetype for a given extension. The extension may have the form "*.xxx" or "xxx".
static double toUserSpace(double value)
Definition SvgUtil.cpp:34
QString toString(const QString &value)

References KoPatternBackground::Bottom, KoPatternBackground::BottomLeft, KoPatternBackground::BottomRight, KoPatternBackground::Center, SvgSavingContext::createUID(), KoPatternBackground::Left, KisMimeDatabase::mimeTypeForSuffix(), KoPatternBackground::Right, KoPatternBackground::Stretched, SvgSavingContext::styleWriter, KoPatternBackground::Top, KoPatternBackground::TopLeft, KoPatternBackground::TopRight, KisDomUtils::toString(), and SvgUtil::toUserSpace().

◆ saveSvgStroke()

void SvgStyleWriter::saveSvgStroke ( KoShapeStrokeModelSP stroke,
SvgSavingContext & context )
static

Saves stroke style of specified shape.

Definition at line 140 of file SvgStyleWriter.cpp.

141{
142 const QSharedPointer<KoShapeStroke> lineBorder = qSharedPointerDynamicCast<KoShapeStroke>(stroke);
143
144 if (! lineBorder)
145 return;
146
147 QString strokeStr("none");
148 if (lineBorder->lineBrush().gradient()) {
149 QString gradientId = saveSvgGradient(lineBorder->lineBrush().gradient(), lineBorder->lineBrush().transform(), context);
150 strokeStr = "url(#" + gradientId + ")";
151 } else {
152 if (lineBorder->color().isValid()) {
153 strokeStr = lineBorder->color().name();
154 }
155 if (lineBorder->color().alphaF() < 1.0) {
156 context.shapeWriter().addAttribute("stroke-opacity", lineBorder->color().alphaF());
157 }
158 }
159 if (!strokeStr.isEmpty())
160 context.shapeWriter().addAttribute("stroke", strokeStr);
161
162 context.shapeWriter().addAttribute("stroke-width", SvgUtil::toUserSpace(lineBorder->lineWidth()));
163
164 if (lineBorder->capStyle() == Qt::FlatCap)
165 context.shapeWriter().addAttribute("stroke-linecap", "butt");
166 else if (lineBorder->capStyle() == Qt::RoundCap)
167 context.shapeWriter().addAttribute("stroke-linecap", "round");
168 else if (lineBorder->capStyle() == Qt::SquareCap)
169 context.shapeWriter().addAttribute("stroke-linecap", "square");
170
171 if (lineBorder->joinStyle() == Qt::MiterJoin) {
172 context.shapeWriter().addAttribute("stroke-linejoin", "miter");
173 context.shapeWriter().addAttribute("stroke-miterlimit", lineBorder->miterLimit());
174 } else if (lineBorder->joinStyle() == Qt::RoundJoin)
175 context.shapeWriter().addAttribute("stroke-linejoin", "round");
176 else if (lineBorder->joinStyle() == Qt::BevelJoin)
177 context.shapeWriter().addAttribute("stroke-linejoin", "bevel");
178
179 // dash
180 if (lineBorder->lineStyle() > Qt::SolidLine) {
181 qreal dashFactor = lineBorder->lineWidth();
182
183 if (lineBorder->dashOffset() != 0)
184 context.shapeWriter().addAttribute("stroke-dashoffset", dashFactor * lineBorder->dashOffset());
185
186 QString dashStr;
187 const QVector<qreal> dashes = lineBorder->lineDashes();
188 int dashCount = dashes.size();
189 for (int i = 0; i < dashCount; ++i) {
190 if (i > 0)
191 dashStr += ",";
192 dashStr += QString("%1").arg(KisDomUtils::toString(dashes[i] * dashFactor));
193 }
194 context.shapeWriter().addAttribute("stroke-dasharray", dashStr);
195 }
196}

References saveSvgGradient(), SvgSavingContext::shapeWriter, KisDomUtils::toString(), and SvgUtil::toUserSpace().

◆ saveSvgStyle()

void SvgStyleWriter::saveSvgStyle ( KoShape * shape,
SvgSavingContext & context )
static

Saves the style of the specified shape.

Definition at line 54 of file SvgStyleWriter.cpp.

55{
56 saveSvgBasicStyle(shape->isVisible(false), shape->transparency(false), shape->paintOrder(), shape->inheritPaintOrder(), context);
57
58 KoPathShape *pathShape = dynamic_cast<KoPathShape*>(shape);
59 bool fillRule = pathShape && pathShape->background() && pathShape->fillRule() == Qt::OddEvenFill? true: false;
60 if (!shape->inheritBackground()) {
61 saveSvgFill(shape->background(), fillRule, shape->outlineRect(), shape->size(), shape->absoluteTransformation(), context);
62 }
63 if (!shape->inheritStroke()) {
64 saveSvgStroke(shape->stroke(), context);
65 }
66
67 saveSvgEffects(shape, context);
68 saveSvgClipping(shape, context);
69 saveSvgMasking(shape, context);
70 saveSvgMarkers(shape, context);
71}
Qt::FillRule fillRule() const
Returns the fill rule for the path object.
virtual QSizeF size() const
Get the size of the shape in pt.
Definition KoShape.cpp:820
virtual QRectF outlineRect() const
Definition KoShape.cpp:637
virtual QVector< PaintOrder > paintOrder() const
paintOrder
Definition KoShape.cpp:773
virtual KoShapeStrokeModelSP stroke() const
Definition KoShape.cpp:1067
bool inheritStroke() const
inheritStroke shows if the shape inherits the stroke from its parent
Definition KoShape.cpp:1098
bool inheritBackground() const
inheritBackground shows if the shape inherits background from its parent
Definition KoShape.cpp:949
QTransform absoluteTransformation() const
Definition KoShape.cpp:382
virtual QSharedPointer< KoShapeBackground > background() const
Definition KoShape.cpp:926
bool inheritPaintOrder() const
inheritPaintOrder
Definition KoShape.cpp:795
bool isVisible(bool recursive=true) const
Definition KoShape.cpp:979
qreal transparency(bool recursive=false) const
Definition KoShape.cpp:730
static void saveSvgMarkers(KoShape *shape, SvgSavingContext &context)
Saves markers of the path shape if present.
static void saveSvgFill(QSharedPointer< KoShapeBackground > background, const bool fillRuleEvenOdd, const QRectF outlineRect, const QSizeF size, const QTransform absoluteTransform, SvgSavingContext &context)
Saves fill style of specified shape.
static void saveSvgClipping(KoShape *shape, SvgSavingContext &context)
Saves clipping of specified shape.
static void saveSvgBasicStyle(const bool isVisible, const qreal transparency, const QVector< KoShape::PaintOrder > paintOrder, bool inheritPaintorder, SvgSavingContext &context, bool textShape=false)
Saves only stroke, fill and transparency of the shape.
static void saveSvgMasking(KoShape *shape, SvgSavingContext &context)
Saves masking of specified shape.
static void saveSvgEffects(KoShape *shape, SvgSavingContext &context)
Saves effects of specified shape.
static void saveSvgStroke(KoShapeStrokeModelSP, SvgSavingContext &context)
Saves stroke style of specified shape.

References KoShape::absoluteTransformation(), KoShape::background(), KoPathShape::fillRule(), KoShape::inheritBackground(), KoShape::inheritPaintOrder(), KoShape::inheritStroke(), KoShape::isVisible(), KoShape::outlineRect(), KoShape::paintOrder(), saveSvgBasicStyle(), saveSvgClipping(), saveSvgEffects(), saveSvgFill(), saveSvgMarkers(), saveSvgMasking(), saveSvgStroke(), KoShape::size(), KoShape::stroke(), and KoShape::transparency().

◆ saveSvgVectorPattern()

QString SvgStyleWriter::saveSvgVectorPattern ( QSharedPointer< KoVectorPatternBackground > pattern,
const QRectF outlineRect,
SvgSavingContext & context )
staticprotected

Definition at line 630 of file SvgStyleWriter.cpp.

631{
632 const QString uid = context.createUID("pattern");
633
634 context.styleWriter().startElement("pattern");
635 context.styleWriter().addAttribute("id", uid);
636
637 context.styleWriter().addAttribute("patternUnits", KoFlake::coordinateToString(pattern->referenceCoordinates()));
638 context.styleWriter().addAttribute("patternContentUnits", KoFlake::coordinateToString(pattern->contentCoordinates()));
639
640 const QRectF rect = pattern->referenceRect();
641
642 context.styleWriter().addAttribute("x", rect.x());
643 context.styleWriter().addAttribute("y", rect.y());
644 context.styleWriter().addAttribute("width", rect.width());
645 context.styleWriter().addAttribute("height", rect.height());
646
647 SvgUtil::writeTransformAttributeLazy("patternTransform", pattern->patternTransform(), context.styleWriter());
648
649 if (pattern->contentCoordinates() == KoFlake::ObjectBoundingBox) {
650 // TODO: move this normalization into the KoVectorPatternBackground itself
651
652 QList<KoShape*> shapes = pattern->shapes();
653 QList<KoShape*> clonedShapes;
654
655 const QTransform relativeToShape = KisAlgebra2D::mapToRect(outlineRect);
656 const QTransform shapeToRelative = relativeToShape.inverted();
657
658 Q_FOREACH (KoShape *shape, shapes) {
659 KoShape *clone = shape->cloneShape();
660 clone->applyAbsoluteTransformation(shapeToRelative);
661 clonedShapes.append(clone);
662 }
663
664 embedShapes(clonedShapes, context.styleWriter());
665 qDeleteAll(clonedShapes);
666
667 } else {
668 QList<KoShape*> shapes = pattern->shapes();
669 embedShapes(shapes, context.styleWriter());
670 }
671
672 context.styleWriter().endElement(); // pattern
673
674 return uid;
675}
void applyAbsoluteTransformation(const QTransform &matrix)
Definition KoShape.cpp:400
QTransform mapToRect(const QRectF &rect)

References KoShape::applyAbsoluteTransformation(), KoShape::cloneShape(), KoFlake::coordinateToString(), SvgSavingContext::createUID(), embedShapes(), KisAlgebra2D::mapToRect(), KoFlake::ObjectBoundingBox, SvgSavingContext::styleWriter, and SvgUtil::writeTransformAttributeLazy().


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