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

#include <SvgParser.h>

Classes

struct  DeferredUseStore
 

Public Types

typedef std::function< QByteArray(const QString &) FileFetcherFunc)
 

Public Member Functions

QString documentDescription () const
 
QString documentTitle () const
 
QList< QExplicitlySharedDataPointer< KoMarker > > knownMarkers () const
 
void parseDefsElement (const QDomElement &e)
 
QList< KoShape * > parseSvg (const QDomElement &e, QSizeF *fragmentSize=0)
 Parses a svg fragment, returning the list of top level child shapes.
 
KoShapeparseTextElement (const QDomElement &e, KoSvgTextShape *mergeIntoShape=0)
 
void setDefaultKraTextVersion (int version)
 
void setFileFetcher (FileFetcherFunc func)
 
void setFillStrokeInheritByDefault (const bool enable)
 
void setResolution (const QRectF boundsInPixels, qreal pixelsPerInch)
 
void setResolveTextPropertiesForTopLevel (const bool enable)
 
void setXmlBaseDir (const QString &baseDir)
 Sets the initial xml base directory (the directory form where the file is read)
 
QList< KoShape * > shapes () const
 Returns the list of all shapes of the svg document.
 
 SvgParser (KoDocumentResourceManager *documentResourceManager)
 
QVector< KoSvgSymbol * > takeSymbols ()
 
QStringList warnings () const
 
virtual ~SvgParser ()
 

Static Public Member Functions

static QDomDocument createDocumentFromSvg (const QByteArray &data, QString *errorMsg=0, int *errorLine=0, int *errorColumn=0)
 
static QDomDocument createDocumentFromSvg (const QString &data, QString *errorMsg=0, int *errorLine=0, int *errorColumn=0)
 
static QDomDocument createDocumentFromSvg (QIODevice *device, QString *errorMsg=0, int *errorLine=0, int *errorColumn=0)
 
static QDomDocument createDocumentFromSvg (QXmlStreamReader reader, QString *errorMsg=0, int *errorLine=0, int *errorColumn=0)
 

Protected Member Functions

void addToGroup (QList< KoShape * > shapes, KoShapeContainer *group)
 Adds list of shapes to the given group shape.
 
void applyClipping (KoShape *shape, const QPointF &shapeToOriginalUserCoordinates)
 Applies the current clip path to the object.
 
void applyCurrentBasicStyle (KoShape *shape)
 
void applyCurrentStyle (KoShape *shape, const QPointF &shapeToOriginalUserCoordinates)
 
void applyFillStyle (KoShape *shape)
 Applies the current fill style to the object.
 
void applyFilter (KoShape *shape)
 Applies the current filter to the object.
 
void applyId (const QString &id, KoShape *shape)
 Applies id to specified shape.
 
void applyMarkers (KoPathShape *shape)
 
void applyMaskClipping (KoShape *shape, const QPointF &shapeToOriginalUserCoordinates)
 
void applyPaintOrder (KoShape *shape)
 
void applyStrokeStyle (KoShape *shape)
 Applies the current stroke style to the object.
 
void applyStyle (KoShape *, const QDomElement &, const QPointF &shapeToOriginalUserCoordinates)
 Applies styles to the given shape.
 
void applyStyle (KoShape *, const SvgStyles &, const QPointF &shapeToOriginalUserCoordinates)
 Applies styles to the given shape.
 
void applyViewBoxTransform (const QDomElement &element)
 
void buildDocument (QList< KoShape * > shapes)
 Builds the document from the given shapes list.
 
QList< KoShape * > createListOfShapesFromCSS (const QDomElement e, const QString value, SvgLoadingContext &context)
 Create a list of shapes from a CSS shapes definition with potentially multiple shapes.
 
KoShapecreateObject (const QDomElement &, const SvgStyles &style=SvgStyles())
 Creates an object from the given xml element.
 
KoShapecreateObjectDirect (const QDomElement &b)
 
KoShapecreatePath (const QDomElement &)
 Create path object from the given xml element.
 
KoShapecreateShape (const QString &shapeID)
 creates a shape from the given shape id
 
KoShapecreateShapeFromCSS (const QDomElement e, const QString value, SvgLoadingContext &context)
 Creates a shape from a CSS shapes definition.
 
KoShapecreateShapeFromElement (const QDomElement &element, SvgLoadingContext &context)
 Creates shape from specified svg element.
 
SvgClipPathHelperfindClipPath (const QString &id)
 find clip path with given id in clip path map
 
SvgFilterHelperfindFilter (const QString &id, const QString &href=QString())
 find filter with given id in filter map
 
SvgGradientHelperfindGradient (const QString &id)
 find gradient with given id in gradient map
 
QSharedPointer< KoVectorPatternBackgroundfindPattern (const QString &id, const KoShape *shape)
 find pattern with given id in pattern map
 
KoShapegetTextPath (const QDomElement &e)
 Get the path for the gives textPath element.
 
QDomText getTheOnlyTextChild (const QDomElement &e)
 
qreal parseAngular (const QString &unit)
 parses a angular attribute values, result in radians
 
bool parseClipMask (const QDomElement &e)
 
bool parseClipPath (const QDomElement &)
 Parses a clip path element.
 
QList< KoShape * > parseContainer (const QDomElement &)
 Parses a container element, returning a list of child shapes.
 
bool parseFilter (const QDomElement &, const QDomElement &referencedBy=QDomElement())
 Parses a filter element.
 
SvgGradientHelperparseGradient (const QDomElement &)
 Parses a gradient element.
 
KoShapeparseGroup (const QDomElement &e, const QDomElement &overrideChildrenFrom=QDomElement(), bool createContext=true)
 Parses a group-like element element, saving all its topmost properties.
 
bool parseMarker (const QDomElement &e)
 
SvgGradientHelperparseMeshGradient (const QDomElement &)
 Parses mesh gradient element.
 
QList< QPair< QString, QColor > > parseMeshPatch (const QDomNode &meshpatch)
 Parses a single meshpatch and returns the pointer.
 
void parseMetadataApplyToShape (const QDomElement &e, KoShape *shape)
 This parses the SVG native title and desc elements and adds them into additional attributes.
 
QSharedPointer< KoVectorPatternBackgroundparsePattern (const QDomElement &e, const KoShape *__shape)
 Parses a pattern element.
 
QList< KoShape * > parseSingleElement (const QDomElement &b, DeferredUseStore *deferredUseStore=0)
 XXX.
 
bool parseSymbol (const QDomElement &e)
 
void parseTextChildren (const QDomElement &e, KoSvgTextLoader &textLoader)
 parse children of a <text > element into the root shape.
 
qreal parseUnit (const QString &, bool horiz=false, bool vert=false, const QRectF &bbox=QRectF())
 parses a length attribute
 
qreal parseUnitX (const QString &unit)
 parses a length attribute in x-direction
 
qreal parseUnitXY (const QString &unit)
 parses a length attribute in xy-direction
 
qreal parseUnitY (const QString &unit)
 parses a length attribute in y-direction
 
KoShapeparseUse (const QDomElement &, DeferredUseStore *deferredUseStore)
 Parses a use element, returning a list of child shapes.
 
KoShaperesolveUse (const QDomElement &e, const QString &key)
 
void uploadStyleToContext (const QDomElement &e)
 

Private Attributes

QMap< QString, QSharedPointer< KoClipMask > > m_clipMasks
 
QMap< QString, SvgClipPathHelperm_clipPaths
 
SvgLoadingContext m_context
 
QList< KoShape * > m_defsShapes
 
QString m_documentDescription
 
KoDocumentResourceManagerm_documentResourceManager
 
QString m_documentTitle
 
QMap< QString, SvgFilterHelperm_filters
 
QMap< QString, SvgGradientHelperm_gradients
 
bool m_inheritStrokeFillByDefault = false
 
bool m_isInsideTextSubtree = false
 
QMap< QString, QExplicitlySharedDataPointer< KoMarker > > m_markers
 
bool m_resolveTextPropertiesForTopLevel = true
 
QMap< KoShape *, QTransform > m_shapeParentTransform
 
QList< KoShape * > m_shapes
 
QMap< QString, KoSvgSymbol * > m_symbols
 
QVector< KoIDm_warnings
 

Detailed Description

Definition at line 39 of file SvgParser.h.

Member Typedef Documentation

◆ FileFetcherFunc

typedef std::function<QByteArray(const QString&) SvgParser::FileFetcherFunc)

Definition at line 82 of file SvgParser.h.

Constructor & Destructor Documentation

◆ SvgParser()

SvgParser::SvgParser ( KoDocumentResourceManager * documentResourceManager)
explicit

Definition at line 127 of file SvgParser.cpp.

128 : m_context(documentResourceManager)
129 , m_documentResourceManager(documentResourceManager)
130{
131}
KoDocumentResourceManager * m_documentResourceManager
Definition SvgParser.h:235
SvgLoadingContext m_context
Definition SvgParser.h:229

◆ ~SvgParser()

SvgParser::~SvgParser ( )
virtual

Definition at line 133 of file SvgParser.cpp.

134{
135 for (auto it = m_symbols.begin(); it != m_symbols.end(); ++it) {
136 delete it.value();
137 }
138 qDeleteAll(m_defsShapes);
139}
QList< KoShape * > m_defsShapes
Definition SvgParser.h:238
QMap< QString, KoSvgSymbol * > m_symbols
Definition SvgParser.h:237

References m_defsShapes, and m_symbols.

Member Function Documentation

◆ addToGroup()

void SvgParser::addToGroup ( QList< KoShape * > shapes,
KoShapeContainer * group )
protected

Adds list of shapes to the given group shape.

Definition at line 1563 of file SvgParser.cpp.

1564{
1565 m_shapes += shapes;
1566
1567 if (!group || shapes.isEmpty())
1568 return;
1569
1570 // not normalized
1571 KoShapeGroupCommand cmd(group, shapes, false);
1572 cmd.redo();
1573}
The undo / redo command for grouping shapes.
QList< KoShape * > shapes() const
Returns the list of all shapes of the svg document.
QList< KoShape * > m_shapes
Definition SvgParser.h:236

References m_shapes, KoShapeGroupCommand::redo(), and shapes().

◆ applyClipping()

void SvgParser::applyClipping ( KoShape * shape,
const QPointF & shapeToOriginalUserCoordinates )
protected

Applies the current clip path to the object.

Definition at line 1470 of file SvgParser.cpp.

1471{
1473 if (! gc)
1474 return;
1475
1476 if (gc->clipPathId.isEmpty())
1477 return;
1478
1479 SvgClipPathHelper *clipPath = findClipPath(gc->clipPathId);
1480 if (!clipPath || clipPath->isEmpty())
1481 return;
1482
1484
1485 Q_FOREACH (KoShape *item, clipPath->shapes()) {
1486 KoShape *clonedShape = item->cloneShape();
1487 KIS_ASSERT_RECOVER(clonedShape) { continue; }
1488
1489 shapes.append(clonedShape);
1490 }
1491
1492 if (!shapeToOriginalUserCoordinates.isNull()) {
1493 const QTransform t =
1494 QTransform::fromTranslate(shapeToOriginalUserCoordinates.x(),
1495 shapeToOriginalUserCoordinates.y());
1496
1497 Q_FOREACH(KoShape *s, shapes) {
1499 }
1500 }
1501
1502 KoClipPath *clipPathObject = new KoClipPath(shapes,
1505 shape->setClipPath(clipPathObject);
1506}
Clip path used to clip shapes.
void applyAbsoluteTransformation(const QTransform &matrix)
Definition KoShape.cpp:400
void setClipPath(KoClipPath *clipPath)
Sets a new clip path, removing the old one.
Definition KoShape.cpp:1121
virtual KoShape * cloneShape() const
creates a deep copy of the shape or shape's subtree
Definition KoShape.cpp:200
KoFlake::CoordinateSystem clipPathUnits() const
Returns the clip path units type.
QList< KoShape * > shapes() const
QString clipPathId
the current clip path id
SvgGraphicsContext * currentGC() const
Returns the current graphics context.
SvgClipPathHelper * findClipPath(const QString &id)
find clip path with given id in clip path map
#define KIS_ASSERT_RECOVER(cond)
Definition kis_assert.h:55

References KoShape::applyAbsoluteTransformation(), SvgGraphicsContext::clipPathId, SvgClipPathHelper::clipPathUnits(), KoShape::cloneShape(), SvgLoadingContext::currentGC(), findClipPath(), SvgClipPathHelper::isEmpty(), KIS_ASSERT_RECOVER, m_context, KoFlake::ObjectBoundingBox, KoShape::setClipPath(), SvgClipPathHelper::shapes(), shapes(), and KoFlake::UserSpaceOnUse.

◆ applyCurrentBasicStyle()

void SvgParser::applyCurrentBasicStyle ( KoShape * shape)
protected

WARNING: here is a small inconsistency with the standard: in the standard, 'display' is not inherited, but in flake it is!

NOTE: though the standard says: "A value of 'display:none' indicates that the given element and <em><strong>its children</strong></em> shall not be rendered directly". Therefore, using setVisible(false) is fully legitimate here (DK 29.11.16).

Definition at line 972 of file SvgParser.cpp.

973{
974 if (!shape) return;
975
977 KIS_ASSERT(gc);
978
979 if (!dynamic_cast<KoShapeGroup*>(shape)) {
980 applyFillStyle(shape);
981 applyStrokeStyle(shape);
982 }
983
984 if (!gc->display || !gc->visible) {
995 shape->setVisible(false);
996 }
997 shape->setTransparency(1.0 - gc->opacity);
998
999 applyPaintOrder(shape);
1000}
void setTransparency(qreal transparency)
Definition KoShape.cpp:722
void setVisible(bool on)
Definition KoShape.cpp:972
bool visible
controls visibility of the shape (inherited)
bool display
controls display of shape
qreal opacity
the shapes opacity
void applyFillStyle(KoShape *shape)
Applies the current fill style to the object.
void applyStrokeStyle(KoShape *shape)
Applies the current stroke style to the object.
void applyPaintOrder(KoShape *shape)
#define KIS_ASSERT(cond)
Definition kis_assert.h:33

References applyFillStyle(), applyPaintOrder(), applyStrokeStyle(), SvgLoadingContext::currentGC(), SvgGraphicsContext::display, KIS_ASSERT, m_context, SvgGraphicsContext::opacity, KoShape::setTransparency(), KoShape::setVisible(), and SvgGraphicsContext::visible.

◆ applyCurrentStyle()

void SvgParser::applyCurrentStyle ( KoShape * shape,
const QPointF & shapeToOriginalUserCoordinates )
protected

Definition at line 956 of file SvgParser.cpp.

957{
958 if (!shape) return;
959
961
962 if (KoPathShape *pathShape = dynamic_cast<KoPathShape*>(shape)) {
963 applyMarkers(pathShape);
964 }
965
966 applyFilter(shape);
967 applyClipping(shape, shapeToOriginalUserCoordinates);
968 applyMaskClipping(shape, shapeToOriginalUserCoordinates);
969
970}
The position of a path point within a path shape.
Definition KoPathShape.h:63
void applyCurrentBasicStyle(KoShape *shape)
void applyMarkers(KoPathShape *shape)
void applyClipping(KoShape *shape, const QPointF &shapeToOriginalUserCoordinates)
Applies the current clip path to the object.
void applyFilter(KoShape *shape)
Applies the current filter to the object.
void applyMaskClipping(KoShape *shape, const QPointF &shapeToOriginalUserCoordinates)

References applyClipping(), applyCurrentBasicStyle(), applyFilter(), applyMarkers(), and applyMaskClipping().

◆ applyFillStyle()

void SvgParser::applyFillStyle ( KoShape * shape)
protected

Applies the current fill style to the object.

Definition at line 1170 of file SvgParser.cpp.

1171{
1173 if (! gc)
1174 return;
1175
1178 } else if (gc->fillType == SvgGraphicsContext::Solid) {
1180 } else if (gc->fillType == SvgGraphicsContext::Complex) {
1181 // try to find referenced gradient
1182 SvgGradientHelper *gradient = findGradient(gc->fillId);
1183 if (gradient) {
1184 QTransform transform;
1185
1186 if (gradient->isMeshGradient()) {
1188
1189 QScopedPointer<SvgMeshGradient> result(prepareMeshGradientForShape(gradient, shape, gc));
1190
1191 bg = toQShared(new KoMeshGradientBackground(result.data(), transform));
1192 shape->setBackground(bg);
1193 } else if (gradient->gradient()) {
1194 QGradient *result = prepareGradientForShape(gradient, shape, gc, &transform);
1195 if (result) {
1197 bg = toQShared(new KoGradientBackground(result));
1198 bg->setTransform(transform);
1199 shape->setBackground(bg);
1200 }
1201 }
1202 } else {
1204 findPattern(gc->fillId, shape);
1205
1206 if (pattern) {
1207 shape->setBackground(pattern);
1208 } else {
1209 // no referenced fill found, use fallback color
1211 }
1212 }
1213 } else if (gc->fillType == SvgGraphicsContext::Inherit) {
1214 shape->setInheritBackground(true);
1215 }
1216
1217 KoPathShape *path = dynamic_cast<KoPathShape*>(shape);
1218 if (path)
1219 path->setFillRule(gc->fillRule);
1220}
QGradient * prepareGradientForShape(const SvgGradientHelper *gradient, const KoShape *shape, const SvgGraphicsContext *gc, QTransform *transform)
SvgMeshGradient * prepareMeshGradientForShape(SvgGradientHelper *gradient, const KoShape *shape, const SvgGraphicsContext *gc)
A simple solid color shape background.
A gradient shape background.
void setFillRule(Qt::FillRule fillRule)
Sets the fill rule to be used for painting the background.
void setInheritBackground(bool value)
setInheritBackground marks a shape as inheriting the background from the parent shape....
Definition KoShape.cpp:940
virtual void setBackground(QSharedPointer< KoShapeBackground > background)
Definition KoShape.cpp:918
QGradient * gradient() const
Returns the gradient.
bool isMeshGradient() const
Qt::FillRule fillRule
the current fill rule
QString fillId
the current fill id (used for gradient/pattern fills)
StyleType fillType
the current fill type
@ Complex
gradient or pattern style
QColor fillColor
the current fill color. Default is black fill as per svg spec
QSharedPointer< KoVectorPatternBackground > findPattern(const QString &id, const KoShape *shape)
find pattern with given id in pattern map
SvgGradientHelper * findGradient(const QString &id)
find gradient with given id in gradient map
QSharedPointer< T > toQShared(T *ptr)

References SvgGraphicsContext::Complex, SvgLoadingContext::currentGC(), SvgGraphicsContext::fillColor, SvgGraphicsContext::fillId, SvgGraphicsContext::fillRule, SvgGraphicsContext::fillType, findGradient(), findPattern(), SvgGradientHelper::gradient(), SvgGraphicsContext::Inherit, SvgGradientHelper::isMeshGradient(), m_context, SvgGraphicsContext::None, prepareGradientForShape(), prepareMeshGradientForShape(), KoShape::setBackground(), KoPathShape::setFillRule(), KoShape::setInheritBackground(), SvgGraphicsContext::Solid, and toQShared().

◆ applyFilter()

void SvgParser::applyFilter ( KoShape * shape)
protected

Applies the current filter to the object.

Definition at line 1286 of file SvgParser.cpp.

1287{
1289 if (! gc)
1290 return;
1291
1292 if (gc->filterId.isEmpty())
1293 return;
1294
1295 SvgFilterHelper *filter = findFilter(gc->filterId);
1296 if (! filter)
1297 return;
1298
1299 QDomElement content = filter->content();
1300
1301 // parse filter region
1302 QRectF bound(shape->position(), shape->size());
1303 // work on bounding box without viewbox transformation applied
1304 // so user space coordinates of bounding box and filter region match up
1305 bound = gc->viewboxTransform.inverted().mapRect(bound);
1306
1307 QRectF filterRegion(filter->position(bound), filter->size(bound));
1308
1309 // convert filter region to boundingbox units
1310 QRectF objectFilterRegion;
1311 objectFilterRegion.setTopLeft(SvgUtil::userSpaceToObject(filterRegion.topLeft(), bound));
1312 objectFilterRegion.setSize(SvgUtil::userSpaceToObject(filterRegion.size(), bound));
1313
1315 context.setShapeBoundingBox(bound);
1316 // enable units conversion
1317 context.enableFilterUnitsConversion(filter->filterUnits() == KoFlake::UserSpaceOnUse);
1318 context.enableFilterPrimitiveUnitsConversion(filter->primitiveUnits() == KoFlake::UserSpaceOnUse);
1319
1321
1322 KoFilterEffectStack *filterStack = 0;
1323
1324 QSet<QString> stdInputs;
1325 stdInputs << "SourceGraphic" << "SourceAlpha";
1326 stdInputs << "BackgroundImage" << "BackgroundAlpha";
1327 stdInputs << "FillPaint" << "StrokePaint";
1328
1329 QMap<QString, KoFilterEffect*> inputs;
1330
1331 // create the filter effects and add them to the shape
1332 for (QDomNode n = content.firstChild(); !n.isNull(); n = n.nextSibling()) {
1333 QDomElement primitive = n.toElement();
1334 KoFilterEffect *filterEffect = registry->createFilterEffectFromXml(primitive, context);
1335 if (!filterEffect) {
1336 debugFlake << "filter effect" << primitive.tagName() << "is not implemented yet";
1337 continue;
1338 }
1339
1340 const QString input = primitive.attribute("in");
1341 if (!input.isEmpty()) {
1342 filterEffect->setInput(0, input);
1343 }
1344 const QString output = primitive.attribute("result");
1345 if (!output.isEmpty()) {
1346 filterEffect->setOutput(output);
1347 }
1348
1349 QRectF subRegion;
1350 // parse subregion
1351 if (filter->primitiveUnits() == KoFlake::UserSpaceOnUse) {
1352 const QString xa = primitive.attribute("x");
1353 const QString ya = primitive.attribute("y");
1354 const QString wa = primitive.attribute("width");
1355 const QString ha = primitive.attribute("height");
1356
1357 if (xa.isEmpty() || ya.isEmpty() || wa.isEmpty() || ha.isEmpty()) {
1358 bool hasStdInput = false;
1359 bool isFirstEffect = filterStack == 0;
1360 // check if one of the inputs is a standard input
1361 Q_FOREACH (const QString &input, filterEffect->inputs()) {
1362 if ((isFirstEffect && input.isEmpty()) || stdInputs.contains(input)) {
1363 hasStdInput = true;
1364 break;
1365 }
1366 }
1367 if (hasStdInput || primitive.tagName() == "feImage") {
1368 // default to 0%, 0%, 100%, 100%
1369 subRegion.setTopLeft(QPointF(0, 0));
1370 subRegion.setSize(QSizeF(1, 1));
1371 } else {
1372 // defaults to bounding rect of all referenced nodes
1373 Q_FOREACH (const QString &input, filterEffect->inputs()) {
1374 if (!inputs.contains(input))
1375 continue;
1376
1377 KoFilterEffect *inputFilter = inputs[input];
1378 if (inputFilter)
1379 subRegion |= inputFilter->filterRect();
1380 }
1381 }
1382 } else {
1383 const qreal x = parseUnitX(xa);
1384 const qreal y = parseUnitY(ya);
1385 const qreal w = parseUnitX(wa);
1386 const qreal h = parseUnitY(ha);
1387 subRegion.setTopLeft(SvgUtil::userSpaceToObject(QPointF(x, y), bound));
1388 subRegion.setSize(SvgUtil::userSpaceToObject(QSizeF(w, h), bound));
1389 }
1390 } else {
1391 // x, y, width, height are in percentages of the object referencing the filter
1392 // so we just parse the percentages
1393 const qreal x = SvgUtil::fromPercentage(primitive.attribute("x", "0"));
1394 const qreal y = SvgUtil::fromPercentage(primitive.attribute("y", "0"));
1395 const qreal w = SvgUtil::fromPercentage(primitive.attribute("width", "1"));
1396 const qreal h = SvgUtil::fromPercentage(primitive.attribute("height", "1"));
1397 subRegion = QRectF(QPointF(x, y), QSizeF(w, h));
1398 }
1399
1400 filterEffect->setFilterRect(subRegion);
1401
1402 if (!filterStack)
1403 filterStack = new KoFilterEffectStack();
1404
1405 filterStack->appendFilterEffect(filterEffect);
1406 inputs[filterEffect->output()] = filterEffect;
1407 }
1408 if (filterStack) {
1409 filterStack->setClipRect(objectFilterRegion);
1410 shape->setFilterEffectStack(filterStack);
1411 }
1412}
#define debugFlake
Definition FlakeDebug.h:15
This class provides a loading context for filter effects.
KoFilterEffect * createFilterEffectFromXml(const QDomElement &element, const KoFilterEffectLoadingContext &context)
static KoFilterEffectRegistry * instance()
This class manages a stack of filter effects.
void setClipRect(const QRectF &clipRect)
Sets the clipping rectangle used for this filter in bounding box units.
void appendFilterEffect(KoFilterEffect *filter)
void setOutput(const QString &output)
QList< QString > inputs
void setFilterRect(const QRectF &filterRect)
Sets the region the filter is applied to in bounding box units.
void setInput(int index, const QString &input)
Sets an existing input to a new value.
virtual QSizeF size() const
Get the size of the shape in pt.
Definition KoShape.cpp:820
void setFilterEffectStack(KoFilterEffectStack *filterEffectStack)
Sets the new filter effect stack, removing the old one.
Definition KoShape.cpp:1299
QPointF position() const
Get the position of the shape in pt.
Definition KoShape.cpp:825
KoFlake::CoordinateSystem filterUnits() const
Returns the filter units type.
QSizeF size(const QRectF &objectBound) const
Returns filter size (objectBound is used when filterUnits == ObjectBoundingBox)
QDomElement content() const
Return the filer element.
QPointF position(const QRectF &objectBound) const
Returns filter position (objectBound is used when filterUnits == ObjectBoundingBox)
KoFlake::CoordinateSystem primitiveUnits() const
Returns the filter primitive units type.
QTransform viewboxTransform
view box transformation
QString filterId
the current filter id
QString xmlBaseDir() const
Returns the current xml base dir.
qreal parseUnitX(const QString &unit)
parses a length attribute in x-direction
SvgFilterHelper * findFilter(const QString &id, const QString &href=QString())
find filter with given id in filter map
qreal parseUnitY(const QString &unit)
parses a length attribute in y-direction
static double fromPercentage(QString s, bool *ok=nullptr)
Definition SvgUtil.cpp:64
static QPointF userSpaceToObject(const QPointF &position, const QRectF &objectBound)
Definition SvgUtil.cpp:86

References KoFilterEffectStack::appendFilterEffect(), SvgFilterHelper::content(), KoFilterEffectRegistry::createFilterEffectFromXml(), SvgLoadingContext::currentGC(), debugFlake, KoFilterEffectLoadingContext::enableFilterPrimitiveUnitsConversion(), KoFilterEffectLoadingContext::enableFilterUnitsConversion(), SvgGraphicsContext::filterId, KoFilterEffect::filterRect, SvgFilterHelper::filterUnits(), findFilter(), SvgUtil::fromPercentage(), KoFilterEffect::inputs, KoFilterEffectRegistry::instance(), m_context, KoFilterEffect::output, parseUnitX(), parseUnitY(), KoShape::position(), SvgFilterHelper::position(), SvgFilterHelper::primitiveUnits(), KoFilterEffectStack::setClipRect(), KoShape::setFilterEffectStack(), KoFilterEffect::setFilterRect(), KoFilterEffect::setInput(), KoFilterEffect::setOutput(), KoFilterEffectLoadingContext::setShapeBoundingBox(), KoShape::size(), SvgFilterHelper::size(), KoFlake::UserSpaceOnUse, SvgUtil::userSpaceToObject(), SvgGraphicsContext::viewboxTransform, and SvgLoadingContext::xmlBaseDir().

◆ applyId()

void SvgParser::applyId ( const QString & id,
KoShape * shape )
protected

Applies id to specified shape.

Definition at line 2367 of file SvgParser.cpp.

2368{
2369 if (id.isEmpty())
2370 return;
2371
2372 KoShape *existingShape = m_context.shapeById(id);
2373 if (existingShape) {
2374 debugFlake << "SVG contains nodes with duplicated id:" << id;
2375 // Generate a random name and just don't register the shape.
2376 // We don't use the name as a unique identifier so we don't need to
2377 // worry about the extremely rare case of name collision.
2378 const QString suffix = QString::number(QRandomGenerator::system()->bounded(0x10000000, 0x7FFFFFFF), 16);
2379 const QString newName = id + '_' + suffix;
2380 shape->setName(newName);
2381 } else {
2382 shape->setName(id);
2383 m_context.registerShape(id, shape);
2384 }
2385}
void setName(const QString &name)
Definition KoShape.cpp:1155
void registerShape(const QString &id, KoShape *shape)
Registers a shape so it can be referenced later.
KoShape * shapeById(const QString &id)
Returns shape with specified id.

References debugFlake, m_context, SvgLoadingContext::registerShape(), KoShape::setName(), and SvgLoadingContext::shapeById().

◆ applyMarkers()

void SvgParser::applyMarkers ( KoPathShape * shape)
protected

Definition at line 1414 of file SvgParser.cpp.

1415{
1417 if (!gc)
1418 return;
1419
1420 if (!gc->markerStartId.isEmpty() && m_markers.contains(gc->markerStartId)) {
1422 }
1423
1424 if (!gc->markerMidId.isEmpty() && m_markers.contains(gc->markerMidId)) {
1426 }
1427
1428 if (!gc->markerEndId.isEmpty() && m_markers.contains(gc->markerEndId)) {
1430 }
1431
1433}
void setAutoFillMarkers(bool value)
void setMarker(KoMarker *marker, KoFlake::MarkerPosition pos)
QMap< QString, QExplicitlySharedDataPointer< KoMarker > > m_markers
Definition SvgParser.h:234
@ EndMarker
Definition KoFlake.h:44
@ StartMarker
Definition KoFlake.h:42
@ MidMarker
Definition KoFlake.h:43

References SvgGraphicsContext::autoFillMarkers, SvgLoadingContext::currentGC(), KoFlake::EndMarker, m_context, m_markers, SvgGraphicsContext::markerEndId, SvgGraphicsContext::markerMidId, SvgGraphicsContext::markerStartId, KoFlake::MidMarker, KoPathShape::setAutoFillMarkers(), KoPathShape::setMarker(), and KoFlake::StartMarker.

◆ applyMaskClipping()

void SvgParser::applyMaskClipping ( KoShape * shape,
const QPointF & shapeToOriginalUserCoordinates )
protected

Definition at line 1508 of file SvgParser.cpp.

1509{
1511 if (!gc)
1512 return;
1513
1514 if (gc->clipMaskId.isEmpty())
1515 return;
1516
1517
1518 QSharedPointer<KoClipMask> originalClipMask = m_clipMasks.value(gc->clipMaskId);
1519 if (!originalClipMask || originalClipMask->isEmpty()) return;
1520
1521 KoClipMask *clipMask = originalClipMask->clone();
1522
1523 clipMask->setExtraShapeOffset(shapeToOriginalUserCoordinates);
1524
1525 shape->setClipMask(clipMask);
1526}
void setClipMask(KoClipMask *clipMask)
Sets a new clip mask, removing the old one. The mask is owned by the shape.
Definition KoShape.cpp:1133
QString clipMaskId
the current clip mask id
QMap< QString, QSharedPointer< KoClipMask > > m_clipMasks
Definition SvgParser.h:233
void setExtraShapeOffset(const QPointF &value)

References SvgGraphicsContext::clipMaskId, SvgLoadingContext::currentGC(), m_clipMasks, m_context, KoShape::setClipMask(), and KoClipMask::setExtraShapeOffset().

◆ applyPaintOrder()

void SvgParser::applyPaintOrder ( KoShape * shape)
protected

Definition at line 1435 of file SvgParser.cpp.

1436{
1438 if (!gc)
1439 return;
1440
1441 if (!gc->paintOrder.isEmpty() && gc->paintOrder != "inherit") {
1442 QStringList paintOrder = gc->paintOrder.split(" ");
1444 Q_FOREACH(const QString p, paintOrder) {
1445 if (p == "fill") {
1446 order.append(KoShape::Fill);
1447 } else if (p == "stroke") {
1448 order.append(KoShape::Stroke);
1449 } else if (p == "markers") {
1450 order.append(KoShape::Markers);
1451 }
1452 }
1453 if (paintOrder.size() == 1 && order.isEmpty()) { // Normal
1455 }
1456 if (order.size() == 1) {
1457 if (order.first() == KoShape::Fill) {
1459 } else if (order.first() == KoShape::Stroke) {
1461 } else if (order.first() == KoShape::Markers) {
1463 }
1464 } else if (order.size() > 1) {
1465 shape->setPaintOrder(order.at(0), order.at(1));
1466 }
1467 }
1468}
const Params2D p
virtual void setPaintOrder(PaintOrder first, PaintOrder second)
setPaintOrder set the paint order. As there's only three entries in any given paintorder,...
Definition KoShape.cpp:749
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
QString paintOrder
String list indicating paint order;.

References SvgLoadingContext::currentGC(), KoShape::defaultPaintOrder(), KoShape::Fill, m_context, KoShape::Markers, p, SvgGraphicsContext::paintOrder, KoShape::setPaintOrder(), and KoShape::Stroke.

◆ applyStrokeStyle()

void SvgParser::applyStrokeStyle ( KoShape * shape)
protected

Applies the current stroke style to the object.

Definition at line 1243 of file SvgParser.cpp.

1244{
1246 if (! gc)
1247 return;
1248
1250 KoShapeStrokeSP stroke(new KoShapeStroke());
1251 stroke->setLineWidth(0.0);
1252 const QColor color = Qt::transparent;
1253 stroke->setColor(color);
1254 shape->setStroke(stroke);
1255 } else if (gc->strokeType == SvgGraphicsContext::Solid) {
1256 KoShapeStrokeSP stroke(new KoShapeStroke(*gc->stroke));
1257 applyDashes(gc->stroke, stroke);
1258 shape->setStroke(stroke);
1259 } else if (gc->strokeType == SvgGraphicsContext::Complex) {
1260 // try to find referenced gradient
1261 SvgGradientHelper *gradient = findGradient(gc->strokeId);
1262 if (gradient) {
1263 QTransform transform;
1264 QGradient *result = prepareGradientForShape(gradient, shape, gc, &transform);
1265 if (result) {
1266 QBrush brush = *result;
1267 delete result;
1268 brush.setTransform(transform);
1269
1270 KoShapeStrokeSP stroke(new KoShapeStroke(*gc->stroke));
1271 stroke->setLineBrush(brush);
1272 applyDashes(gc->stroke, stroke);
1273 shape->setStroke(stroke);
1274 }
1275 } else {
1276 // no referenced stroke found, use fallback color
1277 KoShapeStrokeSP stroke(new KoShapeStroke(*gc->stroke));
1278 applyDashes(gc->stroke, stroke);
1279 shape->setStroke(stroke);
1280 }
1281 } else if (gc->strokeType == SvgGraphicsContext::Inherit) {
1282 shape->setInheritStroke(true);
1283 }
1284}
void applyDashes(const KoShapeStrokeSP srcStroke, KoShapeStrokeSP dstStroke)
virtual void setStroke(KoShapeStrokeModelSP stroke)
Definition KoShape.cpp:1081
void setInheritStroke(bool value)
setInheritStroke marks a shape as inheriting the stroke from the parent shape. NOTE: The currently se...
Definition KoShape.cpp:1090
QString strokeId
the current stroke id (used for gradient strokes)
StyleType strokeType
the current stroke type
KoShapeStrokeSP stroke
the current stroke

References applyDashes(), SvgGraphicsContext::Complex, SvgLoadingContext::currentGC(), findGradient(), SvgGraphicsContext::Inherit, m_context, SvgGraphicsContext::None, prepareGradientForShape(), KoShape::setInheritStroke(), KoShape::setStroke(), SvgGraphicsContext::Solid, SvgGraphicsContext::stroke, SvgGraphicsContext::strokeId, and SvgGraphicsContext::strokeType.

◆ applyStyle() [1/2]

void SvgParser::applyStyle ( KoShape * obj,
const QDomElement & e,
const QPointF & shapeToOriginalUserCoordinates )
protected

Applies styles to the given shape.

Definition at line 1003 of file SvgParser.cpp.

1004{
1005 applyStyle(obj, m_context.styleParser().collectStyles(e), shapeToOriginalUserCoordinates);
1006}
SvgStyleParser * styleParser
void applyStyle(KoShape *, const QDomElement &, const QPointF &shapeToOriginalUserCoordinates)
Applies styles to the given shape.
SvgStyles collectStyles(const QDomElement &)
Creates style map from given xml element.

References applyStyle(), SvgStyleParser::collectStyles(), m_context, and SvgLoadingContext::styleParser.

◆ applyStyle() [2/2]

void SvgParser::applyStyle ( KoShape * obj,
const SvgStyles & styles,
const QPointF & shapeToOriginalUserCoordinates )
protected

Applies styles to the given shape.

Definition at line 1008 of file SvgParser.cpp.

1009{
1011 if (!gc)
1012 return;
1013
1015
1016 if (!obj)
1017 return;
1018
1019 if (!dynamic_cast<KoShapeGroup*>(obj)) {
1020 applyFillStyle(obj);
1021 applyStrokeStyle(obj);
1022 }
1023
1024 if (KoPathShape *pathShape = dynamic_cast<KoPathShape*>(obj)) {
1025 applyMarkers(pathShape);
1026 }
1027
1028 applyFilter(obj);
1029 applyClipping(obj, shapeToOriginalUserCoordinates);
1030 applyMaskClipping(obj, shapeToOriginalUserCoordinates);
1031
1032 if (!gc->display || !gc->visible) {
1033 obj->setVisible(false);
1034 }
1035 obj->setTransparency(1.0 - gc->opacity);
1036 applyPaintOrder(obj);
1037}
bool m_inheritStrokeFillByDefault
Definition SvgParser.h:244
void parseStyle(const SvgStyles &styles, const bool inheritByDefault=false)
Parses specified style attributes.

References applyClipping(), applyFillStyle(), applyFilter(), applyMarkers(), applyMaskClipping(), applyPaintOrder(), applyStrokeStyle(), SvgLoadingContext::currentGC(), SvgGraphicsContext::display, m_context, m_inheritStrokeFillByDefault, SvgGraphicsContext::opacity, SvgStyleParser::parseStyle(), KoShape::setTransparency(), KoShape::setVisible(), SvgLoadingContext::styleParser, and SvgGraphicsContext::visible.

◆ applyViewBoxTransform()

void SvgParser::applyViewBoxTransform ( const QDomElement & element)
protected

Applies viewBox transformation to the current graphical context NOTE: after applying the function currentBoundingBox can become null!

Definition at line 1674 of file SvgParser.cpp.

1675{
1677
1678 QRectF viewRect = gc->currentBoundingBox;
1679 QTransform viewTransform;
1680
1682 &viewRect, &viewTransform)) {
1683
1684 gc->matrix = viewTransform * gc->matrix;
1685 gc->currentBoundingBox = viewRect;
1686 }
1687}
QRectF currentBoundingBox
the current bound box used for bounding box units
QTransform matrix
the current transformation matrix
static bool parseViewBox(const QDomElement &e, const QRectF &elementBounds, QRectF *_viewRect, QTransform *_viewTransform)
Parses a viewbox attribute into an rectangle.
Definition SvgUtil.cpp:133

References SvgGraphicsContext::currentBoundingBox, SvgLoadingContext::currentGC(), m_context, SvgGraphicsContext::matrix, and SvgUtil::parseViewBox().

◆ buildDocument()

void SvgParser::buildDocument ( QList< KoShape * > shapes)
protected

Builds the document from the given shapes list.

◆ createDocumentFromSvg() [1/4]

QDomDocument SvgParser::createDocumentFromSvg ( const QByteArray & data,
QString * errorMsg = 0,
int * errorLine = 0,
int * errorColumn = 0 )
static

Definition at line 146 of file SvgParser.cpp.

147{
148 return createDocumentFromSvg(QXmlStreamReader(data), errorMsg, errorLine, errorColumn);
149}
static QDomDocument createDocumentFromSvg(QIODevice *device, QString *errorMsg=0, int *errorLine=0, int *errorColumn=0)

References createDocumentFromSvg().

◆ createDocumentFromSvg() [2/4]

QDomDocument SvgParser::createDocumentFromSvg ( const QString & data,
QString * errorMsg = 0,
int * errorLine = 0,
int * errorColumn = 0 )
static

Definition at line 151 of file SvgParser.cpp.

152{
153 return createDocumentFromSvg(QXmlStreamReader(data), errorMsg, errorLine, errorColumn);
154}

References createDocumentFromSvg().

◆ createDocumentFromSvg() [3/4]

QDomDocument SvgParser::createDocumentFromSvg ( QIODevice * device,
QString * errorMsg = 0,
int * errorLine = 0,
int * errorColumn = 0 )
static

Definition at line 141 of file SvgParser.cpp.

142{
143 return createDocumentFromSvg(QXmlStreamReader(device), errorMsg, errorLine, errorColumn);
144}

References createDocumentFromSvg().

◆ createDocumentFromSvg() [4/4]

QDomDocument SvgParser::createDocumentFromSvg ( QXmlStreamReader reader,
QString * errorMsg = 0,
int * errorLine = 0,
int * errorColumn = 0 )
static

Definition at line 156 of file SvgParser.cpp.

157{
158 QDomDocument doc;
159 reader.setNamespaceProcessing(false);
160 if (!doc.setContent(&reader, false, errorMsg, errorLine, errorColumn)) {
161 return {};
162 }
163
164 return doc;
165}

◆ createListOfShapesFromCSS()

QList< KoShape * > SvgParser::createListOfShapesFromCSS ( const QDomElement e,
const QString value,
SvgLoadingContext & context )
protected

Create a list of shapes from a CSS shapes definition with potentially multiple shapes.

Definition at line 2321 of file SvgParser.cpp.

2322{
2323 QList<KoShape*> shapeList;
2324 if (value == "auto" || value == "none") {
2325 return shapeList;
2326 }
2327 QStringList params = value.split(")");
2328 Q_FOREACH(const QString param, params) {
2329 KoShape *s = createShapeFromCSS(e, param.trimmed()+")", context);
2330 if (s) {
2331 shapeList.append(s);
2332 }
2333 }
2334 return shapeList;
2335}
float value(const T *src, size_t ch)
KoShape * createShapeFromCSS(const QDomElement e, const QString value, SvgLoadingContext &context)
Creates a shape from a CSS shapes definition.

References createShapeFromCSS(), and value().

◆ createObject()

KoShape * SvgParser::createObject ( const QDomElement & b,
const SvgStyles & style = SvgStyles() )
protected

Creates an object from the given xml element.

Definition at line 2176 of file SvgParser.cpp.

2177{
2179
2181 if (obj) {
2183 const QPointF extraOffset = extraShapeOffset(obj, m_context.currentGC()->matrix);
2184
2185 SvgStyles objStyle = style.isEmpty() ? m_context.styleParser().collectStyles(b) : style;
2186 m_context.styleParser().parseFont(objStyle);
2187 applyStyle(obj, objStyle, extraOffset);
2188
2189 // handle id
2190 applyId(b.attribute("id"), obj);
2193 }
2194
2196
2197 if (obj) {
2199 }
2200
2201 return obj;
2202}
QPointF extraShapeOffset(const KoShape *shape, const QTransform coordinateSystemOnLoading)
QMap< QString, QString > SvgStyles
void setZIndex(qint16 zIndex)
Definition KoShape.cpp:954
SvgGraphicsContext * pushGraphicsContext(const QDomElement &element=QDomElement(), bool inherit=true)
Pushes a new graphics context to the stack.
void popGraphicsContext()
Pops the current graphics context from the stack.
int nextZIndex()
Returns the next z-index.
void parseMetadataApplyToShape(const QDomElement &e, KoShape *shape)
This parses the SVG native title and desc elements and adds them into additional attributes.
KoShape * createShapeFromElement(const QDomElement &element, SvgLoadingContext &context)
Creates shape from specified svg element.
void applyId(const QString &id, KoShape *shape)
Applies id to specified shape.
QMap< KoShape *, QTransform > m_shapeParentTransform
Definition SvgParser.h:243
void parseFont(const SvgStyles &styles)
Parses font attributes.

References KoShape::applyAbsoluteTransformation(), applyId(), applyStyle(), SvgStyleParser::collectStyles(), createShapeFromElement(), SvgLoadingContext::currentGC(), extraShapeOffset(), m_context, m_shapeParentTransform, SvgGraphicsContext::matrix, SvgLoadingContext::nextZIndex(), SvgStyleParser::parseFont(), parseMetadataApplyToShape(), SvgLoadingContext::popGraphicsContext(), SvgLoadingContext::pushGraphicsContext(), KoShape::setZIndex(), and SvgLoadingContext::styleParser.

◆ createObjectDirect()

KoShape * SvgParser::createObjectDirect ( const QDomElement & b)
protected

Definition at line 2150 of file SvgParser.cpp.

2151{
2154
2156 if (obj) {
2158 const QPointF extraOffset = extraShapeOffset(obj, m_context.currentGC()->matrix);
2159
2160 applyCurrentStyle(obj, extraOffset);
2161
2162 // handle id
2163 applyId(b.attribute("id"), obj);
2166 }
2167
2169
2170 if (obj) {
2172 }
2173 return obj;
2174}
void uploadStyleToContext(const QDomElement &e)
void applyCurrentStyle(KoShape *shape, const QPointF &shapeToOriginalUserCoordinates)

References KoShape::applyAbsoluteTransformation(), applyCurrentStyle(), applyId(), createShapeFromElement(), SvgLoadingContext::currentGC(), extraShapeOffset(), m_context, m_shapeParentTransform, SvgGraphicsContext::matrix, SvgLoadingContext::nextZIndex(), parseMetadataApplyToShape(), SvgLoadingContext::popGraphicsContext(), SvgLoadingContext::pushGraphicsContext(), KoShape::setZIndex(), and uploadStyleToContext().

◆ createPath()

KoShape * SvgParser::createPath ( const QDomElement & element)
protected

Create path object from the given xml element.

Definition at line 2080 of file SvgParser.cpp.

2081{
2082 KoShape *obj = 0;
2083 if (element.tagName() == "line") {
2084 KoPathShape *path = static_cast<KoPathShape*>(createShape(KoPathShapeId));
2085 if (path) {
2086 double x1 = element.attribute("x1").isEmpty() ? 0.0 : parseUnitX(element.attribute("x1"));
2087 double y1 = element.attribute("y1").isEmpty() ? 0.0 : parseUnitY(element.attribute("y1"));
2088 double x2 = element.attribute("x2").isEmpty() ? 0.0 : parseUnitX(element.attribute("x2"));
2089 double y2 = element.attribute("y2").isEmpty() ? 0.0 : parseUnitY(element.attribute("y2"));
2090 path->clear();
2091 path->moveTo(QPointF(x1, y1));
2092 path->lineTo(QPointF(x2, y2));
2093 path->normalize();
2094 obj = path;
2095 }
2096 } else if (element.tagName() == "polyline" || element.tagName() == "polygon") {
2097 KoPathShape *path = static_cast<KoPathShape*>(createShape(KoPathShapeId));
2098 if (path) {
2099 path->clear();
2100
2101 bool bFirst = true;
2102 QStringList pointList = SvgUtil::simplifyList(element.attribute("points"));
2103 for (QStringList::Iterator it = pointList.begin(); it != pointList.end(); ++it) {
2104 QPointF point;
2106 ++it;
2107 if (it == pointList.end())
2108 break;
2110 if (bFirst) {
2111 path->moveTo(point);
2112 bFirst = false;
2113 } else
2114 path->lineTo(point);
2115 }
2116 if (element.tagName() == "polygon")
2117 path->close();
2118
2119 path->setPosition(path->normalize());
2120
2121 obj = path;
2122 }
2123 } else if (element.tagName() == "path") {
2124 KoPathShape *path = static_cast<KoPathShape*>(createShape(KoPathShapeId));
2125 if (path) {
2126 path->clear();
2127
2128 KoPathShapeLoader loader(path);
2129 loader.parseSvg(element.attribute("d"), true);
2130 path->setPosition(path->normalize());
2131
2132 QPointF newPosition = QPointF(SvgUtil::fromUserSpace(path->position().x()),
2133 SvgUtil::fromUserSpace(path->position().y()));
2134 QSizeF newSize = QSizeF(SvgUtil::fromUserSpace(path->size().width()),
2135 SvgUtil::fromUserSpace(path->size().height()));
2136
2137 path->setSize(newSize);
2138 path->setPosition(newPosition);
2139
2140 if (element.hasAttribute("sodipodi:nodetypes")) {
2141 path->loadNodeTypes(element.attribute("sodipodi:nodetypes"));
2142 }
2143 obj = path;
2144 }
2145 }
2146
2147 return obj;
2148}
#define KoPathShapeId
Definition KoPathShape.h:20
void clear()
Removes all subpaths and their points from the path.
KoShape * createShape(const QString &shapeID)
creates a shape from the given shape id
static QStringList simplifyList(const QString &str)
Definition SvgUtil.cpp:450
static double fromUserSpace(double value)
Definition SvgUtil.cpp:29
double toDouble(const QString &str, bool *ok=nullptr)

References KoPathShape::clear(), createShape(), SvgUtil::fromUserSpace(), KoPathShapeId, KoPathShapeLoader::parseSvg(), parseUnitX(), parseUnitY(), SvgUtil::simplifyList(), and KisDomUtils::toDouble().

◆ createShape()

KoShape * SvgParser::createShape ( const QString & shapeID)
protected

creates a shape from the given shape id

Definition at line 2337 of file SvgParser.cpp.

2338{
2339 KoShapeFactoryBase *factory = KoShapeRegistry::instance()->get(shapeID);
2340 if (!factory) {
2341 debugFlake << "Could not find factory for shape id" << shapeID;
2342 return 0;
2343 }
2344
2346 if (!shape) {
2347 debugFlake << "Could not create Default shape for shape id" << shapeID;
2348 return 0;
2349 }
2350 if (shape->shapeId().isEmpty()) {
2351 shape->setShapeId(factory->id());
2352 }
2353
2354 // reset transformation that might come from the default shape
2355 shape->setTransformation(QTransform());
2356
2357 // reset border
2358 // ??? KoShapeStrokeModelSP oldStroke = shape->stroke();
2360
2361 // reset fill
2363
2364 return shape;
2365}
QSharedPointer< KoShapeStrokeModel > KoShapeStrokeModelSP
T get(const QString &id) const
virtual KoShape * createDefaultShape(KoDocumentResourceManager *documentResources=0) const
static KoShapeRegistry * instance()
QString shapeId() const
Definition KoShape.cpp:1057
void setTransformation(const QTransform &matrix)
Definition KoShape.cpp:417
void setShapeId(const QString &id)
Definition KoShape.cpp:1062

References KoShapeFactoryBase::createDefaultShape(), debugFlake, KoGenericRegistry< T >::get(), KoShapeFactoryBase::id, KoShapeRegistry::instance(), m_documentResourceManager, KoShape::setBackground(), KoShape::setShapeId(), KoShape::setStroke(), KoShape::setTransformation(), and KoShape::shapeId().

◆ createShapeFromCSS()

KoShape * SvgParser::createShapeFromCSS ( const QDomElement e,
const QString value,
SvgLoadingContext & context )
protected

Creates a shape from a CSS shapes definition.

Definition at line 2249 of file SvgParser.cpp.

2250{
2251 if (value.isEmpty()) {
2252 return 0;
2253 }
2254 unsigned int start = value.indexOf('(') + 1;
2255 unsigned int end = value.indexOf(')', start);
2256
2257 QString val = value.mid(start, end - start);
2258 QString fillRule;
2259 if (val.startsWith("evenodd,")) {
2260 start += QString("evenodd,").size();
2261 fillRule = "evenodd";
2262 } else if (val.startsWith("nonzero,")) {
2263 start += QString("nonzero,").size();
2264 fillRule = "nonzero";
2265 }
2266 val = value.mid(start, end - start);
2267
2268 QDomElement el;
2269 if (value.startsWith("url(")) {
2270 start = value.indexOf('#') + 1;
2271 KoShape *s = m_context.shapeById(value.mid(start, end - start));
2272 if (s) {
2273 const QTransform absTf = s->absoluteTransformation();
2274 KoShape *cloned = s->cloneShape();
2275 cloned->setTransformation(absTf * m_shapeParentTransform.value(s).inverted());
2276 return cloned;
2277 }
2278 } else if (value.startsWith("circle(")) {
2279 el = e.ownerDocument().createElement("circle");
2280 QStringList params = val.split(" ");
2281 el.setAttribute("r", SvgUtil::parseUnitXY(context.currentGC(), context.resolvedProperties(), params.first()));
2282 if (params.contains("at")) {
2283 // 1 == "at"
2284 el.setAttribute("cx", SvgUtil::parseUnitX(context.currentGC(), context.resolvedProperties(), params.at(2)));
2285 el.setAttribute("cy", SvgUtil::parseUnitY(context.currentGC(), context.resolvedProperties(), params.at(3)));
2286 }
2287 } else if (value.startsWith("ellipse(")) {
2288 el = e.ownerDocument().createElement("ellipse");
2289 QStringList params = val.split(" ");
2290 el.setAttribute("rx", SvgUtil::parseUnitX(context.currentGC(), context.resolvedProperties(), params.at(0)));
2291 el.setAttribute("ry", SvgUtil::parseUnitY(context.currentGC(), context.resolvedProperties(), params.at(1)));
2292 if (params.contains("at")) {
2293 // 2 == "at"
2294 el.setAttribute("cx", SvgUtil::parseUnitX(context.currentGC(), context.resolvedProperties(), params.at(3)));
2295 el.setAttribute("cy", SvgUtil::parseUnitY(context.currentGC(), context.resolvedProperties(), params.at(4)));
2296 }
2297 } else if (value.startsWith("polygon(")) {
2298 el = e.ownerDocument().createElement("polygon");
2299 QStringList points;
2300 Q_FOREACH(QString point, SvgUtil::simplifyList(val)) {
2301 bool xVal = points.size() % 2;
2302 if (xVal) {
2303 points.append(QString::number(SvgUtil::parseUnitX(context.currentGC(), context.resolvedProperties(), point)));
2304 } else {
2305 points.append(QString::number(SvgUtil::parseUnitY(context.currentGC(), context.resolvedProperties(), point)));
2306 }
2307 }
2308 el.setAttribute("points", points.join(" "));
2309 } else if (value.startsWith("path(")) {
2310 el = e.ownerDocument().createElement("path");
2311 // SVG path data is inside a string.
2312 start += 1;
2313 end -= 1;
2314 el.setAttribute("d", value.mid(start, end - start));
2315 }
2316
2317 el.setAttribute("fill-rule", fillRule);
2318 return createShapeFromElement(el, context);
2319}
QTransform absoluteTransformation() const
Definition KoShape.cpp:382
KoSvgTextProperties resolvedProperties() const
These are the text properties, completely resolved, ensuring that everything is inherited and the siz...
static qreal parseUnitX(SvgGraphicsContext *gc, const KoSvgTextProperties &resolved, const QString &unit)
parses a length attribute in x-direction
Definition SvgUtil.cpp:304
static qreal parseUnitXY(SvgGraphicsContext *gc, const KoSvgTextProperties &resolved, const QString &unit)
parses a length attribute in xy-direction
Definition SvgUtil.cpp:322
static qreal parseUnitY(SvgGraphicsContext *gc, const KoSvgTextProperties &resolved, const QString &unit)
parses a length attribute in y-direction
Definition SvgUtil.cpp:313

References KoShape::absoluteTransformation(), KoShape::cloneShape(), createShapeFromElement(), SvgLoadingContext::currentGC(), m_context, m_shapeParentTransform, SvgUtil::parseUnitX(), SvgUtil::parseUnitXY(), SvgUtil::parseUnitY(), SvgLoadingContext::resolvedProperties(), KoShape::setTransformation(), SvgLoadingContext::shapeById(), SvgUtil::simplifyList(), KoShape::size(), and value().

◆ createShapeFromElement()

KoShape * SvgParser::createShapeFromElement ( const QDomElement & element,
SvgLoadingContext & context )
protected

Creates shape from specified svg element.

Definition at line 2204 of file SvgParser.cpp.

2205{
2206 KoShape *object = 0;
2207
2208
2209 const QString tagName = SvgUtil::mapExtendedShapeTag(element.tagName(), element);
2211
2212 foreach (KoShapeFactoryBase *f, factories) {
2213 KoShape *shape = f->createDefaultShape(m_documentResourceManager);
2214 if (!shape)
2215 continue;
2216
2217 SvgShape *svgShape = dynamic_cast<SvgShape*>(shape);
2218 if (!svgShape) {
2219 delete shape;
2220 continue;
2221 }
2222
2223 // reset transformation that might come from the default shape
2224 shape->setTransformation(QTransform());
2225
2226 // reset border
2227 KoShapeStrokeModelSP oldStroke = shape->stroke();
2229
2230 // reset fill
2232
2233 if (!svgShape->loadSvg(element, context)) {
2234 delete shape;
2235 continue;
2236 }
2237
2238 object = shape;
2239 break;
2240 }
2241
2242 if (!object) {
2243 object = createPath(element);
2244 }
2245
2246 return object;
2247}
QList< KoShapeFactoryBase * > factoriesForElement(const QString &nameSpace, const QString &elementName)
virtual KoShapeStrokeModelSP stroke() const
Definition KoShape.cpp:1067
static const QString svg
Definition KoXmlNS.h:39
KoShape * createPath(const QDomElement &)
Create path object from the given xml element.
An interface providing svg loading and saving routines.
Definition SvgShape.h:18
virtual bool loadSvg(const QDomElement &element, SvgLoadingContext &context)
Loads data from specified svg element.
Definition SvgShape.cpp:19
static QString mapExtendedShapeTag(const QString &tagName, const QDomElement &element)
Definition SvgUtil.cpp:432

References createPath(), KoShapeRegistry::factoriesForElement(), KoShapeRegistry::instance(), SvgShape::loadSvg(), m_documentResourceManager, SvgUtil::mapExtendedShapeTag(), KoShape::setBackground(), KoShape::setStroke(), KoShape::setTransformation(), KoShape::stroke(), and KoXmlNS::svg.

◆ documentDescription()

QString SvgParser::documentDescription ( ) const

Definition at line 1710 of file SvgParser.cpp.

1711{
1712 return m_documentDescription;
1713}
QString m_documentDescription
Definition SvgParser.h:241

References m_documentDescription.

◆ documentTitle()

QString SvgParser::documentTitle ( ) const

Definition at line 1705 of file SvgParser.cpp.

1706{
1707 return m_documentTitle;
1708}
QString m_documentTitle
Definition SvgParser.h:240

References m_documentTitle.

◆ findClipPath()

SvgClipPathHelper * SvgParser::findClipPath ( const QString & id)
protected

find clip path with given id in clip path map

Definition at line 305 of file SvgParser.cpp.

306{
307 return m_clipPaths.contains(id) ? &m_clipPaths[id] : 0;
308}
QMap< QString, SvgClipPathHelper > m_clipPaths
Definition SvgParser.h:232

References m_clipPaths.

◆ findFilter()

SvgFilterHelper * SvgParser::findFilter ( const QString & id,
const QString & href = QString() )
protected

find filter with given id in filter map

Definition at line 268 of file SvgParser.cpp.

269{
270 // check if filter was already parsed, and return it
271 if (m_filters.contains(id))
272 return &m_filters[ id ];
273
274 // check if filter was stored for later parsing
275 if (!m_context.hasDefinition(id))
276 return 0;
277
278 const QDomElement &e = m_context.definition(id);
279 if (e.childNodes().count() == 0) {
280 QString mhref = e.attribute("xlink:href").mid(1);
281
282 if (m_context.hasDefinition(mhref))
283 return findFilter(mhref, id);
284 else
285 return 0;
286 } else {
287 // ok parse filter now
289 return 0;
290 }
291
292 // return successfully parsed filter or 0
293 QString n;
294 if (href.isEmpty())
295 n = id;
296 else
297 n = href;
298
299 if (m_filters.contains(n))
300 return &m_filters[ n ];
301 else
302 return 0;
303}
QDomElement definition(const QString &id) const
Returns the definition with the specified id.
bool hasDefinition(const QString &id) const
Checks if a definition with the specified id exists.
QMap< QString, SvgFilterHelper > m_filters
Definition SvgParser.h:231
bool parseFilter(const QDomElement &, const QDomElement &referencedBy=QDomElement())
Parses a filter element.

References SvgLoadingContext::definition(), findFilter(), SvgLoadingContext::hasDefinition(), m_context, m_filters, and parseFilter().

◆ findGradient()

SvgGradientHelper * SvgParser::findGradient ( const QString & id)
protected

find gradient with given id in gradient map

Definition at line 231 of file SvgParser.cpp.

232{
233 SvgGradientHelper *result = 0;
234
235 // check if gradient was already parsed, and return it
236 if (m_gradients.contains(id)) {
237 result = &m_gradients[ id ];
238 }
239
240 // check if gradient was stored for later parsing
241 if (!result && m_context.hasDefinition(id)) {
242 const QDomElement &e = m_context.definition(id);
243 if (e.tagName().contains("Gradient")) {
244 result = parseGradient(m_context.definition(id));
245 } else if (e.tagName() == "meshgradient") {
247 }
248 }
249
250 return result;
251}
SvgGradientHelper * parseGradient(const QDomElement &)
Parses a gradient element.
SvgGradientHelper * parseMeshGradient(const QDomElement &)
Parses mesh gradient element.
QMap< QString, SvgGradientHelper > m_gradients
Definition SvgParser.h:230

References SvgLoadingContext::definition(), SvgLoadingContext::hasDefinition(), m_context, m_gradients, parseGradient(), and parseMeshGradient().

◆ findPattern()

QSharedPointer< KoVectorPatternBackground > SvgParser::findPattern ( const QString & id,
const KoShape * shape )
protected

find pattern with given id in pattern map

Definition at line 253 of file SvgParser.cpp.

254{
256
257 // check if gradient was stored for later parsing
258 if (m_context.hasDefinition(id)) {
259 const QDomElement &e = m_context.definition(id);
260 if (e.tagName() == "pattern") {
261 result = parsePattern(m_context.definition(id), shape);
262 }
263 }
264
265 return result;
266}
QSharedPointer< KoVectorPatternBackground > parsePattern(const QDomElement &e, const KoShape *__shape)
Parses a pattern element.

References SvgLoadingContext::definition(), SvgLoadingContext::hasDefinition(), m_context, and parsePattern().

◆ getTextPath()

KoShape * SvgParser::getTextPath ( const QDomElement & e)
protected

Get the path for the gives textPath element.

Definition at line 1782 of file SvgParser.cpp.

1782 {
1783 if (e.hasAttribute("path")) {
1784 QDomElement p = e.ownerDocument().createElement("path");
1785 p.setAttribute("d", e.attribute("path"));
1786 KoShape *s = createPath(p);
1787 return s;
1788 } else {
1789 QString pathId;
1790 if (e.hasAttribute("href")) {
1791 pathId = e.attribute("href").remove(0, 1);
1792 } else if (e.hasAttribute("xlink:href")) {
1793 pathId = e.attribute("xlink:href").remove(0, 1);
1794 }
1795 if (!pathId.isNull()) {
1796 KoShape *s = m_context.shapeById(pathId);
1797 if (s) {
1798 const QTransform absTf = s->absoluteTransformation();
1799 KoShape *cloned = s->cloneShape();
1800 cloned->setTransformation(absTf * m_shapeParentTransform.value(s).inverted());
1801 return cloned;
1802 }
1803 }
1804 }
1805 return nullptr;
1806}

References KoShape::absoluteTransformation(), KoShape::cloneShape(), createPath(), m_context, m_shapeParentTransform, p, KoShape::setTransformation(), and SvgLoadingContext::shapeById().

◆ getTheOnlyTextChild()

QDomText SvgParser::getTheOnlyTextChild ( const QDomElement & e)
protected

Definition at line 1775 of file SvgParser.cpp.

1776{
1777 QDomNode firstChild = e.firstChild();
1778 return !firstChild.isNull() && firstChild == e.lastChild() && firstChild.isText() ?
1779 firstChild.toText() : QDomText();
1780}

◆ knownMarkers()

QList< QExplicitlySharedDataPointer< KoMarker > > SvgParser::knownMarkers ( ) const

Definition at line 1700 of file SvgParser.cpp.

1701{
1702 return m_markers.values();
1703}

References m_markers.

◆ parseAngular()

qreal SvgParser::parseAngular ( const QString & unit)
protected

parses a angular attribute values, result in radians

Definition at line 333 of file SvgParser.cpp.

334{
336}
static qreal parseUnitAngular(SvgGraphicsContext *gc, const QString &unit)
parses angle, result in radians!
Definition SvgUtil.cpp:332

References SvgLoadingContext::currentGC(), m_context, and SvgUtil::parseUnitAngular().

◆ parseClipMask()

bool SvgParser::parseClipMask ( const QDomElement & e)
protected

Definition at line 904 of file SvgParser.cpp.

905{
907
908 const QString id = e.attribute("id");
909 if (id.isEmpty()) return false;
910
911 clipMask->setCoordinates(KoFlake::coordinatesFromString(e.attribute("maskUnits"), KoFlake::ObjectBoundingBox));
912 clipMask->setContentCoordinates(KoFlake::coordinatesFromString(e.attribute("maskContentUnits"), KoFlake::UserSpaceOnUse));
913
914 QRectF maskRect;
915
916 if (clipMask->coordinates() == KoFlake::ObjectBoundingBox) {
917 maskRect.setRect(
918 SvgUtil::fromPercentage(e.attribute("x", "-10%")),
919 SvgUtil::fromPercentage(e.attribute("y", "-10%")),
920 SvgUtil::fromPercentage(e.attribute("width", "120%")),
921 SvgUtil::fromPercentage(e.attribute("height", "120%")));
922 } else {
923 maskRect.setRect(
924 parseUnitX(e.attribute("x", "-10%")), // yes, percents are insane in this case,
925 parseUnitY(e.attribute("y", "-10%")), // but this is what SVG 1.1 tells us...
926 parseUnitX(e.attribute("width", "120%")),
927 parseUnitY(e.attribute("height", "120%")));
928 }
929
930 clipMask->setMaskRect(maskRect);
931
932
933 // ensure that the clip mask is loaded in local coordinates system
935 m_context.currentGC()->matrix = QTransform();
937
938 KoShape *clipShape = parseGroup(e);
939
941
942 if (!clipShape) return false;
943 clipMask->setShapes({clipShape});
944
945 m_clipMasks.insert(id, clipMask);
946 return true;
947}
void workaroundClearInheritedFillProperties()
KoShape * parseGroup(const QDomElement &e, const QDomElement &overrideChildrenFrom=QDomElement(), bool createContext=true)
Parses a group-like element element, saving all its topmost properties.
CoordinateSystem coordinatesFromString(const QString &value, CoordinateSystem defaultValue)

References KoFlake::coordinatesFromString(), SvgLoadingContext::currentGC(), SvgUtil::fromPercentage(), m_clipMasks, m_context, SvgGraphicsContext::matrix, KoFlake::ObjectBoundingBox, parseGroup(), parseUnitX(), parseUnitY(), SvgLoadingContext::popGraphicsContext(), SvgLoadingContext::pushGraphicsContext(), KoFlake::UserSpaceOnUse, and SvgGraphicsContext::workaroundClearInheritedFillProperties().

◆ parseClipPath()

bool SvgParser::parseClipPath ( const QDomElement & e)
protected

Parses a clip path element.

Definition at line 877 of file SvgParser.cpp.

878{
879 SvgClipPathHelper clipPath;
880
881 const QString id = e.attribute("id");
882 if (id.isEmpty()) return false;
883
884 clipPath.setClipPathUnits(
885 KoFlake::coordinatesFromString(e.attribute("clipPathUnits"), KoFlake::UserSpaceOnUse));
886
887 // ensure that the clip path is loaded in local coordinates system
889 m_context.currentGC()->matrix = QTransform();
891
892 KoShape *clipShape = parseGroup(e);
893
895
896 if (!clipShape) return false;
897
898 clipPath.setShapes({clipShape});
899 m_clipPaths.insert(id, clipPath);
900
901 return true;
902}
void setClipPathUnits(KoFlake::CoordinateSystem clipPathUnits)
Set the clip path units type.
void setShapes(const QList< KoShape * > &shapes)

References KoFlake::coordinatesFromString(), SvgLoadingContext::currentGC(), m_clipPaths, m_context, SvgGraphicsContext::matrix, parseGroup(), SvgLoadingContext::popGraphicsContext(), SvgLoadingContext::pushGraphicsContext(), SvgClipPathHelper::setClipPathUnits(), SvgClipPathHelper::setShapes(), KoFlake::UserSpaceOnUse, and SvgGraphicsContext::workaroundClearInheritedFillProperties().

◆ parseContainer()

QList< KoShape * > SvgParser::parseContainer ( const QDomElement & e)
protected

Parses a container element, returning a list of child shapes.

Definition at line 1944 of file SvgParser.cpp.

1945{
1947
1948 // are we parsing a switch container
1949 bool isSwitch = e.tagName() == "switch";
1950
1951 DeferredUseStore deferredUseStore(this);
1952
1953 for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
1954 QDomElement b = n.toElement();
1955 if (b.isNull()) {
1956 continue;
1957 }
1958
1959 if (isSwitch) {
1960 // if we are parsing a switch check the requiredFeatures, requiredExtensions
1961 // and systemLanguage attributes
1962 // TODO: evaluate feature list
1963 if (b.hasAttribute("requiredFeatures")) {
1964 continue;
1965 }
1966 if (b.hasAttribute("requiredExtensions")) {
1967 // we do not support any extensions
1968 continue;
1969 }
1970 if (b.hasAttribute("systemLanguage")) {
1971 // not implemented yet
1972 }
1973 }
1974
1975 QList<KoShape*> currentShapes = parseSingleElement(b, &deferredUseStore);
1976 shapes.append(currentShapes);
1977
1978 // if we are parsing a switch, stop after the first supported element
1979 if (isSwitch && !currentShapes.isEmpty())
1980 break;
1981 }
1982 return shapes;
1983}
QList< KoShape * > parseSingleElement(const QDomElement &b, DeferredUseStore *deferredUseStore=0)
XXX.

References parseSingleElement(), and shapes().

◆ parseDefsElement()

void SvgParser::parseDefsElement ( const QDomElement & e)

Definition at line 1985 of file SvgParser.cpp.

1986{
1987 KIS_SAFE_ASSERT_RECOVER_RETURN(e.tagName() == "defs");
1989}
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128

References KIS_SAFE_ASSERT_RECOVER_RETURN, and parseSingleElement().

◆ parseFilter()

bool SvgParser::parseFilter ( const QDomElement & e,
const QDomElement & referencedBy = QDomElement() )
protected

Parses a filter element.

Definition at line 724 of file SvgParser.cpp.

725{
726 SvgFilterHelper filter;
727
728 // Use the filter that is referencing, or if there isn't one, the original filter
729 QDomElement b;
730 if (!referencedBy.isNull())
731 b = referencedBy;
732 else
733 b = e;
734
735 // check if we are referencing another filter
736 if (e.hasAttribute("xlink:href")) {
737 QString href = e.attribute("xlink:href").mid(1);
738 if (! href.isEmpty()) {
739 // copy the referenced filter if found
740 SvgFilterHelper *refFilter = findFilter(href);
741 if (refFilter)
742 filter = *refFilter;
743 }
744 } else {
745 filter.setContent(b);
746 }
747
748 if (b.attribute("filterUnits") == "userSpaceOnUse")
750 if (b.attribute("primitiveUnits") == "objectBoundingBox")
752
753 // parse filter region rectangle
754 if (filter.filterUnits() == KoFlake::UserSpaceOnUse) {
755 filter.setPosition(QPointF(parseUnitX(b.attribute("x")),
756 parseUnitY(b.attribute("y"))));
757 filter.setSize(QSizeF(parseUnitX(b.attribute("width")),
758 parseUnitY(b.attribute("height"))));
759 } else {
760 // x, y, width, height are in percentages of the object referencing the filter
761 // so we just parse the percentages
762 filter.setPosition(QPointF(SvgUtil::fromPercentage(b.attribute("x", "-0.1")),
763 SvgUtil::fromPercentage(b.attribute("y", "-0.1"))));
764 filter.setSize(QSizeF(SvgUtil::fromPercentage(b.attribute("width", "1.2")),
765 SvgUtil::fromPercentage(b.attribute("height", "1.2"))));
766 }
767
768 m_filters.insert(b.attribute("id"), filter);
769
770 return true;
771}
void setPosition(const QPointF &position)
Sets filter position.
void setContent(const QDomElement &content)
Sets the dom element containing the filter.
void setFilterUnits(KoFlake::CoordinateSystem filterUnits)
Set the filter units type.
void setPrimitiveUnits(KoFlake::CoordinateSystem primitiveUnits)
Set the filter primitive units type.
void setSize(const QSizeF &size)
Sets filter size.

References SvgFilterHelper::filterUnits(), findFilter(), SvgUtil::fromPercentage(), m_filters, KoFlake::ObjectBoundingBox, parseUnitX(), parseUnitY(), SvgFilterHelper::setContent(), SvgFilterHelper::setFilterUnits(), SvgFilterHelper::setPosition(), SvgFilterHelper::setPrimitiveUnits(), SvgFilterHelper::setSize(), and KoFlake::UserSpaceOnUse.

◆ parseGradient()

SvgGradientHelper * SvgParser::parseGradient ( const QDomElement & e)
protected

Parses a gradient element.

Definition at line 339 of file SvgParser.cpp.

340{
341 // IMPROVEMENTS:
342 // - Store the parsed colorstops in some sort of a cache so they don't need to be parsed again.
343 // - A gradient inherits attributes it does not have from the referencing gradient.
344 // - Gradients with no color stops have no fill or stroke.
345 // - Gradients with one color stop have a solid color.
346
348 if (!gc) return 0;
349
350 SvgGradientHelper gradHelper;
351
352 QString gradientId = e.attribute("id");
353 if (gradientId.isEmpty()) return 0;
354
355 // check if we have this gradient already parsed
356 // copy existing gradient if it exists
357 if (m_gradients.contains(gradientId)) {
358 return &m_gradients[gradientId];
359 }
360
361 if (e.hasAttribute("xlink:href")) {
362 // strip the '#' symbol
363 QString href = e.attribute("xlink:href").mid(1);
364
365 if (!href.isEmpty()) {
366 // copy the referenced gradient if found
367 SvgGradientHelper *pGrad = findGradient(href);
368 if (pGrad) {
369 gradHelper = *pGrad;
370 }
371 }
372 }
373
374 const QGradientStops defaultStops = gradHelper.gradient()->stops();
375
376 if (e.attribute("gradientUnits") == "userSpaceOnUse") {
378 }
379
382
383 if (e.tagName() == "linearGradient") {
384 QLinearGradient *g = new QLinearGradient();
385 if (gradHelper.gradientUnits() == KoFlake::ObjectBoundingBox) {
386 g->setCoordinateMode(QGradient::ObjectBoundingMode);
387 g->setStart(QPointF(SvgUtil::fromPercentage(e.attribute("x1", "0%")),
388 SvgUtil::fromPercentage(e.attribute("y1", "0%"))));
389 g->setFinalStop(QPointF(SvgUtil::fromPercentage(e.attribute("x2", "100%")),
390 SvgUtil::fromPercentage(e.attribute("y2", "0%"))));
391 } else {
392 g->setStart(QPointF(parseUnitX(e.attribute("x1")),
393 parseUnitY(e.attribute("y1"))));
394 g->setFinalStop(QPointF(parseUnitX(e.attribute("x2")),
395 parseUnitY(e.attribute("y2"))));
396 }
397 gradHelper.setGradient(g);
398
399 } else if (e.tagName() == "radialGradient") {
400 QRadialGradient *g = new QRadialGradient();
401 if (gradHelper.gradientUnits() == KoFlake::ObjectBoundingBox) {
402 g->setCoordinateMode(QGradient::ObjectBoundingMode);
403 g->setCenter(QPointF(SvgUtil::fromPercentage(e.attribute("cx", "50%")),
404 SvgUtil::fromPercentage(e.attribute("cy", "50%"))));
405 g->setRadius(SvgUtil::fromPercentage(e.attribute("r", "50%")));
406 g->setFocalPoint(QPointF(SvgUtil::fromPercentage(e.attribute("fx", "50%")),
407 SvgUtil::fromPercentage(e.attribute("fy", "50%"))));
408 } else {
409 g->setCenter(QPointF(parseUnitX(e.attribute("cx")),
410 parseUnitY(e.attribute("cy"))));
411 g->setFocalPoint(QPointF(parseUnitX(e.attribute("fx")),
412 parseUnitY(e.attribute("fy"))));
413 g->setRadius(parseUnitXY(e.attribute("r")));
414 }
415 gradHelper.setGradient(g);
416 } else {
417 debugFlake << "WARNING: Failed to parse gradient with tag" << e.tagName();
418 }
419
420 // handle spread method
421 QGradient::Spread spreadMethod = QGradient::PadSpread;
422 QString spreadMethodStr = e.attribute("spreadMethod");
423 if (!spreadMethodStr.isEmpty()) {
424 if (spreadMethodStr == "reflect") {
425 spreadMethod = QGradient::ReflectSpread;
426 } else if (spreadMethodStr == "repeat") {
427 spreadMethod = QGradient::RepeatSpread;
428 }
429 }
430
431 gradHelper.setSpreadMode(spreadMethod);
432
433 // Parse the color stops.
434 m_context.styleParser().parseColorStops(gradHelper.gradient(), e, gc, defaultStops);
435
436 if (e.hasAttribute("gradientTransform")) {
437 SvgTransformParser p(e.attribute("gradientTransform"));
438 if (p.isValid()) {
439 gradHelper.setTransform(p.transform());
440 }
441 }
442
444
445 m_gradients.insert(gradientId, gradHelper);
446
447 return &m_gradients[gradientId];
448}
KoFlake::CoordinateSystem gradientUnits() const
Returns gradient units type.
void setSpreadMode(const QGradient::Spread &spreadMode)
void setGradient(QGradient *g)
Sets the gradient.
void setGradientUnits(KoFlake::CoordinateSystem units)
Sets the gradient units type.
void setTransform(const QTransform &transform)
Sets the gradient transformation.
qreal parseUnitXY(const QString &unit)
parses a length attribute in xy-direction
void parseColorStops(QGradient *, const QDomElement &, SvgGraphicsContext *context, const QGradientStops &defaultStops)
Parses gradient color stops.

References SvgLoadingContext::currentGC(), debugFlake, findGradient(), SvgUtil::fromPercentage(), SvgGradientHelper::gradient(), SvgGradientHelper::gradientUnits(), m_context, m_gradients, KoFlake::ObjectBoundingBox, p, SvgStyleParser::parseColorStops(), parseUnitX(), parseUnitXY(), parseUnitY(), SvgLoadingContext::popGraphicsContext(), SvgLoadingContext::pushGraphicsContext(), SvgGradientHelper::setGradient(), SvgGradientHelper::setGradientUnits(), SvgGradientHelper::setSpreadMode(), SvgGradientHelper::setTransform(), SvgLoadingContext::styleParser, uploadStyleToContext(), and KoFlake::UserSpaceOnUse.

◆ parseGroup()

KoShape * SvgParser::parseGroup ( const QDomElement & e,
const QDomElement & overrideChildrenFrom = QDomElement(),
bool createContext = true )
protected

Parses a group-like element element, saving all its topmost properties.

Definition at line 1730 of file SvgParser.cpp.

1731{
1732 if (createContext) {
1734 }
1735
1736 KoShapeGroup *group = new KoShapeGroup();
1737 group->setZIndex(m_context.nextZIndex());
1738
1739 // groups should also have their own coordinate system!
1741 const QPointF extraOffset = extraShapeOffset(group, m_context.currentGC()->matrix);
1742
1744
1745 QList<KoShape*> childShapes;
1746
1747 if (!overrideChildrenFrom.isNull()) {
1748 // we upload styles from both: <use> and <defs>
1749 uploadStyleToContext(overrideChildrenFrom);
1750 if (overrideChildrenFrom.tagName() == "symbol") {
1751 childShapes = {parseGroup(overrideChildrenFrom)};
1752 } else {
1753 childShapes = parseSingleElement(overrideChildrenFrom, 0);
1754 }
1755 } else {
1756 childShapes = parseContainer(b);
1757 }
1758
1759 // handle id
1760 applyId(b.attribute("id"), group);
1761
1762 addToGroup(childShapes, group);
1763
1764 applyCurrentStyle(group, extraOffset); // apply style to this group after size is set
1765
1766 parseMetadataApplyToShape(b, group);
1767
1768 if (createContext) {
1770 }
1771
1772 return group;
1773}
void addToGroup(QList< KoShape * > shapes, KoShapeContainer *group)
Adds list of shapes to the given group shape.
QList< KoShape * > parseContainer(const QDomElement &)
Parses a container element, returning a list of child shapes.

References addToGroup(), KoShape::applyAbsoluteTransformation(), applyCurrentStyle(), applyId(), SvgLoadingContext::currentGC(), extraShapeOffset(), m_context, SvgGraphicsContext::matrix, SvgLoadingContext::nextZIndex(), parseContainer(), parseGroup(), parseMetadataApplyToShape(), parseSingleElement(), SvgLoadingContext::popGraphicsContext(), SvgLoadingContext::pushGraphicsContext(), KoShape::setZIndex(), and uploadStyleToContext().

◆ parseMarker()

bool SvgParser::parseMarker ( const QDomElement & e)
protected

Definition at line 773 of file SvgParser.cpp.

774{
775 const QString id = e.attribute("id");
776 if (id.isEmpty()) return false;
777
778 QScopedPointer<KoMarker> marker(new KoMarker());
779 marker->setCoordinateSystem(
780 KoMarker::coordinateSystemFromString(e.attribute("markerUnits", "strokeWidth")));
781
782 marker->setReferencePoint(QPointF(parseUnitX(e.attribute("refX")),
783 parseUnitY(e.attribute("refY"))));
784
785 marker->setReferenceSize(QSizeF(parseUnitX(e.attribute("markerWidth", "3")),
786 parseUnitY(e.attribute("markerHeight", "3"))));
787
788 const QString orientation = e.attribute("orient", "0");
789
790 if (orientation == "auto") {
791 marker->setAutoOrientation(true);
792 } else {
793 marker->setExplicitOrientation(parseAngular(orientation));
794 }
795
796 // ensure that the clip path is loaded in local coordinates system
798 m_context.currentGC()->matrix = QTransform();
799 m_context.currentGC()->currentBoundingBox = QRectF(QPointF(0, 0), marker->referenceSize());
800
801 KoShape *markerShape = parseGroup(e);
802
804
805 if (!markerShape) return false;
806
807 marker->setShapes({markerShape});
808
809 m_markers.insert(id, QExplicitlySharedDataPointer<KoMarker>(marker.take()));
810
811 return true;
812}
static MarkerCoordinateSystem coordinateSystemFromString(const QString &value)
Definition KoMarker.cpp:155
qreal parseAngular(const QString &unit)
parses a angular attribute values, result in radians

References KoMarker::coordinateSystemFromString(), SvgGraphicsContext::currentBoundingBox, SvgLoadingContext::currentGC(), m_context, m_markers, SvgGraphicsContext::matrix, parseAngular(), parseGroup(), parseUnitX(), parseUnitY(), SvgLoadingContext::popGraphicsContext(), and SvgLoadingContext::pushGraphicsContext().

◆ parseMeshGradient()

SvgGradientHelper * SvgParser::parseMeshGradient ( const QDomElement & e)
protected

Parses mesh gradient element.

Definition at line 450 of file SvgParser.cpp.

451{
452 SvgGradientHelper gradHelper;
453 QString gradientId = e.attribute("id");
454 QScopedPointer<SvgMeshGradient> g(new SvgMeshGradient);
455
456 // check if we have this gradient already parsed
457 // copy existing gradient if it exists
458 if (m_gradients.contains(gradientId)) {
459 return &m_gradients[gradientId];
460 }
461
462 if (e.hasAttribute("xlink:href")) {
463 // strip the '#' symbol
464 QString href = e.attribute("xlink:href").mid(1);
465
466 if (!href.isEmpty()) {
467 // copy the referenced gradient if found
468 SvgGradientHelper *pGrad = findGradient(href);
469 if (pGrad) {
470 gradHelper = *pGrad;
471 }
472 }
473 }
474
475 if (e.attribute("gradientUnits") == "userSpaceOnUse") {
477 }
478
479 if (e.hasAttribute("transform")) {
480 SvgTransformParser p(e.attribute("transform"));
481 if (p.isValid()) {
482 gradHelper.setTransform(p.transform());
483 }
484 }
485
486 QString type = e.attribute("type");
487 g->setType(SvgMeshGradient::BILINEAR);
488 if (!type.isEmpty() && type == "bicubic") {
489 g->setType(SvgMeshGradient::BICUBIC);
490 }
491
492 int irow = 0, icols;
493 for (int i = 0; i < e.childNodes().size(); ++i) {
494 QDomNode node = e.childNodes().at(i);
495
496 if (node.nodeName() == "meshrow") {
497
498 SvgMeshStop startingNode;
499 if (irow == 0) {
500 startingNode.point = QPointF(
501 parseUnitX(e.attribute("x")),
502 parseUnitY(e.attribute(("y"))));
503 startingNode.color = QColor();
504 }
505
506 icols = 0;
507 g->getMeshArray()->newRow();
508 for (int j = 0; j < node.childNodes().size() ; ++j) {
509 QDomNode meshpatchNode = node.childNodes().at(j);
510
511 if (meshpatchNode.nodeName() == "meshpatch") {
512 if (irow > 0) {
513 // Starting point for this would be the bottom (right) corner of the above patch
514 startingNode = g->getMeshArray()->getStop(SvgMeshPatch::Bottom, irow - 1, icols);
515 } else if (icols != 0) {
516 // Starting point for this would be the right (top) corner of the previous patch
517 startingNode = g->getMeshArray()->getStop(SvgMeshPatch::Right, irow, icols - 1);
518 }
519
520 QList<QPair<QString, QColor>> rawStops = parseMeshPatch(meshpatchNode);
521 // TODO handle the false result
522 if (!g->getMeshArray()->addPatch(rawStops, startingNode.point)) {
523 debugFlake << "WARNING: Failed to create meshpatch";
524 }
525 icols++;
526 }
527 }
528 irow++;
529 }
530 }
531 gradHelper.setMeshGradient(g.data());
532 m_gradients.insert(gradientId, gradHelper);
533
534 return &m_gradients[gradientId];
535}
void setMeshGradient(SvgMeshGradient *g)
Sets the meshgradient.
QList< QPair< QString, QColor > > parseMeshPatch(const QDomNode &meshpatch)
Parses a single meshpatch and returns the pointer.
int size(const Forest< T > &forest)
Definition KisForest.h:1232
QPointF point

References SvgMeshGradient::BICUBIC, SvgMeshGradient::BILINEAR, SvgMeshPatch::Bottom, SvgMeshStop::color, debugFlake, findGradient(), m_gradients, p, parseMeshPatch(), parseUnitX(), parseUnitY(), SvgMeshStop::point, SvgMeshPatch::Right, SvgGradientHelper::setGradientUnits(), SvgGradientHelper::setMeshGradient(), SvgGradientHelper::setTransform(), and KoFlake::UserSpaceOnUse.

◆ parseMeshPatch()

QList< QPair< QString, QColor > > SvgParser::parseMeshPatch ( const QDomNode & meshpatch)
protected

Parses a single meshpatch and returns the pointer.

Definition at line 541 of file SvgParser.cpp.

542{
543 // path and its associated color
545
547 if (!gc) return rawstops;
548
549 QDomElement e = meshpatchNode.toElement();
550
551 QDomElement stop;
552
553 forEachElement(stop, e) {
554 qreal X = 0; // dummy value, don't care, just to ensure the function won't blow up (also to avoid a Coverity issue)
555 QColor color = m_context.styleParser().parseColorStop(stop, gc, X).second;
556
557 QString pathStr = stop.attribute("path");
558
559 rawstops.append({pathStr, color});
560 }
561
562 return rawstops;
563}
#define forEachElement(elem, parent)
QPair< qreal, QColor > parseColorStop(const QDomElement &, SvgGraphicsContext *context, qreal &previousOffset)
const QString X

References SvgLoadingContext::currentGC(), forEachElement, m_context, SvgStyleParser::parseColorStop(), and SvgLoadingContext::styleParser.

◆ parseMetadataApplyToShape()

void SvgParser::parseMetadataApplyToShape ( const QDomElement & e,
KoShape * shape )
protected

This parses the SVG native title and desc elements and adds them into additional attributes.

Definition at line 857 of file SvgParser.cpp.

858{
859 const QString titleTag = "title";
860 const QString descriptionTag = "desc";
861 QDomElement title = e.firstChildElement(titleTag);
862 if (!title.isNull()) {
863 QDomText text = getTheOnlyTextChild(title);
864 if (!text.data().isEmpty()) {
865 shape->setAdditionalAttribute(titleTag, text.data());
866 }
867 }
868 QDomElement description = e.firstChildElement(descriptionTag);
869 if (!description.isNull()) {
870 QDomText text = getTheOnlyTextChild(description);
871 if (!text.data().isEmpty()) {
872 shape->setAdditionalAttribute(descriptionTag, text.data());
873 }
874 }
875}
void setAdditionalAttribute(const QString &name, const QString &value)
Definition KoShape.cpp:1264
QDomText getTheOnlyTextChild(const QDomElement &e)

References getTheOnlyTextChild(), and KoShape::setAdditionalAttribute().

◆ parsePattern()

QSharedPointer< KoVectorPatternBackground > SvgParser::parsePattern ( const QDomElement & e,
const KoShape * __shape )
protected

Parses a pattern element.

Unlike the gradient parsing function, this method is called every time we reference the pattern, not when we define it. Therefore we can already use the coordinate system of the destination.

In Krita shapes X,Y coordinates are baked into the shape global transform, but the pattern should be painted in "user" coordinates. Therefore, we should handle this offset separately.

TODO: Please also note that this offset is different from extraShapeOffset(), because A.inverted() * B != A * B.inverted(). I'm not sure which variant is correct (DK)

Definition at line 576 of file SvgParser.cpp.

577{
585
587 if (!gc) return pattHelper;
588
589 const QString patternId = e.attribute("id");
590 if (patternId.isEmpty()) return pattHelper;
591
592 pattHelper = toQShared(new KoVectorPatternBackground);
593
594 if (e.hasAttribute("xlink:href")) {
595 // strip the '#' symbol
596 QString href = e.attribute("xlink:href").mid(1);
597
598 if (!href.isEmpty() &&href != patternId) {
599 // copy the referenced pattern if found
601 if (pPatt) {
602 pattHelper = pPatt;
603 }
604 }
605 }
606
607 pattHelper->setReferenceCoordinates(
608 KoFlake::coordinatesFromString(e.attribute("patternUnits"),
609 pattHelper->referenceCoordinates()));
610
611 pattHelper->setContentCoordinates(
612 KoFlake::coordinatesFromString(e.attribute("patternContentUnits"),
613 pattHelper->contentCoordinates()));
614
615 if (e.hasAttribute("patternTransform")) {
616 SvgTransformParser p(e.attribute("patternTransform"));
617 if (p.isValid()) {
618 pattHelper->setPatternTransform(p.transform());
619 }
620 }
621
622 if (pattHelper->referenceCoordinates() == KoFlake::ObjectBoundingBox) {
623 QRectF referenceRect(
624 SvgUtil::fromPercentage(e.attribute("x", "0%")),
625 SvgUtil::fromPercentage(e.attribute("y", "0%")),
626 SvgUtil::fromPercentage(e.attribute("width", "0%")), // 0% is according to SVG 1.1, don't ask me why!
627 SvgUtil::fromPercentage(e.attribute("height", "0%"))); // 0% is according to SVG 1.1, don't ask me why!
628
629 pattHelper->setReferenceRect(referenceRect);
630 } else {
631 QRectF referenceRect(
632 parseUnitX(e.attribute("x", "0")),
633 parseUnitY(e.attribute("y", "0")),
634 parseUnitX(e.attribute("width", "0")), // 0 is according to SVG 1.1, don't ask me why!
635 parseUnitY(e.attribute("height", "0"))); // 0 is according to SVG 1.1, don't ask me why!
636
637 pattHelper->setReferenceRect(referenceRect);
638 }
639
650 const QTransform dstShapeTransform = shape->absoluteTransformation();
651 const QTransform shapeOffsetTransform = dstShapeTransform * gc->matrix.inverted();
652 KIS_SAFE_ASSERT_RECOVER_NOOP(shapeOffsetTransform.type() <= QTransform::TxTranslate);
653 const QPointF extraShapeOffset(shapeOffsetTransform.dx(), shapeOffsetTransform.dy());
654
656 gc = m_context.currentGC();
658
659 // start building shape tree from scratch
660 gc->matrix = QTransform();
661
662 const QRectF boundingRect = shape->outline().boundingRect()/*.translated(extraShapeOffset)*/;
663 const QTransform relativeToShape(boundingRect.width(), 0, 0, boundingRect.height(),
664 boundingRect.x(), boundingRect.y());
665
666
667
668 // WARNING1: OBB and ViewBox transformations are *baked* into the pattern shapes!
669 // although we expect the pattern be reusable, but it is not so!
670 // WARNING2: the pattern shapes are stored in *User* coordinate system, although
671 // the "official" content system might be either OBB or User. It means that
672 // this baked transform should be stripped before writing the shapes back
673 // into SVG
674 if (e.hasAttribute("viewBox")) {
676 pattHelper->referenceCoordinates() == KoFlake::ObjectBoundingBox ?
677 relativeToShape.mapRect(pattHelper->referenceRect()) :
678 pattHelper->referenceRect();
679
681 pattHelper->setContentCoordinates(pattHelper->referenceCoordinates());
682
683 } else if (pattHelper->contentCoordinates() == KoFlake::ObjectBoundingBox) {
684 gc->matrix = relativeToShape * gc->matrix;
685 }
686
687 // We do *not* apply patternTransform here! Here we only bake the untransformed
688 // version of the shape. The transformed one will be done in the very end while rendering.
689
690 QList<KoShape*> patternShapes = parseContainer(e);
691
692 if (pattHelper->contentCoordinates() == KoFlake::UserSpaceOnUse) {
693 // In Krita we normalize the shapes, bake this transform into the pattern shapes
694
695 const QPointF offset = bakeShapeOffset(pattHelper->patternTransform(), extraShapeOffset);
696
697 Q_FOREACH (KoShape *shape, patternShapes) {
698 shape->applyAbsoluteTransformation(QTransform::fromTranslate(offset.x(), offset.y()));
699 }
700 }
701
702 if (pattHelper->referenceCoordinates() == KoFlake::UserSpaceOnUse) {
703 // In Krita we normalize the shapes, bake this transform into reference rect
704 // NOTE: this is possible *only* when pattern transform is not perspective
705 // (which is always true for SVG)
706
707 const QPointF offset = bakeShapeOffset(pattHelper->patternTransform(), extraShapeOffset);
708
709 QRectF ref = pattHelper->referenceRect();
710 ref.translate(offset);
711 pattHelper->setReferenceRect(ref);
712 }
713
715 gc = m_context.currentGC();
716
717 if (!patternShapes.isEmpty()) {
718 pattHelper->setShapes(patternShapes);
719 }
720
721 return pattHelper;
722}
QPointF bakeShapeOffset(const QTransform &patternTransform, const QPointF &shapeOffset)
void applyViewBoxTransform(const QDomElement &element)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130

References KoShape::absoluteTransformation(), KoShape::applyAbsoluteTransformation(), applyViewBoxTransform(), bakeShapeOffset(), KoFlake::coordinatesFromString(), SvgGraphicsContext::currentBoundingBox, SvgLoadingContext::currentGC(), extraShapeOffset(), findPattern(), SvgUtil::fromPercentage(), KIS_SAFE_ASSERT_RECOVER_NOOP, m_context, SvgGraphicsContext::matrix, KoFlake::ObjectBoundingBox, KoShape::outline(), p, parseContainer(), parseUnitX(), parseUnitY(), SvgLoadingContext::popGraphicsContext(), SvgLoadingContext::pushGraphicsContext(), toQShared(), KoFlake::UserSpaceOnUse, and SvgGraphicsContext::workaroundClearInheritedFillProperties().

◆ parseSingleElement()

QList< KoShape * > SvgParser::parseSingleElement ( const QDomElement & b,
DeferredUseStore * deferredUseStore = 0 )
protected

XXX.

WARNING: 'defs' are basically 'display:none' style, therefore they should not play any role in shapes outline calculation. But setVisible(false) shapes do! Should be fixed in the future!

Definition at line 1991 of file SvgParser.cpp.

1992{
1994
1995 // save definition for later instantiation with 'use'
1997 if (deferredUseStore) {
1998 deferredUseStore->checkPendingUse(b, shapes);
1999 }
2000
2001 if (b.tagName() == "svg") {
2002 shapes += parseSvg(b);
2003 } else if (b.tagName() == "g" || b.tagName() == "a") {
2004 // treat svg link <a> as group so we don't miss its child elements
2005 shapes += parseGroup(b);
2006 } else if (b.tagName() == "symbol") {
2007 parseSymbol(b);
2008 } else if (b.tagName() == "switch") {
2010 shapes += parseContainer(b);
2012 } else if (b.tagName() == "defs") {
2013 if (b.childNodes().count() > 0) {
2019 KoShape *defsShape = parseGroup(b);
2020 defsShape->setVisible(false);
2021 m_defsShapes << defsShape; // TODO: where to delete the shape!?
2022
2023 }
2024 } else if (b.tagName() == "linearGradient" || b.tagName() == "radialGradient") {
2025 } else if (b.tagName() == "pattern") {
2026 } else if (b.tagName() == "filter") {
2027 parseFilter(b);
2028 } else if (b.tagName() == "clipPath") {
2029 parseClipPath(b);
2030 } else if (b.tagName() == "mask") {
2031 parseClipMask(b);
2032 } else if (b.tagName() == "marker") {
2033 parseMarker(b);
2034 } else if (b.tagName() == "style") {
2036 } else if (b.tagName() == "text" || b.tagName() == "tspan" || b.tagName() == "textPath") {
2038 } else if (b.tagName() == "rect" || b.tagName() == "ellipse" || b.tagName() == "circle" || b.tagName() == "line" || b.tagName() == "polyline"
2039 || b.tagName() == "polygon" || b.tagName() == "path" || b.tagName() == "image") {
2040 KoShape *shape = createObjectDirect(b);
2041
2042 if (shape) {
2043 if (!shape->outlineRect().isNull() || !shape->boundingRect().isNull()) {
2044 shapes.append(shape);
2045 } else {
2046 debugFlake << "WARNING: shape is totally empty!" << shape->shapeId() << ppVar(shape->outlineRect());
2047 debugFlake << " " << shape->shapeId() << ppVar(shape->outline());
2048 {
2049 QString string;
2050 QTextStream stream(&string);
2052 stream << b;
2053 debugFlake << " " << string;
2054 }
2055 delete shape;
2056 }
2057 }
2058 } else if (b.tagName() == "use") {
2059 KoShape* s = parseUse(b, deferredUseStore);
2060 if (s) {
2061 shapes += s;
2062 }
2063 } else if (b.tagName() == "color-profile") {
2065 } else {
2066 // this is an unknown element, so try to load it anyway
2067 // there might be a shape that handles that element
2068 KoShape *shape = createObject(b);
2069 if (shape) {
2070 shapes.append(shape);
2071 }
2072 }
2073
2074 return shapes;
2075}
virtual QRectF outlineRect() const
Definition KoShape.cpp:637
virtual QPainterPath outline() const
Definition KoShape.cpp:630
virtual QRectF boundingRect() const
Get the bounding box of the shape.
Definition KoShape.cpp:335
void addDefinition(const QDomElement &element)
Adds a definition for later use.
void addStyleSheet(const QDomElement &styleSheet)
Adds a css style sheet.
void parseProfile(const QDomElement &element)
parses 'color-profile' tag and saves it in the context
bool parseClipPath(const QDomElement &)
Parses a clip path element.
bool parseClipMask(const QDomElement &e)
bool parseMarker(const QDomElement &e)
KoShape * parseTextElement(const QDomElement &e, KoSvgTextShape *mergeIntoShape=0)
QList< KoShape * > parseSvg(const QDomElement &e, QSizeF *fragmentSize=0)
Parses a svg fragment, returning the list of top level child shapes.
KoShape * parseUse(const QDomElement &, DeferredUseStore *deferredUseStore)
Parses a use element, returning a list of child shapes.
bool parseSymbol(const QDomElement &e)
KoShape * createObjectDirect(const QDomElement &b)
KoShape * createObject(const QDomElement &, const SvgStyles &style=SvgStyles())
Creates an object from the given xml element.
#define ppVar(var)
Definition kis_debug.h:155
void setUtf8OnStream(QTextStream &stream)

References SvgLoadingContext::addDefinition(), SvgLoadingContext::addStyleSheet(), KoShape::boundingRect(), SvgParser::DeferredUseStore::checkPendingUse(), createObject(), createObjectDirect(), debugFlake, m_context, m_defsShapes, KoShape::outline(), KoShape::outlineRect(), parseClipMask(), parseClipPath(), parseContainer(), parseFilter(), parseGroup(), parseMarker(), SvgLoadingContext::parseProfile(), parseSvg(), parseSymbol(), parseTextElement(), parseUse(), SvgLoadingContext::popGraphicsContext(), ppVar, SvgLoadingContext::pushGraphicsContext(), KisPortingUtils::setUtf8OnStream(), KoShape::setVisible(), KoShape::shapeId(), and shapes().

◆ parseSvg()

QList< KoShape * > SvgParser::parseSvg ( const QDomElement & e,
QSizeF * fragmentSize = 0 )

Parses a svg fragment, returning the list of top level child shapes.

In internal SVG coordinate systems pixels are linked to absolute values with a fixed ratio.

See CSS specification: https://www.w3.org/TR/css-values-3/#absolute-lengths

Definition at line 1575 of file SvgParser.cpp.

1576{
1577 // check if we are the root svg element
1578 const bool isRootSvg = m_context.isRootContext();
1579
1580 // parse 'transform' field if preset
1582
1583 applyStyle(0, e, QPointF());
1584
1585 const QString w = e.attribute("width");
1586 const QString h = e.attribute("height");
1587
1588 qreal width = w.isEmpty() ? 666.0 : parseUnitX(w);
1589 qreal height = h.isEmpty() ? 555.0 : parseUnitY(h);
1590
1591 if (w.isEmpty() || h.isEmpty()) {
1592 QRectF viewRect;
1593 QTransform viewTransform_unused;
1594 QRectF fakeBoundingRect(0.0, 0.0, 1.0, 1.0);
1595
1596 if (SvgUtil::parseViewBox(e, fakeBoundingRect,
1597 &viewRect, &viewTransform_unused)) {
1598
1599 QSizeF estimatedSize = viewRect.size();
1600
1601 if (estimatedSize.isValid()) {
1602
1603 if (!w.isEmpty()) {
1604 estimatedSize = QSizeF(width, width * estimatedSize.height() / estimatedSize.width());
1605 } else if (!h.isEmpty()) {
1606 estimatedSize = QSizeF(height * estimatedSize.width() / estimatedSize.height(), height);
1607 }
1608
1609 width = estimatedSize.width();
1610 height = estimatedSize.height();
1611 }
1612 }
1613 }
1614
1615 QSizeF svgFragmentSize(QSizeF(width, height));
1616
1617 if (fragmentSize) {
1618 *fragmentSize = svgFragmentSize;
1619 }
1620
1621 gc->currentBoundingBox = QRectF(QPointF(0, 0), svgFragmentSize);
1622
1623 if (!isRootSvg) {
1624 // x and y attribute has no meaning for outermost svg elements
1625 const qreal x = parseUnit(e.attribute("x", "0"));
1626 const qreal y = parseUnit(e.attribute("y", "0"));
1627
1628 QTransform move = QTransform::fromTranslate(x, y);
1629 gc->matrix = move * gc->matrix;
1630 }
1631
1639 gc->pixelsPerInch = 96.0;
1640
1642
1644
1645 // First find the metadata
1646 for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
1647 QDomElement b = n.toElement();
1648 if (b.isNull())
1649 continue;
1650
1651 if (b.tagName() == "title") {
1652 m_documentTitle = b.text().trimmed();
1653 }
1654 else if (b.tagName() == "desc") {
1655 m_documentDescription = b.text().trimmed();
1656 }
1657 else if (b.tagName() == "metadata") {
1658 // TODO: parse the metadata
1659 }
1660 }
1661
1662
1663 // SVG 1.1: skip the rendering of the element if it has null viewBox; however an inverted viewbox is just peachy
1664 // and as mother makes them -- if mother is inkscape.
1665 if (gc->currentBoundingBox.normalized().isValid()) {
1667 }
1668
1670
1671 return shapes;
1672}
qreal pixelsPerInch
controls the resolution of the image raster
qreal parseUnit(const QString &, bool horiz=false, bool vert=false, const QRectF &bbox=QRectF())
parses a length attribute

References applyStyle(), applyViewBoxTransform(), SvgGraphicsContext::currentBoundingBox, SvgLoadingContext::isRootContext(), m_context, m_documentDescription, m_documentTitle, SvgGraphicsContext::matrix, parseContainer(), parseUnit(), parseUnitX(), parseUnitY(), SvgUtil::parseViewBox(), SvgGraphicsContext::pixelsPerInch, SvgLoadingContext::popGraphicsContext(), SvgLoadingContext::pushGraphicsContext(), and shapes().

◆ parseSymbol()

bool SvgParser::parseSymbol ( const QDomElement & e)
protected

Definition at line 814 of file SvgParser.cpp.

815{
816 const QString id = e.attribute("id");
817
818 if (id.isEmpty()) return false;
819
820 QScopedPointer<KoSvgSymbol> svgSymbol(new KoSvgSymbol());
821
822 // ensure that the clip path is loaded in local coordinates system
824 m_context.currentGC()->matrix = QTransform();
825 m_context.currentGC()->currentBoundingBox = QRectF(0.0, 0.0, 1.0, 1.0);
826
827 QString title = e.firstChildElement("title").toElement().text();
828
829 QScopedPointer<KoShape> symbolShape(parseGroup(e));
830
832
833 if (!symbolShape) return false;
834
835 svgSymbol->shape = symbolShape.take();
836 svgSymbol->title = title;
837 svgSymbol->id = id;
838 if (title.isEmpty()) svgSymbol->title = id;
839
840 if (svgSymbol->shape->boundingRect() == QRectF(0.0, 0.0, 0.0, 0.0)) {
841 debugFlake << "Symbol" << id << "seems to be empty, discarding";
842 return false;
843 }
844
845 // TODO: out default set of symbols had duplicated ids! We should
846 // make sure they are unique!
847 if (m_symbols.contains(id)) {
848 delete m_symbols[id];
849 m_symbols.remove(id);
850 }
851
852 m_symbols.insert(id, svgSymbol.take());
853
854 return true;
855}

References SvgGraphicsContext::currentBoundingBox, SvgLoadingContext::currentGC(), debugFlake, m_context, m_symbols, SvgGraphicsContext::matrix, parseGroup(), SvgLoadingContext::popGraphicsContext(), and SvgLoadingContext::pushGraphicsContext().

◆ parseTextChildren()

void SvgParser::parseTextChildren ( const QDomElement & e,
KoSvgTextLoader & textLoader )
protected

parse children of a <text > element into the root shape.

TODO: we should skip dublin core metadata too...

Definition at line 1808 of file SvgParser.cpp.

1808 {
1809 QDomText t = getTheOnlyTextChild(e);
1810 if (!t.isNull()) {
1811 textLoader.loadSvgText(t, m_context);
1812 } else {
1813 textLoader.enterNodeSubtree();
1814 for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
1815 QDomElement b = n.toElement();
1816 if (b.tagName() == "title" || b.tagName() == "desc") continue;
1817 textLoader.nextNode();
1818 if (b.isNull()) {
1819 textLoader.loadSvgText(n.toText(), m_context);
1820 KoShape *styleDummy = new KoPathShape();
1821 applyCurrentBasicStyle(styleDummy);
1822 textLoader.setStyleInfo(styleDummy);
1823 } else {
1826 textLoader.loadSvg(b, m_context);
1827 if (b.hasChildNodes()) {
1828 parseTextChildren(b, textLoader);
1829 }
1832 }
1833 }
1834 textLoader.leaveNodeSubtree();
1835 }
1836 KoShape *styleDummy = new KoPathShape();
1837 applyCurrentBasicStyle(styleDummy);
1838 textLoader.setStyleInfo(styleDummy);
1839}
void leaveNodeSubtree()
Set the current node to its parent, leaving the subtree.
bool loadSvgText(const QDomText &text, SvgLoadingContext &context)
Loads the textt into the current node.
void setTextPathOnCurrentNode(KoShape *s)
Set the textPath on the current node.
void nextNode()
Switch to next node.
void enterNodeSubtree()
Set the current node to its first child, entering the subtree.
void setStyleInfo(KoShape *s)
Set the style info from the shape. This is necessary because SVGParser only understands loading the b...
bool loadSvg(const QDomElement &element, SvgLoadingContext &context, bool root=false)
Create a new text node.
KoShape * getTextPath(const QDomElement &e)
Get the path for the gives textPath element.
void parseTextChildren(const QDomElement &e, KoSvgTextLoader &textLoader)
parse children of a <text > element into the root shape.

References applyCurrentBasicStyle(), KoSvgTextLoader::enterNodeSubtree(), getTextPath(), getTheOnlyTextChild(), KoSvgTextLoader::leaveNodeSubtree(), KoSvgTextLoader::loadSvg(), KoSvgTextLoader::loadSvgText(), m_context, KoSvgTextLoader::nextNode(), parseTextChildren(), SvgLoadingContext::popGraphicsContext(), SvgLoadingContext::pushGraphicsContext(), KoSvgTextLoader::setStyleInfo(), KoSvgTextLoader::setTextPathOnCurrentNode(), and uploadStyleToContext().

◆ parseTextElement()

KoShape * SvgParser::parseTextElement ( const QDomElement & e,
KoSvgTextShape * mergeIntoShape = 0 )

Definition at line 1841 of file SvgParser.cpp.

1842{
1843 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(e.tagName() == "text" || e.tagName() == "tspan" || e.tagName() == "textPath", 0);
1845 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(e.tagName() == "text" || !mergeIntoShape, 0);
1846
1847 KoSvgTextShape *rootTextShape = 0;
1848
1849 if (mergeIntoShape) {
1850 rootTextShape = mergeIntoShape;
1851 } else {
1852 KoShapeFactoryBase *factory = KoShapeRegistry::instance()->value("KoSvgTextShapeID");
1853 rootTextShape = dynamic_cast<KoSvgTextShape*>(factory->createDefaultShape(m_documentResourceManager));
1854 }
1855 KoSvgTextLoader textLoader(rootTextShape);
1856
1857 if (rootTextShape) {
1858 m_isInsideTextSubtree = true;
1859 }
1860
1863
1864 if (rootTextShape) {
1865 if (!m_context.currentGC()->shapeInsideValue.isEmpty()) {
1867 rootTextShape->setShapesInside(shapesInside);
1868 }
1869
1870 if (!m_context.currentGC()->shapeSubtractValue.isEmpty()) {
1872 rootTextShape->setShapesSubtract(shapesSubtract);
1873 }
1874 }
1875
1876 if (e.hasAttribute("krita:textVersion")) {
1877 m_context.currentGC()->textProperties.setProperty(KoSvgTextProperties::KraTextVersionId, e.attribute("krita:textVersion", "1").toInt());
1878
1880 debugFlake << "WARNING: \"krita:textVersion\" attribute appeared in non-root text shape";
1881 }
1882 }
1883
1884 parseMetadataApplyToShape(e, rootTextShape);
1885
1886 if (!mergeIntoShape) {
1887 rootTextShape->setZIndex(m_context.nextZIndex());
1888 }
1889
1890
1893
1894 static const KoID warning("warn_text_version_1",
1895 i18nc("warning while loading SVG text",
1896 "The document has vector text created "
1897 "in Krita 4.x. When you save the document, "
1898 "the text object will be converted into "
1899 "Krita 5 format that will no longer be "
1900 "compatible with Krita 4.x"));
1901
1902 if (!m_warnings.contains(warning)) {
1903 m_warnings << warning;
1904 }
1905 }
1906
1907 textLoader.loadSvg(e, m_context, m_resolveTextPropertiesForTopLevel);
1908
1909 // 1) apply transformation only in case we are not overriding the shape!
1910 // 2) the transformation should be applied *before* the shape is added to the group!
1911 if (!mergeIntoShape) {
1912 // groups should also have their own coordinate system!
1914 const QPointF extraOffset = extraShapeOffset(rootTextShape, m_context.currentGC()->matrix);
1915
1916 // handle id
1917 applyId(e.attribute("id"), rootTextShape);
1918 applyCurrentStyle(rootTextShape, extraOffset); // apply style to this group after size is set
1919 } else {
1920 m_context.currentGC()->matrix = mergeIntoShape->absoluteTransformation();
1921 applyCurrentBasicStyle(rootTextShape);
1922 }
1923
1924 QDomText onlyTextChild = getTheOnlyTextChild(e);
1925 if (!onlyTextChild.isNull()) {
1926 textLoader.loadSvgText(onlyTextChild, m_context);
1927
1928 } else {
1929 parseTextChildren(e, textLoader);
1930
1931 }
1932
1934
1935 m_isInsideTextSubtree = false;
1936
1937 //rootTextShape->debugParsing();
1938 rootTextShape->relayout();
1939
1940
1941 return rootTextShape;
1942}
const T value(const QString &id) const
Definition KoID.h:30
@ KraTextVersionId
Int, used for handling incorrectly saved files.
QVariant property(PropertyId id, const QVariant &defaultValue=QVariant()) const
bool hasProperty(PropertyId id) const
void setProperty(PropertyId id, const QVariant &value)
void setShapesSubtract(QList< KoShape * > shapesSubtract)
setShapesSubtract
void setShapesInside(QList< KoShape * > shapesInside)
setShapesInside
void relayout() const
KoSvgTextProperties textProperties
Stores textProperties.
QString shapeSubtractValue
String of value shape-subtract, will be parsed later.
QString shapeInsideValue
String of value shape-inside, will be parsed later.
bool m_isInsideTextSubtree
Definition SvgParser.h:239
bool m_resolveTextPropertiesForTopLevel
Definition SvgParser.h:245
QVector< KoID > m_warnings
Definition SvgParser.h:242
QList< KoShape * > createListOfShapesFromCSS(const QDomElement e, const QString value, SvgLoadingContext &context)
Create a list of shapes from a CSS shapes definition with potentially multiple shapes.
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129

References KoShape::absoluteTransformation(), KoShape::applyAbsoluteTransformation(), applyCurrentBasicStyle(), applyCurrentStyle(), applyId(), KoShapeFactoryBase::createDefaultShape(), createListOfShapesFromCSS(), SvgLoadingContext::currentGC(), debugFlake, extraShapeOffset(), getTheOnlyTextChild(), KoSvgTextProperties::hasProperty(), KoShapeRegistry::instance(), KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE, KoSvgTextProperties::KraTextVersionId, KoSvgTextLoader::loadSvg(), KoSvgTextLoader::loadSvgText(), m_context, m_documentResourceManager, m_isInsideTextSubtree, m_resolveTextPropertiesForTopLevel, m_warnings, SvgGraphicsContext::matrix, SvgLoadingContext::nextZIndex(), parseMetadataApplyToShape(), parseTextChildren(), SvgLoadingContext::popGraphicsContext(), KoSvgTextProperties::property(), SvgLoadingContext::pushGraphicsContext(), KoSvgTextShape::relayout(), KoSvgTextProperties::setProperty(), KoSvgTextShape::setShapesInside(), KoSvgTextShape::setShapesSubtract(), KoShape::setZIndex(), SvgGraphicsContext::shapeInsideValue, SvgGraphicsContext::shapeSubtractValue, SvgGraphicsContext::textProperties, uploadStyleToContext(), and KoGenericRegistry< T >::value().

◆ parseUnit()

qreal SvgParser::parseUnit ( const QString & unit,
bool horiz = false,
bool vert = false,
const QRectF & bbox = QRectF() )
protected

parses a length attribute

Definition at line 313 of file SvgParser.cpp.

314{
315 return SvgUtil::parseUnit(m_context.currentGC(), m_context.resolvedProperties(), unit, horiz, vert, bbox);
316}
static qreal parseUnit(SvgGraphicsContext *gc, const KoSvgTextProperties &resolved, QStringView, bool horiz=false, bool vert=false, const QRectF &bbox=QRectF())
Parses a length attribute.
Definition SvgUtil.cpp:218

References SvgLoadingContext::currentGC(), m_context, SvgUtil::parseUnit(), and SvgLoadingContext::resolvedProperties().

◆ parseUnitX()

qreal SvgParser::parseUnitX ( const QString & unit)
protected

parses a length attribute in x-direction

Definition at line 318 of file SvgParser.cpp.

References SvgLoadingContext::currentGC(), m_context, SvgUtil::parseUnitX(), and SvgLoadingContext::resolvedProperties().

◆ parseUnitXY()

qreal SvgParser::parseUnitXY ( const QString & unit)
protected

parses a length attribute in xy-direction

Definition at line 328 of file SvgParser.cpp.

References SvgLoadingContext::currentGC(), m_context, SvgUtil::parseUnitXY(), and SvgLoadingContext::resolvedProperties().

◆ parseUnitY()

qreal SvgParser::parseUnitY ( const QString & unit)
protected

parses a length attribute in y-direction

Definition at line 323 of file SvgParser.cpp.

References SvgLoadingContext::currentGC(), m_context, SvgUtil::parseUnitY(), and SvgLoadingContext::resolvedProperties().

◆ parseUse()

KoShape * SvgParser::parseUse ( const QDomElement & e,
DeferredUseStore * deferredUseStore )
protected

Parses a use element, returning a list of child shapes.

Definition at line 1528 of file SvgParser.cpp.

1529{
1530 QString href = e.attribute("xlink:href");
1531 if (href.isEmpty())
1532 return 0;
1533
1534 QString key = href.mid(1);
1535 const bool gotDef = m_context.hasDefinition(key);
1536 if (gotDef) {
1537 return resolveUse(e, key);
1538 } else if (deferredUseStore) {
1539 deferredUseStore->add(&e, key);
1540 return 0;
1541 }
1542 debugFlake << "WARNING: Did not find reference for svg 'use' element. Skipping. Id: "
1543 << key;
1544 return 0;
1545}
KoShape * resolveUse(const QDomElement &e, const QString &key)

References SvgParser::DeferredUseStore::add(), debugFlake, SvgLoadingContext::hasDefinition(), m_context, and resolveUse().

◆ resolveUse()

KoShape * SvgParser::resolveUse ( const QDomElement & e,
const QString & key )
protected

Definition at line 1547 of file SvgParser.cpp.

1548{
1549 KoShape *result = 0;
1550
1552
1553 // TODO: parse 'width' and 'height' as well
1554 gc->matrix.translate(parseUnitX(e.attribute("x", "0")), parseUnitY(e.attribute("y", "0")));
1555
1556 const QDomElement &referencedElement = m_context.definition(key);
1557 result = parseGroup(e, referencedElement, false);
1558
1560 return result;
1561}

References SvgLoadingContext::definition(), m_context, SvgGraphicsContext::matrix, parseGroup(), parseUnitX(), parseUnitY(), SvgLoadingContext::popGraphicsContext(), and SvgLoadingContext::pushGraphicsContext().

◆ setDefaultKraTextVersion()

◆ setFileFetcher()

void SvgParser::setFileFetcher ( SvgParser::FileFetcherFunc func)

Definition at line 1715 of file SvgParser.cpp.

1716{
1718}
void setFileFetcher(FileFetcherFunc func)

References m_context, and SvgLoadingContext::setFileFetcher().

◆ setFillStrokeInheritByDefault()

void SvgParser::setFillStrokeInheritByDefault ( const bool enable)

Definition at line 206 of file SvgParser.cpp.

207{
209}

References m_inheritStrokeFillByDefault.

◆ setResolution()

void SvgParser::setResolution ( const QRectF boundsInPixels,
qreal pixelsPerInch )

◆ setResolveTextPropertiesForTopLevel()

void SvgParser::setResolveTextPropertiesForTopLevel ( const bool enable)

Definition at line 211 of file SvgParser.cpp.

212{
214}

References m_resolveTextPropertiesForTopLevel.

◆ setXmlBaseDir()

void SvgParser::setXmlBaseDir ( const QString & baseDir)

Sets the initial xml base directory (the directory form where the file is read)

Definition at line 167 of file SvgParser.cpp.

168{
170
172 [this](const QString &name) {
173 QStringList possibleNames;
174 possibleNames << name;
175 possibleNames << QDir::cleanPath(QDir(m_context.xmlBaseDir()).absoluteFilePath(name));
176 for (QString fileName : possibleNames) {
177 QFile file(fileName);
178 if (file.exists()) {
179 file.open(QIODevice::ReadOnly);
180 return file.readAll();
181 }
182 }
183 return QByteArray();
184 });
185}
void setInitialXmlBaseDir(const QString &baseDir)
Sets the initial xml base dir, i.e. the directory the svg file is read from.
void setFileFetcher(FileFetcherFunc func)
const char * name(StandardAction id)

References m_context, setFileFetcher(), SvgLoadingContext::setInitialXmlBaseDir(), and SvgLoadingContext::xmlBaseDir().

◆ shapes()

QList< KoShape * > SvgParser::shapes ( ) const

Returns the list of all shapes of the svg document.

Definition at line 216 of file SvgParser.cpp.

217{
218 return m_shapes;
219}

References m_shapes.

◆ takeSymbols()

QVector< KoSvgSymbol * > SvgParser::takeSymbols ( )

Takes the collection of symbols contained in the svg document. The parser will no longer know about the symbols.

Definition at line 221 of file SvgParser.cpp.

222{
223 QVector<KoSvgSymbol*> symbols = m_symbols.values().toVector();
224 m_symbols.clear();
225 return symbols;
226}

References m_symbols.

◆ uploadStyleToContext()

◆ warnings()

QStringList SvgParser::warnings ( ) const

Definition at line 1689 of file SvgParser.cpp.

1690{
1692
1693 Q_FOREACH (const KoID &id, m_warnings) {
1694 warnings << id.name();
1695 }
1696
1697 return warnings;
1698}
QStringList warnings() const

References m_warnings, and warnings().

Member Data Documentation

◆ m_clipMasks

QMap<QString, QSharedPointer<KoClipMask> > SvgParser::m_clipMasks
private

Definition at line 233 of file SvgParser.h.

◆ m_clipPaths

QMap<QString, SvgClipPathHelper> SvgParser::m_clipPaths
private

Definition at line 232 of file SvgParser.h.

◆ m_context

SvgLoadingContext SvgParser::m_context
private

Definition at line 229 of file SvgParser.h.

◆ m_defsShapes

QList<KoShape*> SvgParser::m_defsShapes
private

Definition at line 238 of file SvgParser.h.

◆ m_documentDescription

QString SvgParser::m_documentDescription
private

Definition at line 241 of file SvgParser.h.

◆ m_documentResourceManager

KoDocumentResourceManager* SvgParser::m_documentResourceManager
private

Definition at line 235 of file SvgParser.h.

◆ m_documentTitle

QString SvgParser::m_documentTitle
private

Definition at line 240 of file SvgParser.h.

◆ m_filters

QMap<QString, SvgFilterHelper> SvgParser::m_filters
private

Definition at line 231 of file SvgParser.h.

◆ m_gradients

QMap<QString, SvgGradientHelper> SvgParser::m_gradients
private

Definition at line 230 of file SvgParser.h.

◆ m_inheritStrokeFillByDefault

bool SvgParser::m_inheritStrokeFillByDefault = false
private

Definition at line 244 of file SvgParser.h.

◆ m_isInsideTextSubtree

bool SvgParser::m_isInsideTextSubtree = false
private

Definition at line 239 of file SvgParser.h.

◆ m_markers

QMap<QString, QExplicitlySharedDataPointer<KoMarker> > SvgParser::m_markers
private

Definition at line 234 of file SvgParser.h.

◆ m_resolveTextPropertiesForTopLevel

bool SvgParser::m_resolveTextPropertiesForTopLevel = true
private

Definition at line 245 of file SvgParser.h.

◆ m_shapeParentTransform

QMap<KoShape *, QTransform> SvgParser::m_shapeParentTransform
private

Definition at line 243 of file SvgParser.h.

◆ m_shapes

QList<KoShape*> SvgParser::m_shapes
private

Definition at line 236 of file SvgParser.h.

◆ m_symbols

QMap<QString, KoSvgSymbol*> SvgParser::m_symbols
private

Definition at line 237 of file SvgParser.h.

◆ m_warnings

QVector<KoID> SvgParser::m_warnings
private

Definition at line 242 of file SvgParser.h.


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