QGIS API Documentation 4.3.0-Master (3b7b3208a79)
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 "qgspainting.h"
28#include "qgsreadwritecontext.h"
30#include "qgssvgcache.h"
31#include "qgssymbol.h"
32#include "qgssymbollayerutils.h"
33
34#include <QGraphicsPathItem>
35#include <QString>
36#include <QSvgRenderer>
37#include <QVector2D>
38
39#include "moc_qgslayoutitempolyline.cpp"
40
41using namespace Qt::StringLiterals;
42
45{
46 createDefaultPolylineStyleSymbol();
47}
48
50 : QgsLayoutNodesItem( polyline, layout )
51{
52 createDefaultPolylineStyleSymbol();
53}
54
56
61
66
68{
69 return QgsApplication::getThemeIcon( u"/mLayoutItemPolyline.svg"_s );
70}
71
72bool QgsLayoutItemPolyline::_addNode( const int indexPoint, QPointF newPoint, const double radius )
73{
74 const double distStart = computeDistance( newPoint, mPolygon[0] );
75 const double distEnd = computeDistance( newPoint, mPolygon[mPolygon.size() - 1] );
76
77 if ( indexPoint == ( mPolygon.size() - 1 ) )
78 {
79 if ( distEnd < radius )
80 mPolygon.append( newPoint );
81 else if ( distStart < radius )
82 mPolygon.insert( 0, newPoint );
83 }
84 else
85 mPolygon.insert( indexPoint + 1, newPoint );
86
87 return true;
88}
89
91{
92 if ( index < 0 || index >= mPolygon.size() || mPolygon.size() <= 2 )
93 return false;
94
95 mPolygon.remove( index );
96
97 int newSelectNode = index;
98 if ( index >= mPolygon.size() )
99 newSelectNode = mPolygon.size() - 1;
100 setSelectedNode( newSelectNode );
101
102 return true;
103}
104
105void QgsLayoutItemPolyline::createDefaultPolylineStyleSymbol()
106{
107 QVariantMap properties;
108 properties.insert( u"color"_s, u"0,0,0,255"_s );
109 properties.insert( u"width"_s, u"0.3"_s );
110 properties.insert( u"capstyle"_s, u"square"_s );
111
112 mPolylineStyleSymbol = QgsLineSymbol::createSimple( properties );
113 refreshSymbol();
114}
115
116void QgsLayoutItemPolyline::refreshSymbol()
117{
118 if ( auto *lLayout = layout() )
119 {
120 const QgsRenderContext rc = QgsLayoutUtils::createRenderContextForLayout( lLayout, nullptr, lLayout->renderContext().dpi() );
121 mMaxSymbolBleed = ( 25.4 / lLayout->renderContext().dpi() ) * QgsSymbolLayerUtils::estimateMaxSymbolBleed( mPolylineStyleSymbol.get(), rc );
122 }
123
125
126 emit frameChanged();
127}
128
129void QgsLayoutItemPolyline::drawStartMarker( QPainter *painter )
130{
131 if ( mPolygon.size() < 2 )
132 return;
133
134 switch ( mStartMarker )
135 {
137 break;
138
140 {
141 // calculate angle at start of line
142 if ( mVersion == 2 )
143 {
144 const QLineF startLine( mPolygon.at( 1 ), mPolygon.at( 0 ) );
145 const double angle = startLine.angle();
146
147 // move start point depending on arrow width
148 const QVector2D dir = QVector2D( startLine.dx(), startLine.dy() ).normalized();
149 QPointF startPoint = startLine.p2();
150 startPoint += ( dir * 0.5 * mArrowHeadWidth ).toPointF();
151
152 drawArrow( painter, startPoint, angle );
153 }
154 else if ( mVersion == 1 )
155 {
156 const QLineF startLine( mPolygon.at( 0 ), mPolygon.at( 1 ) );
157 const double angle = startLine.angle();
158 drawArrow( painter, mPolygon.at( 0 ), angle );
159 }
160
161 break;
162 }
163
165 {
166 // calculate angle at start of line
167 QLineF startLine;
168 if ( mVersion == 2 )
169 {
170 startLine = QLineF( mPolygon.at( 1 ), mPolygon.at( 0 ) );
171 }
172 else if ( mVersion == 1 )
173 {
174 startLine = QLineF( mPolygon.at( 0 ), mPolygon.at( 1 ) );
175 }
176 const double angle = startLine.angle();
177 drawSvgMarker( painter, mPolygon.at( 0 ), angle, mStartMarkerFile, mStartArrowHeadHeight );
178 break;
179 }
180 }
181}
182
183void QgsLayoutItemPolyline::drawEndMarker( QPainter *painter )
184{
185 if ( mPolygon.size() < 2 )
186 return;
187
188 switch ( mEndMarker )
189 {
191 break;
192
194 {
195 // calculate angle at end of line
196 const QLineF endLine( mPolygon.at( mPolygon.count() - 2 ), mPolygon.at( mPolygon.count() - 1 ) );
197 const double angle = endLine.angle();
198
199 // move end point depending on arrow width
200 const QVector2D dir = QVector2D( endLine.dx(), endLine.dy() ).normalized();
201 QPointF endPoint = endLine.p2();
202 endPoint += ( dir * 0.5 * mArrowHeadWidth ).toPointF();
203
204 drawArrow( painter, endPoint, angle );
205 break;
206 }
208 {
209 // calculate angle at end of line
210 const QLineF endLine( mPolygon.at( mPolygon.count() - 2 ), mPolygon.at( mPolygon.count() - 1 ) );
211 const double angle = endLine.angle();
212 drawSvgMarker( painter, endLine.p2(), angle, mEndMarkerFile, mEndArrowHeadHeight );
213 break;
214 }
215 }
216}
217
218void QgsLayoutItemPolyline::drawArrow( QPainter *painter, QPointF center, double angle )
219{
220 // translate angle from ccw from axis to cw from north
221 angle = 90 - angle;
222 QPen p;
223 p.setColor( mArrowHeadStrokeColor );
224 p.setWidthF( mArrowHeadStrokeWidth );
225 painter->setPen( p );
226 QBrush b;
227 b.setColor( mArrowHeadFillColor );
228 painter->setBrush( b );
229
230 drawArrowHead( painter, center.x(), center.y(), angle, mArrowHeadWidth );
231}
232
233void QgsLayoutItemPolyline::updateMarkerSvgSizes()
234{
235 setStartSvgMarkerPath( mStartMarkerFile );
236 setEndSvgMarkerPath( mEndMarkerFile );
237}
238
239void QgsLayoutItemPolyline::drawArrowHead( QPainter *p, const double x, const double y, const double angle, const double arrowHeadWidth )
240{
241 if ( !p )
242 return;
243
244 const double angleRad = angle / 180.0 * M_PI;
245 const QPointF middlePoint( x, y );
246
247 //rotate both arrow points
248 const QPointF p1 = QPointF( -arrowHeadWidth / 2.0, arrowHeadWidth );
249 const QPointF p2 = QPointF( arrowHeadWidth / 2.0, arrowHeadWidth );
250
251 QPointF p1Rotated, p2Rotated;
252 p1Rotated.setX( p1.x() * std::cos( angleRad ) + p1.y() * -std::sin( angleRad ) );
253 p1Rotated.setY( p1.x() * std::sin( angleRad ) + p1.y() * std::cos( angleRad ) );
254 p2Rotated.setX( p2.x() * std::cos( angleRad ) + p2.y() * -std::sin( angleRad ) );
255 p2Rotated.setY( p2.x() * std::sin( angleRad ) + p2.y() * std::cos( angleRad ) );
256
257 QPolygonF arrowHeadPoly;
258 arrowHeadPoly << middlePoint;
259 arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
260 arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );
261 QPen arrowPen = p->pen();
262 arrowPen.setJoinStyle( Qt::RoundJoin );
263 QBrush arrowBrush = p->brush();
264 arrowBrush.setStyle( Qt::SolidPattern );
265 p->setPen( arrowPen );
266 p->setBrush( arrowBrush );
267 arrowBrush.setStyle( Qt::SolidPattern );
268 p->drawPolygon( arrowHeadPoly );
269}
270
271void QgsLayoutItemPolyline::drawSvgMarker( QPainter *p, QPointF point, double angle, const QString &markerPath, double height ) const
272{
273 // translate angle from ccw from axis to cw from north
274 angle = 90 - angle;
275
276 if ( mArrowHeadWidth <= 0 || height <= 0 )
277 {
278 //bad image size
279 return;
280 }
281
282 if ( markerPath.isEmpty() )
283 return;
284
285 QSvgRenderer r;
286 const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( markerPath, mArrowHeadWidth, mArrowHeadFillColor, mArrowHeadStrokeColor, mArrowHeadStrokeWidth, 1.0 );
287 r.load( svgContent );
288
289 const QgsScopedQPainterState painterState( p );
290 p->translate( point.x(), point.y() );
291 p->rotate( angle );
292 p->translate( -mArrowHeadWidth / 2.0, -height / 2.0 );
293 r.render( p, QRectF( 0, 0, mArrowHeadWidth, height ) );
294}
295
297{
298 if ( !id().isEmpty() )
299 return id();
300
301 return tr( "<Polyline>" );
302}
303
304void QgsLayoutItemPolyline::_draw( QgsLayoutItemRenderContext &context, const QStyleOptionGraphicsItem * )
305{
306 QgsRenderContext renderContext = context.renderContext();
307 // symbol clipping messes with geometry generators used in the symbol for this item, and has no
308 // valid use here. See https://github.com/qgis/QGIS/issues/58909
310
311 const QgsScopedQPainterState painterState( renderContext.painter() );
312 //setup painter scaling to dots so that raster symbology is drawn to scale
313 const double scale = renderContext.convertToPainterUnits( 1, Qgis::RenderUnit::Millimeters );
314 const QTransform t = QTransform::fromScale( scale, scale );
315
316 mPolylineStyleSymbol->startRender( renderContext );
317 mPolylineStyleSymbol->renderPolyline( t.map( mPolygon ), nullptr, renderContext );
318 mPolylineStyleSymbol->stopRender( renderContext );
319
320 // painter is scaled to dots, so scale back to layout units
321 renderContext.painter()->scale( renderContext.scaleFactor(), renderContext.scaleFactor() );
322
323 drawStartMarker( renderContext.painter() );
324 drawEndMarker( renderContext.painter() );
325}
326
327void QgsLayoutItemPolyline::_readXmlStyle( const QDomElement &elmt, const QgsReadWriteContext &context )
328{
329 mPolylineStyleSymbol = QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( elmt, context );
330}
331
333{
334 mPolylineStyleSymbol.reset( static_cast<QgsLineSymbol *>( symbol->clone() ) );
335 refreshSymbol();
336}
337
339{
340 mStartMarker = mode;
341 update();
342}
343
345{
346 mEndMarker = mode;
347 update();
348}
349
351{
352 mArrowHeadWidth = width;
353 updateMarkerSvgSizes();
354 update();
355}
356
358{
359 QPainterPath path;
360 path.addPolygon( mPolygon );
361
362 QPainterPathStroker ps;
363
364 ps.setWidth( 2 * mMaxSymbolBleed );
365 const QPainterPath strokedOutline = ps.createStroke( path );
366
367 return strokedOutline;
368}
369
371{
372 // A Polyline is valid if it has at least 2 unique points
373 QList<QPointF> uniquePoints;
374 int seen = 0;
375 for ( QPointF point : mPolygon )
376 {
377 if ( !uniquePoints.contains( point ) )
378 {
379 uniquePoints.append( point );
380 if ( ++seen > 1 )
381 return true;
382 }
383 }
384 return false;
385}
386
388{
389 return mPolylineStyleSymbol.get();
390}
391
393{
394 QSvgRenderer r;
395 mStartMarkerFile = path;
396 if ( path.isEmpty() || !r.load( path ) )
397 {
398 mStartArrowHeadHeight = 0;
399 }
400 else
401 {
402 //calculate mArrowHeadHeight from svg file and mArrowHeadWidth
403 const QRect viewBox = r.viewBox();
404 mStartArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
405 }
407}
408
410{
411 QSvgRenderer r;
412 mEndMarkerFile = path;
413 if ( path.isEmpty() || !r.load( path ) )
414 {
415 mEndArrowHeadHeight = 0;
416 }
417 else
418 {
419 //calculate mArrowHeadHeight from svg file and mArrowHeadWidth
420 const QRect viewBox = r.viewBox();
421 mEndArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
422 }
424}
425
427{
428 mArrowHeadStrokeColor = color;
429 update();
430}
431
433{
434 mArrowHeadFillColor = color;
435 update();
436}
437
439{
440 mArrowHeadStrokeWidth = width;
442 update();
443}
444
446{
447 if ( mPolylineStyleSymbol )
448 {
449 QgsStyleSymbolEntity entity( mPolylineStyleSymbol.get() );
450 if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, uuid(), displayName() ) ) )
451 return false;
452 }
453
454 return true;
455}
456
457void QgsLayoutItemPolyline::_writeXmlStyle( QDomDocument &doc, QDomElement &elmt, const QgsReadWriteContext &context ) const
458{
459 const QDomElement pe = QgsSymbolLayerUtils::saveSymbol( QString(), mPolylineStyleSymbol.get(), doc, context );
460 elmt.appendChild( pe );
461}
462
463bool QgsLayoutItemPolyline::writePropertiesToElement( QDomElement &elmt, QDomDocument &doc, const QgsReadWriteContext &context ) const
464{
466
467 // absolute paths to relative
468 const QString startMarkerPath = QgsSymbolLayerUtils::svgSymbolPathToName( mStartMarkerFile, context.pathResolver() );
469 const QString endMarkerPath = QgsSymbolLayerUtils::svgSymbolPathToName( mEndMarkerFile, context.pathResolver() );
470
471 elmt.setAttribute( u"arrowHeadWidth"_s, QString::number( mArrowHeadWidth ) );
472 elmt.setAttribute( u"arrowHeadFillColor"_s, QgsColorUtils::colorToString( mArrowHeadFillColor ) );
473 elmt.setAttribute( u"arrowHeadOutlineColor"_s, QgsColorUtils::colorToString( mArrowHeadStrokeColor ) );
474 elmt.setAttribute( u"outlineWidth"_s, QString::number( mArrowHeadStrokeWidth ) );
475 elmt.setAttribute( u"markerMode"_s, mEndMarker );
476 elmt.setAttribute( u"startMarkerMode"_s, mStartMarker );
477 elmt.setAttribute( u"startMarkerFile"_s, startMarkerPath );
478 elmt.setAttribute( u"endMarkerFile"_s, endMarkerPath );
479 elmt.setAttribute( u"version"_s, mVersion );
480
481 return true;
482}
483
484bool QgsLayoutItemPolyline::readPropertiesFromElement( const QDomElement &elmt, const QDomDocument &doc, const QgsReadWriteContext &context )
485{
486 mArrowHeadWidth = elmt.attribute( u"arrowHeadWidth"_s, u"2.0"_s ).toDouble();
487 mArrowHeadFillColor = QgsColorUtils::colorFromString( elmt.attribute( u"arrowHeadFillColor"_s, u"0,0,0,255"_s ) );
488 mArrowHeadStrokeColor = QgsColorUtils::colorFromString( elmt.attribute( u"arrowHeadOutlineColor"_s, u"0,0,0,255"_s ) );
489 mArrowHeadStrokeWidth = elmt.attribute( u"outlineWidth"_s, u"1.0"_s ).toDouble();
490 // relative paths to absolute
491 const QString startMarkerPath = elmt.attribute( u"startMarkerFile"_s, QString() );
492 const QString endMarkerPath = elmt.attribute( u"endMarkerFile"_s, QString() );
495 mEndMarker = static_cast< QgsLayoutItemPolyline::MarkerMode >( elmt.attribute( u"markerMode"_s, u"0"_s ).toInt() );
496 mStartMarker = static_cast< QgsLayoutItemPolyline::MarkerMode >( elmt.attribute( u"startMarkerMode"_s, u"0"_s ).toInt() );
497 mVersion = elmt.attribute( u"version"_s, u"1"_s ).toInt();
498
500
502 return true;
503}
504
506{
507 QRectF br = rect();
508
509 double margin = std::max( mMaxSymbolBleed, computeMarkerMargin() );
510 if ( mEndMarker == ArrowHead )
511 {
512 margin += 0.5 * mArrowHeadWidth;
513 }
514 br.adjust( -margin, -margin, margin, margin );
515 prepareGeometryChange();
517
518 // update
519 update();
520}
521
522
523double QgsLayoutItemPolyline::computeMarkerMargin() const
524{
525 double margin = 0;
526
527 if ( mStartMarker == ArrowHead || mEndMarker == ArrowHead )
528 {
529 margin = mArrowHeadStrokeWidth / 2.0 + mArrowHeadWidth * M_SQRT2;
530 }
531
532 if ( mStartMarker == SvgMarker )
533 {
534 const double startMarkerMargin = std::sqrt( 0.25 * ( mStartArrowHeadHeight * mStartArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
535 margin = std::max( startMarkerMargin, margin );
536 }
537
538 if ( mEndMarker == SvgMarker )
539 {
540 const double endMarkerMargin = std::sqrt( 0.25 * ( mEndArrowHeadHeight * mEndArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
541 margin = std::max( endMarkerMargin, margin );
542 }
543
544 return margin;
545}
@ Millimeters
Millimeters.
Definition qgis.h:5759
@ DisableSymbolClippingToExtent
Force symbol clipping to map extent to be disabled in all situations. This will result in slower rend...
Definition qgis.h:2986
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.