QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 
17 #include "qgslayoutitempolyline.h"
18 #include "qgslayoutitemregistry.h"
19 #include "qgssymbollayerutils.h"
20 #include "qgssymbol.h"
21 #include "qgslayout.h"
22 #include "qgsmapsettings.h"
23 #include "qgslayoututils.h"
24 #include "qgsreadwritecontext.h"
25 #include "qgssvgcache.h"
26 #include "qgsstyleentityvisitor.h"
27 #include "qgslinesymbol.h"
28 
29 #include <QSvgRenderer>
30 #include <limits>
31 #include <QGraphicsPathItem>
32 #include <QVector2D>
33 
35  : QgsLayoutNodesItem( layout )
36 {
37  createDefaultPolylineStyleSymbol();
38 }
39 
40 QgsLayoutItemPolyline::QgsLayoutItemPolyline( const QPolygonF &polyline, QgsLayout *layout )
41  : QgsLayoutNodesItem( polyline, layout )
42 {
43  createDefaultPolylineStyleSymbol();
44 }
45 
47 
49 {
50  return new QgsLayoutItemPolyline( layout );
51 }
52 
54 {
56 }
57 
59 {
60  return QgsApplication::getThemeIcon( QStringLiteral( "/mLayoutItemPolyline.svg" ) );
61 }
62 
63 bool QgsLayoutItemPolyline::_addNode( const int indexPoint,
64  QPointF newPoint,
65  const double radius )
66 {
67  const double distStart = computeDistance( newPoint, mPolygon[0] );
68  const double distEnd = computeDistance( newPoint, mPolygon[mPolygon.size() - 1] );
69 
70  if ( indexPoint == ( mPolygon.size() - 1 ) )
71  {
72  if ( distEnd < radius )
73  mPolygon.append( newPoint );
74  else if ( distStart < radius )
75  mPolygon.insert( 0, newPoint );
76  }
77  else
78  mPolygon.insert( indexPoint + 1, newPoint );
79 
80  return true;
81 }
82 
83 bool QgsLayoutItemPolyline::_removeNode( const int index )
84 {
85  if ( index < 0 || index >= mPolygon.size() )
86  return false;
87 
88  mPolygon.remove( index );
89 
90  if ( mPolygon.size() < 2 )
91  mPolygon.clear();
92  else
93  {
94  int newSelectNode = index;
95  if ( index >= mPolygon.size() )
96  newSelectNode = mPolygon.size() - 1;
97  setSelectedNode( newSelectNode );
98  }
99 
100  return true;
101 }
102 
103 void QgsLayoutItemPolyline::createDefaultPolylineStyleSymbol()
104 {
105  QVariantMap properties;
106  properties.insert( QStringLiteral( "color" ), QStringLiteral( "0,0,0,255" ) );
107  properties.insert( QStringLiteral( "width" ), QStringLiteral( "0.3" ) );
108  properties.insert( QStringLiteral( "capstyle" ), QStringLiteral( "square" ) );
109 
110  mPolylineStyleSymbol.reset( QgsLineSymbol::createSimple( properties ) );
111  refreshSymbol();
112 }
113 
114 void QgsLayoutItemPolyline::refreshSymbol()
115 {
116  if ( auto *lLayout = layout() )
117  {
118  QgsRenderContext rc = QgsLayoutUtils::createRenderContextForLayout( lLayout, nullptr, lLayout->renderContext().dpi() );
119  mMaxSymbolBleed = ( 25.4 / lLayout->renderContext().dpi() ) * QgsSymbolLayerUtils::estimateMaxSymbolBleed( mPolylineStyleSymbol.get(), rc );
120  }
121 
122  updateSceneRect();
123 
124  emit frameChanged();
125 }
126 
127 void QgsLayoutItemPolyline::drawStartMarker( QPainter *painter )
128 {
129  if ( mPolygon.size() < 2 )
130  return;
131 
132  switch ( mStartMarker )
133  {
134  case MarkerMode::NoMarker:
135  break;
136 
137  case MarkerMode::ArrowHead:
138  {
139  // calculate angle at start of line
140  QLineF startLine( mPolygon.at( 0 ), mPolygon.at( 1 ) );
141  double angle = startLine.angle();
142  drawArrow( painter, mPolygon.at( 0 ), angle );
143  break;
144  }
145 
146  case MarkerMode::SvgMarker:
147  {
148  // calculate angle at start of line
149  QLineF startLine( mPolygon.at( 0 ), mPolygon.at( 1 ) );
150  double angle = startLine.angle();
151  drawSvgMarker( painter, mPolygon.at( 0 ), angle, mStartMarkerFile, mStartArrowHeadHeight );
152  break;
153  }
154  }
155 
156 }
157 
158 void QgsLayoutItemPolyline::drawEndMarker( QPainter *painter )
159 {
160  if ( mPolygon.size() < 2 )
161  return;
162 
163  switch ( mEndMarker )
164  {
165  case MarkerMode::NoMarker:
166  break;
167 
168  case MarkerMode::ArrowHead:
169  {
170  // calculate angle at end of line
171  QLineF endLine( mPolygon.at( mPolygon.count() - 2 ), mPolygon.at( mPolygon.count() - 1 ) );
172  double angle = endLine.angle();
173 
174  //move end point depending on arrow width
175  QVector2D dir = QVector2D( endLine.dx(), endLine.dy() ).normalized();
176  QPointF endPoint = endLine.p2();
177  endPoint += ( dir * 0.5 * mArrowHeadWidth ).toPointF();
178 
179  drawArrow( painter, endPoint, angle );
180  break;
181  }
182  case MarkerMode::SvgMarker:
183  {
184  // calculate angle at end of line
185  QLineF endLine( mPolygon.at( mPolygon.count() - 2 ), mPolygon.at( mPolygon.count() - 1 ) );
186  double angle = endLine.angle();
187  drawSvgMarker( painter, endLine.p2(), angle, mEndMarkerFile, mEndArrowHeadHeight );
188  break;
189  }
190  }
191 }
192 
193 void QgsLayoutItemPolyline::drawArrow( QPainter *painter, QPointF center, double angle )
194 {
195  // translate angle from ccw from axis to cw from north
196  angle = 90 - angle;
197  QPen p;
198  p.setColor( mArrowHeadStrokeColor );
199  p.setWidthF( mArrowHeadStrokeWidth );
200  painter->setPen( p );
201  QBrush b;
202  b.setColor( mArrowHeadFillColor );
203  painter->setBrush( b );
204 
205  drawArrowHead( painter, center.x(), center.y(), angle, mArrowHeadWidth );
206 }
207 
208 void QgsLayoutItemPolyline::updateMarkerSvgSizes()
209 {
210  setStartSvgMarkerPath( mStartMarkerFile );
211  setEndSvgMarkerPath( mEndMarkerFile );
212 }
213 
214 void QgsLayoutItemPolyline::drawArrowHead( QPainter *p, const double x, const double y, const double angle, const double arrowHeadWidth )
215 {
216  if ( !p )
217  return;
218 
219  double angleRad = angle / 180.0 * M_PI;
220  QPointF middlePoint( x, y );
221 
222  //rotate both arrow points
223  QPointF p1 = QPointF( -arrowHeadWidth / 2.0, arrowHeadWidth );
224  QPointF p2 = QPointF( arrowHeadWidth / 2.0, arrowHeadWidth );
225 
226  QPointF p1Rotated, p2Rotated;
227  p1Rotated.setX( p1.x() * std::cos( angleRad ) + p1.y() * -std::sin( angleRad ) );
228  p1Rotated.setY( p1.x() * std::sin( angleRad ) + p1.y() * std::cos( angleRad ) );
229  p2Rotated.setX( p2.x() * std::cos( angleRad ) + p2.y() * -std::sin( angleRad ) );
230  p2Rotated.setY( p2.x() * std::sin( angleRad ) + p2.y() * std::cos( angleRad ) );
231 
232  QPolygonF arrowHeadPoly;
233  arrowHeadPoly << middlePoint;
234  arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
235  arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );
236  QPen arrowPen = p->pen();
237  arrowPen.setJoinStyle( Qt::RoundJoin );
238  QBrush arrowBrush = p->brush();
239  arrowBrush.setStyle( Qt::SolidPattern );
240  p->setPen( arrowPen );
241  p->setBrush( arrowBrush );
242  arrowBrush.setStyle( Qt::SolidPattern );
243  p->drawPolygon( arrowHeadPoly );
244 }
245 
246 void QgsLayoutItemPolyline::drawSvgMarker( QPainter *p, QPointF point, double angle, const QString &markerPath, double height ) const
247 {
248  // translate angle from ccw from axis to cw from north
249  angle = 90 - angle;
250 
251  if ( mArrowHeadWidth <= 0 || height <= 0 )
252  {
253  //bad image size
254  return;
255  }
256 
257  if ( markerPath.isEmpty() )
258  return;
259 
260  QSvgRenderer r;
261  const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( markerPath, mArrowHeadWidth, mArrowHeadFillColor, mArrowHeadStrokeColor, mArrowHeadStrokeWidth,
262  1.0 );
263  r.load( svgContent );
264 
265  QgsScopedQPainterState painterState( p );
266  p->translate( point.x(), point.y() );
267  p->rotate( angle );
268  p->translate( -mArrowHeadWidth / 2.0, -height / 2.0 );
269  r.render( p, QRectF( 0, 0, mArrowHeadWidth, height ) );
270 }
271 
273 {
274  if ( !id().isEmpty() )
275  return id();
276 
277  return tr( "<Polyline>" );
278 }
279 
280 void QgsLayoutItemPolyline::_draw( QgsLayoutItemRenderContext &context, const QStyleOptionGraphicsItem * )
281 {
282  QgsScopedQPainterState painterState( context.renderContext().painter() );
283  //setup painter scaling to dots so that raster symbology is drawn to scale
285  QTransform t = QTransform::fromScale( scale, scale );
286 
287  mPolylineStyleSymbol->startRender( context.renderContext() );
288  mPolylineStyleSymbol->renderPolyline( t.map( mPolygon ), nullptr, context.renderContext() );
289  mPolylineStyleSymbol->stopRender( context.renderContext() );
290 
291  // painter is scaled to dots, so scale back to layout units
292  context.renderContext().painter()->scale( context.renderContext().scaleFactor(), context.renderContext().scaleFactor() );
293 
294  drawStartMarker( context.renderContext().painter() );
295  drawEndMarker( context.renderContext().painter() );
296 }
297 
298 void QgsLayoutItemPolyline::_readXmlStyle( const QDomElement &elmt, const QgsReadWriteContext &context )
299 {
300  mPolylineStyleSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( elmt, context ) );
301 }
302 
304 {
305  mPolylineStyleSymbol.reset( static_cast<QgsLineSymbol *>( symbol->clone() ) );
306  refreshSymbol();
307 }
308 
310 {
311  mStartMarker = mode;
312  update();
313 }
314 
316 {
317  mEndMarker = mode;
318  update();
319 }
320 
322 {
323  mArrowHeadWidth = width;
324  updateMarkerSvgSizes();
325  update();
326 }
327 
328 QPainterPath QgsLayoutItemPolyline::shape() const
329 {
330  QPainterPath path;
331  path.addPolygon( mPolygon );
332 
333  QPainterPathStroker ps;
334 
335  ps.setWidth( 2 * mMaxSymbolBleed );
336  QPainterPath strokedOutline = ps.createStroke( path );
337 
338  return strokedOutline;
339 }
340 
342 {
343  return mPolylineStyleSymbol.get();
344 }
345 
347 {
348  QSvgRenderer r;
349  mStartMarkerFile = path;
350  if ( path.isEmpty() || !r.load( path ) )
351  {
352  mStartArrowHeadHeight = 0;
353  }
354  else
355  {
356  //calculate mArrowHeadHeight from svg file and mArrowHeadWidth
357  QRect viewBox = r.viewBox();
358  mStartArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
359  }
361 }
362 
364 {
365  QSvgRenderer r;
366  mEndMarkerFile = path;
367  if ( path.isEmpty() || !r.load( path ) )
368  {
369  mEndArrowHeadHeight = 0;
370  }
371  else
372  {
373  //calculate mArrowHeadHeight from svg file and mArrowHeadWidth
374  QRect viewBox = r.viewBox();
375  mEndArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
376  }
378 }
379 
381 {
382  mArrowHeadStrokeColor = color;
383  update();
384 }
385 
387 {
388  mArrowHeadFillColor = color;
389  update();
390 }
391 
393 {
394  mArrowHeadStrokeWidth = width;
396  update();
397 }
398 
400 {
401  if ( mPolylineStyleSymbol )
402  {
403  QgsStyleSymbolEntity entity( mPolylineStyleSymbol.get() );
404  if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, uuid(), displayName() ) ) )
405  return false;
406  }
407 
408  return true;
409 }
410 
411 void QgsLayoutItemPolyline::_writeXmlStyle( QDomDocument &doc, QDomElement &elmt, const QgsReadWriteContext &context ) const
412 {
413  const QDomElement pe = QgsSymbolLayerUtils::saveSymbol( QString(),
414  mPolylineStyleSymbol.get(),
415  doc,
416  context );
417  elmt.appendChild( pe );
418 }
419 
420 bool QgsLayoutItemPolyline::writePropertiesToElement( QDomElement &elmt, QDomDocument &doc, const QgsReadWriteContext &context ) const
421 {
422  QgsLayoutNodesItem::writePropertiesToElement( elmt, doc, context );
423 
424  // absolute paths to relative
425  QString startMarkerPath = QgsSymbolLayerUtils::svgSymbolPathToName( mStartMarkerFile, context.pathResolver() );
426  QString endMarkerPath = QgsSymbolLayerUtils::svgSymbolPathToName( mEndMarkerFile, context.pathResolver() );
427 
428  elmt.setAttribute( QStringLiteral( "arrowHeadWidth" ), QString::number( mArrowHeadWidth ) );
429  elmt.setAttribute( QStringLiteral( "arrowHeadFillColor" ), QgsSymbolLayerUtils::encodeColor( mArrowHeadFillColor ) );
430  elmt.setAttribute( QStringLiteral( "arrowHeadOutlineColor" ), QgsSymbolLayerUtils::encodeColor( mArrowHeadStrokeColor ) );
431  elmt.setAttribute( QStringLiteral( "outlineWidth" ), QString::number( mArrowHeadStrokeWidth ) );
432  elmt.setAttribute( QStringLiteral( "markerMode" ), mEndMarker );
433  elmt.setAttribute( QStringLiteral( "startMarkerMode" ), mStartMarker );
434  elmt.setAttribute( QStringLiteral( "startMarkerFile" ), startMarkerPath );
435  elmt.setAttribute( QStringLiteral( "endMarkerFile" ), endMarkerPath );
436 
437  return true;
438 }
439 
440 bool QgsLayoutItemPolyline::readPropertiesFromElement( const QDomElement &elmt, const QDomDocument &doc, const QgsReadWriteContext &context )
441 {
442  mArrowHeadWidth = elmt.attribute( QStringLiteral( "arrowHeadWidth" ), QStringLiteral( "2.0" ) ).toDouble();
443  mArrowHeadFillColor = QgsSymbolLayerUtils::decodeColor( elmt.attribute( QStringLiteral( "arrowHeadFillColor" ), QStringLiteral( "0,0,0,255" ) ) );
444  mArrowHeadStrokeColor = QgsSymbolLayerUtils::decodeColor( elmt.attribute( QStringLiteral( "arrowHeadOutlineColor" ), QStringLiteral( "0,0,0,255" ) ) );
445  mArrowHeadStrokeWidth = elmt.attribute( QStringLiteral( "outlineWidth" ), QStringLiteral( "1.0" ) ).toDouble();
446  // relative paths to absolute
447  QString startMarkerPath = elmt.attribute( QStringLiteral( "startMarkerFile" ), QString() );
448  QString endMarkerPath = elmt.attribute( QStringLiteral( "endMarkerFile" ), QString() );
451  mEndMarker = static_cast< QgsLayoutItemPolyline::MarkerMode >( elmt.attribute( QStringLiteral( "markerMode" ), QStringLiteral( "0" ) ).toInt() );
452  mStartMarker = static_cast< QgsLayoutItemPolyline::MarkerMode >( elmt.attribute( QStringLiteral( "startMarkerMode" ), QStringLiteral( "0" ) ).toInt() );
453 
454  QgsLayoutNodesItem::readPropertiesFromElement( elmt, doc, context );
455 
457  return true;
458 }
459 
461 {
462  QRectF br = rect();
463 
464  double margin = std::max( mMaxSymbolBleed, computeMarkerMargin() );
465  if ( mEndMarker == ArrowHead )
466  {
467  margin += 0.5 * mArrowHeadWidth;
468  }
469  br.adjust( -margin, -margin, margin, margin );
470  mCurrentRectangle = br;
471 
472  // update
473  prepareGeometryChange();
474  update();
475 }
476 
477 
478 double QgsLayoutItemPolyline::computeMarkerMargin() const
479 {
480  double margin = 0;
481 
482  if ( mStartMarker == ArrowHead || mEndMarker == ArrowHead )
483  {
484  margin = mArrowHeadStrokeWidth / 2.0 + mArrowHeadWidth * M_SQRT2;
485  }
486 
487  if ( mStartMarker == SvgMarker )
488  {
489  double startMarkerMargin = std::sqrt( 0.25 * ( mStartArrowHeadHeight * mStartArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
490  margin = std::max( startMarkerMargin, margin );
491  }
492 
493  if ( mEndMarker == SvgMarker )
494  {
495  double endMarkerMargin = std::sqrt( 0.25 * ( mEndArrowHeadHeight * mEndArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
496  margin = std::max( endMarkerMargin, margin );
497  }
498 
499  return margin;
500 }
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...
Layout item for node based polyline shapes.
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.
@ SvgMarker
Show SVG marker.
int type() const override
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.
Definition: qgslayoutitem.h:45
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Definition: qgslayoutitem.h:72
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.
An abstract layout item that provides generic methods for node based shapes such as polygon or polyli...
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.
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.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:51
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgslinesymbol.h:30
QgsLineSymbol * clone() const override
Returns a deep copy of this symbol.
static QgsLineSymbol * createSimple(const QVariantMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties.
The class is used as a container of context for various read/write operations on other 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.
QPainter * painter()
Returns the destination QPainter for the render operation.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
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:1219
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 QColor decodeColor(const QString &str)
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
static QString encodeColor(const QColor &color)
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.
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:169
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)
Definition: MathUtils.cpp:786
Contains information relating to the style entity currently being visited.