QGIS API Documentation 4.3.0-Master (bf28115e945)
Loading...
Searching...
No Matches
qgslayoutitempolyline.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayoutitempolyline.cpp
3 begin : March 2016
4 copyright : (C) 2016 Paul Blottiere, Oslandia
5 email : paul dot blottiere at oslandia dot com
6 ***************************************************************************/
7
8/***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
18
19#include <limits>
20
21#include "qgscolorutils.h"
22#include "qgslayout.h"
25#include "qgslayoututils.h"
26#include "qgslinesymbol.h"
27#include "qgsreadwritecontext.h"
29#include "qgssvgcache.h"
30#include "qgssymbol.h"
31#include "qgssymbollayerutils.h"
32
33#include <QGraphicsPathItem>
34#include <QString>
35#include <QSvgRenderer>
36#include <QVector2D>
37
38#include "moc_qgslayoutitempolyline.cpp"
39
40using namespace Qt::StringLiterals;
41
44{
45 createDefaultPolylineStyleSymbol();
46}
47
49 : QgsLayoutNodesItem( polyline, layout )
50{
51 createDefaultPolylineStyleSymbol();
52}
53
55
60
65
67{
68 return QgsApplication::getThemeIcon( u"/mLayoutItemPolyline.svg"_s );
69}
70
71bool QgsLayoutItemPolyline::_addNode( const int indexPoint, QPointF newPoint, const double radius )
72{
73 const double distStart = computeDistance( newPoint, mPolygon[0] );
74 const double distEnd = computeDistance( newPoint, mPolygon[mPolygon.size() - 1] );
75
76 if ( indexPoint == ( mPolygon.size() - 1 ) )
77 {
78 if ( distEnd < radius )
79 mPolygon.append( newPoint );
80 else if ( distStart < radius )
81 mPolygon.insert( 0, newPoint );
82 }
83 else
84 mPolygon.insert( indexPoint + 1, newPoint );
85
86 return true;
87}
88
90{
91 if ( index < 0 || index >= mPolygon.size() || mPolygon.size() <= 2 )
92 return false;
93
94 mPolygon.remove( index );
95
96 int newSelectNode = index;
97 if ( index >= mPolygon.size() )
98 newSelectNode = mPolygon.size() - 1;
99 setSelectedNode( newSelectNode );
100
101 return true;
102}
103
104void QgsLayoutItemPolyline::createDefaultPolylineStyleSymbol()
105{
106 QVariantMap properties;
107 properties.insert( u"color"_s, u"0,0,0,255"_s );
108 properties.insert( u"width"_s, u"0.3"_s );
109 properties.insert( u"capstyle"_s, u"square"_s );
110
111 mPolylineStyleSymbol = QgsLineSymbol::createSimple( properties );
112 refreshSymbol();
113}
114
115void QgsLayoutItemPolyline::refreshSymbol()
116{
117 if ( auto *lLayout = layout() )
118 {
119 const QgsRenderContext rc = QgsLayoutUtils::createRenderContextForLayout( lLayout, nullptr, lLayout->renderContext().dpi() );
120 mMaxSymbolBleed = ( 25.4 / lLayout->renderContext().dpi() ) * QgsSymbolLayerUtils::estimateMaxSymbolBleed( mPolylineStyleSymbol.get(), rc );
121 }
122
124
125 emit frameChanged();
126}
127
128void QgsLayoutItemPolyline::drawStartMarker( QPainter *painter )
129{
130 if ( mPolygon.size() < 2 )
131 return;
132
133 switch ( mStartMarker )
134 {
136 break;
137
139 {
140 // calculate angle at start of line
141 if ( mVersion == 2 )
142 {
143 const QLineF startLine( mPolygon.at( 1 ), mPolygon.at( 0 ) );
144 const double angle = startLine.angle();
145
146 // move start point depending on arrow width
147 const QVector2D dir = QVector2D( startLine.dx(), startLine.dy() ).normalized();
148 QPointF startPoint = startLine.p2();
149 startPoint += ( dir * 0.5 * mArrowHeadWidth ).toPointF();
150
151 drawArrow( painter, startPoint, angle );
152 }
153 else if ( mVersion == 1 )
154 {
155 const QLineF startLine( mPolygon.at( 0 ), mPolygon.at( 1 ) );
156 const double angle = startLine.angle();
157 drawArrow( painter, mPolygon.at( 0 ), angle );
158 }
159
160 break;
161 }
162
164 {
165 // calculate angle at start of line
166 QLineF startLine;
167 if ( mVersion == 2 )
168 {
169 startLine = QLineF( mPolygon.at( 1 ), mPolygon.at( 0 ) );
170 }
171 else if ( mVersion == 1 )
172 {
173 startLine = QLineF( mPolygon.at( 0 ), mPolygon.at( 1 ) );
174 }
175 const double angle = startLine.angle();
176 drawSvgMarker( painter, mPolygon.at( 0 ), angle, mStartMarkerFile, mStartArrowHeadHeight );
177 break;
178 }
179 }
180}
181
182void QgsLayoutItemPolyline::drawEndMarker( QPainter *painter )
183{
184 if ( mPolygon.size() < 2 )
185 return;
186
187 switch ( mEndMarker )
188 {
190 break;
191
193 {
194 // calculate angle at end of line
195 const QLineF endLine( mPolygon.at( mPolygon.count() - 2 ), mPolygon.at( mPolygon.count() - 1 ) );
196 const double angle = endLine.angle();
197
198 // move end point depending on arrow width
199 const QVector2D dir = QVector2D( endLine.dx(), endLine.dy() ).normalized();
200 QPointF endPoint = endLine.p2();
201 endPoint += ( dir * 0.5 * mArrowHeadWidth ).toPointF();
202
203 drawArrow( painter, endPoint, angle );
204 break;
205 }
207 {
208 // calculate angle at end of line
209 const QLineF endLine( mPolygon.at( mPolygon.count() - 2 ), mPolygon.at( mPolygon.count() - 1 ) );
210 const double angle = endLine.angle();
211 drawSvgMarker( painter, endLine.p2(), angle, mEndMarkerFile, mEndArrowHeadHeight );
212 break;
213 }
214 }
215}
216
217void QgsLayoutItemPolyline::drawArrow( QPainter *painter, QPointF center, double angle )
218{
219 // translate angle from ccw from axis to cw from north
220 angle = 90 - angle;
221 QPen p;
222 p.setColor( mArrowHeadStrokeColor );
223 p.setWidthF( mArrowHeadStrokeWidth );
224 painter->setPen( p );
225 QBrush b;
226 b.setColor( mArrowHeadFillColor );
227 painter->setBrush( b );
228
229 drawArrowHead( painter, center.x(), center.y(), angle, mArrowHeadWidth );
230}
231
232void QgsLayoutItemPolyline::updateMarkerSvgSizes()
233{
234 setStartSvgMarkerPath( mStartMarkerFile );
235 setEndSvgMarkerPath( mEndMarkerFile );
236}
237
238void QgsLayoutItemPolyline::drawArrowHead( QPainter *p, const double x, const double y, const double angle, const double arrowHeadWidth )
239{
240 if ( !p )
241 return;
242
243 const double angleRad = angle / 180.0 * M_PI;
244 const QPointF middlePoint( x, y );
245
246 //rotate both arrow points
247 const QPointF p1 = QPointF( -arrowHeadWidth / 2.0, arrowHeadWidth );
248 const QPointF p2 = QPointF( arrowHeadWidth / 2.0, arrowHeadWidth );
249
250 QPointF p1Rotated, p2Rotated;
251 p1Rotated.setX( p1.x() * std::cos( angleRad ) + p1.y() * -std::sin( angleRad ) );
252 p1Rotated.setY( p1.x() * std::sin( angleRad ) + p1.y() * std::cos( angleRad ) );
253 p2Rotated.setX( p2.x() * std::cos( angleRad ) + p2.y() * -std::sin( angleRad ) );
254 p2Rotated.setY( p2.x() * std::sin( angleRad ) + p2.y() * std::cos( angleRad ) );
255
256 QPolygonF arrowHeadPoly;
257 arrowHeadPoly << middlePoint;
258 arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
259 arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );
260 QPen arrowPen = p->pen();
261 arrowPen.setJoinStyle( Qt::RoundJoin );
262 QBrush arrowBrush = p->brush();
263 arrowBrush.setStyle( Qt::SolidPattern );
264 p->setPen( arrowPen );
265 p->setBrush( arrowBrush );
266 arrowBrush.setStyle( Qt::SolidPattern );
267 p->drawPolygon( arrowHeadPoly );
268}
269
270void QgsLayoutItemPolyline::drawSvgMarker( QPainter *p, QPointF point, double angle, const QString &markerPath, double height ) const
271{
272 // translate angle from ccw from axis to cw from north
273 angle = 90 - angle;
274
275 if ( mArrowHeadWidth <= 0 || height <= 0 )
276 {
277 //bad image size
278 return;
279 }
280
281 if ( markerPath.isEmpty() )
282 return;
283
284 QSvgRenderer r;
285 const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( markerPath, mArrowHeadWidth, mArrowHeadFillColor, mArrowHeadStrokeColor, mArrowHeadStrokeWidth, 1.0 );
286 r.load( svgContent );
287
288 const QgsScopedQPainterState painterState( p );
289 p->translate( point.x(), point.y() );
290 p->rotate( angle );
291 p->translate( -mArrowHeadWidth / 2.0, -height / 2.0 );
292 r.render( p, QRectF( 0, 0, mArrowHeadWidth, height ) );
293}
294
296{
297 if ( !id().isEmpty() )
298 return id();
299
300 return tr( "<Polyline>" );
301}
302
303void QgsLayoutItemPolyline::_draw( QgsLayoutItemRenderContext &context, const QStyleOptionGraphicsItem * )
304{
305 QgsRenderContext renderContext = context.renderContext();
306 // symbol clipping messes with geometry generators used in the symbol for this item, and has no
307 // valid use here. See https://github.com/qgis/QGIS/issues/58909
309
310 const QgsScopedQPainterState painterState( renderContext.painter() );
311 //setup painter scaling to dots so that raster symbology is drawn to scale
312 const double scale = renderContext.convertToPainterUnits( 1, Qgis::RenderUnit::Millimeters );
313 const QTransform t = QTransform::fromScale( scale, scale );
314
315 mPolylineStyleSymbol->startRender( renderContext );
316 mPolylineStyleSymbol->renderPolyline( t.map( mPolygon ), nullptr, renderContext );
317 mPolylineStyleSymbol->stopRender( renderContext );
318
319 // painter is scaled to dots, so scale back to layout units
320 renderContext.painter()->scale( renderContext.scaleFactor(), renderContext.scaleFactor() );
321
322 drawStartMarker( renderContext.painter() );
323 drawEndMarker( renderContext.painter() );
324}
325
326void QgsLayoutItemPolyline::_readXmlStyle( const QDomElement &elmt, const QgsReadWriteContext &context )
327{
328 mPolylineStyleSymbol = QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( elmt, context );
329}
330
332{
333 mPolylineStyleSymbol.reset( static_cast<QgsLineSymbol *>( symbol->clone() ) );
334 refreshSymbol();
335}
336
338{
339 mStartMarker = mode;
340 update();
341}
342
344{
345 mEndMarker = mode;
346 update();
347}
348
350{
351 mArrowHeadWidth = width;
352 updateMarkerSvgSizes();
353 update();
354}
355
357{
358 QPainterPath path;
359 path.addPolygon( mPolygon );
360
361 QPainterPathStroker ps;
362
363 ps.setWidth( 2 * mMaxSymbolBleed );
364 const QPainterPath strokedOutline = ps.createStroke( path );
365
366 return strokedOutline;
367}
368
370{
371 // A Polyline is valid if it has at least 2 unique points
372 QList<QPointF> uniquePoints;
373 int seen = 0;
374 for ( QPointF point : mPolygon )
375 {
376 if ( !uniquePoints.contains( point ) )
377 {
378 uniquePoints.append( point );
379 if ( ++seen > 1 )
380 return true;
381 }
382 }
383 return false;
384}
385
387{
388 return mPolylineStyleSymbol.get();
389}
390
392{
393 QSvgRenderer r;
394 mStartMarkerFile = path;
395 if ( path.isEmpty() || !r.load( path ) )
396 {
397 mStartArrowHeadHeight = 0;
398 }
399 else
400 {
401 //calculate mArrowHeadHeight from svg file and mArrowHeadWidth
402 const QRect viewBox = r.viewBox();
403 mStartArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
404 }
406}
407
409{
410 QSvgRenderer r;
411 mEndMarkerFile = path;
412 if ( path.isEmpty() || !r.load( path ) )
413 {
414 mEndArrowHeadHeight = 0;
415 }
416 else
417 {
418 //calculate mArrowHeadHeight from svg file and mArrowHeadWidth
419 const QRect viewBox = r.viewBox();
420 mEndArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
421 }
423}
424
426{
427 mArrowHeadStrokeColor = color;
428 update();
429}
430
432{
433 mArrowHeadFillColor = color;
434 update();
435}
436
438{
439 mArrowHeadStrokeWidth = width;
441 update();
442}
443
445{
446 if ( mPolylineStyleSymbol )
447 {
448 QgsStyleSymbolEntity entity( mPolylineStyleSymbol.get() );
449 if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, uuid(), displayName() ) ) )
450 return false;
451 }
452
453 return true;
454}
455
456void QgsLayoutItemPolyline::_writeXmlStyle( QDomDocument &doc, QDomElement &elmt, const QgsReadWriteContext &context ) const
457{
458 const QDomElement pe = QgsSymbolLayerUtils::saveSymbol( QString(), mPolylineStyleSymbol.get(), doc, context );
459 elmt.appendChild( pe );
460}
461
462bool QgsLayoutItemPolyline::writePropertiesToElement( QDomElement &elmt, QDomDocument &doc, const QgsReadWriteContext &context ) const
463{
465
466 // absolute paths to relative
467 const QString startMarkerPath = QgsSymbolLayerUtils::svgSymbolPathToName( mStartMarkerFile, context.pathResolver() );
468 const QString endMarkerPath = QgsSymbolLayerUtils::svgSymbolPathToName( mEndMarkerFile, context.pathResolver() );
469
470 elmt.setAttribute( u"arrowHeadWidth"_s, QString::number( mArrowHeadWidth ) );
471 elmt.setAttribute( u"arrowHeadFillColor"_s, QgsColorUtils::colorToString( mArrowHeadFillColor ) );
472 elmt.setAttribute( u"arrowHeadOutlineColor"_s, QgsColorUtils::colorToString( mArrowHeadStrokeColor ) );
473 elmt.setAttribute( u"outlineWidth"_s, QString::number( mArrowHeadStrokeWidth ) );
474 elmt.setAttribute( u"markerMode"_s, mEndMarker );
475 elmt.setAttribute( u"startMarkerMode"_s, mStartMarker );
476 elmt.setAttribute( u"startMarkerFile"_s, startMarkerPath );
477 elmt.setAttribute( u"endMarkerFile"_s, endMarkerPath );
478 elmt.setAttribute( u"version"_s, mVersion );
479
480 return true;
481}
482
483bool QgsLayoutItemPolyline::readPropertiesFromElement( const QDomElement &elmt, const QDomDocument &doc, const QgsReadWriteContext &context )
484{
485 mArrowHeadWidth = elmt.attribute( u"arrowHeadWidth"_s, u"2.0"_s ).toDouble();
486 mArrowHeadFillColor = QgsColorUtils::colorFromString( elmt.attribute( u"arrowHeadFillColor"_s, u"0,0,0,255"_s ) );
487 mArrowHeadStrokeColor = QgsColorUtils::colorFromString( elmt.attribute( u"arrowHeadOutlineColor"_s, u"0,0,0,255"_s ) );
488 mArrowHeadStrokeWidth = elmt.attribute( u"outlineWidth"_s, u"1.0"_s ).toDouble();
489 // relative paths to absolute
490 const QString startMarkerPath = elmt.attribute( u"startMarkerFile"_s, QString() );
491 const QString endMarkerPath = elmt.attribute( u"endMarkerFile"_s, QString() );
494 mEndMarker = static_cast< QgsLayoutItemPolyline::MarkerMode >( elmt.attribute( u"markerMode"_s, u"0"_s ).toInt() );
495 mStartMarker = static_cast< QgsLayoutItemPolyline::MarkerMode >( elmt.attribute( u"startMarkerMode"_s, u"0"_s ).toInt() );
496 mVersion = elmt.attribute( u"version"_s, u"1"_s ).toInt();
497
499
501 return true;
502}
503
505{
506 QRectF br = rect();
507
508 double margin = std::max( mMaxSymbolBleed, computeMarkerMargin() );
509 if ( mEndMarker == ArrowHead )
510 {
511 margin += 0.5 * mArrowHeadWidth;
512 }
513 br.adjust( -margin, -margin, margin, margin );
514 prepareGeometryChange();
516
517 // update
518 update();
519}
520
521
522double QgsLayoutItemPolyline::computeMarkerMargin() const
523{
524 double margin = 0;
525
526 if ( mStartMarker == ArrowHead || mEndMarker == ArrowHead )
527 {
528 margin = mArrowHeadStrokeWidth / 2.0 + mArrowHeadWidth * M_SQRT2;
529 }
530
531 if ( mStartMarker == SvgMarker )
532 {
533 const double startMarkerMargin = std::sqrt( 0.25 * ( mStartArrowHeadHeight * mStartArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
534 margin = std::max( startMarkerMargin, margin );
535 }
536
537 if ( mEndMarker == SvgMarker )
538 {
539 const double endMarkerMargin = std::sqrt( 0.25 * ( mEndArrowHeadHeight * mEndArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
540 margin = std::max( endMarkerMargin, margin );
541 }
542
543 return margin;
544}
@ Millimeters
Millimeters.
Definition qgis.h:5635
@ DisableSymbolClippingToExtent
Force symbol clipping to map extent to be disabled in all situations. This will result in slower rend...
Definition qgis.h:2948
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
bool isValid() const override
Must be reimplemented in subclasses.
void setArrowHeadWidth(double width)
Sets the width of line arrow heads in mm.
void setEndMarker(MarkerMode mode)
Sets the end marker mode, which controls what marker is drawn at the end of the line.
void setEndSvgMarkerPath(const QString &path)
Sets the path to a SVG marker to draw at the end of the line.
void _writeXmlStyle(QDomDocument &doc, QDomElement &elmt, const QgsReadWriteContext &context) const override
Method called in writeXml.
void setArrowHeadStrokeWidth(double width)
Sets the pen width in millimeters for the stroke of the arrow head.
void _readXmlStyle(const QDomElement &elmt, const QgsReadWriteContext &context) override
Method called in readXml.
void setArrowHeadFillColor(const QColor &color)
Sets the color used to fill the arrow head.
bool _removeNode(int nodeIndex) override
Method called in removeNode.
QgsLineSymbol * symbol()
Returns the line symbol used to draw the shape.
void setArrowHeadStrokeColor(const QColor &color)
Sets the color used to draw the stroke around the arrow head.
void setStartMarker(MarkerMode mode)
Sets the start marker mode, which controls what marker is drawn at the start of the line.
MarkerMode
Vertex marker mode.
@ ArrowHead
Show arrow marker.
@ NoMarker
Don't show marker.
QPainterPath shape() const override
~QgsLayoutItemPolyline() override
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
QString displayName() const override
Gets item display name.
static QgsLayoutItemPolyline * create(QgsLayout *layout)
Returns a new polyline item for the specified layout.
bool _addNode(int indexPoint, QPointF newPoint, double radius) override
Method called in addNode.
void setSymbol(QgsLineSymbol *symbol)
Sets the symbol used to draw the shape.
QIcon icon() const override
Returns the item's icon.
double arrowHeadWidth() const
Returns the width of line arrow heads in mm.
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
void _draw(QgsLayoutItemRenderContext &context, const QStyleOptionGraphicsItem *itemStyle=nullptr) override
Method called in paint.
void setStartSvgMarkerPath(const QString &path)
Sets the path to a SVG marker to draw at the start of the line.
QgsLayoutItemPolyline(QgsLayout *layout)
Constructor for QgsLayoutItemPolyline for the specified layout.
@ LayoutPolyline
Polyline shape item.
Contains settings and helpers relating to a render of a QgsLayoutItem.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
friend class QgsLayout
virtual QString uuid() const
Returns the item identification string.
QString id() const
Returns the item's ID name.
void frameChanged()
Emitted if the item's frame style changes.
double mMaxSymbolBleed
Max symbol bleed.
QRectF mCurrentRectangle
Current bounding rectangle of shape.
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
bool setSelectedNode(int index)
Selects a node by index.
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
void updateSceneRect()
Update the current scene rectangle for this item.
double computeDistance(QPointF pt1, QPointF pt2) const
Compute an euclidean distance between 2 nodes.
QgsLayoutNodesItem(QgsLayout *layout)
Constructor for QgsLayoutNodesItem, attached to the specified layout.
QPolygonF mPolygon
Shape's nodes.
const QgsLayout * layout() const
Returns the layout the object is attached to.
static QgsRenderContext createRenderContextForLayout(QgsLayout *layout, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout and painter destination.
A line symbol type, for rendering LineString and MultiLineString geometries.
static std::unique_ptr< QgsLineSymbol > createSimple(const QVariantMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties.
A container for the context for various read/write operations on objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
Contains information about the context of a rendering operation.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected).
Scoped object for saving and restoring a QPainter object's state.
An interface for classes which can visit style entity (e.g.
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
A symbol entity for QgsStyle databases.
Definition qgsstyle.h:1462
QByteArray svgContent(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, double fixedAspectRatio=0, bool blocking=false, const QMap< QString, QString > &parameters=QMap< QString, QString >(), bool *isMissingImage=nullptr)
Gets the SVG content corresponding to the given path.
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored).
Contains information relating to the style entity currently being visited.